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