Go to the documentation of this file. 10 #ifndef __XEN_PUBLIC_IO_RING_H__ 11 #define __XEN_PUBLIC_IO_RING_H__ 31 #include "../xen-compat.h" 33 #if __XEN_INTERFACE_VERSION__ < 0x00030208 35 #define xen_rmb() rmb() 36 #define xen_wmb() wmb() 42 #define __RD2(_x) (((_x) & 0x00000002) ? 0x2 : ((_x) & 0x1)) 43 #define __RD4(_x) (((_x) & 0x0000000c) ? __RD2((_x)>>2)<<2 : __RD2(_x)) 44 #define __RD8(_x) (((_x) & 0x000000f0) ? __RD4((_x)>>4)<<4 : __RD4(_x)) 45 #define __RD16(_x) (((_x) & 0x0000ff00) ? __RD8((_x)>>8)<<8 : __RD8(_x)) 46 #define __RD32(_x) (((_x) & 0xffff0000) ? __RD16((_x)>>16)<<16 : __RD16(_x)) 54 #define __CONST_RING_SIZE(_s, _sz) \ 55 (__RD32(((_sz) - offsetof(struct _s##_sring, ring)) / \ 56 sizeof(((struct _s##_sring *)0)->ring[0]))) 60 #define __RING_SIZE(_s, _sz) \ 61 (__RD32(((_sz) - (long)(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0]))) 94 #define DEFINE_RING_TYPES(__name, __req_t, __rsp_t) \ 97 union __name##_sring_entry { \ 103 struct __name##_sring { \ 104 RING_IDX req_prod, req_event; \ 105 RING_IDX rsp_prod, rsp_event; \ 108 uint8_t smartpoll_active; \ 113 uint8_t pvt_pad[4]; \ 116 union __name##_sring_entry ring[1]; \ 120 struct __name##_front_ring { \ 121 RING_IDX req_prod_pvt; \ 123 unsigned int nr_ents; \ 124 struct __name##_sring *sring; \ 128 struct __name##_back_ring { \ 129 RING_IDX rsp_prod_pvt; \ 131 unsigned int nr_ents; \ 132 struct __name##_sring *sring; \ 136 typedef struct __name##_sring __name##_sring_t; \ 137 typedef struct __name##_front_ring __name##_front_ring_t; \ 138 typedef struct __name##_back_ring __name##_back_ring_t 156 #define SHARED_RING_INIT(_s) do { \ 157 (_s)->req_prod = (_s)->rsp_prod = 0; \ 158 (_s)->req_event = (_s)->rsp_event = 1; \ 159 (void)memset((_s)->pvt.pvt_pad, 0, sizeof((_s)->pvt.pvt_pad)); \ 160 (void)memset((_s)->__pad, 0, sizeof((_s)->__pad)); \ 163 #define FRONT_RING_ATTACH(_r, _s, _i, __size) do { \ 164 (_r)->req_prod_pvt = (_i); \ 165 (_r)->rsp_cons = (_i); \ 166 (_r)->nr_ents = __RING_SIZE(_s, __size); \ 167 (_r)->sring = (_s); \ 170 #define FRONT_RING_INIT(_r, _s, __size) FRONT_RING_ATTACH(_r, _s, 0, __size) 172 #define XEN_FRONT_RING_INIT(r, s, size) do { \ 173 SHARED_RING_INIT(s); \ 174 FRONT_RING_INIT(r, s, size); \ 177 #define BACK_RING_ATTACH(_r, _s, _i, __size) do { \ 178 (_r)->rsp_prod_pvt = (_i); \ 179 (_r)->req_cons = (_i); \ 180 (_r)->nr_ents = __RING_SIZE(_s, __size); \ 181 (_r)->sring = (_s); \ 184 #define BACK_RING_INIT(_r, _s, __size) BACK_RING_ATTACH(_r, _s, 0, __size) 187 #define RING_SIZE(_r) \ 191 #define RING_FREE_REQUESTS(_r) \ 192 (RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons)) 197 #define RING_FULL(_r) \ 198 (RING_FREE_REQUESTS(_r) == 0) 201 #define XEN_RING_NR_UNCONSUMED_RESPONSES(_r) \ 202 ((_r)->sring->rsp_prod - (_r)->rsp_cons) 205 #define XEN_RING_NR_UNCONSUMED_REQUESTS(_r) ({ \ 206 unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \ 207 unsigned int rsp = RING_SIZE(_r) - \ 208 ((_r)->req_cons - (_r)->rsp_prod_pvt); \ 209 req < rsp ? req : rsp; \ 213 #define XEN_RING_NR_UNCONSUMED_REQUESTS(_r) \ 214 ((((_r)->sring->req_prod - (_r)->req_cons) < \ 215 (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) ? \ 216 ((_r)->sring->req_prod - (_r)->req_cons) : \ 217 (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) 220 #ifdef XEN_RING_HAS_UNCONSUMED_IS_BOOL 225 #define RING_HAS_UNCONSUMED_RESPONSES(_r) \ 226 (!!XEN_RING_NR_UNCONSUMED_RESPONSES(_r)) 227 #define RING_HAS_UNCONSUMED_REQUESTS(_r) \ 228 (!!XEN_RING_NR_UNCONSUMED_REQUESTS(_r)) 230 #define RING_HAS_UNCONSUMED_RESPONSES(_r) XEN_RING_NR_UNCONSUMED_RESPONSES(_r) 231 #define RING_HAS_UNCONSUMED_REQUESTS(_r) XEN_RING_NR_UNCONSUMED_REQUESTS(_r) 235 #define RING_GET_REQUEST(_r, _idx) \ 236 (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req)) 238 #define RING_GET_RESPONSE(_r, _idx) \ 239 (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp)) 250 #define RING_COPY_(type, r, idx, dest) do { \ 252 *(dest) = *(volatile __typeof__(dest))RING_GET_##type(r, idx); \ 255 #define RING_COPY_REQUEST(r, idx, req) RING_COPY_(REQUEST, r, idx, req) 256 #define RING_COPY_RESPONSE(r, idx, rsp) RING_COPY_(RESPONSE, r, idx, rsp) 259 #define RING_REQUEST_CONS_OVERFLOW(_r, _cons) \ 260 (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r)) 263 #define RING_REQUEST_PROD_OVERFLOW(_r, _prod) \ 264 (((_prod) - (_r)->rsp_prod_pvt) > RING_SIZE(_r)) 267 #define RING_RESPONSE_PROD_OVERFLOW(_r, _prod) \ 268 (((_prod) - (_r)->rsp_cons) > RING_SIZE(_r)) 270 #define RING_PUSH_REQUESTS(_r) do { \ 272 (_r)->sring->req_prod = (_r)->req_prod_pvt; \ 275 #define RING_PUSH_RESPONSES(_r) do { \ 277 (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt; \ 310 #define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do { \ 311 RING_IDX __old = (_r)->sring->req_prod; \ 312 RING_IDX __new = (_r)->req_prod_pvt; \ 314 (_r)->sring->req_prod = __new; \ 316 (_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) < \ 317 (RING_IDX)(__new - __old)); \ 320 #define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do { \ 321 RING_IDX __old = (_r)->sring->rsp_prod; \ 322 RING_IDX __new = (_r)->rsp_prod_pvt; \ 324 (_r)->sring->rsp_prod = __new; \ 326 (_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) < \ 327 (RING_IDX)(__new - __old)); \ 330 #define RING_FINAL_CHECK_FOR_REQUESTS(_r, _work_to_do) do { \ 331 (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \ 332 if (_work_to_do) break; \ 333 (_r)->sring->req_event = (_r)->req_cons + 1; \ 335 (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \ 338 #define RING_FINAL_CHECK_FOR_RESPONSES(_r, _work_to_do) do { \ 339 (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \ 340 if (_work_to_do) break; \ 341 (_r)->sring->rsp_event = (_r)->rsp_cons + 1; \ 343 (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \ 388 #ifndef XEN_PAGE_SHIFT 393 #define XEN_PAGE_SHIFT 12 395 #define XEN_FLEX_RING_SIZE(order) \ 396 (1UL << ((order) + XEN_PAGE_SHIFT - 1)) 398 #define DEFINE_XEN_FLEX_RING(name) \ 399 static inline RING_IDX name##_mask(RING_IDX idx, RING_IDX ring_size) \ 401 return idx & (ring_size - 1); \ 404 static inline unsigned char *name##_get_ring_ptr(unsigned char *buf, \ 406 RING_IDX ring_size) \ 408 return buf + name##_mask(idx, ring_size); \ 411 static inline void name##_read_packet(void *opaque, \ 412 const unsigned char *buf, \ 414 RING_IDX masked_prod, \ 415 RING_IDX *masked_cons, \ 416 RING_IDX ring_size) \ 418 if (*masked_cons < masked_prod || \ 419 size <= ring_size - *masked_cons) { \ 420 memcpy(opaque, buf + *masked_cons, size); \ 422 memcpy(opaque, buf + *masked_cons, ring_size - *masked_cons); \ 423 memcpy((unsigned char *)opaque + ring_size - *masked_cons, buf, \ 424 size - (ring_size - *masked_cons)); \ 426 *masked_cons = name##_mask(*masked_cons + size, ring_size); \ 429 static inline void name##_write_packet(unsigned char *buf, \ 430 const void *opaque, \ 432 RING_IDX *masked_prod, \ 433 RING_IDX masked_cons, \ 434 RING_IDX ring_size) \ 436 if (*masked_prod < masked_cons || \ 437 size <= ring_size - *masked_prod) { \ 438 memcpy(buf + *masked_prod, opaque, size); \ 440 memcpy(buf + *masked_prod, opaque, ring_size - *masked_prod); \ 441 memcpy(buf, (unsigned char *)opaque + (ring_size - *masked_prod), \ 442 size - (ring_size - *masked_prod)); \ 444 *masked_prod = name##_mask(*masked_prod + size, ring_size); \ 447 static inline RING_IDX name##_queued(RING_IDX prod, \ 449 RING_IDX ring_size) \ 456 prod = name##_mask(prod, ring_size); \ 457 cons = name##_mask(cons, ring_size); \ 463 size = prod - cons; \ 465 size = ring_size - (cons - prod); \ 469 struct name##_data { \ 471 unsigned char *out; \ 474 #define DEFINE_XEN_FLEX_RING_AND_INTF(name) \ 475 struct name##_data_intf { \ 476 RING_IDX in_cons, in_prod; \ 480 RING_IDX out_cons, out_prod; \ 484 RING_IDX ring_order; \ 487 DEFINE_XEN_FLEX_RING(name)