Struct machina_virtio_device::Device

source ·
pub struct Device<'a, N> { /* private fields */ }
Expand description

State for managing a virtio device and its queues using futures.

Provides a wrapper around one or more [Queue]s along with helpers to send and receive queue notifications to the guest driver. These wrappers focus on presenting a asynchronous futures interface on top of the underlying objects.

Primary this provides a wrapper around a [DescChainStream] for processing descriptor chains. The guest signals that there are descriptors available either using a GuestBellTrap or via a VirtioDeviceRequest::NotifyQueue message. Connecting these two sources of notifications to the underlying waker from the [DescChainStream] can be done in a most easily using [run_device_notify]. It will run forever processing messages from a VirtioDeviceRequestStream, and from any GuestBellTrap, performing [notify_queue] as needed.

If the the device needs to run its own message loop on the stream, and therefore cannot give it to [run_device_notify], it can also just [take_bell_traps] and use GuestBellTrap::complete or GuestBellTrap::complete_or_pending to process them. In this case the device message loop should use [notify_queue] for any VirtioDeviceRequest::NotifyQueue it receives.

The [DriverNotify] object that was configured in the [DeviceBuilder] can be retrieved using [get_notify]. The notify object might be needed by a device to:

  • Signal a configuration change
  • Flush pending queue notifications if something like [virtio_device::util::BufferedNotify] is being used.

Implementations§

source§

impl<'a, N> Device<'a, N>

source

pub fn take_stream<'b>( &'b self, idx: u16, ) -> Result<WrappedDescChainStream<'a, 'b, N>, DeviceError>

Take a [Stream] that yields [DescChain] for the requested queue

This returns an error if the specified queue either was not configured in the DeviceBuilder, or has already been taken and not returned. The WrappedDescChainStream that this returns will automatically return itself when dropped.

Note that the [Stream] needs to have its waker signalled to work correctly, see [struct] (Device) level comment for details.

source

pub fn get_notify(&self) -> &N

Retrieve underlying driver notification object

source

pub fn configured_queues<'b>(&'b self) -> impl Iterator<Item = u16> + 'b
where 'b: 'a,

Query the configured queues.

Returns an iterator of the queue numbers that were configured.

source

pub fn notify_queue(&self, idx: u16) -> Result<(), DeviceError>

Notify a queue in response to a notification from the driver.

This signals the waker for the given queue and is required to have the streams returned from [take_stream] yield items.

See struct level documentation for more details.

source

pub fn take_bell_traps(&self) -> Option<GuestBellTrap>

Take any [GuestBellTraps] that might have been configured.

If bell traps were provided in the DeviceBuilder this returns them. This completely removes them from the Device and the caller is now responsible for them and forwarding any notifications from the driver to [notify_queue].

Internally [run_device_notify] uses this to get the bell traps and so once you call it this will always return a None. Similarly if you call this [run_device_notify] will not be able to process bell traps, since you are responsible for them.

The normal reason to use this is if you need to run your own message loop and cannot use [run_device_notify], in which case you almost always want to

GuestBellTrap::complete_or_pending(device.take_bell_traps(), &device)
source

pub fn get_features(&self) -> u32

Return the negotiated features from [DeviceBuilder::give_ready]

source

pub async fn run_device_notify( &self, stream: VirtioDeviceRequestStream, ) -> Result<(), DeviceError>

Run any notifications from the driver till completion.

Consumes both a [VirtioDeviceStream] as well as any bell traps to receive any notifications from the driver, for the device, and calls [notify_queue] with them. Will never yield a success and only ever yields an error should either source of notifications close unexpectedly, or indicate an invalidate queue.

This method is ideal if you do not need to process device specific messages from the FIDL channel.

source

pub async fn run_device_notify_stream( &self, stream: VirtioDeviceRequestStream, ) -> Result<(), DeviceError>

Process all queue notifications on a VirtioDeviceRequestStream

Unlike [run_device_notify] this does not [take_bell_trap] and process those messages. This will also yield an Ok(()) should the stream end, leaving the caller to determine if that is an error condition or not.

Auto Trait Implementations§

§

impl<'a, N> !Freeze for Device<'a, N>

§

impl<'a, N> !RefUnwindSafe for Device<'a, N>

§

impl<'a, N> !Send for Device<'a, N>

§

impl<'a, N> !Sync for Device<'a, N>

§

impl<'a, N> Unpin for Device<'a, N>
where N: Unpin,

§

impl<'a, N> !UnwindSafe for Device<'a, N>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T, D> Encode<Ambiguous1, D> for T
where D: ResourceDialect,

source§

unsafe fn encode( self, _encoder: &mut Encoder<'_, D>, _offset: usize, _depth: Depth, ) -> Result<(), Error>

Encodes the object into the encoder’s buffers. Any handles stored in the object are swapped for Handle::INVALID. Read more
source§

impl<T, D> Encode<Ambiguous2, D> for T
where D: ResourceDialect,

source§

unsafe fn encode( self, _encoder: &mut Encoder<'_, D>, _offset: usize, _depth: Depth, ) -> Result<(), Error>

Encodes the object into the encoder’s buffers. Any handles stored in the object are swapped for Handle::INVALID. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more