Virtio: Difference between revisions

[unchecked revision][unchecked revision]
Content deleted Content added
No edit summary
m Bot: Replace deprecated source tag with syntaxhighlight
 
(24 intermediate revisions by 7 users not shown)
Line 3:
== Technical Details ==
 
VirtIO devices appear, to the guest VM, to be normal [[PCI]] devices with a specific VendorID and DeviceID. All VirtIO devices have a Vendor ID of 0x1AF4, and have a DeviceID between 0x1000 and 0x103F. The type of VirtIO device (Network Adapter, Block Device, etc.) can be determined by the Subsystem ID field in the [[PCI#Configuration_Space|PCI Configuration Space]] for the device. The currently defined types are:
 
{| {{wikitable}}
Line 60:
 
The Device Status field is used by the guest VM to communicate the current state of the guest VM driver. The flags in this register designate when the driver has found the device, when the driver has determined that the device is supported, and when the all of the necessary registers have been configured by the guest driver, and communication between the guest and host may begin.
 
{| {{wikitable}}
! Flags
! Description
|-
| 01 || Device Acknowledged
|-
| 02 || Driver Loaded
|-
| 04 || Driver Ready
|-
| 40 || Device Error
|-
| 80 || Driver Failed
|-
|}
 
== Device Specific Registers ==
Line 84 ⟶ 100:
|-
| 1A || Status
|-
|}
 
=== Block Device Registers ===
 
{| {{wikitable}}
! Offset (Hex)
! Name
|-
| 14 || Total Sector Count
|-
| 1C || Maximum Segment Size
|-
| 20 || Maximum Segment Count
|-
| 24 || Cylinder Count
|-
| 26 || Head Count
|-
| 27 || Sector Count
|-
| 28 || Block Length
|-
|}
Line 95 ⟶ 133:
=== Virtual Queue Descriptor ===
 
<sourcesyntaxhighlight lang="c">
 
struct VirtualQueue
Line 101 ⟶ 139:
struct Buffers[QueueSize]
{
longuint64_t Address; // 64-bit address of the buffer on the guest machine.
intuint32_t Length; // 32-bit length of the buffer.
shortuint16_t Flags; // 1: Next field contains linked buffer index.; 2: Buffer is write-only (clear for read-only). 4:Buffer contains additional buffer addresses.
// 4: Buffer contains additional buffer addresses.
shortuint16_t Next; // If flag is set, contains index of next buffer in chain.
}
struct Available
{
shortuint16_t Flags; // 1: Do not trigger interrupts.
shortuint16_t Index; // Index of the next ring index to be used. (Last available ring buffer index+1)
shortuint16_t [QueueSize] Ring; // List of available buffer indexes from the Buffers array above.
uint16_t EventIndex; // Only used if VIRTIO_F_EVENT_IDX was negotiated
short InterruptIndex; // If enabled, device will trigger interrupt after this ring index has been processed.
}
byteuint8_t[] Padding; // Reserved
// 4096 byte alignment
struct Used
{
shortuint16_t Flags; // 1: Do not notify device when buffers are added to available ring.
shortuint16_t Index; // Index of the next ring index to be used. (Last used ring buffer index+1)
struct Ring[QueueSize]
{
intuint32_t Index; // Index of the used buffer in the Buffers array above.
intuint32_t Length; // Total bytes written to buffer.
}
uint16_t AvailEvent; // Only used if VIRTIO_F_EVENT_IDX was negotiated
short InterruptIndex; // If enabled, device will trigger interrupt after this ring index has been used.
}
}
 
</syntaxhighlight>
</source>
 
== Communication ==
Line 140 ⟶ 181:
=== Network Packets ===
 
Each ethernet packet placed in a buffer must be immediately preceeded by a VirtIO Network Packet header.
 
<syntaxhighlight lang="c">
 
struct PacketHeader
{
uint8_t Flags; // Bit 0: Needs checksum; Bit 1: Received packet has valid data;
// Bit 2: If VIRTIO_NET_F_RSC_EXT was negotiated, the device processes
// duplicated ACK segments, reports number of coalesced TCP segments in ChecksumStart
// field and number of duplicated ACK segments in ChecksumOffset field,
// and sets bit 2 in Flags(VIRTIO_NET_HDR_F_RSC_INFO)
uint8_t SegmentationOffload; // 0:None 1:TCPv4 3:UDP 4:TCPv6 0x80:ECN
uint16_t HeaderLength; // Size of header to be used during segmentation.
uint16_t SegmentLength; // Maximum segment size (not including header).
uint16_t ChecksumStart; // The position to begin calculating the checksum.
uint16_t ChecksumOffset; // The position after ChecksumStart to store the checksum.
uint16_t BufferCount; // Used when merging buffers.
}
 
</syntaxhighlight>
 
Note: Since the PacketHeader structure is Read-Only, and the incoming Network Packet is Write-Only (for incoming packets), you may need to separate these two areas into separate buffers, linked by the Next field.
 
=== Block Device Packets ===
 
Each block device request placed in a buffer must be filled with a VirtIO Block Request record.
 
<syntaxhighlight lang="c">
 
struct BlockRequest
{
uint32_t Type; // 0: Read; 1: Write; 4: Flush; 11: Discard; 13: Write zeroes
uint32_t Reserved;
uint64_t Sector;
uint8_t Data[]; // Data's size must be a multiple of 512
uint8_t Status; // 0: OK; 1: Error; 2: Unsupported
}
 
</syntaxhighlight>
 
Note: Since the BlockRequest structure contains both read-only and write-only fields, it may be necessary to split this structure up into multiple buffers. The Type, Priority and Sector fields should be placed in a Read-Only buffer, and the Data and Status fields should be placed in a Write-Only buffer. The buffers will need to be linked together using the Next field. For Write requests, the buffer containing the Data field should be Read-Only, and the Status field buffer should be Write-Only, which would require 3 buffer entries.
 
== See Also ==
===External Links===
* [https://docs.oasis-open.org/virtio/virtio/v1.1/virtio-v1.1.html VirtIO specification]
* [http://www.dumaisnet.ca/index.php?article=aca38a9a2b065b24dfa1dee728062a12 VirtIO Driver Example]
* [https://github.com/torokernel/torokernel/blob/7d6df4c40fa4cc85febd5fd5799404592ffdff53/rtl/drivers/VirtIONet.pas VirtIO Network Driver Example]
* [https://github.com/torokernel/torokernel/blob/7d6df4c40fa4cc85febd5fd5799404592ffdff53/rtl/drivers/VirtIOBlk.pas VirtIO Block Driver Example]
* [https://github.com/torokernel/torokernel/blob/master/rtl/drivers/VirtIOFS.pas VirtIO FS Driver Example]
* [https://github.com/torokernel/torokernel/blob/master/rtl/drivers/VirtIOVSocket.pas VirtIO VSocket Driver Example]
[[Category:Virtual]]
[[Category:Standards]]