summaryrefslogtreecommitdiffstats
path: root/sys/xen/evtchn
diff options
context:
space:
mode:
authorkmacy <kmacy@FreeBSD.org>2008-10-25 00:25:25 +0000
committerkmacy <kmacy@FreeBSD.org>2008-10-25 00:25:25 +0000
commitc3afb352a006f24c06fa3a10f75834d3e843e425 (patch)
tree669faac4f9624a849475dbf6ffff834ca12b464d /sys/xen/evtchn
parent62b23eaa56554d03da21df76b2ef3095e4aa84c6 (diff)
downloadFreeBSD-src-c3afb352a006f24c06fa3a10f75834d3e843e425.zip
FreeBSD-src-c3afb352a006f24c06fa3a10f75834d3e843e425.tar.gz
Merge basic SMP support from HEAD
Diffstat (limited to 'sys/xen/evtchn')
-rw-r--r--sys/xen/evtchn/evtchn.c93
1 files changed, 69 insertions, 24 deletions
diff --git a/sys/xen/evtchn/evtchn.c b/sys/xen/evtchn/evtchn.c
index c296664..a782f24 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>
@@ -28,6 +29,7 @@ __FBSDID("$FreeBSD$");
#include <machine/xen/synch_bitops.h>
#include <machine/xen/evtchn.h>
#include <machine/xen/hypervisor.h>
+#include <sys/smp.h>
@@ -101,27 +103,58 @@ enum {
IRQT_VIRQ,
IRQT_IPI,
IRQT_LOCAL_PORT,
- IRQT_CALLER_PORT
+ IRQT_CALLER_PORT,
+ _IRQT_COUNT
+
};
+
+#define _IRQT_BITS 4
+#define _EVTCHN_BITS 12
+#define _INDEX_BITS (32 - _IRQT_BITS - _EVTCHN_BITS)
+
/* Constructor for packed IRQ information. */
-#define mk_irq_info(type, index, evtchn) \
- (((uint32_t)(type) << 24) | ((uint32_t)(index) << 16) | (uint32_t)(evtchn))
+static inline uint32_t
+mk_irq_info(uint32_t type, uint32_t index, uint32_t evtchn)
+{
+
+ return ((type << (32 - _IRQT_BITS)) | (index << _EVTCHN_BITS) | evtchn);
+}
+
+/* Constructor for packed IRQ information. */
+
/* Convenient shorthand for packed representation of an unbound IRQ. */
#define IRQ_UNBOUND mk_irq_info(IRQT_UNBOUND, 0, 0)
-/* Accessor macros for packed IRQ information. */
-#define evtchn_from_irq(irq) ((uint16_t)(irq_info[irq]))
-#define index_from_irq(irq) ((uint8_t)(irq_info[irq] >> 16))
-#define type_from_irq(irq) ((uint8_t)(irq_info[irq] >> 24))
+
+/*
+ * Accessors for packed IRQ information.
+ */
+
+static inline unsigned int evtchn_from_irq(int irq)
+{
+ return irq_info[irq] & ((1U << _EVTCHN_BITS) - 1);
+}
+
+static inline unsigned int index_from_irq(int irq)
+{
+ return (irq_info[irq] >> _EVTCHN_BITS) & ((1U << _INDEX_BITS) - 1);
+}
+
+static inline unsigned int type_from_irq(int irq)
+{
+ return irq_info[irq] >> (32 - _IRQT_BITS);
+}
+
/* 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)];
@@ -131,9 +164,9 @@ static int irq_bindcount[NR_IRQS];
#define VALID_EVTCHN(_chn) ((_chn) != 0)
-#ifdef CONFIG_SMP
+#ifdef SMP
-static u8 cpu_evtchn[NR_EVENT_CHANNELS];
+static uint8_t cpu_evtchn[NR_EVENT_CHANNELS];
static unsigned long cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/BITS_PER_LONG];
#define active_evtchns(cpu,sh,idx) \
@@ -224,8 +257,10 @@ evtchn_do_upcall(struct intrframe *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];
+
notify_remote_via_irq(irq);
}
@@ -333,6 +368,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,
@@ -340,7 +378,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);
@@ -350,13 +387,16 @@ bind_virq_to_irq(unsigned int virq, unsigned int cpu)
}
irq_bindcount[irq]++;
-
+out:
mtx_unlock_spin(&irq_mapping_update_lock);
return irq;
}
-static int
+
+extern int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu);
+
+int
bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
{
struct evtchn_bind_ipi bind_ipi;
@@ -372,7 +412,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);
@@ -380,7 +419,6 @@ bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
bind_evtchn_to_cpu(evtchn, cpu);
}
-
irq_bindcount[irq]++;
out:
@@ -518,9 +556,8 @@ bind_ipi_to_irqhandler(unsigned int ipi,
driver_intr_t handler,
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, handler, NULL, irqflags, NULL);
@@ -742,6 +779,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 */
@@ -792,6 +831,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);
@@ -992,8 +1034,11 @@ evtchn_init(void *dummy __unused)
int i, cpu;
struct xenpic_intsrc *pin, *tpin;
- /* No VIRQ or IPI bindings. */
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
+
+ init_evtchn_cpu_bindings();
+
+ /* No VIRQ or IPI bindings. */
+ 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++)
@@ -1060,7 +1105,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