int xencons_ring_send_no_notify(struct consfront_dev *dev, const char *data, unsigned len) { int sent = 0; struct xencons_interface *intf; XENCONS_RING_IDX cons, prod; if (!dev) intf = xencons_interface(); else intf = dev->ring; if (!intf) return sent; while (sent < len) { cons = intf->out_cons; prod = intf->out_prod; mb(); BUG_ON((prod - cons) > sizeof(intf->out)); while ((sent < len) && ((prod - cons) < sizeof(intf->out))) intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++]; wmb(); intf->out_prod = prod; if (sent < len) { block_domain(MILLISECS(10)); } } return sent; }
void console_handle_input(evtchn_port_t port, struct pt_regs *regs, void *data) { struct consfront_dev *dev = (struct consfront_dev *) data; #ifdef HAVE_LIBC int fd = dev ? dev->fd : -1; if (fd != -1) files[fd].read = 1; wake_up(&console_queue); #else struct xencons_interface *intf = xencons_interface(); XENCONS_RING_IDX cons, prod; cons = intf->in_cons; prod = intf->in_prod; mb(); BUG_ON((prod - cons) > sizeof(intf->in)); while (cons != prod) { xencons_rx(intf->in+MASK_XENCONS_IDX(cons,intf->in), 1, regs); cons++; } mb(); intf->in_cons = cons; notify_daemon(dev); xencons_tx(); #endif }
int xencons_ring_send(const char *data, unsigned len) { struct xencons_interface *intf; XENCONS_RING_IDX cons, prod; int sent; intf = xencons_interface(); cons = intf->out_cons; prod = intf->out_prod; sent = 0; mb(); KASSERT((prod - cons) <= sizeof(intf->out), ("console send ring inconsistent")); while ((sent < len) && ((prod - cons) < sizeof(intf->out))) intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++]; wmb(); intf->out_prod = prod; notify_remote_via_evtchn(xen_start_info->console_evtchn); return sent; }
int xencons_ring_recv(struct consfront_dev *dev, char *data, unsigned len) { struct xencons_interface *intf; XENCONS_RING_IDX cons, prod; unsigned filled = 0; if (!dev) intf = xencons_interface(); else intf = dev->ring; cons = intf->in_cons; prod = intf->in_prod; mb(); BUG_ON((prod - cons) > sizeof(intf->in)); while (filled < len && cons + filled != prod) { data[filled] = *(intf->in + MASK_XENCONS_IDX(cons + filled, intf->in)); filled++; } mb(); intf->in_cons = cons + filled; notify_daemon(dev); return filled; }
void xencons_handle_input(void *unused) { struct xencons_interface *intf; XENCONS_RING_IDX cons, prod; CN_LOCK(cn_mtx); intf = xencons_interface(); cons = intf->in_cons; prod = intf->in_prod; CN_UNLOCK(cn_mtx); /* XXX needs locking */ while (cons != prod) { xencons_rx(intf->in + MASK_XENCONS_IDX(cons, intf->in), 1); cons++; } mb(); intf->in_cons = cons; CN_LOCK(cn_mtx); notify_remote_via_evtchn(xen_start_info->console_evtchn); xencons_tx(); CN_UNLOCK(cn_mtx); }
int xencons_has_input(void) { struct xencons_interface *intf; intf = xencons_interface(); return (intf->in_cons != intf->in_prod); }
int xencons_ring_avail(struct consfront_dev *dev) { struct xencons_interface *intf; XENCONS_RING_IDX cons, prod; if (!dev) intf = xencons_interface(); else intf = dev->ring; cons = intf->in_cons; prod = intf->in_prod; mb(); BUG_ON((prod - cons) > sizeof(intf->in)); return prod - cons; }
static int domU_read_console(uint32_t vtermno, char *buf, int len) { struct xencons_interface *intf = xencons_interface(); XENCONS_RING_IDX cons, prod; int recv = 0; cons = intf->in_cons; prod = intf->in_prod; mb(); /* get pointers before reading ring */ BUG_ON((prod - cons) > sizeof(intf->in)); while (cons != prod && recv < len) buf[recv++] = intf->in[MASK_XENCONS_IDX(cons++, intf->in)]; mb(); /* read ring before consuming */ intf->in_cons = cons; notify_daemon(); return recv; }
static int write_console(uint32_t vtermno, const char *data, int len) { struct xencons_interface *intf = xencons_interface(); XENCONS_RING_IDX cons, prod; int sent = 0; cons = intf->out_cons; prod = intf->out_prod; mb(); /* update queue values before going on */ BUG_ON((prod - cons) > sizeof(intf->out)); while ((sent < len) && ((prod - cons) < sizeof(intf->out))) intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++]; wmb(); /* write ring before updating pointer */ intf->out_prod = prod; notify_daemon(); return sent; }
int xencons_ring_send(const char *data, unsigned len) { int sent = 0; struct xencons_interface *intf = xencons_interface(); XENCONS_RING_IDX cons, prod; cons = intf->out_cons; prod = intf->out_prod; mb(); BUG_ON((prod - cons) > sizeof(intf->out)); while ((sent < len) && ((prod - cons) < sizeof(intf->out))) intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++]; wmb(); intf->out_prod = prod; notify_daemon(); return sent; }
int xencons_has_input(void) { struct xencons_interface *intf; if (xen_initial_domain()) { /* * Since the Dom0 console works with hypercalls * there's no way to know if there's input unless * we actually try to retrieve it, so always return * like there's pending data. Then if the hypercall * returns no input, we can handle it without problems * in xencons_handle_input(). */ return 1; } intf = xencons_interface(); return (intf->in_cons != intf->in_prod); }
void console_handle_input(evtchn_port_t port, struct pt_regs *regs, void *data) { struct consfront_dev *dev = (struct consfront_dev *) data; struct xencons_interface *intf = xencons_interface(); XENCONS_RING_IDX cons, prod; cons = intf->in_cons; prod = intf->in_prod; mb(); BUG_ON((prod - cons) > sizeof(intf->in)); while (cons != prod) { xencons_rx(intf->in+MASK_XENCONS_IDX(cons,intf->in), 1, regs); cons++; } mb(); intf->in_cons = cons; notify_daemon(dev); xencons_tx(); }
static irqreturn_t handle_input(int irq, void *unused, struct pt_regs *regs) { struct xencons_interface *intf = xencons_interface(); XENCONS_RING_IDX cons, prod; cons = intf->in_cons; prod = intf->in_prod; mb(); BUG_ON((prod - cons) > sizeof(intf->in)); while (cons != prod) { xencons_rx(intf->in+MASK_XENCONS_IDX(cons,intf->in), 1, regs); cons++; } mb(); intf->in_cons = cons; notify_daemon(); xencons_tx(); return IRQ_HANDLED; }
int xencons_ring_send(const char *data, unsigned len) { struct xencons_interface *intf; XENCONS_RING_IDX cons, prod; int sent; struct evtchn_send send = { .port = HYPERVISOR_start_info->console_evtchn }; intf = xencons_interface(); cons = intf->out_cons; prod = intf->out_prod; sent = 0; mb(); KASSERT((prod - cons) <= sizeof(intf->out), ("console send ring inconsistent")); while ((sent < len) && ((prod - cons) < sizeof(intf->out))) intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++]; wmb(); intf->out_prod = prod; if (cnsl_evt_reg) xen_intr_signal(console_handle); else HYPERVISOR_event_channel_op(EVTCHNOP_send, &send); return sent; } static xencons_receiver_func *xencons_receiver; void xencons_handle_input(void *unused) { struct xencons_interface *intf; XENCONS_RING_IDX cons, prod; CN_LOCK(cn_mtx); if (xen_initial_domain()) { static char rbuf[DOM0_BUFFER_SIZE]; int l; while ((l = HYPERVISOR_console_io(CONSOLEIO_read, DOM0_BUFFER_SIZE, rbuf)) > 0) xencons_rx(rbuf, l); CN_UNLOCK(cn_mtx); return; } intf = xencons_interface(); cons = intf->in_cons; prod = intf->in_prod; CN_UNLOCK(cn_mtx); /* XXX needs locking */ while (cons != prod) { xencons_rx(intf->in + MASK_XENCONS_IDX(cons, intf->in), 1); cons++; } mb(); intf->in_cons = cons; CN_LOCK(cn_mtx); xen_intr_signal(console_handle); xencons_tx(); CN_UNLOCK(cn_mtx); } void xencons_ring_register_receiver(xencons_receiver_func *f) { xencons_receiver = f; } int xencons_ring_init(void) { int err; if (HYPERVISOR_start_info->console_evtchn == 0) return 0; err = xen_intr_bind_local_port(xencons_dev, HYPERVISOR_start_info->console_evtchn, NULL, xencons_handle_input, NULL, INTR_TYPE_MISC | INTR_MPSAFE, &console_handle); if (err) { return err; } return 0; }