1 //
2 // virtio device definitions.
3 // for both the mmio interface, and virtio descriptors.
4 // only tested with qemu.
5 //
6 // the virtio spec:
7 // https://docs.oasis-open.org/virtio/virtio/v1.1/virtio-v1.1.pdf
8 //
9
10 // virtio mmio control registers, mapped starting at 0x10001000.
11 // from qemu virtio_mmio.h
12 // clang-format off
13 #define VIRTIO_MMIO_MAGIC_VALUE 0x000 // 0x74726976
14 #define VIRTIO_MMIO_VERSION 0x004 // version; should be 2
15 #define VIRTIO_MMIO_DEVICE_ID 0x008 // device type; 1 is net, 2 is disk
16 #define VIRTIO_MMIO_VENDOR_ID 0x00c // 0x554d4551
17 #define VIRTIO_MMIO_DEVICE_FEATURES 0x010
18 #define VIRTIO_MMIO_DRIVER_FEATURES 0x020
19 #define VIRTIO_MMIO_QUEUE_SEL 0x030 // select queue, write-only
20 #define VIRTIO_MMIO_QUEUE_NUM_MAX 0x034 // max size of current queue, read-only
21 #define VIRTIO_MMIO_QUEUE_NUM 0x038 // size of current queue, write-only
22 #define VIRTIO_MMIO_QUEUE_READY 0x044 // ready bit
23 #define VIRTIO_MMIO_QUEUE_NOTIFY 0x050 // write-only
24 #define VIRTIO_MMIO_INTERRUPT_STATUS 0x060 // read-only
25 #define VIRTIO_MMIO_INTERRUPT_ACK 0x064 // write-only
26 #define VIRTIO_MMIO_STATUS 0x070 // read/write
27 #define VIRTIO_MMIO_QUEUE_DESC_LOW 0x080 // physical address for descriptor table, write-only
28 #define VIRTIO_MMIO_QUEUE_DESC_HIGH 0x084
29 #define VIRTIO_MMIO_DRIVER_DESC_LOW 0x090 // physical address for available ring, write-only
30 #define VIRTIO_MMIO_DRIVER_DESC_HIGH 0x094
31 #define VIRTIO_MMIO_DEVICE_DESC_LOW 0x0a0 // physical address for used ring, write-only
32 #define VIRTIO_MMIO_DEVICE_DESC_HIGH 0x0a4
33 // clang-format on
34
35 // status register bits, from qemu virtio_config.h
36 #define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
37 #define VIRTIO_CONFIG_S_DRIVER 2
38 #define VIRTIO_CONFIG_S_DRIVER_OK 4
39 #define VIRTIO_CONFIG_S_FEATURES_OK 8
40
41 // device feature bits
42 #define VIRTIO_BLK_F_RO 5 /* Disk is read-only */
43 #define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */
44 #define VIRTIO_BLK_F_FLUSH 9 /* Cache flush command supported */
45 #define VIRTIO_BLK_F_CONFIG_WCE 11 /* Writeback mode available in config */
46 #define VIRTIO_BLK_F_MQ 12 /* support more than one vq */
47 #define VIRTIO_F_ANY_LAYOUT 27
48 #define VIRTIO_RING_F_INDIRECT_DESC 28
49 #define VIRTIO_RING_F_EVENT_IDX 29
50
51 // this many virtio descriptors.
52 // must be a power of two.
53 #define NUM 8
54
55 // a single descriptor, from the spec.
56 struct virtq_desc {
57 uint64 addr;
58 uint32 len;
59 uint16 flags;
60 uint16 next;
61 };
62 #define VRING_DESC_F_NEXT 1 // chained with another descriptor
63 #define VRING_DESC_F_WRITE 2 // device writes (vs read)
64
65 // the (entire) avail ring, from the spec.
66 struct virtq_avail {
67 uint16 flags; // always zero
68 uint16 idx; // driver will write ring[idx] next
69 uint16 ring[NUM]; // descriptor numbers of chain heads
70 uint16 unused;
71 };
72
73 // one entry in the "used" ring, with which the
74 // device tells the driver about completed requests.
75 struct virtq_used_elem {
76 uint32 id; // index of start of completed descriptor chain
77 uint32 len;
78 };
79
80 struct virtq_used {
81 uint16 flags; // always zero
82 uint16 idx; // device increments when it adds a ring[] entry
83 struct virtq_used_elem ring[NUM];
84 };
85
86 // these are specific to virtio block devices, e.g. disks,
87 // described in Section 5.2 of the spec.
88
89 #define VIRTIO_BLK_T_IN 0 // read the disk
90 #define VIRTIO_BLK_T_OUT 1 // write the disk
91
92 // the format of the first descriptor in a disk request.
93 // to be followed by two more descriptors containing
94 // the block, and a one-byte status.
95 struct virtio_blk_req {
96 uint32 type; // VIRTIO_BLK_T_IN or ..._OUT
97 uint32 reserved;
98 uint64 sector;
99 };