OpenAMP Library
virtio_ring.h
Go to the documentation of this file.
1 /*
2  * Copyright Rusty Russell IBM Corporation 2007.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  * $FreeBSD$
7  */
8 
9 #ifndef VIRTIO_RING_H
10 #define VIRTIO_RING_H
11 
12 #include <metal/compiler.h>
13 
14 #if defined __cplusplus
15 extern "C" {
16 #endif
17 
18 /* This marks a buffer as continuing via the next field. */
19 #define VRING_DESC_F_NEXT 1
20 /* This marks a buffer as write-only (otherwise read-only). */
21 #define VRING_DESC_F_WRITE 2
22 /* This means the buffer contains a list of buffer descriptors. */
23 #define VRING_DESC_F_INDIRECT 4
24 
25 /* The Host uses this in used->flags to advise the Guest: don't kick me
26  * when you add a buffer. It's unreliable, so it's simply an
27  * optimization. Guest will still kick if it's out of buffers.
28  */
29 #define VRING_USED_F_NO_NOTIFY 1
30 /* The Guest uses this in avail->flags to advise the Host: don't
31  * interrupt me when you consume a buffer. It's unreliable, so it's
32  * simply an optimization.
33  */
34 #define VRING_AVAIL_F_NO_INTERRUPT 1
35 
36 /* VirtIO ring descriptors: 16 bytes.
37  * These can chain together via "next".
38  */
39 METAL_PACKED_BEGIN
40 struct vring_desc {
41  /* Address (guest-physical). */
42  uint64_t addr;
43  /* Length. */
44  uint32_t len;
45  /* The flags as indicated above. */
46  uint16_t flags;
47  /* We chain unused descriptors via this, too. */
48  uint16_t next;
50 
51 METAL_PACKED_BEGIN
52 struct vring_avail {
53  uint16_t flags;
54  uint16_t idx;
55  uint16_t ring[0];
57 
58 /* uint32_t is used here for ids for padding reasons. */
59 METAL_PACKED_BEGIN
61  union {
62  uint16_t event;
63  /* Index of start of used descriptor chain. */
64  uint32_t id;
65  };
66  /* Total length of the descriptor chain which was written to. */
67  uint32_t len;
69 
70 METAL_PACKED_BEGIN
71 struct vring_used {
72  uint16_t flags;
73  uint16_t idx;
74  struct vring_used_elem ring[0];
76 
77 struct vring {
78  unsigned int num;
79 
80  struct vring_desc *desc;
81  struct vring_avail *avail;
82  struct vring_used *used;
83 };
84 
85 /* The standard layout for the ring is a continuous chunk of memory which
86  * looks like this. We assume num is a power of 2.
87  *
88  * struct vring {
89  * // The actual descriptors (16 bytes each)
90  * struct vring_desc desc[num];
91  *
92  * // A ring of available descriptor heads with free-running index.
93  * __u16 avail_flags;
94  * __u16 avail_idx;
95  * __u16 available[num];
96  * __u16 used_event_idx;
97  *
98  * // Padding to the next align boundary.
99  * char pad[];
100  *
101  * // A ring of used descriptor heads with free-running index.
102  * __u16 used_flags;
103  * __u16 used_idx;
104  * struct vring_used_elem used[num];
105  * __u16 avail_event_idx;
106  * };
107  *
108  * NOTE: for VirtIO PCI, align is 4096.
109  */
110 
111 /*
112  * We publish the used event index at the end of the available ring, and vice
113  * versa. They are at the end for backwards compatibility.
114  */
115 #define vring_used_event(vr) ((vr)->avail->ring[(vr)->num])
116 #define vring_avail_event(vr) ((vr)->used->ring[(vr)->num].event)
117 
118 static inline int vring_size(unsigned int num, unsigned long align)
119 {
120  int size;
121 
122  size = num * sizeof(struct vring_desc);
123  size += sizeof(struct vring_avail) + (num * sizeof(uint16_t)) +
124  sizeof(uint16_t);
125  size = (size + align - 1) & ~(align - 1);
126  size += sizeof(struct vring_used) +
127  (num * sizeof(struct vring_used_elem)) + sizeof(uint16_t);
128 
129  return size;
130 }
131 
132 static inline void
133 vring_init(struct vring *vr, unsigned int num, uint8_t *p, unsigned long align)
134 {
135  vr->num = num;
136  vr->desc = (struct vring_desc *)p;
137  vr->avail = (struct vring_avail *)(p + num * sizeof(struct vring_desc));
138  vr->used = (struct vring_used *)
139  (((unsigned long)&vr->avail->ring[num] + sizeof(uint16_t) +
140  align - 1) & ~(align - 1));
141 }
142 
143 /*
144  * The following is used with VIRTIO_RING_F_EVENT_IDX.
145  *
146  * Assuming a given event_idx value from the other size, if we have
147  * just incremented index from old to new_idx, should we trigger an
148  * event?
149  */
150 static inline int
151 vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old)
152 {
153  return (uint16_t)(new_idx - event_idx - 1) <
154  (uint16_t)(new_idx - old);
155 }
156 
157 #if defined __cplusplus
158 }
159 #endif
160 
161 #endif /* VIRTIO_RING_H */
Definition: virtio_ring.h:52
uint16_t idx
Definition: virtio_ring.h:54
uint16_t flags
Definition: virtio_ring.h:53
uint16_t ring[0]
Definition: virtio_ring.h:55
Definition: virtio_ring.h:40
uint64_t addr
Definition: virtio_ring.h:42
uint16_t next
Definition: virtio_ring.h:48
uint16_t flags
Definition: virtio_ring.h:46
uint32_t len
Definition: virtio_ring.h:44
Definition: virtio_ring.h:60
uint16_t event
Definition: virtio_ring.h:62
uint32_t id
Definition: virtio_ring.h:64
uint32_t len
Definition: virtio_ring.h:67
Definition: virtio_ring.h:71
struct vring_used_elem ring[0]
Definition: virtio_ring.h:74
uint16_t idx
Definition: virtio_ring.h:73
uint16_t flags
Definition: virtio_ring.h:72
Definition: virtio_ring.h:77
struct vring_desc * desc
Definition: virtio_ring.h:80
struct vring_avail * avail
Definition: virtio_ring.h:81
unsigned int num
Definition: virtio_ring.h:78
struct vring_used * used
Definition: virtio_ring.h:82
METAL_PACKED_BEGIN struct vring_desc METAL_PACKED_END
static int vring_size(unsigned int num, unsigned long align)
Definition: virtio_ring.h:118
static int vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old)
Definition: virtio_ring.h:151
static void vring_init(struct vring *vr, unsigned int num, uint8_t *p, unsigned long align)
Definition: virtio_ring.h:133