From b4da10a5c2bff1d2b944c0550a717c871fb2930e Mon Sep 17 00:00:00 2001 From: rusty Date: Thu, 31 Oct 2013 22:49:17 +0000 Subject: Use le types in all non-legacy places. Emphasize that legacy endian was different, but change all the basic types to use le32 etc as a constant reminder. Signed-off-by: Rusty Russell git-svn-id: https://tools.oasis-open.org/version-control/svn/virtio@78 0c8fb4dd-22a2-4bb5-bc14-6c75a5f43652 --- virtio-v1.0-wd01-part1-specification.txt | 231 ++++++++++++++++--------------- 1 file 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 */ -- cgit v1.2.3