162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci.. _virtio: 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci=============== 662306a36Sopenharmony_ciVirtio on Linux 762306a36Sopenharmony_ci=============== 862306a36Sopenharmony_ci 962306a36Sopenharmony_ciIntroduction 1062306a36Sopenharmony_ci============ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ciVirtio is an open standard that defines a protocol for communication 1362306a36Sopenharmony_cibetween drivers and devices of different types, see Chapter 5 ("Device 1462306a36Sopenharmony_ciTypes") of the virtio spec (`[1]`_). Originally developed as a standard 1562306a36Sopenharmony_cifor paravirtualized devices implemented by a hypervisor, it can be used 1662306a36Sopenharmony_cito interface any compliant device (real or emulated) with a driver. 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciFor illustrative purposes, this document will focus on the common case 1962306a36Sopenharmony_ciof a Linux kernel running in a virtual machine and using paravirtualized 2062306a36Sopenharmony_cidevices provided by the hypervisor, which exposes them as virtio devices 2162306a36Sopenharmony_civia standard mechanisms such as PCI. 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ciDevice - Driver communication: virtqueues 2562306a36Sopenharmony_ci========================================= 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ciAlthough the virtio devices are really an abstraction layer in the 2862306a36Sopenharmony_cihypervisor, they're exposed to the guest as if they are physical devices 2962306a36Sopenharmony_ciusing a specific transport method -- PCI, MMIO or CCW -- that is 3062306a36Sopenharmony_ciorthogonal to the device itself. The virtio spec defines these transport 3162306a36Sopenharmony_cimethods in detail, including device discovery, capabilities and 3262306a36Sopenharmony_ciinterrupt handling. 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ciThe communication between the driver in the guest OS and the device in 3562306a36Sopenharmony_cithe hypervisor is done through shared memory (that's what makes virtio 3662306a36Sopenharmony_cidevices so efficient) using specialized data structures called 3762306a36Sopenharmony_civirtqueues, which are actually ring buffers [#f1]_ of buffer descriptors 3862306a36Sopenharmony_cisimilar to the ones used in a network device: 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci.. kernel-doc:: include/uapi/linux/virtio_ring.h 4162306a36Sopenharmony_ci :identifiers: struct vring_desc 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ciAll the buffers the descriptors point to are allocated by the guest and 4462306a36Sopenharmony_ciused by the host either for reading or for writing but not for both. 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ciRefer to Chapter 2.5 ("Virtqueues") of the virtio spec (`[1]`_) for the 4762306a36Sopenharmony_cireference definitions of virtqueues and "Virtqueues and virtio ring: How 4862306a36Sopenharmony_cithe data travels" blog post (`[2]`_) for an illustrated overview of how 4962306a36Sopenharmony_cithe host device and the guest driver communicate. 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ciThe :c:type:`vring_virtqueue` struct models a virtqueue, including the 5262306a36Sopenharmony_ciring buffers and management data. Embedded in this struct is the 5362306a36Sopenharmony_ci:c:type:`virtqueue` struct, which is the data structure that's 5462306a36Sopenharmony_ciultimately used by virtio drivers: 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci.. kernel-doc:: include/linux/virtio.h 5762306a36Sopenharmony_ci :identifiers: struct virtqueue 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ciThe callback function pointed by this struct is triggered when the 6062306a36Sopenharmony_cidevice has consumed the buffers provided by the driver. More 6162306a36Sopenharmony_cispecifically, the trigger will be an interrupt issued by the hypervisor 6262306a36Sopenharmony_ci(see vring_interrupt()). Interrupt request handlers are registered for 6362306a36Sopenharmony_cia virtqueue during the virtqueue setup process (transport-specific). 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci.. kernel-doc:: drivers/virtio/virtio_ring.c 6662306a36Sopenharmony_ci :identifiers: vring_interrupt 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ciDevice discovery and probing 7062306a36Sopenharmony_ci============================ 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ciIn the kernel, the virtio core contains the virtio bus driver and 7362306a36Sopenharmony_citransport-specific drivers like `virtio-pci` and `virtio-mmio`. Then 7462306a36Sopenharmony_cithere are individual virtio drivers for specific device types that are 7562306a36Sopenharmony_ciregistered to the virtio bus driver. 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ciHow a virtio device is found and configured by the kernel depends on how 7862306a36Sopenharmony_cithe hypervisor defines it. Taking the `QEMU virtio-console 7962306a36Sopenharmony_ci<https://gitlab.com/qemu-project/qemu/-/blob/master/hw/char/virtio-console.c>`__ 8062306a36Sopenharmony_cidevice as an example. When using PCI as a transport method, the device 8162306a36Sopenharmony_ciwill present itself on the PCI bus with vendor 0x1af4 (Red Hat, Inc.) 8262306a36Sopenharmony_ciand device id 0x1003 (virtio console), as defined in the spec, so the 8362306a36Sopenharmony_cikernel will detect it as it would do with any other PCI device. 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ciDuring the PCI enumeration process, if a device is found to match the 8662306a36Sopenharmony_civirtio-pci driver (according to the virtio-pci device table, any PCI 8762306a36Sopenharmony_cidevice with vendor id = 0x1af4):: 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci /* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */ 9062306a36Sopenharmony_ci static const struct pci_device_id virtio_pci_id_table[] = { 9162306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_ANY_ID) }, 9262306a36Sopenharmony_ci { 0 } 9362306a36Sopenharmony_ci }; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cithen the virtio-pci driver is probed and, if the probing goes well, the 9662306a36Sopenharmony_cidevice is registered to the virtio bus:: 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci static int virtio_pci_probe(struct pci_dev *pci_dev, 9962306a36Sopenharmony_ci const struct pci_device_id *id) 10062306a36Sopenharmony_ci { 10162306a36Sopenharmony_ci ... 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci if (force_legacy) { 10462306a36Sopenharmony_ci rc = virtio_pci_legacy_probe(vp_dev); 10562306a36Sopenharmony_ci /* Also try modern mode if we can't map BAR0 (no IO space). */ 10662306a36Sopenharmony_ci if (rc == -ENODEV || rc == -ENOMEM) 10762306a36Sopenharmony_ci rc = virtio_pci_modern_probe(vp_dev); 10862306a36Sopenharmony_ci if (rc) 10962306a36Sopenharmony_ci goto err_probe; 11062306a36Sopenharmony_ci } else { 11162306a36Sopenharmony_ci rc = virtio_pci_modern_probe(vp_dev); 11262306a36Sopenharmony_ci if (rc == -ENODEV) 11362306a36Sopenharmony_ci rc = virtio_pci_legacy_probe(vp_dev); 11462306a36Sopenharmony_ci if (rc) 11562306a36Sopenharmony_ci goto err_probe; 11662306a36Sopenharmony_ci } 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci ... 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci rc = register_virtio_device(&vp_dev->vdev); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ciWhen the device is registered to the virtio bus the kernel will look 12362306a36Sopenharmony_cifor a driver in the bus that can handle the device and call that 12462306a36Sopenharmony_cidriver's ``probe`` method. 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ciAt this point, the virtqueues will be allocated and configured by 12762306a36Sopenharmony_cicalling the appropriate ``virtio_find`` helper function, such as 12862306a36Sopenharmony_civirtio_find_single_vq() or virtio_find_vqs(), which will end up calling 12962306a36Sopenharmony_cia transport-specific ``find_vqs`` method. 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ciReferences 13362306a36Sopenharmony_ci========== 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci_`[1]` Virtio Spec v1.2: 13662306a36Sopenharmony_cihttps://docs.oasis-open.org/virtio/virtio/v1.2/virtio-v1.2.html 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci.. Check for later versions of the spec as well. 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci_`[2]` Virtqueues and virtio ring: How the data travels 14162306a36Sopenharmony_cihttps://www.redhat.com/en/blog/virtqueues-and-virtio-ring-how-data-travels 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci.. rubric:: Footnotes 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci.. [#f1] that's why they may be also referred to as virtrings. 146