summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--virtio-v1.0-wd01-part1-specification.txt231
1 files changed, 121 insertions, 110 deletions
diff --git a/virtio-v1.0-wd01-part1-specification.txt b/virtio-v1.0-wd01-part1-specification.txt
index 899ca99..666ee60 100644
--- a/virtio-v1.0-wd01-part1-specification.txt
+++ b/virtio-v1.0-wd01-part1-specification.txt
@@ -93,6 +93,7 @@ o Configuration space
o One or more virtqueues
Unless explicitly specified otherwise, all multi-byte fields are little-endian.
+To reinforce this the examples use typenames like "le16" instead of "uint16_t".
2.1.1. Device Status Field
-------------------------
@@ -234,8 +235,8 @@ for multi-byte fields.
100.100.4.1. Legacy Interface: A Note on Configuration Space endian-ness
--------------------------------------
-Note that for legacy interfaces, configuration space is generally the guest's native endian,
-rather than PCI's little-endian.
+Note that for legacy interfaces, configuration space is generally the
+guest's native endian, rather than PCI's little-endian.
2.1.3.1. Legacy Interface: Configuration Space
-------------------------
@@ -344,7 +345,7 @@ The legacy virtqueue layout structure therefore looks like this:
--------------------------------------
Note that the endian of fields and in the virtqueue is the native
-endian of the guest, not little-endian as PCI normally is.
+endian of the guest, not little-endian as specified by this standard.
It is assumed that the host is already aware of the guest endian.
2.1.4.2. Message Framing
@@ -387,13 +388,18 @@ can be chained via the next field. Each descriptor describes a
buffer which is read-only or write-only, but a chain of
descriptors can contain both read-only and write-only buffers.
+The actual contents of the memory offered to the device depends on the
+device type. Most common is to begin the data with a header
+(containing little-endian fields) for the device to read, and postfix
+it with a status tailer for the device to write.
+
No descriptor chain may be more than 2^32 bytes long in total.
struct vring_desc {
/* Address (guest-physical). */
- u64 addr;
+ le64 addr;
/* Length. */
- u32 len;
+ le32 len;
/* This marks a buffer as continuing via the next field. */
#define VRING_DESC_F_NEXT 1
@@ -402,9 +408,9 @@ No descriptor chain may be more than 2^32 bytes long in total.
/* This means the buffer contains a list of buffer descriptors. */
#define VRING_DESC_F_INDIRECT 4
/* The flags as indicated above. */
- u16 flags;
+ le16 flags;
/* Next field if flags & NEXT */
- u16 next;
+ le16 next;
};
The number of descriptors in the table is defined by the queue size
@@ -461,10 +467,10 @@ entry (modulo the queue size). This starts at 0, and increases.
struct vring_avail {
#define VRING_AVAIL_F_NO_INTERRUPT 1
- u16 flags;
- u16 idx;
- u16 ring[ /* Queue Size */ ];
- u16 used_event; /* Only if VIRTIO_RING_F_EVENT_IDX */
+ le16 flags;
+ le16 idx;
+ le16 ring[ /* Queue Size */ ];
+ le16 used_event; /* Only if VIRTIO_RING_F_EVENT_IDX */
};
2.1.4.5. The Virtqueue Used Ring
@@ -490,20 +496,20 @@ for guests using untrusted buffers: if you do not know exactly
how much has been written by the device, you usually have to zero
the buffer to ensure no data leakage occurs.
- /* u32 is used here for ids for padding reasons. */
+ /* le32 is used here for ids for padding reasons. */
struct vring_used_elem {
/* Index of start of used descriptor chain. */
- u32 id;
+ le32 id;
/* Total length of the descriptor chain which was used (written to) */
- u32 len;
+ le32 len;
};
struct vring_used {
#define VRING_USED_F_NO_NOTIFY 1
- u16 flags;
- u16 idx;
+ le16 flags;
+ le16 idx;
struct vring_used_elem ring[ /* Queue Size */];
- u16 avail_event; /* Only if VIRTIO_RING_F_EVENT_IDX */
+ le16 avail_event; /* Only if VIRTIO_RING_F_EVENT_IDX */
};
2.1.4.6. Helpers for Operating Virtqueues
@@ -664,7 +670,8 @@ free descriptors before beginning the mappings.
-------------------------------------
The head of the buffer we mapped is the first d in the algorithm
-above. A naive implementation would do the following:
+above. A naive implementation would do the following (with the
+appropriate conversion to-and-from little-endian assumed):
avail->ring[avail->idx % qsz] = head;
@@ -752,11 +759,11 @@ suppressed by the device:
vring_disable_interrupts(vq);
for (;;) {
- if (vq->last_seen_used != vring->used.idx) {
+ if (vq->last_seen_used != le16_to_cpu(vring->used.idx)) {
vring_enable_interrupts(vq);
mb();
- if (vq->last_seen_used != vring->used.idx)
+ if (vq->last_seen_used != le16_to_cpu(vring->used.idx))
break;
}
@@ -2211,7 +2218,7 @@ VIRTIO_NET_S_LINK_UP and VIRTIO_NET_S_ANNOUNCE.
struct virtio_net_config {
u8 mac[6];
- u16 status;
+ le16 status;
};
2.4.1.4. Device Initialization
@@ -2274,12 +2281,12 @@ case, the packet itself is preceeded by a header:
#define VIRTIO_NET_HDR_GSO_TCPV6 4
#define VIRTIO_NET_HDR_GSO_ECN 0x80
u8 gso_type;
- u16 hdr_len;
- u16 gso_size;
- u16 csum_start;
- u16 csum_offset;
+ le16 hdr_len;
+ le16 gso_size;
+ le16 csum_start;
+ le16 csum_offset;
/* Only if VIRTIO_NET_F_MRG_RXBUF: */
- u16 num_buffers;
+ le16 num_buffers;
};
The controlq is used to control device features such as
@@ -2446,7 +2453,7 @@ off. The command-specific-data is one byte containing 0 (off) or
-----------------------------------------
struct virtio_net_ctrl_mac {
- u32 entries;
+ le32 entries;
u8 macs[entries][ETH_ALEN];
};
@@ -2512,7 +2519,7 @@ send control commands for dynamic offloads state configuration.
2.4.1.5.4.3.1. Setting Offloads State
-------------------------------------
- u64 offloads;
+ le64 offloads;
#define VIRTIO_NET_F_GUEST_CSUM 1
#define VIRTIO_NET_F_GUEST_TSO4 7
@@ -2526,7 +2533,7 @@ send control commands for dynamic offloads state configuration.
The class VIRTIO_NET_CTRL_GUEST_OFFLOADS has one command:
VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET applies the new offloads configuration.
-u64 value passed as command data is a bitmask, bits set define
+le64 value passed as command data is a bitmask, bits set define
offloads to be enabled, bits cleared - offloads to be disabled.
There is a corresponding device feature for each offload. Upon feature
@@ -2595,24 +2602,24 @@ present. The availability of the others all depend on various feature
bits as indicated above.
struct virtio_blk_config {
- u64 capacity;
- u32 size_max;
- u32 seg_max;
+ le64 capacity;
+ le32 size_max;
+ le32 seg_max;
struct virtio_blk_geometry {
- u16 cylinders;
+ le16 cylinders;
u8 heads;
u8 sectors;
} geometry;
- u32 blk_size;
+ le32 blk_size;
struct virtio_blk_topology {
// # of logical blocks per physical block (log2)
u8 physical_block_exp;
// offset of first aligned logical block
u8 alignment_offset;
// suggested minimum I/O size in blocks
- u16 min_io_size;
+ le16 min_io_size;
// optimal (suggested maximum) I/O size in blocks
- u32 opt_io_size;
+ le32 opt_io_size;
} topology;
u8 reserved;
};
@@ -2661,9 +2668,9 @@ The driver queues requests to the virtqueue, and they are used by
the device (not necessarily in order). Each request is of form:
struct virtio_blk_req {
- u32 type;
- u32 reserved;
- u64 sector;
+ le32 type;
+ le32 reserved;
+ le64 sector;
char data[][512];
u8 status;
};
@@ -2818,9 +2825,9 @@ data and outgoing characters are placed in the transmit queue.
be fetched.
struct virtio_console_config {
- u16 cols;
- u16 rows;
- u32 max_nr_ports;
+ le16 cols;
+ le16 rows;
+ le32 max_nr_ports;
};
2.4.3.5. Device Initialization
@@ -2875,9 +2882,9 @@ data and outgoing characters are placed in the transmit queue.
buffer and the events associated are:
struct virtio_console_control {
- uint32_t id; /* Port number */
- uint16_t event; /* The kind of control event */
- uint16_t value; /* Extra information for the event */
+ le32 id; /* Port number */
+ le16 event; /* The kind of control event */
+ le16 value; /* Extra information for the event */
};
/* Some events for the internal messages (control packets) */
@@ -2956,14 +2963,18 @@ guest memory statistics to the host.
2.4.5.4. Device configuration layout
-----------------------------------
Both fields of this configuration
- are always available. Note that they are little endian, despite
- convention that device fields are guest endian:
+ are always available.
struct virtio_balloon_config {
- u32 num_pages;
- u32 actual;
+ le32 num_pages;
+ le32 actual;
};
+2.4.5.4.1. Legacy Interface: Device configuration layout
+-----------------------------------
+Note that these fields are always little endian, despite convention
+that legacy device fields are guest endian.
+
2.4.5.5. Device Initialization
-----------------------------
@@ -3050,8 +3061,8 @@ as follows:
#define VIRTIO_BALLOON_S_MINFLT 3
#define VIRTIO_BALLOON_S_MEMFREE 4
#define VIRTIO_BALLOON_S_MEMTOT 5
- u16 tag;
- u64 val;
+ le16 tag;
+ le64 val;
} __attribute__((packed));
2.4.5.6.2. Memory Statistics Tags
@@ -3125,16 +3136,16 @@ targets that receive and process the requests.
and cdb_size are writable by the guest.
struct virtio_scsi_config {
- u32 num_queues;
- u32 seg_max;
- u32 max_sectors;
- u32 cmd_per_lun;
- u32 event_info_size;
- u32 sense_size;
- u32 cdb_size;
- u16 max_channel;
- u16 max_target;
- u32 max_lun;
+ le32 num_queues;
+ le32 seg_max;
+ le32 max_sectors;
+ le32 cmd_per_lun;
+ le32 event_info_size;
+ le32 sense_size;
+ le32 cdb_size;
+ le16 max_channel;
+ le16 max_target;
+ le32 max_lun;
};
num_queues is the total number of request virtqueues exposed by
@@ -3206,16 +3217,16 @@ Requests have the following format:
struct virtio_scsi_req_cmd {
// Read-only
u8 lun[8];
- u64 id;
+ le64 id;
u8 task_attr;
u8 prio;
u8 crn;
char cdb[cdb_size];
char dataout[];
// Write-only part
- u32 sense_len;
- u32 residual;
- u16 status_qualifier;
+ le32 sense_len;
+ le32 residual;
+ le16 status_qualifier;
u8 status;
u8 response;
u8 sense[sense_size];
@@ -3322,7 +3333,7 @@ The controlq is used for other SCSI transport operations.
Requests have the following format:
struct virtio_scsi_ctrl {
- u32 type;
+ le32 type;
...
u8 response;
};
@@ -3356,12 +3367,12 @@ The following commands are defined:
struct virtio_scsi_ctrl_tmf
{
// Read-only part
- u32 type;
- u32 subtype;
- u8 lun[8];
- u64 id;
+ le32 type;
+ le32 subtype;
+ u8 lun[8];
+ le64 id;
// Write-only part
- u8 response;
+ u8 response;
}
/* command-specific response values */
@@ -3391,12 +3402,12 @@ The following commands are defined:
struct virtio_scsi_ctrl_an {
// Read-only part
- u32 type;
- u8 lun[8];
- u32 event_requested;
+ le32 type;
+ u8 lun[8];
+ le32 event_requested;
// Write-only part
- u32 event_actual;
- u8 response;
+ le32 event_actual;
+ u8 response;
}
#define VIRTIO_SCSI_EVT_ASYNC_OPERATIONAL_CHANGE 2
@@ -3424,12 +3435,12 @@ The following commands are defined:
struct virtio_scsi_ctrl_an {
// Read-only part
- u32 type;
- u8 lun[8];
- u32 event_requested;
+ le32 type;
+ u8 lun[8];
+ le32 event_requested;
// Write-only part
- u32 event_actual;
- u8 response;
+ le32 event_actual;
+ u8 response;
}
By sending this command, the driver asks the specified LUN to
@@ -3474,9 +3485,9 @@ following format:
struct virtio_scsi_event {
// Write-only part
- u32 event;
+ le32 event;
u8 lun[8];
- i32 reason;
+ le32 reason;
}
If bit 31 is set in the event field, the device failed to report
@@ -3713,35 +3724,35 @@ VIRTIO_F_ANY_LAYOUT (27) This feature indicates that the device
* These can chain together via "next". */
struct vring_desc {
/* Address (guest-physical). */
- uint64_t addr;
+ le64 addr;
/* Length. */
- uint32_t len;
+ le32 len;
/* The flags as indicated above. */
- uint16_t flags;
+ le16 flags;
/* We chain unused descriptors via this, too */
- uint16_t next;
+ le16 next;
};
struct vring_avail {
- uint16_t flags;
- uint16_t idx;
- uint16_t ring[];
- /* Only if VIRTIO_RING_F_EVENT_IDX: uint16_t used_event; */
+ le16 flags;
+ le16 idx;
+ le16 ring[];
+ /* Only if VIRTIO_RING_F_EVENT_IDX: le16 used_event; */
};
-/* u32 is used here for ids for padding reasons. */
+/* le32 is used here for ids for padding reasons. */
struct vring_used_elem {
/* Index of start of used descriptor chain. */
- uint32_t id;
+ le32 id;
/* Total length of the descriptor chain which was written to. */
- uint32_t len;
+ le32 len;
};
struct vring_used {
- uint16_t flags;
- uint16_t idx;
+ le16 flags;
+ le16 idx;
struct vring_used_elem ring[];
- /* Only if VIRTIO_RING_F_EVENT_IDX: uint16_t avail_event; */
+ /* Only if VIRTIO_RING_F_EVENT_IDX: le16 avail_event; */
};
struct vring {
@@ -3760,19 +3771,19 @@ struct vring {
* struct vring_desc desc[num];
*
* // A ring of available descriptor heads with free-running index.
- * __u16 avail_flags;
- * __u16 avail_idx;
- * __u16 available[num];
- * __u16 used_event_idx; // Only if VIRTIO_RING_F_EVENT_IDX
+ * le16 avail_flags;
+ * le16 avail_idx;
+ * le16 available[num];
+ * le16 used_event_idx; // Only if VIRTIO_RING_F_EVENT_IDX
*
* // Padding to the next align boundary.
* char pad[];
*
* // A ring of used descriptor heads with free-running index.
- * __u16 used_flags;
- * __u16 used_idx;
+ * le16 used_flags;
+ * le16 used_idx;
* struct vring_used_elem used[num];
- * __u16 avail_event_idx; // Only if VIRTIO_RING_F_EVENT_IDX
+ * le16 avail_event_idx; // Only if VIRTIO_RING_F_EVENT_IDX
* };
* Note: for virtio PCI, align is 4096.
*/
@@ -3782,16 +3793,16 @@ static inline void vring_init(struct vring *vr, unsigned int num, void *p,
vr->num = num;
vr->desc = p;
vr->avail = p + num*sizeof(struct vring_desc);
- vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + sizeof(uint16_t)
+ vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + sizeof(le16)
+ align-1)
& ~(align - 1));
}
static inline unsigned vring_size(unsigned int num, unsigned long align)
{
- return ((sizeof(struct vring_desc)*num + sizeof(uint16_t)*(3+num)
+ return ((sizeof(struct vring_desc)*num + sizeof(le16)*(3+num)
+ align - 1) & ~(align - 1))
- + sizeof(uint16_t)*3 + sizeof(struct vring_used_elem)*num;
+ + sizeof(le16)*3 + sizeof(struct vring_used_elem)*num;
}
static inline int vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old_idx)
@@ -3800,16 +3811,16 @@ static inline int vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_
}
/* Get location of event indices (only with VIRTIO_RING_F_EVENT_IDX) */
-static inline uint16_t *vring_used_event(struct vring *vr)
+static inline le16 *vring_used_event(struct vring *vr)
{
/* For backwards compat, used event index is at *end* of avail ring. */
return &vr->avail->ring[vr->num];
}
-static inline uint16_t *vring_avail_event(struct vring *vr)
+static inline le16 *vring_avail_event(struct vring *vr)
{
/* For backwards compat, avail event index is at *end* of used ring. */
- return (uint16_t *)&vr->used->ring[vr->num];
+ return (le16 *)&vr->used->ring[vr->num];
}
#endif /* VIRTIO_RING_H */