summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--virtio-spec.txt38
1 files changed, 31 insertions, 7 deletions
diff --git a/virtio-spec.txt b/virtio-spec.txt
index d1c1cea..25ab6a0 100644
--- a/virtio-spec.txt
+++ b/virtio-spec.txt
@@ -178,8 +178,8 @@ required for the virtqueue according to the following formula:
#define ALIGN(x) (((x) + PAGE_SIZE) & ~PAGE_SIZE)
static inline unsigned vring_size(unsigned int qsz)
{
- return ALIGN(sizeof(struct vring_desc)*qsz + sizeof(u16)*(2 + qsz))
- + ALIGN(sizeof(u16)*2 + sizeof(struct vring_used_elem)*qsz);
+ return ALIGN(sizeof(struct vring_desc)*qsz + sizeof(u16)*(3 + qsz))
+ + ALIGN(sizeof(u16)*3 + sizeof(struct vring_used_elem)*qsz);
}
This currently wastes some space with padding, but also allows future
@@ -2526,11 +2526,14 @@ Currently there are five device-independent feature bits defined:
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+#include <stdint.h>
/* This marks a buffer as continuing via the next field. */
#define VRING_DESC_F_NEXT 1
/* This marks a buffer as write-only (otherwise read-only). */
#define VRING_DESC_F_WRITE 2
+/* This means the buffer contains a list of buffer descriptors. */
+#define VRING_DESC_F_INDIRECT 4
/* The Host uses this in used->flags to advise the Guest: don't kick me
* when you add a buffer. It's unreliable, so it's simply an
@@ -2541,6 +2544,12 @@ Currently there are five device-independent feature bits defined:
* simply an optimization. */
#define VRING_AVAIL_F_NO_INTERRUPT 1
+/* Support for indirect descriptors */
+#define VIRTIO_RING_F_INDIRECT_DESC 28
+
+/* Support for avail_idx and used_idx fields */
+#define VIRTIO_RING_F_EVENT_IDX 29
+
/* Virtio ring descriptors: 16 bytes.
* These can chain together via "next". */
struct vring_desc {
@@ -2558,7 +2567,7 @@ struct vring_avail {
uint16_t flags;
uint16_t idx;
uint16_t ring[];
- uint16_t used_event;
+ /* Only if VIRTIO_RING_F_EVENT_IDX: uint16_t used_event; */
};
/* u32 is used here for ids for padding reasons. */
@@ -2573,7 +2582,7 @@ struct vring_used {
uint16_t flags;
uint16_t idx;
struct vring_used_elem ring[];
- uint16_t avail_event;
+ /* Only if VIRTIO_RING_F_EVENT_IDX: uint16_t avail_event; */
};
struct vring {
@@ -2595,14 +2604,16 @@ struct vring {
* __u16 avail_flags;
* __u16 avail_idx;
* __u16 available[num];
+ * __u16 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 EVENT_IDX;
+ * __u16 used_idx;
* struct vring_used_elem used[num];
+ * __u16 avail_event_idx; // Only if VIRTIO_RING_F_EVENT_IDX
* };
* Note: for virtio PCI, align is 4096.
*/
@@ -2612,14 +2623,14 @@ 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]
+ vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + sizeof(uint16_t)
+ align-1)
& ~(align - 1));
}
static inline unsigned vring_size(unsigned int num, unsigned long align)
{
- return ((sizeof(struct vring_desc)*num + sizeof(uint16_t)*(2+num)
+ return ((sizeof(struct vring_desc)*num + sizeof(uint16_t)*(3+num)
+ align - 1) & ~(align - 1))
+ sizeof(uint16_t)*3 + sizeof(struct vring_used_elem)*num;
}
@@ -2628,6 +2639,19 @@ static inline int vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_
{
return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old_idx);
}
+
+/* Get location of event indices (only with VIRTIO_RING_F_EVENT_IDX) */
+static inline uint16_t *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)
+{
+ /* For backwards compat, avail event index is at *end* of used ring. */
+ return (uint16_t *)&vr->used->ring[vr->num];
+}
#endif /* VIRTIO_RING_H */