virtio_device/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Write virtio devices in Rust.
//!
//! This crate provides utilities for virtio devices to manipulate descriptor rings. Only the device
//! side is targeted, and this crate is completely unsuitable, and not intended, for writing
//! drivers.
//!
//! The provided wrappers are built up in a series of layers, each providing a higher level and more
//! convenient interface, at the cost of injecting some policy opinions for managing the rings. The
//! layers/modules are:
//! - [`chain`] High level iteration and walking of descriptor chains as series of byte ranges
//! including manipulation through [`std::io::read`] and [`std::io::write`] interfaces.
//! - [`queue`] Provides functional virt queue management allowing for descriptor chains to be
//! retrieved, iterated and returned.
//! - [`ring`] Provides the barest minimum Rust type safety over accessing the rings.
//! This is not expected to generally be needed, with [`queue`] completely hiding all [`ring`]
//! details.
//! There are some additional modules providing:
//! - [`mem`] Definitions for memory translation between drivers and devices.
//! - [`util`] Small wrappers and trait implementations that are commonly useful, but very
//! opinionated.
//! - [`fake_queue`] Helpers for writing unittests against virtio devices.
//!
//! What this crate does not provide is any transport or device type specific management. The user
//! then is responsible for performing all setup and feature negotiation prior to using this crate
//! to manage the negotiated queues. The user therefore needs to provide:
//! - Location of negotiated desc, used and avail rings as [`mem::DeviceRange`] definitions.
//! - Implementation of [`mem::DriverMem`] for driver to device memory address translation.
//! - Implementation of [`queue::DriverNotify`] for signaling the driver.
//! - A way to receive signals from the driver to know when to check for descriptors.
//!
//! With these pieces existing a typical usage of this crate is expected to be:
//! - Construct a [`queue::Queue`] by passing the ring definitions to [`queue::Queue::new`]
//! - Build a [`util::DescChainStream`] from the [`queue::Queue`] and connect the
//! [`util::DescChainStream::waker`]
//! - Construct [`chain::ReadableChain`] or [`chain::WritableChain`] from the [`queue::DescChain`]
//! items generated by the [`util::DescChainStream`]
//! - Process the [`chain::ReadableChain`] or [`chain::WritableChain`] using their provided methods
//! or the [`std::io::read`] and [`std::io::write`] trait implementations.
//! - Explicitly [return](chain::ReadableChain::return_complete) the chain or let it `drop` to have
//! the [`queue::Queue`] return it to the driver.
//!
//! Commonly if expecting to process descriptors chains in batches you will also want to wrap your
//! [`queue::DriverNotify`] in a [`util::BufferedNotify`], but you must ensure to call
//! [`util::BufferedNotify::flush`].
pub mod chain;
pub mod fake_queue;
pub mod mem;
pub mod queue;
pub mod ring;
pub mod util;