2019-06-13 10:49:02 +00:00
|
|
|
//
|
|
|
|
// virtio device definitions.
|
|
|
|
// for both the mmio interface, and virtio descriptors.
|
|
|
|
// only tested with qemu.
|
|
|
|
//
|
2019-06-13 13:40:17 +00:00
|
|
|
// the virtio spec:
|
|
|
|
// https://docs.oasis-open.org/virtio/virtio/v1.1/virtio-v1.1.pdf
|
|
|
|
//
|
2019-06-13 10:49:02 +00:00
|
|
|
|
|
|
|
// virtio mmio control registers, mapped starting at 0x10001000.
|
|
|
|
// from qemu virtio_mmio.h
|
|
|
|
#define VIRTIO_MMIO_MAGIC_VALUE 0x000 // 0x74726976
|
2022-08-08 15:10:54 +00:00
|
|
|
#define VIRTIO_MMIO_VERSION 0x004 // version; should be 2
|
2019-06-13 13:40:17 +00:00
|
|
|
#define VIRTIO_MMIO_DEVICE_ID 0x008 // device type; 1 is net, 2 is disk
|
2019-06-13 10:49:02 +00:00
|
|
|
#define VIRTIO_MMIO_VENDOR_ID 0x00c // 0x554d4551
|
|
|
|
#define VIRTIO_MMIO_DEVICE_FEATURES 0x010
|
|
|
|
#define VIRTIO_MMIO_DRIVER_FEATURES 0x020
|
|
|
|
#define VIRTIO_MMIO_QUEUE_SEL 0x030 // select queue, write-only
|
|
|
|
#define VIRTIO_MMIO_QUEUE_NUM_MAX 0x034 // max size of current queue, read-only
|
|
|
|
#define VIRTIO_MMIO_QUEUE_NUM 0x038 // size of current queue, write-only
|
|
|
|
#define VIRTIO_MMIO_QUEUE_READY 0x044 // ready bit
|
|
|
|
#define VIRTIO_MMIO_QUEUE_NOTIFY 0x050 // write-only
|
|
|
|
#define VIRTIO_MMIO_INTERRUPT_STATUS 0x060 // read-only
|
|
|
|
#define VIRTIO_MMIO_INTERRUPT_ACK 0x064 // write-only
|
|
|
|
#define VIRTIO_MMIO_STATUS 0x070 // read/write
|
2021-10-18 05:33:39 +00:00
|
|
|
#define VIRTIO_MMIO_QUEUE_DESC_LOW 0x080 // physical address for descriptor table, write-only
|
|
|
|
#define VIRTIO_MMIO_QUEUE_DESC_HIGH 0x084
|
|
|
|
#define VIRTIO_MMIO_DRIVER_DESC_LOW 0x090 // physical address for available ring, write-only
|
|
|
|
#define VIRTIO_MMIO_DRIVER_DESC_HIGH 0x094
|
|
|
|
#define VIRTIO_MMIO_DEVICE_DESC_LOW 0x0a0 // physical address for used ring, write-only
|
|
|
|
#define VIRTIO_MMIO_DEVICE_DESC_HIGH 0x0a4
|
2019-06-13 10:49:02 +00:00
|
|
|
|
|
|
|
// status register bits, from qemu virtio_config.h
|
|
|
|
#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
|
|
|
|
#define VIRTIO_CONFIG_S_DRIVER 2
|
|
|
|
#define VIRTIO_CONFIG_S_DRIVER_OK 4
|
|
|
|
#define VIRTIO_CONFIG_S_FEATURES_OK 8
|
|
|
|
|
|
|
|
// device feature bits
|
2019-06-13 14:00:50 +00:00
|
|
|
#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */
|
|
|
|
#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */
|
|
|
|
#define VIRTIO_BLK_F_CONFIG_WCE 11 /* Writeback mode available in config */
|
|
|
|
#define VIRTIO_BLK_F_MQ 12 /* support more than one vq */
|
|
|
|
#define VIRTIO_F_ANY_LAYOUT 27
|
|
|
|
#define VIRTIO_RING_F_INDIRECT_DESC 28
|
|
|
|
#define VIRTIO_RING_F_EVENT_IDX 29
|
2019-06-13 10:49:02 +00:00
|
|
|
|
2019-07-01 12:20:35 +00:00
|
|
|
// this many virtio descriptors.
|
|
|
|
// must be a power of two.
|
|
|
|
#define NUM 8
|
|
|
|
|
2020-10-05 10:26:58 +00:00
|
|
|
// a single descriptor, from the spec.
|
|
|
|
struct virtq_desc {
|
2019-06-13 10:49:02 +00:00
|
|
|
uint64 addr;
|
|
|
|
uint32 len;
|
|
|
|
uint16 flags;
|
|
|
|
uint16 next;
|
|
|
|
};
|
2019-06-13 14:00:50 +00:00
|
|
|
#define VRING_DESC_F_NEXT 1 // chained with another descriptor
|
|
|
|
#define VRING_DESC_F_WRITE 2 // device writes (vs read)
|
2019-06-13 10:49:02 +00:00
|
|
|
|
2020-10-05 10:26:58 +00:00
|
|
|
// the (entire) avail ring, from the spec.
|
|
|
|
struct virtq_avail {
|
|
|
|
uint16 flags; // always zero
|
|
|
|
uint16 idx; // driver will write ring[idx] next
|
|
|
|
uint16 ring[NUM]; // descriptor numbers of chain heads
|
|
|
|
uint16 unused;
|
|
|
|
};
|
|
|
|
|
|
|
|
// one entry in the "used" ring, with which the
|
|
|
|
// device tells the driver about completed requests.
|
|
|
|
struct virtq_used_elem {
|
2019-06-13 14:00:50 +00:00
|
|
|
uint32 id; // index of start of completed descriptor chain
|
2019-06-13 10:49:02 +00:00
|
|
|
uint32 len;
|
|
|
|
};
|
|
|
|
|
2020-10-05 10:26:58 +00:00
|
|
|
struct virtq_used {
|
|
|
|
uint16 flags; // always zero
|
|
|
|
uint16 idx; // device increments when it adds a ring[] entry
|
|
|
|
struct virtq_used_elem ring[NUM];
|
|
|
|
};
|
|
|
|
|
|
|
|
// these are specific to virtio block devices, e.g. disks,
|
|
|
|
// described in Section 5.2 of the spec.
|
|
|
|
|
2019-06-13 14:00:50 +00:00
|
|
|
#define VIRTIO_BLK_T_IN 0 // read the disk
|
|
|
|
#define VIRTIO_BLK_T_OUT 1 // write the disk
|
2019-07-01 12:20:35 +00:00
|
|
|
|
2020-10-05 10:26:58 +00:00
|
|
|
// the format of the first descriptor in a disk request.
|
|
|
|
// to be followed by two more descriptors containing
|
|
|
|
// the block, and a one-byte status.
|
|
|
|
struct virtio_blk_req {
|
|
|
|
uint32 type; // VIRTIO_BLK_T_IN or ..._OUT
|
|
|
|
uint32 reserved;
|
|
|
|
uint64 sector;
|
2019-07-01 12:20:35 +00:00
|
|
|
};
|