CAMLprim value caml_sring_push_responses(value v_sring, value v_rsp_prod_pvt) { struct sring *sring = SRING_VAL(v_sring); xen_wmb(); /* ensure requests are seen before the index is updated */ sring->rsp_prod = Int_val(v_rsp_prod_pvt); return Val_unit; }
/* Non-privileged console interrupt routine */ static int xencons_handler(void *arg) { struct xencons_softc *sc = arg; XENCONS_RING_IDX cons, prod, len; int s = spltty(); if (sc->polling) { splx(s); return 1; } #define XNC_IN (xencons_interface->in) cons = xencons_interface->in_cons; prod = xencons_interface->in_prod; xen_rmb(); while (cons != prod) { if (MASK_XENCONS_IDX(cons, XNC_IN) < MASK_XENCONS_IDX(prod, XNC_IN)) len = MASK_XENCONS_IDX(prod, XNC_IN) - MASK_XENCONS_IDX(cons, XNC_IN); else len = sizeof(XNC_IN) - MASK_XENCONS_IDX(cons, XNC_IN); xencons_tty_input(sc, __UNVOLATILE( &XNC_IN[MASK_XENCONS_IDX(cons, XNC_IN)]), len); if (__predict_false(xencons_interface->in_cons != cons)) { /* catch up with xenconscn_getc() */ cons = xencons_interface->in_cons; prod = xencons_interface->in_prod; xen_rmb(); } else { cons += len; xen_wmb(); xencons_interface->in_cons = cons; xen_wmb(); } } hypervisor_notify_via_evtchn(xen_start_info.console.domU.evtchn); splx(s); return 1; #undef XNC_IN }
CAMLprim value caml_sring_push_requests(value v_sring, value v_req_prod_pvt) { struct sring *sring = SRING_VAL(v_sring); ASSERT(((unsigned long)sring % PAGE_SIZE) == 0); xen_wmb(); /* ensure requests are seen before the index is updated */ sring->req_prod = Int_val(v_req_prod_pvt); return Val_unit; }
static void xen_9pfs_push_and_notify(V9fsPDU *pdu) { RING_IDX prod; Xen9pfsDev *priv = container_of(pdu->s, Xen9pfsDev, state); Xen9pfsRing *ring = &priv->rings[pdu->tag % priv->num_rings]; g_free(ring->sg); ring->sg = NULL; ring->intf->out_cons = ring->out_cons; xen_wmb(); prod = ring->intf->in_prod; xen_rmb(); ring->intf->in_prod = prod + pdu->size; xen_wmb(); ring->inprogress = false; xenevtchn_notify(ring->evtchndev, ring->local_port); qemu_bh_schedule(ring->bh); }
static void xenfb_send_event(struct XenFB *xenfb, union xenfb_in_event *event) { uint32_t prod; struct xenfb_page *page = xenfb->c.page; prod = page->in_prod; /* caller ensures !xenfb_queue_full() */ xen_mb(); /* ensure ring space available */ XENFB_IN_RING_REF(page, prod) = *event; xen_wmb(); /* ensure ring contents visible */ page->in_prod = prod + 1; xen_be_send_notify(&xenfb->c.xendev); }
static void xenfb_send_event(struct xenfb *xenfb, union xenfb_in_event *event) { uint32_t prod; struct xenfb_page *page = xenfb->fb.page; prod = page->in_prod; /* caller ensures !xenfb_queue_full() */ xen_mb(); /* ensure ring space available */ XENFB_IN_RING_REF(page, prod) = *event; xen_wmb(); /* ensure ring contents visible */ page->in_prod = prod + 1; xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port); }
/** * returns -1 on error, or size on success */ static int do_send(struct libxenvchan *ctrl, const void *data, size_t size) { int real_idx = wr_prod(ctrl) & (wr_ring_size(ctrl) - 1); int avail_contig = wr_ring_size(ctrl) - real_idx; if (avail_contig > size) avail_contig = size; xen_mb(); /* read indexes /then/ write data */ memcpy(wr_ring(ctrl) + real_idx, data, avail_contig); if (avail_contig < size) { // we rolled across the end of the ring memcpy(wr_ring(ctrl), data + avail_contig, size - avail_contig); } xen_wmb(); /* write data /then/ notify */ wr_prod(ctrl) += size; if (send_notify(ctrl, VCHAN_NOTIFY_WRITE)) return -1; return size; }
/* Send an event to the keyboard frontend driver */ static int xenfb_kbd_event(struct xenfb *xenfb, union xenkbd_in_event *event) { uint32_t prod; struct xenkbd_page *page = xenfb->kbd.page; if (xenfb->kbd.state != XenbusStateConnected) return 0; prod = page->in_prod; if (prod - page->in_cons == XENKBD_IN_RING_LEN) { errno = EAGAIN; return -1; } xen_mb(); /* ensure ring space available */ XENKBD_IN_RING_REF(page, prod) = *event; xen_wmb(); /* ensure ring contents visible */ page->in_prod = prod + 1; return xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port); }
static void xencons_receive(void *opaque, const uint8_t *buf, int len) { struct XenConsole *con = opaque; struct xencons_interface *intf = con->sring; XENCONS_RING_IDX prod; int i, max; max = ring_free_bytes(con); /* The can_receive() func limits this, but check again anyway */ if (max < len) len = max; prod = intf->in_prod; for (i = 0; i < len; i++) { intf->in[MASK_XENCONS_IDX(prod++, intf->in)] = buf[i]; } xen_wmb(); intf->in_prod = prod; xen_pv_send_notify(&con->xendev); }
/* Send an event to the keyboard frontend driver */ static int xenfb_kbd_event(struct XenInput *xenfb, union xenkbd_in_event *event) { struct xenkbd_page *page = xenfb->c.page; uint32_t prod; if (xenfb->c.xendev.be_state != XenbusStateConnected) return 0; if (!page) return 0; prod = page->in_prod; if (prod - page->in_cons == XENKBD_IN_RING_LEN) { errno = EAGAIN; return -1; } xen_mb(); /* ensure ring space available */ XENKBD_IN_RING_REF(page, prod) = *event; xen_wmb(); /* ensure ring contents visible */ page->in_prod = prod + 1; return xen_be_send_notify(&xenfb->c.xendev); }
void xencons_start(struct tty *tp) { struct clist *cl; int s; s = spltty(); if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) goto out; tp->t_state |= TS_BUSY; splx(s); /* * We need to do this outside spl since it could be fairly * expensive and we don't want our serial ports to overflow. */ cl = &tp->t_outq; if (xendomain_is_dom0()) { int len, r; u_char buf[XENCONS_BURST+1]; len = q_to_b(cl, buf, XENCONS_BURST); while (len > 0) { r = HYPERVISOR_console_io(CONSOLEIO_write, len, buf); if (r <= 0) break; len -= r; } } else { XENCONS_RING_IDX cons, prod, len; #define XNC_OUT (xencons_interface->out) cons = xencons_interface->out_cons; prod = xencons_interface->out_prod; xen_rmb(); while (prod != cons + sizeof(xencons_interface->out)) { if (MASK_XENCONS_IDX(prod, XNC_OUT) < MASK_XENCONS_IDX(cons, XNC_OUT)) { len = MASK_XENCONS_IDX(cons, XNC_OUT) - MASK_XENCONS_IDX(prod, XNC_OUT); } else { len = sizeof(XNC_OUT) - MASK_XENCONS_IDX(prod, XNC_OUT); } len = q_to_b(cl, __UNVOLATILE( &XNC_OUT[MASK_XENCONS_IDX(prod, XNC_OUT)]), len); if (len == 0) break; prod = prod + len; } xen_wmb(); xencons_interface->out_prod = prod; xen_wmb(); hypervisor_notify_via_evtchn(xen_start_info.console.domU.evtchn); #undef XNC_OUT } s = spltty(); tp->t_state &= ~TS_BUSY; if (ttypull(tp)) { tp->t_state |= TS_TIMEOUT; callout_schedule(&tp->t_rstrt_ch, 1); } out: splx(s); }