Table of Contents

Virtio

A hypervisor can emulate a real network card register by register, but each register access the guest makes is an expensive exit from the virtual machine into the hypervisor, and a real card's driver makes many per packet. Virtio is a family of paravirtual devices: devices designed for a hypervisor to implement, which keep register accesses to a minimum and do their work in shared memory. One specification defines network cards, block devices, GPUs, input devices and more, each with a device type number.

The same device can reach the guest over different transports. Over PCI it is a function with vendor id 0x1AF4 whose capabilities locate its virtio registers; over MMIO it is a register block at a fixed address the platform describes. Above the transport the protocol is the same.

Bringing a device up is a handshake through its status register. The driver resets the device by writing 0, sets ACKNOWLEDGE and DRIVER, then negotiates features: the device offers a bitmap of optional features, the driver writes back the subset it understands and sets FEATURES_OK, and a device that clears that bit again refuses the subset. Bit 32, VIRTIO_F_VERSION_1, marks a device that follows the 1.0 specification rather than the legacy interface. The driver then sets up its virtqueues and sets DRIVER_OK, and the device is live. A virtqueue is a descriptor ring in three parts: a descriptor table, an available ring where the driver offers buffers, and a used ring where the device returns them. The driver writes a notify register when the available ring grows, and the device interrupts when the used ring does.

The trap is acting on the requested features rather than the negotiated ones: a feature outside the negotiated set is off, and some features change the layout of the data the device exchanges.

In the driver kit, VirtioAccess runs this handshake. The kit resets the device and sets ACKNOWLEDGE and DRIVER before every probe; NegotiateFeatures takes the low 32 bits a driver understands, adds VIRTIO_F_VERSION_1 when offered and returns false when FEATURES_OK does not stick; TryCreateQueue builds a Virtqueue in the binding's DMA memory; and SetDriverOk comes before the first Notify. A driver calls Reset() in OnDetach so the device stops writing into rings the kit is about to free; see The virtio access object and Queues.