Skip to content

[DRAFT] virtio: add virtiofs #86768

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions MAINTAINERS.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2160,6 +2160,20 @@ Release Notes:
tests:
- drivers.video

"Drivers: VIRTIO":
status: maintained
maintainers:
- fkokosinski
- tgorochowik
collaborators:
- kgugala
files:
- drivers/virtio/
- dts/bindings/virtio/
- include/zephyr/virtio/
labels:
- "area: VIRTIO"

"Drivers: W1":
status: maintained
maintainers:
Expand Down
1 change: 1 addition & 0 deletions doc/hardware/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ Hardware Support
peripherals/index.rst
pinctrl/index.rst
porting/index
virtualization/index.rst
11 changes: 11 additions & 0 deletions doc/hardware/virtualization/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.. _virtualization:

Virtualization
##############

These pages document Zephyr virtualization facilities.

.. toctree::
:maxdepth: 1

virtio.rst
142 changes: 142 additions & 0 deletions doc/hardware/virtualization/virtio.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
Virtual I/O (VIRTIO)
##########################

Overview
********

Virtual I/O (VIRTIO) is a protocol used for communication with various devices, typically used in
virtualized environments. Its main goal is to provide an efficient and standardized mechanism for
interfacing with virtual devices from within a virtual machine. The communication relies on virtqueues
and standard transfer methods like PCI or MMIO.

Concepts
**********************************

Virtio defines various components used during communication and initialization. It specifies both the
host (named "device" in the specification) and guest (named "driver" in the specification) sides.
Currently Zephyr can only work as a guest. On top of the facilities exposed by the Virtio driver,
a driver for a specific device (e.g. network card) can be implemented.

A high-level overview of a system with a Virtio device is shown below.

.. graphviz::
:caption: Virtual I/O overview

digraph {

subgraph cluster_host {
style=filled;
color=lightgrey;
label = "Host";
labeljust=r;

virtio_device [label = "virtio device"];
}

transfer_method [label = "virtio transfer method"];

subgraph cluster_guest {
style=filled;
color=lightgrey;
label = "Guest";
labeljust=r;

virtio_driver [label = "virtio driver"];
specific_device_driver [label = "specific device driver"];
device_user [label = "device user"];
}

virtio_device -> transfer_method;
transfer_method -> virtio_device;
transfer_method -> virtio_driver;
virtio_driver -> transfer_method;
virtio_driver -> specific_device_driver;
specific_device_driver -> virtio_driver;
specific_device_driver -> device_user;
device_user -> specific_device_driver;
}

Configuration space
===================
Each device provides configuration space, used for initialization and configuration. It allows
selection of device and driver features, enabling specific virtqueues and setting their addresses.
Once the device is configured, most of its configuration cannot be changed without resetting the device.
The exact layout of the configuration space depends on the transfer method.

Driver and device features
--------------------------
The configuration space provides a way to negotiate feature bits, determining some non-mandatory
capabilities of the devices. The exact available feature bits depend on the device and platform.

Device-specific configuration
-----------------------------
Some of the devices offer device-specific configuration space, providing additional configuration options.

Virtqueues
==========
The main mechanism used for transferring data between host and guest is a virtqueue. Specific
devices have different numbers of virtqueues, for example devices supporting bidirectional transfer
usually have one or more tx/rx virtqueue pairs. Virtio specifies two types of virtqueues: split
virtqueues and packed virtqueues. Zephyr currently supports only split virtqueues.

Split virtqueues
----------------
A split virtqueue consists of three parts: descriptor table, available ring and used ring.

The descriptor table holds descriptors of buffers, that is their physical addresses, lengths and flags.
Each descriptor is either device writeable or driver writeable. The descriptors can be chained, creating
descriptor chains. Typically a chain begins with descriptors containing the data for the device to read
and ends with the device writeable part, where the device places its response.

The main part of the available ring is a circular buffer of references (in the form of indexes) to the
descriptors in the descriptor table. Once the guest decides to send the data to the host, it adds the index of
the head of the descriptor chain to the top of the available ring.

The used ring is similar to the available ring, but it's used by the host to return descriptors to the guest. In
addition to storing descriptor indexes, it also provides information about the amount of data written to them.

Common Virtio libraries
***********************

