OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

virtio message

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]


Subject: [PATCH 3/6] 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 <rusty@au1.ibm.com>
---
 virtio-v1.0-wd01-part1-specification.txt | 227 ++++++++++++++++---------------
 1 file changed, 119 insertions(+), 108 deletions(-)

diff --git a/virtio-v1.0-wd01-part1-specification.txt b/virtio-v1.0-wd01-part1-specification.txt
index 7a49d6d..db79dc7 100644
--- a/virtio-v1.0-wd01-part1-specification.txt
+++ b/virtio-v1.0-wd01-part1-specification.txt
@@ -89,6 +89,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
 -------------------------
@@ -211,8 +212,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.4. Virtqueues
 ----------------
@@ -312,7 +313,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
@@ -355,13 +356,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
@@ -370,9 +376,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
@@ -429,10 +435,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
@@ -458,20 +464,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
@@ -606,7 +612,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;
 
@@ -694,11 +701,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;
 		}
 
@@ -1843,7 +1850,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
@@ -1906,12 +1913,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
@@ -2078,7 +2085,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];
 	};
 
@@ -2144,7 +2151,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
@@ -2158,7 +2165,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
@@ -2217,15 +2224,15 @@ 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;
 	};
 
 
@@ -2252,9 +2259,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;
 	};
@@ -2408,9 +2415,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
@@ -2465,9 +2472,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) */
@@ -2546,14 +2553,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
 -----------------------------
 
@@ -2640,8 +2651,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
@@ -2715,16 +2726,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
@@ -2796,16 +2807,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];
@@ -2912,7 +2923,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;
 	};
@@ -2946,12 +2957,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 */
@@ -2981,12 +2992,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
@@ -3014,12 +3025,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
@@ -3064,9 +3075,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
@@ -3303,35 +3314,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 {
@@ -3350,19 +3361,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.
  */
@@ -3372,16 +3383,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)
@@ -3390,16 +3401,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 */
 
-- 
1.8.1.2



[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]