1
2
3
4
5
6
7
8
9
10 #ifndef __XEN_PUBLIC_IO_RING_H__
11 #define __XEN_PUBLIC_IO_RING_H__
12
13 #include <xen/interface/grant_table.h>
14
15 typedef unsigned int RING_IDX;
16
17
18 #define __RD2(_x) (((_x) & 0x00000002) ? 0x2 : ((_x) & 0x1))
19 #define __RD4(_x) (((_x) & 0x0000000c) ? __RD2((_x)>>2)<<2 : __RD2(_x))
20 #define __RD8(_x) (((_x) & 0x000000f0) ? __RD4((_x)>>4)<<4 : __RD4(_x))
21 #define __RD16(_x) (((_x) & 0x0000ff00) ? __RD8((_x)>>8)<<8 : __RD8(_x))
22 #define __RD32(_x) (((_x) & 0xffff0000) ? __RD16((_x)>>16)<<16 : __RD16(_x))
23
24
25
26
27
28
29
30 #define __CONST_RING_SIZE(_s, _sz) \
31 (__RD32(((_sz) - offsetof(struct _s##_sring, ring)) / \
32 sizeof(((struct _s##_sring *)0)->ring[0])))
33
34
35
36
37 #define __RING_SIZE(_s, _sz) \
38 (__RD32(((_sz) - (long)&(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 #define DEFINE_RING_TYPES(__name, __req_t, __rsp_t) \
75 \
76 \
77 union __name##_sring_entry { \
78 __req_t req; \
79 __rsp_t rsp; \
80 }; \
81 \
82 \
83 struct __name##_sring { \
84 RING_IDX req_prod, req_event; \
85 RING_IDX rsp_prod, rsp_event; \
86 uint8_t pad[48]; \
87 union __name##_sring_entry ring[1]; \
88 }; \
89 \
90 \
91 struct __name##_front_ring { \
92 RING_IDX req_prod_pvt; \
93 RING_IDX rsp_cons; \
94 unsigned int nr_ents; \
95 struct __name##_sring *sring; \
96 }; \
97 \
98 \
99 struct __name##_back_ring { \
100 RING_IDX rsp_prod_pvt; \
101 RING_IDX req_cons; \
102 unsigned int nr_ents; \
103 struct __name##_sring *sring; \
104 };
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122 #define SHARED_RING_INIT(_s) do { \
123 (_s)->req_prod = (_s)->rsp_prod = 0; \
124 (_s)->req_event = (_s)->rsp_event = 1; \
125 memset((_s)->pad, 0, sizeof((_s)->pad)); \
126 } while(0)
127
128 #define FRONT_RING_INIT(_r, _s, __size) do { \
129 (_r)->req_prod_pvt = 0; \
130 (_r)->rsp_cons = 0; \
131 (_r)->nr_ents = __RING_SIZE(_s, __size); \
132 (_r)->sring = (_s); \
133 } while (0)
134
135 #define BACK_RING_INIT(_r, _s, __size) do { \
136 (_r)->rsp_prod_pvt = 0; \
137 (_r)->req_cons = 0; \
138 (_r)->nr_ents = __RING_SIZE(_s, __size); \
139 (_r)->sring = (_s); \
140 } while (0)
141
142
143 #define FRONT_RING_ATTACH(_r, _s, __size) do { \
144 (_r)->sring = (_s); \
145 (_r)->req_prod_pvt = (_s)->req_prod; \
146 (_r)->rsp_cons = (_s)->rsp_prod; \
147 (_r)->nr_ents = __RING_SIZE(_s, __size); \
148 } while (0)
149
150 #define BACK_RING_ATTACH(_r, _s, __size) do { \
151 (_r)->sring = (_s); \
152 (_r)->rsp_prod_pvt = (_s)->rsp_prod; \
153 (_r)->req_cons = (_s)->req_prod; \
154 (_r)->nr_ents = __RING_SIZE(_s, __size); \
155 } while (0)
156
157
158 #define RING_SIZE(_r) \
159 ((_r)->nr_ents)
160
161
162 #define RING_FREE_REQUESTS(_r) \
163 (RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons))
164
165
166
167
168 #define RING_FULL(_r) \
169 (RING_FREE_REQUESTS(_r) == 0)
170
171
172 #define RING_HAS_UNCONSUMED_RESPONSES(_r) \
173 ((_r)->sring->rsp_prod - (_r)->rsp_cons)
174
175 #define RING_HAS_UNCONSUMED_REQUESTS(_r) \
176 ({ \
177 unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \
178 unsigned int rsp = RING_SIZE(_r) - \
179 ((_r)->req_cons - (_r)->rsp_prod_pvt); \
180 req < rsp ? req : rsp; \
181 })
182
183
184 #define RING_GET_REQUEST(_r, _idx) \
185 (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req))
186
187
188
189
190
191
192
193
194
195
196 #define RING_COPY_REQUEST(_r, _idx, _req) do { \
197 \
198 *(_req) = *(volatile typeof(_req))RING_GET_REQUEST(_r, _idx); \
199 } while (0)
200
201 #define RING_GET_RESPONSE(_r, _idx) \
202 (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
203
204
205 #define RING_REQUEST_CONS_OVERFLOW(_r, _cons) \
206 (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r))
207
208
209 #define RING_REQUEST_PROD_OVERFLOW(_r, _prod) \
210 (((_prod) - (_r)->rsp_prod_pvt) > RING_SIZE(_r))
211
212
213 #define RING_PUSH_REQUESTS(_r) do { \
214 virt_wmb(); \
215 (_r)->sring->req_prod = (_r)->req_prod_pvt; \
216 } while (0)
217
218 #define RING_PUSH_RESPONSES(_r) do { \
219 virt_wmb(); \
220 (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt; \
221 } while (0)
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253 #define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do { \
254 RING_IDX __old = (_r)->sring->req_prod; \
255 RING_IDX __new = (_r)->req_prod_pvt; \
256 virt_wmb(); \
257 (_r)->sring->req_prod = __new; \
258 virt_mb(); \
259 (_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) < \
260 (RING_IDX)(__new - __old)); \
261 } while (0)
262
263 #define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do { \
264 RING_IDX __old = (_r)->sring->rsp_prod; \
265 RING_IDX __new = (_r)->rsp_prod_pvt; \
266 virt_wmb(); \
267 (_r)->sring->rsp_prod = __new; \
268 virt_mb(); \
269 (_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) < \
270 (RING_IDX)(__new - __old)); \
271 } while (0)
272
273 #define RING_FINAL_CHECK_FOR_REQUESTS(_r, _work_to_do) do { \
274 (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \
275 if (_work_to_do) break; \
276 (_r)->sring->req_event = (_r)->req_cons + 1; \
277 virt_mb(); \
278 (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \
279 } while (0)
280
281 #define RING_FINAL_CHECK_FOR_RESPONSES(_r, _work_to_do) do { \
282 (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
283 if (_work_to_do) break; \
284 (_r)->sring->rsp_event = (_r)->rsp_cons + 1; \
285 virt_mb(); \
286 (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
287 } while (0)
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331 #ifndef XEN_PAGE_SHIFT
332
333
334
335
336 #define XEN_PAGE_SHIFT 12
337 #endif
338 #define XEN_FLEX_RING_SIZE(order) \
339 (1UL << ((order) + XEN_PAGE_SHIFT - 1))
340
341 #define DEFINE_XEN_FLEX_RING(name) \
342 static inline RING_IDX name##_mask(RING_IDX idx, RING_IDX ring_size) \
343 { \
344 return idx & (ring_size - 1); \
345 } \
346 \
347 static inline unsigned char *name##_get_ring_ptr(unsigned char *buf, \
348 RING_IDX idx, \
349 RING_IDX ring_size) \
350 { \
351 return buf + name##_mask(idx, ring_size); \
352 } \
353 \
354 static inline void name##_read_packet(void *opaque, \
355 const unsigned char *buf, \
356 size_t size, \
357 RING_IDX masked_prod, \
358 RING_IDX *masked_cons, \
359 RING_IDX ring_size) \
360 { \
361 if (*masked_cons < masked_prod || \
362 size <= ring_size - *masked_cons) { \
363 memcpy(opaque, buf + *masked_cons, size); \
364 } else { \
365 memcpy(opaque, buf + *masked_cons, ring_size - *masked_cons); \
366 memcpy((unsigned char *)opaque + ring_size - *masked_cons, buf, \
367 size - (ring_size - *masked_cons)); \
368 } \
369 *masked_cons = name##_mask(*masked_cons + size, ring_size); \
370 } \
371 \
372 static inline void name##_write_packet(unsigned char *buf, \
373 const void *opaque, \
374 size_t size, \
375 RING_IDX *masked_prod, \
376 RING_IDX masked_cons, \
377 RING_IDX ring_size) \
378 { \
379 if (*masked_prod < masked_cons || \
380 size <= ring_size - *masked_prod) { \
381 memcpy(buf + *masked_prod, opaque, size); \
382 } else { \
383 memcpy(buf + *masked_prod, opaque, ring_size - *masked_prod); \
384 memcpy(buf, (unsigned char *)opaque + (ring_size - *masked_prod), \
385 size - (ring_size - *masked_prod)); \
386 } \
387 *masked_prod = name##_mask(*masked_prod + size, ring_size); \
388 } \
389 \
390 static inline RING_IDX name##_queued(RING_IDX prod, \
391 RING_IDX cons, \
392 RING_IDX ring_size) \
393 { \
394 RING_IDX size; \
395 \
396 if (prod == cons) \
397 return 0; \
398 \
399 prod = name##_mask(prod, ring_size); \
400 cons = name##_mask(cons, ring_size); \
401 \
402 if (prod == cons) \
403 return ring_size; \
404 \
405 if (prod > cons) \
406 size = prod - cons; \
407 else \
408 size = ring_size - (cons - prod); \
409 return size; \
410 } \
411 \
412 struct name##_data { \
413 unsigned char *in; \
414 unsigned char *out; \
415 }
416
417 #define DEFINE_XEN_FLEX_RING_AND_INTF(name) \
418 struct name##_data_intf { \
419 RING_IDX in_cons, in_prod; \
420 \
421 uint8_t pad1[56]; \
422 \
423 RING_IDX out_cons, out_prod; \
424 \
425 uint8_t pad2[56]; \
426 \
427 RING_IDX ring_order; \
428 grant_ref_t ref[]; \
429 }; \
430 DEFINE_XEN_FLEX_RING(name)
431
432 #endif