summaryrefslogtreecommitdiffstats
path: root/sys/xen/evtchn
diff options
context:
space:
mode:
authorkmacy <kmacy@FreeBSD.org>2008-10-23 07:20:43 +0000
committerkmacy <kmacy@FreeBSD.org>2008-10-23 07:20:43 +0000
commitb20c19bc667aef513fa9f5449df2d4a833e42d3d (patch)
tree8fc37a55848ad367da0d0d422b2b9a90e107edc2 /sys/xen/evtchn
parentea4a9c958548a61ba7a299ab941ae4794e09faf0 (diff)
downloadFreeBSD-src-b20c19bc667aef513fa9f5449df2d4a833e42d3d.zip
FreeBSD-src-b20c19bc667aef513fa9f5449df2d4a833e42d3d.tar.gz
Fix IPI support
Diffstat (limited to 'sys/xen/evtchn')
-rw-r--r--sys/xen/evtchn/evtchn.c41
1 files changed, 26 insertions, 15 deletions
diff --git a/sys/xen/evtchn/evtchn.c b/sys/xen/evtchn/evtchn.c
index 53b41ac..155b38e 100644
--- a/sys/xen/evtchn/evtchn.c
+++ b/sys/xen/evtchn/evtchn.c
@@ -18,6 +18,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/interrupt.h>
+#include <sys/pcpu.h>
#include <machine/cpufunc.h>
#include <machine/intr_machdep.h>
@@ -26,6 +27,7 @@ __FBSDID("$FreeBSD$");
#include <machine/xen/synch_bitops.h>
#include <machine/xen/evtchn.h>
#include <machine/xen/hypervisor.h>
+#include <sys/smp.h>
@@ -113,13 +115,14 @@ enum {
#define type_from_irq(irq) ((uint8_t)(irq_info[irq] >> 24))
/* IRQ <-> VIRQ mapping. */
-DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1};
/* IRQ <-> IPI mapping. */
-#ifndef NR_IPIS
+#ifndef NR_IPIS
+#ifdef SMP
+#error "NR_IPIS not defined"
+#endif
#define NR_IPIS 1
#endif
-DEFINE_PER_CPU(int, ipi_to_irq[NR_IPIS]) = {[0 ... NR_IPIS-1] = -1};
/* Bitmap indicating which PIRQs require Xen to be notified on unmask. */
static unsigned long pirq_needs_unmask_notify[NR_PIRQS/sizeof(unsigned long)];
@@ -222,8 +225,11 @@ evtchn_do_upcall(struct trapframe *frame)
void
ipi_pcpu(unsigned int cpu, int vector)
{
- int irq = per_cpu(ipi_to_irq, cpu)[vector];
+ int irq;
+ irq = per_cpu(ipi_to_irq, cpu)[vector];
+ irq = (pcpu_find((cpu))->pc_ipi_to_irq)[vector];
+
notify_remote_via_irq(irq);
}
@@ -331,6 +337,9 @@ bind_virq_to_irq(unsigned int virq, unsigned int cpu)
mtx_lock_spin(&irq_mapping_update_lock);
if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) {
+ if ((irq = find_unbound_irq()) < 0)
+ goto out;
+
bind_virq.virq = virq;
bind_virq.vcpu = cpu;
PANIC_IF(HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
@@ -338,7 +347,6 @@ bind_virq_to_irq(unsigned int virq, unsigned int cpu)
evtchn = bind_virq.port;
- irq = find_unbound_irq();
evtchn_to_irq[evtchn] = irq;
irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
@@ -348,7 +356,7 @@ bind_virq_to_irq(unsigned int virq, unsigned int cpu)
}
irq_bindcount[irq]++;
-
+out:
mtx_unlock_spin(&irq_mapping_update_lock);
return irq;
@@ -370,7 +378,6 @@ bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
PANIC_IF(HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind_ipi) != 0);
evtchn = bind_ipi.port;
- irq = find_unbound_irq();
evtchn_to_irq[evtchn] = irq;
irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
@@ -378,7 +385,6 @@ bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
bind_evtchn_to_cpu(evtchn, cpu);
}
-
irq_bindcount[irq]++;
out:
@@ -515,15 +521,15 @@ int
bind_ipi_to_irqhandler(unsigned int ipi,
unsigned int cpu,
const char *devname,
- driver_intr_t handler,
+ driver_filter_t filter,
unsigned long irqflags)
{
- unsigned int irq;
- int retval;
-
+ int irq, retval;
+
irq = bind_ipi_to_irq(ipi, cpu);
intr_register_source(&xp->xp_pins[irq].xp_intsrc);
- retval = intr_add_handler(devname, irq, NULL, handler, NULL, irqflags, NULL);
+ retval = intr_add_handler(devname, irq, filter, NULL,
+ NULL, irqflags, NULL);
if (retval != 0) {
unbind_from_irq(irq);
return -retval;
@@ -760,6 +766,8 @@ notify_remote_via_irq(int irq)
if (VALID_EVTCHN(evtchn))
notify_remote_via_evtchn(evtchn);
+ else
+ panic("invalid evtchn");
}
/* required for support of physical devices */
@@ -810,6 +818,9 @@ xenpic_pirq_enable_intr(struct intsrc *isrc)
bind_pirq.flags = probing_irq(irq) ? 0 : BIND_PIRQ__WILL_SHARE;
if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq) != 0) {
+#ifndef XEN_PRIVILEGED_GUEST
+ panic("unexpected pirq call");
+#endif
if (!probing_irq(irq)) /* Some failures are expected when probing. */
printf("Failed to obtain physical IRQ %d\n", irq);
mtx_unlock_spin(&irq_mapping_update_lock);
@@ -1037,7 +1048,7 @@ evtchn_init(void *dummy __unused)
struct xenpic_intsrc *pin, *tpin;
/* No VIRQ or IPI bindings. */
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ for (cpu = 0; cpu < mp_ncpus; cpu++) {
for (i = 0; i < NR_VIRQS; i++)
per_cpu(virq_to_irq, cpu)[i] = -1;
for (i = 0; i < NR_IPIS; i++)
@@ -1104,7 +1115,7 @@ evtchn_init(void *dummy __unused)
}
}
-SYSINIT(evtchn_init, SI_SUB_INTR, SI_ORDER_ANY, evtchn_init, NULL);
+SYSINIT(evtchn_init, SI_SUB_INTR, SI_ORDER_MIDDLE, evtchn_init, NULL);
/*
* irq_mapping_update_lock: in order to allow an interrupt to occur in a critical
* section, to set pcpu->ipending (etc...) properly, we
OpenPOWER on IntegriCloud