mirror of
https://github.com/apache/nuttx.git
synced 2026-10-11 16:20:21 +00:00
The documentation grew one page at a time, so the tree follows the
history of who wrote what and not the shape of NuttX. Scheduling is
spread over three places, a driver page can sit above the subsystem
that owns it, and the front page lists everything at the same level.
That is a lot to face when all you want to know is where the scheduler
lives.
This change files every page under the code it describes. It is a move,
not a rewrite: outside the ten pages named below, every page keeps the
text that is already in master, and no page's text is deleted.
What it does:
* Groups the table of contents into nine chapters.
* Moves the OS subsystems under os/: scheduling, memory, drivers,
filesystem, networking, IPC, interrupts, libs, time.
* Renames the platform pages to the names the source tree uses, and
derives their tags from the tree instead of by hand.
* Splits guides/ by subject.
* Adds Documentation/redirects.py, with a rule for every page that left
its old path, so old URLs keep working. The redirect page also carries
a link's #anchor across to the new page.
Ten pages have text that is new or rewritten. Nine of them are the
landing page of a chapter, which has to exist for the new structure:
index the front page
os/index OS Design
os/scheduling/index Scheduling
os/interrupts/index Interrupts
os/ipc/index IPC
os/time/index Time and timers
about/index About
developing/index Developing NuttX
ReleaseNotes/index Release notes
The tenth is os/libs/libbuiltin, the only page here with technical
content: libs/libbuiltin/ had no page at all. Five SVG diagrams come
with these pages, hand-written XML with no editor metadata.
Nothing outside Documentation/ is touched.
How it was checked:
* Sphinx builds with -W: no warnings, and no document left outside a
toctree.
* A script, offered in the PR, proves the narrow claim this rests on.
For every page outside the ten named above it erases what a move
touches -- link target, path, tag line, toctree block, table border --
from the whole old text and the whole new text, and requires the two
to be byte for byte identical. It also requires every sentence of a
deleted page to turn up somewhere, and every page that left its old
path to have a redirect, from a URL that existed, to where its content
went. It exits non-zero and names the page if any of that is not true,
and it tests added pages too, so forgetting to declare one cannot make
it pass.
* An independent audit checked 133 factual claims on these ten pages
against the tree, one shell command per claim: 130 confirmed, 1
refuted and fixed here, 2 not checkable.
* tools/checkpatch.sh is clean over the range.
The diff is large because moving a page changes every link that points
to it. Most of it is pure renames, and board pages that gained one tag
line.
Assisted-by: Claude:claude-opus-5
269 lines
11 KiB
ReStructuredText
269 lines
11 KiB
ReStructuredText
================
|
|
VirtIO Framework
|
|
================
|
|
|
|
Introduction
|
|
============
|
|
|
|
NuttX implements a complete VirtIO framework based on OpenAMP. The framework
|
|
supports various VirtIO drivers compatible with the VirtIO standard (such as
|
|
VirtIO-Net, VirtIO-Block, etc.) at the upper layer, and different VirtIO
|
|
transport layer implementations (including VirtIO-MMIO, VirtIO-PCI,
|
|
VirtIO-Remoteproc, etc.) at the lower layer.
|
|
|
|
Architecture
|
|
============
|
|
|
|
Framework Overview
|
|
------------------
|
|
|
|
The VirtIO framework consists of three main layers:
|
|
|
|
.. code-block:: text
|
|
|
|
+------------------------------------------------------------------+
|
|
| VirtIO Driver Layer |
|
|
| +----------+ +----------+ +----------+ +-----+ +-------------+ |
|
|
| | VirtIO | | VirtIO | | VirtIO | | ... | | VirtIO | |
|
|
| | Sock | | Net | | Blk | | | | Rpmsg | |
|
|
| +----------+ +----------+ +----------+ +-----+ +-------------+ |
|
|
+------------------------------------------------------------------+
|
|
|
|
|
v
|
|
+------------------------------------------------------------------+
|
|
| VirtIO Framework Layer |
|
|
| VirtIO Framework |
|
|
+------------------------------------------------------------------+
|
|
|
|
|
+---------------------+---------------------+
|
|
| | |
|
|
v v v
|
|
+----------------+ +----------------+ +----------------+
|
|
| VirtIO MMIO | | VirtIO PCI | | VirtIO Rptun |
|
|
+----------------+ +----------------+ +----------------+
|
|
| Memory Map | | PCI Framework | | Rptun |
|
|
+----------------+ +----------------+ +----------------+
|
|
| | PCI Controller | | Rptun Driver |
|
|
| +----------------+ +----------------+
|
|
| | | +----------------------+
|
|
| | +-----------------> | Remoteproc Processor |
|
|
v v +----------------------+
|
|
+------------------------------------------------------------------+
|
|
| Hypervisor |
|
|
+------------------------------------------------------------------+
|
|
|
|
The framework can be divided into the following three parts:
|
|
|
|
1. **VirtIO Driver Layer**: The driver layer is responsible for interfacing
|
|
VirtIO with the NuttX driver framework. The driver layer completes device
|
|
initialization and data interaction by calling the unified interfaces
|
|
provided by VirtIO.
|
|
|
|
2. **VirtIO Framework Layer**: The VirtIO layer provides unified interfaces
|
|
for drivers, supporting registration, unregistration, and matching
|
|
mechanisms for Drivers and Devices.
|
|
|
|
3. **VirtIO Transport Layer**: The transport layer provides support for
|
|
different transport methods, including MMIO, RemoteProc, and PCI.
|
|
|
|
Workflow
|
|
--------
|
|
|
|
The following describes the matching process and calling relationship between
|
|
VirtIO Device and VirtIO Driver:
|
|
|
|
.. code-block:: text
|
|
|
|
+------------------------------------------------------------------+
|
|
| VirtIO Drivers |
|
|
| +--------+ +--------+ +--------+ +--------+ +--------+ +-------+ |
|
|
| |VirtIO | |VirtIO | |VirtIO | |VirtIO | |VirtIO | | ... | |
|
|
| |Net | |Sock | |Blk | |Serial | |Sound | | | |
|
|
| +--------+ +--------+ +--------+ +--------+ +--------+ +-------+ |
|
|
+------------------------------------------------------------------+
|
|
|
|
|
| virtio_register_driver()
|
|
v
|
|
+------------------------------------------------------------------+
|
|
| VirtIO Bus |
|
|
+------------------------------------------------------------------+
|
|
^
|
|
| virtio_register_device()
|
|
|
|
|
+------------------------------------------------------------------+
|
|
| Transport Layer |
|
|
| +----------------+ +----------------+ +----------------+ |
|
|
| | VirtIO-MMIO | | VirtIO-PCI | | VirtIO-Rptun | |
|
|
| | Device Memory | | PCI Framework | | Resource Table | |
|
|
| | and IRQ | | Device in PCI | | | |
|
|
| +----------------+ +----------------+ +----------------+ |
|
|
+------------------------------------------------------------------+
|
|
|
|
||
|
|
|| Match Success
|
|
vv
|
|
|
|
+------------------------------------------------------------------+
|
|
| virtio_xxx_probe() |
|
|
| Reset, configure, feature negotiation, memory allocation |
|
|
+------------------------------------------------------------------+
|
|
|
|
|
| VirtIO API
|
|
v
|
|
+------------------------------------------------------------------+
|
|
| Port to NuttX Various Frameworks |
|
|
| Normal Driver/Socket etc operations |
|
|
+------------------------------------------------------------------+
|
|
|
|
|
v
|
|
+------------------------------------------------------------------+
|
|
| VFS |
|
|
+------------------------------------------------------------------+
|
|
|
|
1. **Driver Registration**:
|
|
During NuttX initialization, ``virtio_register_drivers()`` is called to
|
|
register all supported VirtIO Drivers to the VirtIO bus.
|
|
|
|
2. **Device Registration**:
|
|
The registration process is initiated by the transport layer:
|
|
|
|
- MMIO transport layer calls ``virtio_register_mmio_device()``
|
|
- REMOTEPROC transport layer calls ``rptun_register_device()``
|
|
- PCI transport layer calls ``virtio_pci_probe()``
|
|
|
|
After the transport layer completes initialization, it calls
|
|
``virtio_register_device()`` to register the VirtIO Device to the VirtIO bus.
|
|
|
|
3. **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 ``probe`` function implemented
|
|
by the Driver is executed. In the ``probe`` function, the driver initializes,
|
|
configures, and performs feature negotiation on the VirtIO Device. Depending
|
|
on the complexity and type of the device, it may also need to initialize
|
|
private structures or perform additional operations.
|
|
|
|
4. **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.
|
|
|
|
5. **Runtime**:
|
|
During runtime, the Driver calls the ``virtqueue`` common interfaces provided
|
|
by OpenAMP to exchange data and notifications in VirtIO standard format,
|
|
thereby implementing driver functionality.
|
|
|
|
Source Code
|
|
===========
|
|
|
|
.. code-block:: text
|
|
|
|
nuttx/
|
|
├── drivers/
|
|
│ └── virtio/
|
|
│ └── virtio.c # VirtIO framework core implementation
|
|
├── include/
|
|
│ └── nuttx/
|
|
│ └── virtio/
|
|
│ └── virtio.h # VirtIO header file
|
|
└── openamp/
|
|
└── open-amp/ # OpenAMP repository
|
|
|
|
API Reference
|
|
=============
|
|
|
|
This section describes the interfaces that need to be called during VirtIO
|
|
driver adaptation.
|
|
|
|
NuttX Log Interfaces
|
|
--------------------
|
|
|
|
``vrtinfo(...)``
|
|
INFO level VirtIO system log interface.
|
|
|
|
``vrtwarn(...)``
|
|
WARNING level VirtIO system log interface.
|
|
|
|
``vrterr(...)``
|
|
ERROR level VirtIO system log interface.
|
|
|
|
NuttX VirtIO Framework Interface
|
|
--------------------------------
|
|
|
|
.. c:function:: int virtio_register_driver(FAR struct virtio_driver *driver)
|
|
|
|
Register a VirtIO Driver to the VirtIO bus. When a corresponding device
|
|
already exists in the bus, it will immediately match and call the ``probe``
|
|
function implemented by the driver. If there is no corresponding device in
|
|
the bus, the driver's ``probe`` function will be called back after a
|
|
corresponding VirtIO device is registered to the VirtIO bus to complete
|
|
driver initialization.
|
|
|
|
:param driver: Pointer to the virtio_driver structure
|
|
:return: 0 on success, negative errno on failure
|
|
|
|
OpenAMP Interfaces
|
|
------------------
|
|
|
|
Prerequisites
|
|
~~~~~~~~~~~~~
|
|
|
|
- **Driver TX virtqueue**:
|
|
The driver's transmit queue. Get a buffer from the ``used ring`` of ``txvq``,
|
|
fill in the data to be sent, and then add it to the ``avail ring`` of ``txvq``
|
|
to complete the data transmission process.
|
|
|
|
- **Driver RX virtqueue**:
|
|
The driver's receive queue. Get a buffer from the ``used ring`` of ``rxvq``,
|
|
read the data from it, and then return it to the ``avail ring`` of ``rxvq``
|
|
to complete the data reception process.
|
|
|
|
Interface Description
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. c:function:: void *virtqueue_get_buffer(struct virtqueue *vq, uint32_t *len, uint16_t *idx)
|
|
|
|
Get a buffer from the ``used ring`` of virtqueue.
|
|
|
|
:param vq: Pointer to the virtqueue
|
|
:param len: Length of the obtained buffer
|
|
:param idx: Index of the obtained buffer in the ``used ring``
|
|
:return: Pointer to the buffer, or NULL if no buffer available
|
|
|
|
.. c:function:: int virtqueue_add_buffer(struct virtqueue *vq, struct virtqueue_buf *buf_list, int readable, int writable, void *cookie)
|
|
|
|
Add a buffer to the ``avail ring`` of virtqueue.
|
|
|
|
:param vq: Pointer to the virtqueue
|
|
:param buf_list: Array of buffers to be added
|
|
:param readable: Number of readable buffers in ``buf_list``, indicating the
|
|
part that the Device should read
|
|
:param writable: Number of writable buffers in ``buf_list``, indicating the
|
|
part that the Device should fill
|
|
:param cookie: Cache pointer, this value will be returned when calling
|
|
``virtqueue_get_buffer`` to get the buffer
|
|
:return: 0 on success, negative errno on failure
|
|
|
|
.. c:function:: void virtqueue_kick(struct virtqueue *vq)
|
|
|
|
Notify the Device. Usually called after sending data to the device side or
|
|
returning a buffer to the device side to notify the device that it can
|
|
proceed to the next operation.
|
|
|
|
:param vq: Pointer to the virtqueue
|
|
|
|
.. c:function:: void virtqueue_enable_cb(struct virtqueue *vq)
|
|
|
|
Enable virtqueue interrupt.
|
|
|
|
:param vq: Pointer to the virtqueue
|
|
|
|
.. c:function:: void virtqueue_disable_cb(struct virtqueue *vq)
|
|
|
|
Disable virtqueue interrupt.
|
|
|
|
:param vq: Pointer to the virtqueue
|
|
|
|
References
|
|
==========
|
|
|
|
- `virtio: Towards a De-Facto Standard For Virtual I/O Devices <https://ozlabs.org/~rusty/virtio-spec/virtio-paper.pdf>`_
|
|
- `Virtual I/O Device (VIRTIO) Version 1.2 <https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.pdf>`_
|