diff options
-rw-r--r-- | virtio-spec.txt | 38 |
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 */ |