Vhost Framework
Introduction
The NuttX Vhost architecture is highly modular and forms a perfect symmetry with the VirtIO frontend architecture. Vhost serves as the VirtIO backend (Device side) implementation, enabling cross-core communication through shared memory and inter-core interrupts.
Architecture
Framework Overview
The Vhost framework consists of three main layers:
+----------------------------------------------------------------+
| Vhost Service Layer |
| +----------+ +----------+ +----------+ |
| | Vhost | | Vhost | | ... | |
| | Rpmsg | | Rng | | | |
| +----------+ +----------+ +----------+ |
+----------------------------------------------------------------+
|
v
+----------------------------------------------------------------+
| Vhost Framework Layer |
| Vhost Framework |
+----------------------------------------------------------------+
|
v
+----------------------------------------------------------------+
| Vhost Transport Layer |
| +----------------+ |
| | Vhost Rptun | |
| +----------------+ |
| | Rptun | |
| +----------------+ |
| | Rptun Driver | |
| +----------------+ |
+----------------------------------------------------------------+
|
v
+----------------------------------------------------------------+
| Share Memory && Interrupt |
+----------------------------------------------------------------+
The framework can be divided into the following three parts:
Vhost Service Layer: Located at the top layer, corresponding to
Vhost Rpmsg,Vhost Rng, etc. This layer implements specific device logic conforming to the VirtIO standard. For example,Vhost Rngparses read requests from the frontend and converts them into operations on the underlying physical storage.Vhost Framework Layer: This is the core middle layer that implements the Vhost bus logic and encapsulates an easy-to-use Virtqueue API. It manages device lifecycle, parses descriptor chains, and provides a unified data interface to the service layer.
Vhost Transport Layer: This layer handles low-level physical communication, particularly Vhost Rptun implemented for AMP scenarios. It uses shared memory and inter-core interrupts to establish physical connections with the peer VirtIO Rptun.
Workflow
The following describes the matching process and calling relationship between Vhost Device and Vhost Driver:
+------------------------------------------------------------------+
| Vhost Drivers |
| +--------+ +--------+ +-------+ |
| | Vhost | | Vhost | | ... | |
| | Rng | | Rpmsg | | | |
| +--------+ +--------+ +-------+ |
+------------------------------------------------------------------+
|
| vhost_register_driver()
v
+------------------------------------------------------------------+
| Vhost Bus |
+------------------------------------------------------------------+
^
| vhost_register_device()
|
+------------------------------------------------------------------+
| Transport Layer |
| +----------------+ |
| | Vhost-Rptun | |
| | Resource Table | |
| +----------------+ |
+------------------------------------------------------------------+
||
|| Match Success
vv
+------------------------------------------------------------------+
| vhost_xxx_probe() |
| Reset, configure, feature negotiation, memory allocation |
+------------------------------------------------------------------+
|
| Vhost API
v
+------------------------------------------------------------------+
| Port to NuttX Various Frameworks |
| Normal Driver/Socket etc operations |
+------------------------------------------------------------------+
|
v
+------------------------------------------------------------------+
| VFS/Other Driver |
+------------------------------------------------------------------+
Driver Registration: During NuttX initialization,
vhost_register_drivers()is called to register all supported Vhost Drivers to the Vhost bus.Device Registration: The registration process is initiated by the transport layer. The REMOTEPROC transport layer calls
rptun_register_device().Driver and Device Matching: When a device is registered to the bus, the system attempts to match Driver and Device. If the match is successful, the
probefunction implemented by the Driver is executed. In theprobefunction, the driver initializes, configures, and performs feature negotiation on the Vhost Device. Depending on the complexity and type of the device, it may also need to initialize private structures or perform additional operations.Register NuttX Driver: Call the API provided by the NuttX driver framework to register the driver to the Virtual File System (VFS) for user access or access other system drivers through the VFS.
Runtime: During runtime, the Driver calls the
virtqueuecommon interfaces provided by OpenAMP to exchange data and notifications in VirtIO standard format, thereby implementing driver functionality.
Note
If the peer VirtIO Driver is not ready (status is not DRIVER_OK), the
device will be added to a deferred probe queue. The system will periodically
check and complete matching when ready.
Source Code
nuttx/
├── drivers/
│ └── vhost/
│ └── vhost.c # Vhost framework core implementation
├── include/
│ └── nuttx/
│ └── vhost/
│ └── vhost.h # Vhost header file
└── openamp/
└── open-amp/ # OpenAMP repository
API Reference
Data Structures
struct vhost_device
Vhost device structure, which is an alias for struct virtio_device
(defined via macro #define vhost_device virtio_device). Used to represent
a Vhost device instance, containing basic device information and state.
struct vhost_driver
Vhost driver structure, used to define a Vhost driver program.
struct vhost_driver
{
uint32_t device; /* Device ID for matching Vhost device */
CODE int (*probe)(FAR struct vhost_device *hdev); /* Device probe callback */
CODE void (*remove)(FAR struct vhost_device *hdev); /* Device remove callback */
struct dq_entry_s node; /* List node for driver list */
};
Core APIs
vhost_register_device
-
int vhost_register_device(FAR struct vhost_device *hdev)
Register a Vhost device to the Vhost bus.
- Parameters:
hdev – Pointer to the Vhost device structure to register
- Returns:
0 on success, negative errno on failure
If the peer VirtIO Driver is not ready (status is not
DRIVER_OK), the device will be added to a deferred probe queue. The system will periodically check and complete matching when ready. If the peer is already ready, it will immediately attempt to match with registered drivers.
vhost_unregister_device
-
int vhost_unregister_device(FAR struct vhost_device *hdev)
Unregister a Vhost device from the Vhost bus.
- Parameters:
hdev – Pointer to the Vhost device structure to unregister
- Returns:
0 on success, negative errno on failure
If the device has been matched with a driver, the driver’s
removecallback will be called first. Then the device is removed from the device list and related resources are released.
vhost_register_driver
-
int vhost_register_driver(FAR struct vhost_driver *hdrv)
Register a Vhost driver to the Vhost bus.
- Parameters:
hdrv – Pointer to the Vhost driver structure to register
- Returns:
0 on success, negative errno on failure
After driver registration, it will automatically attempt to match with registered devices. If a match is successful, the driver’s
probecallback will be called.
vhost_unregister_driver
-
int vhost_unregister_driver(FAR struct vhost_driver *hdrv)
Unregister a Vhost driver from the Vhost bus.
- Parameters:
hdrv – Pointer to the Vhost driver structure to unregister
- Returns:
0 on success, negative errno on failure
This will iterate through all devices matched with this driver and call the driver’s
removecallback. Then the driver is removed from the driver list.
vhost_register_drivers
-
void vhost_register_drivers(void)
Register all configured Vhost drivers.
- Returns:
None
Called during system initialization. This will initialize the OpenAMP metal library and register corresponding Vhost drivers based on Kconfig configuration (such as
vhost-rng,vhost-rpmsg, etc.).
vhost_get_vq_buffers
-
int vhost_get_vq_buffers(FAR struct virtqueue *vq, FAR struct virtqueue_buf *vb, size_t vbsize, FAR size_t *vbcnt)
Get a set of available buffers from a Virtqueue.
- Parameters:
vq – Pointer to the Virtqueue
vb – Output parameter, array for storing buffer information
vbsize – Size of the
vbarray (maximum number of buffers)vbcnt – Output parameter, returns the actual number of buffers obtained
- Returns:
Head index of the descriptor chain on success, negative errno on failure
Return values:
-ENOMEM: No available buffers-EINVAL:vbsizeis insufficient to hold all buffers
This function automatically traverses the entire descriptor chain and fills all buffer information into the
vbarray. The returned head index can be used for subsequent calls tovirtqueue_add_consumed_bufferto return buffers.
Macro APIs
The following APIs are wrappers for VirtIO standard interfaces, used to operate Vhost devices:
Macro |
Corresponding VirtIO API |
Description |
|---|---|---|
|
|
Create Virtqueue |
|
|
Delete Virtqueue |
|
|
Set device status |
|
|
Get device status |
|
|
Set device features |
|
|
Get device features |
|
|
Read device config |
|
|
Write device config |
|
|
Check feature support |
|
|
Read config struct member |
|
|
Write config struct member |