PERFORCE change 132025 for review
Kip Macy
kmacy at FreeBSD.org
Sat Dec 29 21:18:12 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=132025
Change 132025 by kmacy at pandemonium:kmacy:xen31 on 2007/12/30 05:17:47
update event channel code
fix pic registration so that we actually get clock interrupts
and console interrupts now
next up - block device interrupts
Affected files ...
.. //depot/projects/xen31/sys/dev/xen/blkfront/blkfront.c#4 edit
.. //depot/projects/xen31/sys/dev/xen/console/xencons_ring.c#3 edit
.. //depot/projects/xen31/sys/i386/include/xen/evtchn.h#3 edit
.. //depot/projects/xen31/sys/i386/include/xen/xen-os.h#3 edit
.. //depot/projects/xen31/sys/i386/include/xen/xen_intr.h#2 edit
.. //depot/projects/xen31/sys/i386/xen/xen_bus.c#1 add
.. //depot/projects/xen31/sys/xen/evtchn/evtchn.c#3 edit
.. //depot/projects/xen31/sys/xen/xenbus/xenbus_comms.c#3 edit
.. //depot/projects/xen31/sys/xen/xenbus/xenbus_xs.c#6 edit
Differences ...
==== //depot/projects/xen31/sys/dev/xen/blkfront/blkfront.c#4 (text+ko) ====
@@ -378,11 +378,8 @@
}
info->ring_ref = err;
- err = xenbus_alloc_evtchn(dev, &info->evtchn);
- if (err)
- goto fail;
- err = bind_evtchn_to_irqhandler(info->evtchn, "xbd",
- (driver_intr_t *)blkif_int,
+ err = bind_listening_port_to_irqhandler(dev->otherend_id,
+ "xbd", (driver_intr_t *)blkif_int,
info, INTR_TYPE_BIO | INTR_MPSAFE, NULL);
if (err <= 0) {
xenbus_dev_fatal(dev, err,
@@ -421,7 +418,11 @@
break;
case XenbusStateClosing:
- panic("not implemented");
+ if (info->users > 0)
+ xenbus_dev_error(dev, -EBUSY,
+ "Device in use; refusing to close");
+ else
+ blkfront_closing(dev);
#ifdef notyet
bd = bdget(info->dev);
if (bd == NULL)
==== //depot/projects/xen31/sys/dev/xen/console/xencons_ring.c#3 (text+ko) ====
@@ -101,7 +101,7 @@
if (!xen_start_info->console_evtchn)
return 0;
- err = bind_evtchn_to_irqhandler(xen_start_info->console_evtchn,
+ err = bind_caller_port_to_irqhandler(xen_start_info->console_evtchn,
"xencons", handle_input, NULL,
INTR_TYPE_MISC | INTR_MPSAFE, NULL);
if (err) {
==== //depot/projects/xen31/sys/i386/include/xen/evtchn.h#3 (text+ko) ====
==== //depot/projects/xen31/sys/i386/include/xen/xen-os.h#3 (text+ko) ====
@@ -118,15 +118,16 @@
preempt_enable_no_resched(); \
} while (0)
-
+/*
+ * Add critical_{enter, exit}?
+ *
+ */
#define __save_and_cli(x) \
do { \
vcpu_info_t *_vcpu; \
- preempt_disable(); \
_vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \
(x) = _vcpu->evtchn_upcall_mask; \
_vcpu->evtchn_upcall_mask = 1; \
- preempt_enable_no_resched(); \
barrier(); \
} while (0)
==== //depot/projects/xen31/sys/i386/include/xen/xen_intr.h#2 (text+ko) ====
@@ -30,12 +30,25 @@
extern void unbind_from_irq(int irq);
extern void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu);
-extern int bind_evtchn_to_irqhandler(unsigned int evtchn, const char *devname,
- driver_intr_t handler, void *arg, unsigned long irqflags, void **cookiep);
+extern int bind_caller_port_to_irqhandler(unsigned int caller_port,
+ const char *devname, driver_intr_t handler, void *arg,
+ unsigned long irqflags, void **cookiep);
+extern int bind_listening_port_to_irqhandler(unsigned int remote_domain,
+ const char *devname, driver_intr_t handler, void *arg, unsigned long irqflags,
+ void **cookiep);
extern int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, const char *devname,
driver_filter_t filter, driver_intr_t handler, unsigned long irqflags);
extern int bind_ipi_to_irqhandler(unsigned int ipi, unsigned int cpu, const char *devname,
driver_intr_t handler, unsigned long irqflags);
+extern int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain,
+ unsigned int remote_port,
+ const char *devname,
+ driver_filter_t filter,
+ driver_intr_t handler,
+ unsigned long irqflags);
+
+
+
extern void unbind_from_irqhandler(unsigned int evtchn, void *dev_id);
static __inline__ int irq_cannonicalize(int irq)
{
==== //depot/projects/xen31/sys/xen/evtchn/evtchn.c#3 (text+ko) ====
@@ -82,10 +82,6 @@
struct xenpic_intsrc xp_pins[0];
};
-
-
-
-
#define TODO printf("%s: not implemented!\n", __func__)
/* IRQ <-> event-channel mappings. */
@@ -94,7 +90,15 @@
/* Packed IRQ information: binding type, sub-type index, and event channel. */
static uint32_t irq_info[NR_IRQS];
/* Binding types. */
-enum { IRQT_UNBOUND, IRQT_PIRQ, IRQT_VIRQ, IRQT_IPI, IRQT_EVTCHN };
+enum {
+ IRQT_UNBOUND,
+ IRQT_PIRQ,
+ IRQT_VIRQ,
+ IRQT_IPI,
+ IRQT_LOCAL_PORT,
+ IRQT_CALLER_PORT
+};
+
/* Constructor for packed IRQ information. */
#define mk_irq_info(type, index, evtchn) \
(((uint32_t)(type) << 24) | ((uint32_t)(index) << 16) | (uint32_t)(evtchn))
@@ -227,25 +231,82 @@
return irq;
}
-static int
-bind_evtchn_to_irq(unsigned int evtchn)
+static int
+bind_caller_port_to_irq(unsigned int caller_port)
+{
+ int irq;
+
+ mtx_lock_spin(&irq_mapping_update_lock);
+
+ if ((irq = evtchn_to_irq[caller_port]) == -1) {
+ if ((irq = find_unbound_irq()) < 0)
+ goto out;
+
+ evtchn_to_irq[caller_port] = irq;
+ irq_info[irq] = mk_irq_info(IRQT_CALLER_PORT, 0, caller_port);
+ }
+
+ irq_bindcount[irq]++;
+
+ out:
+ mtx_unlock_spin(&irq_mapping_update_lock);
+ return irq;
+}
+
+static int
+bind_local_port_to_irq(unsigned int local_port)
+{
+ int irq;
+
+ mtx_lock_spin(&irq_mapping_update_lock);
+
+ PANIC_IF(evtchn_to_irq[local_port] != -1);
+
+ if ((irq = find_unbound_irq()) < 0) {
+ struct evtchn_close close = { .port = local_port };
+ PANIC_IF(HYPERVISOR_event_channel_op(EVTCHNOP_close, &close));
+
+ goto out;
+ }
+
+ evtchn_to_irq[local_port] = irq;
+ irq_info[irq] = mk_irq_info(IRQT_LOCAL_PORT, 0, local_port);
+ irq_bindcount[irq]++;
+
+ out:
+ mtx_unlock_spin(&irq_mapping_update_lock);
+ return irq;
+}
+
+static int
+bind_listening_port_to_irq(unsigned int remote_domain)
+{
+ struct evtchn_alloc_unbound alloc_unbound;
+ int err;
+
+ alloc_unbound.dom = DOMID_SELF;
+ alloc_unbound.remote_dom = remote_domain;
+
+ err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
+ &alloc_unbound);
+
+ return err ? : bind_local_port_to_irq(alloc_unbound.port);
+}
+
+static int
+bind_interdomain_evtchn_to_irq(unsigned int remote_domain,
+ unsigned int remote_port)
{
- int irq;
+ struct evtchn_bind_interdomain bind_interdomain;
+ int err;
- mtx_lock_spin(&irq_mapping_update_lock);
-
- if ((irq = evtchn_to_irq[evtchn]) == -1) {
- irq = find_unbound_irq();
- evtchn_to_irq[evtchn] = irq;
- irq_info[irq] = mk_irq_info(IRQT_EVTCHN, 0, evtchn);
- }
+ bind_interdomain.remote_dom = remote_domain;
+ bind_interdomain.remote_port = remote_port;
- irq_bindcount[irq]++;
- intr_register_source(&xp->xp_pins[irq].xp_intsrc);
+ err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
+ &bind_interdomain);
- mtx_unlock_spin(&irq_mapping_update_lock);
-
- return irq;
+ return err ? : bind_local_port_to_irq(bind_interdomain.local_port);
}
static int
@@ -348,7 +409,30 @@
}
int
-bind_evtchn_to_irqhandler(unsigned int evtchn,
+bind_caller_port_to_irqhandler(unsigned int caller_port,
+ const char *devname,
+ driver_intr_t handler,
+ void *arg,
+ unsigned long irqflags,
+ void **cookiep)
+{
+ unsigned int irq;
+ int retval;
+
+ irq = bind_caller_port_to_irq(caller_port);
+ intr_register_source(&xp->xp_pins[irq].xp_intsrc);
+ retval = intr_add_handler(devname, irq, NULL, handler, arg, irqflags, cookiep);
+ if (retval != 0) {
+ unbind_from_irq(irq);
+ return -retval;
+ }
+
+ return irq;
+}
+
+int
+bind_listening_port_to_irqhandler(
+ unsigned int remote_domain,
const char *devname,
driver_intr_t handler,
void *arg,
@@ -358,7 +442,7 @@
unsigned int irq;
int retval;
- irq = bind_evtchn_to_irq(evtchn);
+ irq = bind_listening_port_to_irq(remote_domain);
intr_register_source(&xp->xp_pins[irq].xp_intsrc);
retval = intr_add_handler(devname, irq, NULL, handler, arg, irqflags, cookiep);
if (retval != 0) {
@@ -370,6 +454,29 @@
}
int
+bind_interdomain_evtchn_to_irqhandler(
+ unsigned int remote_domain,
+ unsigned int remote_port,
+ const char *devname,
+ driver_filter_t filter,
+ driver_intr_t handler,
+ unsigned long irqflags)
+{
+ unsigned int irq;
+ int retval;
+
+ irq = bind_interdomain_evtchn_to_irq(remote_domain, remote_port);
+ intr_register_source(&xp->xp_pins[irq].xp_intsrc);
+ retval = intr_add_handler(devname, irq, filter, handler, NULL, irqflags, NULL);
+ if (retval != 0) {
+ unbind_from_irq(irq);
+ return -retval;
+ }
+
+ return irq;
+}
+
+int
bind_virq_to_irqhandler(unsigned int virq,
unsigned int cpu,
const char *devname,
@@ -405,13 +512,14 @@
retval = intr_add_handler(devname, irq, NULL, handler, NULL, irqflags, NULL);
if (retval != 0) {
unbind_from_irq(irq);
- return retval;
+ return -retval;
}
return irq;
}
-void unbind_from_irqhandler(unsigned int irq, void *dev_id)
+void
+unbind_from_irqhandler(unsigned int irq, void *dev_id)
{
if (dev_id)
intr_remove_handler(dev_id); /* XXX */
@@ -420,7 +528,8 @@
#if 0
/* Rebind an evtchn so that it gets delivered to a specific cpu */
-static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
+static void
+rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
{
evtchn_op_t op = { .cmd = EVTCHNOP_bind_vcpu };
int evtchn;
@@ -789,14 +898,14 @@
return;
}
- synch_clear_bit(port, &s->evtchn_mask[0]);
+ synch_clear_bit(port, &s->evtchn_mask);
/*
* The following is basically the equivalent of 'hw_resend_irq'. Just
* like a real IO-APIC we 'lose the interrupt edge' if the channel is
* masked.
*/
- if (synch_test_bit(port, &s->evtchn_pending[0]) &&
+ if (synch_test_bit(port, &s->evtchn_pending) &&
!synch_test_and_set_bit(port / BITS_PER_LONG,
&vcpu_info->evtchn_pending_sel)) {
vcpu_info->evtchn_upcall_pending = 1;
@@ -912,6 +1021,13 @@
xp->xp_numintr = NR_IRQS;
bzero(xp->xp_pins, sizeof(struct xenpic_intsrc) * NR_IRQS);
+
+ /* We need to register our PIC's beforehand */
+ if (intr_register_pic(&xenpic_pirq_template))
+ panic("XEN: intr_register_pic() failure");
+ if (intr_register_pic(&xenpic_dynirq_template))
+ panic("XEN: intr_register_pic() failure");
+
/*
* Initialize the dynamic IRQ's - we initialize the structures, but
* we do not bind them (bind_evtchn_to_irqhandle() does this)
@@ -924,14 +1040,9 @@
tpin = &pin[dynirq_to_irq(i)];
tpin->xp_intsrc.is_pic = xp->xp_dynirq_pic;
tpin->xp_vector = dynirq_to_irq(i);
+
+ intr_register_source(&tpin->xp_intsrc);
}
-
- /* We need to register our PIC's beforehand */
- if (intr_register_pic(&xenpic_pirq_template))
- panic("XEN: intr_register_pic() failure");
- if (intr_register_pic(&xenpic_dynirq_template))
- panic("XEN: intr_register_pic() failure");
-
/*
* Now, we go ahead and claim every PIRQ there is.
*/
==== //depot/projects/xen31/sys/xen/xenbus/xenbus_comms.c#3 (text+ko) ====
@@ -194,7 +194,7 @@
if (xenbus_irq)
unbind_from_irqhandler(xenbus_irq, &xb_waitq);
- err = bind_evtchn_to_irqhandler(
+ err = bind_caller_port_to_irqhandler(
xen_start_info->store_evtchn, "xenbus", wake_waiting, NULL, INTR_TYPE_NET, NULL);
if (err <= 0) {
printk("XENBUS request irq failed %i\n", err);
==== //depot/projects/xen31/sys/xen/xenbus/xenbus_xs.c#6 (text+ko) ====
@@ -145,12 +145,12 @@
char *body;
int i;
- if (HYPERVISOR_shared_info->evtchn_mask[curcpu] & 1) {
+ if (HYPERVISOR_shared_info->evtchn_mask[curcpu] & 0x2) {
/*
* Give other domain time to run :-/
*/
- for (i = 0; i < 1000; i++)
- HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
+ for (i = 0; i < 5000; i++)
+ HYPERVISOR_yield();
xs_process_msg();
}
More information about the p4-projects
mailing list