void evtchn_device_upcall(int port) { struct per_user_data *u; spin_lock(&port_user_lock); mask_evtchn(port); clear_evtchn(port); if ((u = port_user[port]) != NULL) { if ((u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE) { u->ring[EVTCHN_RING_MASK(u->ring_prod)] = port; wmb(); /* Ensure ring contents visible */ if (u->ring_cons == u->ring_prod++) { wake_up_interruptible(&u->evtchn_wait); kill_fasync(&u->evtchn_async_queue, SIGIO, POLL_IN); } } else { u->ring_overflow = 1; } } spin_unlock(&port_user_lock); }
void unbind_all_ports(void) { int i; int cpu = 0; shared_info_t *s = HYPERVISOR_shared_info; vcpu_info_t *vcpu_info = &s->vcpu_info[cpu]; int rc; for ( i = 0; i < NR_EVS; i++ ) { if ( i == start_info.console.domU.evtchn || i == start_info.store_evtchn) continue; if ( test_and_clear_bit(i, bound_ports) ) { struct evtchn_close close; printk("port %d still bound!\n", i); mask_evtchn(i); close.port = i; rc = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); if ( rc ) printk("WARN: close_port %s failed rc=%d. ignored\n", i, rc); clear_evtchn(i); } } vcpu_info->evtchn_upcall_pending = 0; vcpu_info->evtchn_pending_sel = 0; }
/* Process PCI operation */ static int do_pci_op(struct pcifront_device *pdev, struct xen_pci_op *op) { int err = 0; struct xen_pci_op *active_op = &pdev->sh_info->op; evtchn_port_t port = pdev->evtchn; time_t timeout; mtx_lock(&pdev->sh_info_lock); memcpy(active_op, op, sizeof(struct xen_pci_op)); /* Go */ wmb(); set_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags); notify_remote_via_evtchn(port); timeout = time_uptime + 2; clear_evtchn(port); /* Spin while waiting for the answer */ while (test_bit (_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags)) { int err = HYPERVISOR_poll(&port, 1, 3 * hz); if (err) panic("Failed HYPERVISOR_poll: err=%d", err); clear_evtchn(port); if (time_uptime > timeout) { WPRINTF("pciback not responding!!!\n"); clear_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags); err = XEN_PCI_ERR_dev_not_found; goto out; } } memcpy(op, active_op, sizeof(struct xen_pci_op)); err = op->err; out: mtx_unlock(&pdev->sh_info_lock); return err; }
static void ack_dynirq(unsigned int irq) { int evtchn = evtchn_from_irq(irq); move_native_irq(irq); if (VALID_EVTCHN(evtchn)) { mask_evtchn(evtchn); clear_evtchn(evtchn); } }
void unbind_evtchn(evtchn_port_t port) { struct evtchn_close close; int rc; mask_evtchn(port); clear_evtchn(port); close.port = port; rc = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); if ( rc ) printk("WARN: close_port %s failed rc=%d. ignored\n", port, rc); }
void unbind_evtchn(evtchn_port_t port) { struct evtchn_close close; int rc; if (ev_actions[port].handler == default_handler) printk("WARN: No handler for port %d when unbinding\n", port); mask_evtchn(port); clear_evtchn(port); ev_actions[port].handler = default_handler; wmb(); ev_actions[port].data = NULL; clear_bit(port, bound_ports); close.port = port; rc = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); if (rc) printk("WARN: close_port %s failed rc=%d. ignored\n", port, rc); }
/* * Demux events to different handlers. */ int do_event(evtchn_port_t port, struct pt_regs *regs) { ev_action_t *action; clear_evtchn(port); if (port >= NR_EVS) { DEBUG("WARN: do_event(): Port number too large: %d\n", port); return 1; } DEBUG("Interrupt recevied on the port :%d \n",port); action = &ev_actions[port]; action->count++; /* call the handler */ action->handler(port, regs, action->data); return 1; }
void evtchn_do_upcall(struct trapframe *frame) { unsigned long l1, l2; unsigned int l1i, l2i, port; int irq, cpu; shared_info_t *s; vcpu_info_t *vcpu_info; cpu = PCPU_GET(cpuid); s = HYPERVISOR_shared_info; vcpu_info = &s->vcpu_info[cpu]; vcpu_info->evtchn_upcall_pending = 0; /* NB. No need for a barrier here -- XCHG is a barrier on x86. */ l1 = xen_xchg(&vcpu_info->evtchn_pending_sel, 0); while (l1 != 0) { l1i = __ffs(l1); l1 &= ~(1 << l1i); while ((l2 = active_evtchns(cpu, s, l1i)) != 0) { l2i = __ffs(l2); port = (l1i * LONG_BIT) + l2i; if ((irq = evtchn_to_irq[port]) != -1) { struct intsrc *isrc = intr_lookup_source(irq); /* * ack */ mask_evtchn(port); clear_evtchn(port); intr_execute_handlers(isrc, frame); } else { evtchn_device_upcall(port); } } } }
void evtchn_device_upcall(int port) { mtx_lock(&upcall_lock); mask_evtchn(port); clear_evtchn(port); if ( ring != NULL ) { if ( (ring_prod - ring_cons) < EVTCHN_RING_SIZE ) { ring[EVTCHN_RING_MASK(ring_prod)] = (uint16_t)port; if ( ring_cons == ring_prod++ ) { wakeup(evtchn_waddr); } } else { ring_overflow = 1; } } mtx_unlock(&upcall_lock); }