Go to the documentation of this file. 10 #ifndef __XEN_PUBLIC_IO_RING_H__ 11 #define __XEN_PUBLIC_IO_RING_H__ 30 #include "../xen-compat.h" 32 #if __XEN_INTERFACE_VERSION__ < 0x00030208 34 #define xen_rmb() rmb() 35 #define xen_wmb() wmb() 41 #define __RD2(_x) (((_x) & 0x00000002) ? 0x2 : ((_x) & 0x1)) 42 #define __RD4(_x) (((_x) & 0x0000000c) ? __RD2((_x)>>2)<<2 : __RD2(_x)) 43 #define __RD8(_x) (((_x) & 0x000000f0) ? __RD4((_x)>>4)<<4 : __RD4(_x)) 44 #define __RD16(_x) (((_x) & 0x0000ff00) ? __RD8((_x)>>8)<<8 : __RD8(_x)) 45 #define __RD32(_x) (((_x) & 0xffff0000) ? __RD16((_x)>>16)<<16 : __RD16(_x)) 53 #define __CONST_RING_SIZE(_s, _sz) \ 54 (__RD32(((_sz) - offsetof(struct _s##_sring, ring)) / \ 55 sizeof(((struct _s##_sring *)0)->ring[0]))) 59 #define __RING_SIZE(_s, _sz) \ 60 (__RD32(((_sz) - (long)(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0]))) 93 #define DEFINE_RING_TYPES(__name, __req_t, __rsp_t) \ 96 union __name##_sring_entry { \ 102 struct __name##_sring { \ 103 RING_IDX req_prod, req_event; \ 104 RING_IDX rsp_prod, rsp_event; \ 107 uint8_t smartpoll_active; \ 112 uint8_t pvt_pad[4]; \ 115 union __name##_sring_entry ring[1]; \ 119 struct __name##_front_ring { \ 120 RING_IDX req_prod_pvt; \ 122 unsigned int nr_ents; \ 123 struct __name##_sring *sring; \ 127 struct __name##_back_ring { \ 128 RING_IDX rsp_prod_pvt; \ 130 unsigned int nr_ents; \ 131 struct __name##_sring *sring; \ 135 typedef struct __name##_sring __name##_sring_t; \ 136 typedef struct __name##_front_ring __name##_front_ring_t; \ 137 typedef struct __name##_back_ring __name##_back_ring_t 155 #define SHARED_RING_INIT(_s) do { \ 156 (_s)->req_prod = (_s)->rsp_prod = 0; \ 157 (_s)->req_event = (_s)->rsp_event = 1; \ 158 (void)memset((_s)->pvt.pvt_pad, 0, sizeof((_s)->pvt.pvt_pad)); \ 159 (void)memset((_s)->__pad, 0, sizeof((_s)->__pad)); \ 162 #define FRONT_RING_ATTACH(_r, _s, _i, __size) do { \ 163 (_r)->req_prod_pvt = (_i); \ 164 (_r)->rsp_cons = (_i); \ 165 (_r)->nr_ents = __RING_SIZE(_s, __size); \ 166 (_r)->sring = (_s); \ 169 #define FRONT_RING_INIT(_r, _s, __size) FRONT_RING_ATTACH(_r, _s, 0, __size) 171 #define XEN_FRONT_RING_INIT(r, s, size) do { \ 172 SHARED_RING_INIT(s); \ 173 FRONT_RING_INIT(r, s, size); \ 176 #define BACK_RING_ATTACH(_r, _s, _i, __size) do { \ 177 (_r)->rsp_prod_pvt = (_i); \ 178 (_r)->req_cons = (_i); \ 179 (_r)->nr_ents = __RING_SIZE(_s, __size); \ 180 (_r)->sring = (_s); \ 183 #define BACK_RING_INIT(_r, _s, __size) BACK_RING_ATTACH(_r, _s, 0, __size) 186 #define RING_SIZE(_r) \ 190 #define RING_FREE_REQUESTS(_r) \ 191 (RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons)) 196 #define RING_FULL(_r) \ 197 (RING_FREE_REQUESTS(_r) == 0) 200 #define XEN_RING_NR_UNCONSUMED_RESPONSES(_r) \ 201 ((_r)->sring->rsp_prod - (_r)->rsp_cons) 204 #define XEN_RING_NR_UNCONSUMED_REQUESTS(_r) ({ \ 205 unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \ 206 unsigned int rsp = RING_SIZE(_r) - \ 207 ((_r)->req_cons - (_r)->rsp_prod_pvt); \ 208 req < rsp ? req : rsp; \ 212 #define XEN_RING_NR_UNCONSUMED_REQUESTS(_r) \ 213 ((((_r)->sring->req_prod - (_r)->req_cons) < \ 214 (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) ? \ 215 ((_r)->sring->req_prod - (_r)->req_cons) : \ 216 (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) 219 #ifdef XEN_RING_HAS_UNCONSUMED_IS_BOOL 224 #define RING_HAS_UNCONSUMED_RESPONSES(_r) \ 225 (!!XEN_RING_NR_UNCONSUMED_RESPONSES(_r)) 226 #define RING_HAS_UNCONSUMED_REQUESTS(_r) \ 227 (!!XEN_RING_NR_UNCONSUMED_REQUESTS(_r)) 229 #define RING_HAS_UNCONSUMED_RESPONSES(_r) XEN_RING_NR_UNCONSUMED_RESPONSES(_r) 230 #define RING_HAS_UNCONSUMED_REQUESTS(_r) XEN_RING_NR_UNCONSUMED_REQUESTS(_r) 234 #define RING_GET_REQUEST(_r, _idx) \ 235 (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req)) 237 #define RING_GET_RESPONSE(_r, _idx) \ 238 (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp)) 249 #define RING_COPY_(type, r, idx, dest) do { \ 251 *(dest) = *(volatile __typeof__(dest))RING_GET_##type(r, idx); \ 254 #define RING_COPY_REQUEST(r, idx, req) RING_COPY_(REQUEST, r, idx, req) 255 #define RING_COPY_RESPONSE(r, idx, rsp) RING_COPY_(RESPONSE, r, idx, rsp) 258 #define RING_REQUEST_CONS_OVERFLOW(_r, _cons) \ 259 (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r)) 262 #define RING_REQUEST_PROD_OVERFLOW(_r, _prod) \ 263 (((_prod) - (_r)->rsp_prod_pvt) > RING_SIZE(_r)) 266 #define RING_RESPONSE_PROD_OVERFLOW(_r, _prod) \ 267 (((_prod) - (_r)->rsp_cons) > RING_SIZE(_r)) 269 #define RING_PUSH_REQUESTS(_r) do { \ 271 (_r)->sring->req_prod = (_r)->req_prod_pvt; \ 274 #define RING_PUSH_RESPONSES(_r) do { \ 276 (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt; \ 309 #define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do { \ 310 RING_IDX __old = (_r)->sring->req_prod; \ 311 RING_IDX __new = (_r)->req_prod_pvt; \ 313 (_r)->sring->req_prod = __new; \ 315 (_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) < \ 316 (RING_IDX)(__new - __old)); \ 319 #define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do { \ 320 RING_IDX __old = (_r)->sring->rsp_prod; \ 321 RING_IDX __new = (_r)->rsp_prod_pvt; \ 323 (_r)->sring->rsp_prod = __new; \ 325 (_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) < \ 326 (RING_IDX)(__new - __old)); \ 329 #define RING_FINAL_CHECK_FOR_REQUESTS(_r, _work_to_do) do { \ 330 (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \ 331 if (_work_to_do) break; \ 332 (_r)->sring->req_event = (_r)->req_cons + 1; \ 334 (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \ 337 #define RING_FINAL_CHECK_FOR_RESPONSES(_r, _work_to_do) do { \ 338 (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \ 339 if (_work_to_do) break; \ 340 (_r)->sring->rsp_event = (_r)->rsp_cons + 1; \ 342 (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \ 387 #ifndef XEN_PAGE_SHIFT 392 #define XEN_PAGE_SHIFT 12 394 #define XEN_FLEX_RING_SIZE(order) \ 395 (1UL << ((order) + XEN_PAGE_SHIFT - 1)) 397 #define DEFINE_XEN_FLEX_RING(name) \ 398 static inline RING_IDX name##_mask(RING_IDX idx, RING_IDX ring_size) \ 400 return idx & (ring_size - 1); \ 403 static inline unsigned char *name##_get_ring_ptr(unsigned char *buf, \ 405 RING_IDX ring_size) \ 407 return buf + name##_mask(idx, ring_size); \ 410 static inline void name##_read_packet(void *opaque, \ 411 const unsigned char *buf, \ 413 RING_IDX masked_prod, \ 414 RING_IDX *masked_cons, \ 415 RING_IDX ring_size) \ 417 if (*masked_cons < masked_prod || \ 418 size <= ring_size - *masked_cons) { \ 419 memcpy(opaque, buf + *masked_cons, size); \ 421 memcpy(opaque, buf + *masked_cons, ring_size - *masked_cons); \ 422 memcpy((unsigned char *)opaque + ring_size - *masked_cons, buf, \ 423 size - (ring_size - *masked_cons)); \ 425 *masked_cons = name##_mask(*masked_cons + size, ring_size); \ 428 static inline void name##_write_packet(unsigned char *buf, \ 429 const void *opaque, \ 431 RING_IDX *masked_prod, \ 432 RING_IDX masked_cons, \ 433 RING_IDX ring_size) \ 435 if (*masked_prod < masked_cons || \ 436 size <= ring_size - *masked_prod) { \ 437 memcpy(buf + *masked_prod, opaque, size); \ 439 memcpy(buf + *masked_prod, opaque, ring_size - *masked_prod); \ 440 memcpy(buf, (unsigned char *)opaque + (ring_size - *masked_prod), \ 441 size - (ring_size - *masked_prod)); \ 443 *masked_prod = name##_mask(*masked_prod + size, ring_size); \ 446 static inline RING_IDX name##_queued(RING_IDX prod, \ 448 RING_IDX ring_size) \ 455 prod = name##_mask(prod, ring_size); \ 456 cons = name##_mask(cons, ring_size); \ 462 size = prod - cons; \ 464 size = ring_size - (cons - prod); \ 468 struct name##_data { \ 470 unsigned char *out; \ 473 #define DEFINE_XEN_FLEX_RING_AND_INTF(name) \ 474 struct name##_data_intf { \ 475 RING_IDX in_cons, in_prod; \ 479 RING_IDX out_cons, out_prod; \ 483 RING_IDX ring_order; \ 486 DEFINE_XEN_FLEX_RING(name)