Zephyr provides an API for interfacing with Virtio devices and virtqueues, which allows performing necessary operations
over the lifetime of the Virtio device.

Device initialization
=====================
Once the Virtio driver finishes performing low-level initialization common to the all devices using a given transfer method,
like finding device on the bus and mapping Virtio structures, the device specific driver steps in and performs the next
stages of initialization with the help of the Virtio API.

The first thing the device-specific driver does is feature bits negotiation. It uses :c:func:`read_device_feature_bit`
to determine which features the device offers, and then selects the ones it needs using :c:func:`write_driver_feature_bit`.
After all required features have been selected, the device-specific driver calls :c:func:`commit_feature_bits`. Then, virtqueues
are initialized with :c:func:`init_virtqueues`. This function enumerates the virtqueues, invoking the provided callback
:c:type:`virtio_enumerate_queues` to determine the required size of each virtqueue. From this point, if none of the
functions returned errors, the virtqueues are operational. If the specific device provides one, the device-specific config
can be obtained by calling :c:func:`get_device_specific_config`.

Virtqueue operation
===================
Once the virtqueues are operational, they can be used to send and receive data. To do so, the pointer to the nth
virtqueue has to be acquired using :c:func:`get_virtqueue`. To send data consisting of a descriptor chain,
:c:func:`virtq_add_buffer_chain` has to be used. Along the descriptor chain, it takes pointer to the callback that
will be invoked once the device returns the given descriptor chain. After that, the virtqueue has to be notified using
:c:func:`notify_queue` from the Virtio API.

Guest-side Virtio drivers
*************************
Currently Zephyr provides a driver only for Virtio over PCI and a driver for one device using virtio - virtio-fs, used
to access the filesystem of the host.

Virtio samples
**************
A sample showcasing the use of a driver relying on Virtio is provided in :zephyr:code-sample:`virtiofs`. If you wish
to check code interfacing directly with the Virtio driver, you can check the virtiofs driver, especially :c:func:`virtiofs_init`
for initialization and :c:func:`virtiofs_send_receive` with the :c:func:`virtiofs_recv_cb` for data transfer to/from
the Virtio device.

API Reference
*************

.. doxygengroup:: virtio_interface
.. doxygengroup:: virtqueue_interface
1 change: 1 addition & 0 deletions drivers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ add_subdirectory_ifdef(CONFIG_SYSCON syscon)
add_subdirectory_ifdef(CONFIG_SYS_CLOCK_EXISTS timer)
add_subdirectory_ifdef(CONFIG_TEE tee)
add_subdirectory_ifdef(CONFIG_VIDEO video)
add_subdirectory_ifdef(CONFIG_VIRTIO_PCI virtio)
add_subdirectory_ifdef(CONFIG_VIRTUALIZATION virtualization)
add_subdirectory_ifdef(CONFIG_W1 w1)
add_subdirectory_ifdef(CONFIG_WATCHDOG watchdog)
Expand Down
1 change: 1 addition & 0 deletions drivers/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ source "drivers/timer/Kconfig"
source "drivers/usb/Kconfig"
source "drivers/usb_c/Kconfig"
source "drivers/video/Kconfig"
source "drivers/virtio/Kconfig"
source "drivers/virtualization/Kconfig"
source "drivers/w1/Kconfig"
source "drivers/watchdog/Kconfig"
Expand Down
7 changes: 7 additions & 0 deletions drivers/virtio/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Copyright (c) 2024 Antmicro <www.antmicro.com>
# SPDX-License-Identifier: Apache-2.0

zephyr_library()

zephyr_library_sources_ifdef(CONFIG_VIRTIO virtqueue.c)
zephyr_library_sources_ifdef(CONFIG_VIRTIO_PCI virtio_pci.c)
22 changes: 22 additions & 0 deletions drivers/virtio/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright (c) 2024 Antmicro <www.antmicro.com>
# SPDX-License-Identifier: Apache-2.0

config VIRTIO
bool "support for VIRTIO"
help
Enable options for VIRTIO

if VIRTIO

config VIRTIO_PCI
bool "support for VIRTIO over PCI"
default y
depends on DT_HAS_VIRTIO_PCI_ENABLED
help
Enable options for VIRTIO over PCI

endif # VIRTIO

module = VIRTIO
module-str = VIRTIO
source "subsys/logging/Kconfig.template.log_config"
Loading