Пример #1
0
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);
}
Пример #2
0
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;
}
Пример #3
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;
}
Пример #4
0
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);
	}
}
Пример #5
0
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);
}
Пример #6
0
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);

}
Пример #7
0
/*
 * 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;

}
Пример #8
0
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);
			}
		}
	}
}
Пример #9
0
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);
}