Port-xen archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: interrupt cleanup #1
Cherry G. Mathew <cherry%zyx.in@localhost> writes:
> Hello Xen,
>
>
> Here's a first preview patch - it's just API reshuffling, but I'd be
> grateful if people could test it both on domU and dom0.
>
Hello - here's a version easier to patch:
Many thanks,
--
~cherry
Index: arch/x86/include/intr.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/include/intr.h,v
retrieving revision 1.51
diff -u -r1.51 intr.h
--- arch/x86/include/intr.h 16 Jul 2017 14:02:48 -0000 1.51
+++ arch/x86/include/intr.h 20 Oct 2017 00:47:12 -0000
@@ -124,11 +124,11 @@
void *ih_realarg;
struct intrhand *ih_next;
struct intrhand **ih_prevp;
-#if !defined(XEN)
int ih_pin;
int ih_slot;
-#else
+#if defined(XEN)
struct intrhand *ih_evt_next;
+ int pic_type;
#endif
struct cpu_info *ih_cpu;
};
Index: arch/x86/include/pic.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/include/pic.h,v
retrieving revision 1.8
diff -u -r1.8 pic.h
--- arch/x86/include/pic.h 27 Apr 2015 07:03:58 -0000 1.8
+++ arch/x86/include/pic.h 20 Oct 2017 00:47:12 -0000
@@ -34,8 +34,10 @@
#define PIC_MSI 3
#define PIC_MSIX 4
#define PIC_SOFT 5
+#define PIC_XEN 6
extern struct pic i8259_pic;
extern struct pic local_pic;
extern struct pic softintr_pic;
+extern struct pic xen_pic;
#endif
Index: arch/x86/isa/isa_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/isa/isa_machdep.c,v
retrieving revision 1.36
diff -u -r1.36 isa_machdep.c
--- arch/x86/isa/isa_machdep.c 21 Jul 2017 12:27:48 -0000 1.36
+++ arch/x86/isa/isa_machdep.c 20 Oct 2017 00:47:35 -0000
@@ -245,7 +245,7 @@
mpih |= APIC_IRQ_LEGACY_IRQ(irq);
- evtch = xen_intr_map((int *)&mpih, type); /* XXX: legacy - xen just tosses irq back at us */
+ evtch = xen_pirq_alloc((intr_handle_t *)&mpih, type); /* XXX: legacy - xen just tosses irq back at us */
if (evtch == -1)
return NULL;
#if NIOAPIC > 0
Index: arch/x86/pci/pciide_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/pci/pciide_machdep.c,v
retrieving revision 1.16
diff -u -r1.16 pciide_machdep.c
--- arch/x86/pci/pciide_machdep.c 15 Oct 2016 16:46:14 -0000 1.16
+++ arch/x86/pci/pciide_machdep.c 20 Oct 2017 00:47:36 -0000
@@ -61,6 +61,7 @@
#include <machine/mpbiosvar.h>
#endif
+#ifdef __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH
void *
pciide_machdep_compat_intr_establish(device_t dev,
const struct pci_attach_args *pa, int chan, int (*func)(void *),
@@ -96,7 +97,9 @@
PCIIDE_CHANNEL_NAME(chan), irq);
return cookie;
}
+#endif /* __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH */
+#ifdef __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_DISESTABLISH
void
pciide_machdep_compat_intr_disestablish(device_t dev, pci_chipset_tag_t pc,
int chan, void *cookie)
@@ -104,3 +107,4 @@
isa_intr_disestablish(NULL, cookie);
return;
}
+#endif /* __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_DISESTABLISH */
Index: arch/x86/x86/idt.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/x86/idt.c,v
retrieving revision 1.5
diff -u -r1.5 idt.c
--- arch/x86/x86/idt.c 7 Aug 2017 17:10:09 -0000 1.5
+++ arch/x86/x86/idt.c 20 Oct 2017 00:47:37 -0000
@@ -75,9 +75,12 @@
#include <machine/segments.h>
+/* On xen PV this is just numberspace management - used in x86/intr.c */
#if !defined(XEN)
struct gate_descriptor *idt;
+#endif
+
static char idt_allocmap[NIDT];
/*
@@ -120,8 +123,10 @@
{
KASSERT(idt_allocmap[vec] == 1);
+#if !defined(XEN)
setgate(&idt[vec], function, 0, SDT_SYS386IGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
+#endif
}
/*
@@ -131,8 +136,9 @@
idt_vec_free(int vec)
{
+#if !defined(XEN)
unsetgate(&idt[vec]);
+#endif
idt_allocmap[vec] = 0;
}
-#endif /* !defined(XEN) */
Index: arch/x86/x86/ioapic.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/x86/ioapic.c,v
retrieving revision 1.52
diff -u -r1.52 ioapic.c
--- arch/x86/x86/ioapic.c 27 Jul 2015 15:45:20 -0000 1.52
+++ arch/x86/x86/ioapic.c 20 Oct 2017 00:47:38 -0000
@@ -565,6 +565,25 @@
pp->ip_vector = idtvec;
pp->ip_cpu = ci;
apic_set_redir(sc, pin, idtvec, ci);
+
+#if defined(XEN)
+ /*
+ * This is kludgy, and not the right place, but we can't bind
+ * before the routing has been set to the appropriate 'vector'.
+ * in x86/intr.c, this is done after idt_vec_set(), where this
+ * would have been more appropriate to put this.
+ */
+
+ int port, irq;
+ irq = vect2irq[idtvec];
+ port = bind_pirq_to_evtch(irq);
+ KASSERT(port < NR_EVENT_CHANNELS);
+
+ irq2port[irq] = port;
+
+ xen_atomic_set_bit(&ci->ci_evtmask[0], port);
+#endif
+
}
static void
@@ -573,6 +592,16 @@
{
ioapic_hwmask(pic, pin);
+
+#if defined(XEN)
+ int port, irq;
+ irq = vect2irq[idtvec];
+ port = bind_pirq_to_evtch(irq);
+ port = unbind_pirq_from_evtch(irq);
+
+ KASSERT(port < NR_EVENT_CHANNELS);
+#endif
+
}
#ifdef DDB
Index: arch/xen/conf/files.xen
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/conf/files.xen,v
retrieving revision 1.153
diff -u -r1.153 files.xen
--- arch/xen/conf/files.xen 9 Aug 2017 18:48:53 -0000 1.153
+++ arch/xen/conf/files.xen 20 Oct 2017 00:47:49 -0000
@@ -137,4 +137,5 @@
file arch/xen/x86/consinit.c machdep
file arch/x86/x86/identcpu.c machdep
file arch/xen/x86/intr.c machdep
+file arch/xen/x86/pintr.c machdep & dom0ops
file arch/xen/x86/xen_ipi.c multiprocessor
@@ -231,7 +233,7 @@
include "dev/i2o/files.i2o"
include "dev/pci/files.pci"
include "dev/pci/files.agp"
-file arch/xen/xen/pciide_machdep.c pciide_common
+file arch/x86/pci/pciide_machdep.c pciide_common
device pciback {unit = -1}
attach pciback at pci
@@ -383,7 +385,9 @@
file arch/xen/xen/privcmd.c dom0ops
file arch/xen/x86/xen_shm_machdep.c dom0ops
file arch/x86/pci/pci_machdep.c hypervisor & pci & dom0ops
-file arch/xen/xen/pci_intr_machdep.c hypervisor & pci
+file arch/x86/pci/pci_intr_machdep.c hypervisor & pci
+file arch/x86/pci/pci_msi_machdep.c hypervisor & pci
+file arch/x86/pci/msipic.c hypervisor & pci
file arch/x86/isa/isa_machdep.c hypervisor & dom0ops
file arch/xen/xen/xenevt.c xenevt & dom0ops
file arch/xen/xen/xennetback_xenbus.c xvif
Index: arch/xen/include/evtchn.h
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/include/evtchn.h,v
retrieving revision 1.24
diff -u -r1.24 evtchn.h
--- arch/xen/include/evtchn.h 16 Jul 2017 05:03:36 -0000 1.24
+++ arch/xen/include/evtchn.h 20 Oct 2017 00:47:49 -0000
@@ -44,6 +44,9 @@
int event_set_handler(int, int (*func)(void *), void *, int, const char *);
int event_remove_handler(int, int (*func)(void *), void *);
+void xen_channel_free(evtchn_port_t);
+void xen_channel_set(evtchn_port_t, void *, int, int);
+
struct cpu_info;
struct intrhand;
void event_set_iplhandler(struct cpu_info *, struct intrhand *, int);
@@ -64,6 +67,7 @@
int evtch;
int (*func)(void *);
void *arg;
+ int pic_type;
};
struct pintrhand *pirq_establish(int, int, int (*)(void *), void *, int,
Index: arch/xen/include/intr.h
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/include/intr.h,v
retrieving revision 1.42
diff -u -r1.42 intr.h
--- arch/xen/include/intr.h 16 Jul 2017 14:02:48 -0000 1.42
+++ arch/xen/include/intr.h 20 Oct 2017 00:47:49 -0000
@@ -58,18 +58,21 @@
struct evcnt ev_evcnt; /* interrupt counter */
struct cpu_info *ev_cpu; /* cpu on which this event is bound */
char ev_evname[32]; /* event counter name */
+ void (*ist_entry); /* stub handler for this channel */
+ int slot; /* Slot corresponding to entry */
+ int level; /* IPL_XXX interrupt priority */
};
extern struct intrstub xenev_stubs[];
-
+extern int irq2vect[256];
+extern int vect2irq[256];
+extern int irq2port[NR_EVENT_CHANNELS];
#ifdef MULTIPROCESSOR
int xen_intr_biglock_wrapper(void *);
#endif
-int xen_intr_map(int *, int);
-struct pic *intr_findpic(int);
-void intr_add_pcibus(struct pcibus_attach_args *);
+int xen_pirq_alloc(intr_handle_t *, int);
#ifdef MULTIPROCESSOR
void xen_ipi_init(void);
Index: arch/xen/x86/intr.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/x86/intr.c,v
retrieving revision 1.32
diff -u -r1.32 intr.c
--- arch/xen/x86/intr.c 16 Jul 2017 06:14:24 -0000 1.32
+++ arch/xen/x86/intr.c 20 Oct 2017 00:47:50 -0000
@@ -113,6 +113,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/kmem.h>
#include <sys/syslog.h>
#include <sys/device.h>
#include <sys/malloc.h>
@@ -140,6 +141,7 @@
struct intrstub x2apic_level_stubs[MAX_INTR_SOURCES] = {{0,0}};
#include <machine/i82093var.h>
+int irq2port[NR_EVENT_CHANNELS] = {0};
int irq2vect[256] = {0};
int vect2irq[256] = {0};
#endif /* NIOAPIC */
@@ -155,6 +157,44 @@
#include <dev/pci/ppbreg.h>
#endif
+const char * /* XXX: transitional - will axe this for x86/intr.c */
+intr_string(intr_handle_t ih, char *buf, size_t len)
+{
+#if NIOAPIC > 0
+ struct ioapic_softc *pic;
+#endif
+
+ if (ih == 0)
+ panic("%s: bogus handle 0x%" PRIx64, __func__, ih);
+
+#if NIOAPIC > 0
+ if (ih & APIC_INT_VIA_APIC) {
+ pic = ioapic_find(APIC_IRQ_APIC(ih));
+ if (pic != NULL) {
+ snprintf(buf, len, "%s pin %d",
+ device_xname(pic->sc_dev), APIC_IRQ_PIN(ih));
+ } else {
+ snprintf(buf, len,
+ "apic %d int %d (irq %d)",
+ APIC_IRQ_APIC(ih),
+ APIC_IRQ_PIN(ih),
+ APIC_IRQ_LEGACY_IRQ(ih));
+ }
+ } else
+ snprintf(buf, len, "irq %d", APIC_IRQ_LEGACY_IRQ(ih));
+#else
+
+ snprintf(buf, len, "irq %d" APIC_IRQ_LEGACY_IRQ(ih));
+#endif
+ return buf;
+
+}
+
+void
+intr_free_io_intrsource(const char *intrid)
+{
+ /* XXX: Transitional - will axe for x86/intr.c */
+}
/*
* Fake interrupt handler structures for the benefit of symmetry with
* other interrupt sources.
@@ -207,6 +247,26 @@
struct pintrhand *ih;
int evtchn;
char evname[16];
+
+ if (pic->pic_type == PIC_XEN) {
+ struct intrhand *rih;
+ event_set_handler(pin, handler,
+ arg, IPL_CLOCK, "clock");
+
+ rih = kmem_zalloc(sizeof(struct intrhand),
+ cold ? KM_NOSLEEP : KM_SLEEP);
+ if (rih == NULL) {
+ printf("%s: can't allocate handler info\n", __func__);
+ return NULL;
+ }
+
+ rih->ih_pin = pin; /* port */
+ rih->ih_fun = handler;
+ rih->ih_arg = arg;
+ rih->pic_type = pic->pic_type;
+ return rih;
+ } /* Else we assume pintr */
+
#ifdef DIAGNOSTIC
if (legacy_irq != -1 && (legacy_irq < 0 || legacy_irq > 15))
panic("intr_establish: bad legacy IRQ value");
@@ -227,64 +287,12 @@
} else
snprintf(evname, sizeof(evname), "irq%d", legacy_irq);
- evtchn = xen_intr_map(&legacy_irq, type);
+ evtchn = xen_pirq_alloc((intr_handle_t *)&legacy_irq, type);
ih = pirq_establish(legacy_irq & 0xff, evtchn, handler, arg, level,
evname);
return ih;
}
-int
-xen_intr_map(int *pirq, int type)
-{
- int irq = *pirq;
-#if NIOAPIC > 0
- extern struct cpu_info phycpu_info_primary; /* XXX */
- /*
- * The hypervisor has already allocated vectors and IRQs for the
- * devices. Reusing the same IRQ doesn't work because as we bind
- * them for each devices, we can't then change the route entry
- * of the next device if this one used this IRQ. The easiest is
- * to allocate IRQs top-down, starting with a high number.
- * 250 and 230 have been tried, but got rejected by Xen.
- *
- * Xen 3.5 also rejects 200. Try out all values until Xen accepts
- * or none is available.
- */
- static int xen_next_irq = 200;
- struct ioapic_softc *ioapic = ioapic_find(APIC_IRQ_APIC(*pirq));
- struct pic *pic = &ioapic->sc_pic;
- int pin = APIC_IRQ_PIN(*pirq);
- physdev_op_t op;
-
- if (*pirq & APIC_INT_VIA_APIC) {
- irq = vect2irq[ioapic->sc_pins[pin].ip_vector];
- if (ioapic->sc_pins[pin].ip_vector == 0 || irq == 0) {
- /* allocate IRQ */
- irq = APIC_IRQ_LEGACY_IRQ(*pirq);
- if (irq <= 0 || irq > 15)
- irq = xen_next_irq--;
-retry:
- /* allocate vector and route interrupt */
- op.cmd = PHYSDEVOP_ASSIGN_VECTOR;
- op.u.irq_op.irq = irq;
- if (HYPERVISOR_physdev_op(&op) < 0) {
- irq = xen_next_irq--;
- if (xen_next_irq == 15)
- panic("PHYSDEVOP_ASSIGN_VECTOR irq %d", irq);
- goto retry;
- }
- irq2vect[irq] = op.u.irq_op.vector;
- vect2irq[op.u.irq_op.vector] = irq;
- pic->pic_addroute(pic, &phycpu_info_primary, pin,
- op.u.irq_op.vector, type);
- }
- *pirq &= ~0xff;
- *pirq |= irq;
- }
-#endif /* NIOAPIC */
- return bind_pirq_to_evtch(irq);
-}
-
void
intr_disestablish(struct intrhand *ih)
{
Index: arch/xen/x86/xen_ipi.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/x86/xen_ipi.c,v
retrieving revision 1.20
diff -u -r1.20 xen_ipi.c
--- arch/xen/x86/xen_ipi.c 7 Jul 2016 06:55:40 -0000 1.20
+++ arch/xen/x86/xen_ipi.c 20 Oct 2017 00:47:50 -0000
@@ -82,12 +82,17 @@
xen_ipi_generic,
};
-static void
-xen_ipi_handler(struct cpu_info *ci, struct intrframe *regs)
+static int
+xen_ipi_handler(void *arg)
{
uint32_t pending;
int bit;
+ struct cpu_info *ci;
+ struct intrframe *regs;
+ ci = curcpu();
+ regs = arg;
+
pending = atomic_swap_32(&ci->ci_ipis, 0);
KDASSERT((pending >> XEN_NIPIS) == 0);
@@ -102,6 +107,8 @@
/* NOTREACHED */
}
}
+
+ return 0;
}
/* Must be called once for every cpu that expects to send/recv ipis */
@@ -122,9 +129,9 @@
KASSERT(evtchn != -1 && evtchn < NR_EVENT_CHANNELS);
- if (0 != event_set_handler(evtchn, (int (*)(void *))xen_ipi_handler,
- ci, IPL_HIGH, "ipi")) {
- panic("event_set_handler(...) KPI violation\n");
+ if(intr_establish_xname(0, &xen_pic, evtchn, IST_LEVEL, IPL_HIGH,
+ xen_ipi_handler, ci, true, "ipi") == NULL) {
+ panic("%s: unable to register ipi handler\n", __func__);
/* NOTREACHED */
}
Index: arch/xen/xen/clock.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/xen/clock.c,v
retrieving revision 1.64
diff -u -r1.64 clock.c
--- arch/xen/xen/clock.c 12 Jun 2016 09:08:09 -0000 1.64
+++ arch/xen/xen/clock.c 20 Oct 2017 00:47:50 -0000
@@ -49,7 +49,8 @@
#include <dev/clock_subr.h>
#include <x86/rtc.h>
-static int xen_timer_handler(void *, struct intrframe *);
+static int xen_timer_handler(void *);
+static struct intrhand *ih;
/* A timecounter: Xen system_time extrapolated with a TSC. */
u_int xen_get_timecount(struct timecounter*);
@@ -509,7 +510,7 @@
KASSERT(evtch != -1);
hypervisor_mask_event(evtch);
- event_remove_handler(evtch, (int (*)(void *))xen_timer_handler, ci);
+ intr_disestablish(ih);
aprint_verbose("Xen clock: removed event channel %d\n", evtch);
}
@@ -522,8 +523,11 @@
evtch = bind_virq_to_evtch(VIRQ_TIMER);
KASSERT(evtch != -1);
- event_set_handler(evtch, (int (*)(void *))xen_timer_handler,
- ci, IPL_CLOCK, "clock");
+ ih = intr_establish_xname(0, &xen_pic, evtch, IST_LEVEL, IPL_CLOCK,
+ xen_timer_handler, ci, true, "clock");
+
+ KASSERT(ih != NULL);
+
hypervisor_enable_event(evtch);
aprint_verbose("Xen clock: using event channel %d\n", evtch);
@@ -531,11 +535,12 @@
/* ARGSUSED */
static int
-xen_timer_handler(void *arg, struct intrframe *regs)
+xen_timer_handler(void *arg)
{
int64_t delta;
struct cpu_info *ci = curcpu();
- KASSERT(arg == ci);
+ struct intrframe *regs = arg;
+
int err;
again:
mutex_enter(&tmutex);
Index: arch/xen/xen/evtchn.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/xen/evtchn.c,v
retrieving revision 1.73
diff -u -r1.73 evtchn.c
--- arch/xen/xen/evtchn.c 16 Jul 2017 14:02:48 -0000 1.73
+++ arch/xen/xen/evtchn.c 20 Oct 2017 00:47:51 -0000
@@ -115,6 +115,87 @@
};
#endif
+static void xen_evtchn_mask(struct pic *, int);
+static void xen_evtchn_unmask(struct pic *, int);
+static void xen_evtchn_addroute(struct pic *, struct cpu_info *, int, int, int);
+static void xen_evtchn_delroute(struct pic *, struct cpu_info *, int, int, int);
+static bool xen_evtchn_trymask(struct pic *, int);
+
+
+struct pic xen_pic = {
+ .pic_name = "xenev0",
+ .pic_type = PIC_XEN,
+ .pic_vecbase = 0,
+ .pic_apicid = 0,
+ .pic_lock = __SIMPLELOCK_UNLOCKED,
+ .pic_hwmask = xen_evtchn_mask,
+ .pic_hwunmask = xen_evtchn_unmask,
+ .pic_addroute = xen_evtchn_addroute,
+ .pic_delroute = xen_evtchn_delroute,
+ .pic_trymask = xen_evtchn_trymask,
+ .pic_level_stubs = xenev_stubs,
+ .pic_edge_stubs = xenev_stubs,
+};
+
+/*
+ * We try to stick to the traditional x86 PIC semantics wrt Xen
+ * events.
+ *
+ * PIC pins exist in a global namespace which may be hierarchical, and
+ * are mapped to a cpu bus concept called 'IRQ' numbers, which are
+ * also global, but linear. Thus a PIC, pin tuple will always map to
+ * an IRQ number. These tuples can alias to the same IRQ number, thus
+ * causing IRQ "sharing". IRQ numbers can be bound to specific CPUs,
+ * and to specific callback vector indices on the CPU called idt_vec,
+ * which are aliases to handlers meant to run on destination
+ * CPUs. This binding can also happen at interrupt time and resolved
+ * 'round-robin' between all CPUs, depending on the setup. In this
+ * case, all CPUs need to have identical idt_vec->handler mappings.
+ *
+ * The job of pic_addroute() is to setup this 'wiring' between the
+ * source pin, and the destination CPU handler, ideally on a specific
+ * CPU in MP systems (or 'round-robin').
+ *
+ * On Xen, a global namespace of 'events' exist, which are initially
+ * bound to nothing. This is similar to the relationship between
+ * realworld realworld IRQ numbers wrt PIC pins, since before routing,
+ * IRQ numbers by themselves have no causal connection setup with the
+ * real world. (Except for the hardwired cases on the PC Architecture,
+ * which we ignore for the purpose of this description).
+ *
+ * To be useful, events are bound to underlying real world events like
+ * IRQ lines, interdomain RPCs, "Virtual IRQ requests (eg: timer) or
+ * Inter Processor Interrupts. However, unlike PIC pins, the above set
+ * of namespaces are collisive and not mutually exclusive. This means
+ * that they need to be expressed as a tuple, indicating the
+ * namespace. There are two ways to do this - the first is to consider
+ * each namespace as a separate 'slave' PIC which maps pins to global
+ * 'IRQ's. Each slave PIC is then connected to a master PIC which does
+ * the final routing to the global event number.
+ * Thus the tuple will contain the pic handle and the pin
+ * number, for eg: pic_type == PIC_XEN_VIRQ, pin == VIRQ_TIMER, ...
+ *
+ * I felt that this scheme is unnecessarily complicated, especially
+ * since the handler code and EOI protocol for Xen events are all
+ * identical irrespective of the underlying source.
+ * I thus decided to map the namespace separation idea onto the
+ * interrupt "type" on a single virtual PIC.
+ * Thus we have:
+ * pic_type == PIC_XEN, type == IST_XEN_VIRQ, pin == VIRQ_TIMER, ...
+ *
+ * The job of pic_addroute() therefore is to make the causal
+ * connection between realworld events and an actual vcpu handler.
+ *
+ * In order to do this, we make the following conceptual mappings
+ * between real PICs and our imaginary one:
+ *
+ * pin => "real world event" (eg: VIRQ, PIRQ, IPI).
+ * type => IST_$NAMESPACE (eg: IST_VIRQ, IST_PIRQ, IST_IPI)
+ * IRQ => event number
+ * idt_vec => Constant. On PVHVM, this is a fixed per-VCPU vector.
+ *
+ */
+
int debug_port = -1;
// #define IRQ_DEBUG 4
@@ -359,6 +440,123 @@
#define PRIuCPUID "lu" /* XXX: move this somewhere more appropriate */
+void
+xen_channel_free(evtchn_port_t evtchn)
+{
+ KASSERT((evtchn > 0) && (evtchn < NR_EVENT_CHANNELS));
+
+ mutex_spin_enter(&evtchn_lock);
+ evtsource[evtchn]->ist_entry = NULL; /* XXX: confirm invalid */
+ evtsource[evtchn]->slot = -1;
+ mutex_spin_exit(&evtchn_lock);
+}
+
+void
+xen_channel_set(evtchn_port_t evtchn, void *stub, int slot, int level)
+{
+ KASSERT((evtchn > 0) && (evtchn < NR_EVENT_CHANNELS));
+ KASSERT(stub != NULL);
+
+ mutex_spin_enter(&evtchn_lock);
+ /* XXX: reset the corresponding evtmask */
+ evtsource[evtchn]->ist_entry = stub; /* XXX: confirm invalid */
+ evtsource[evtchn]->slot = slot;
+ evtsource[evtchn]->level = level;
+ mutex_spin_exit(&evtchn_lock);
+}
+
+/* PIC callbacks */
+/* pic "pin"s are conceptually mapped to event port numbers */
+static void
+xen_evtchn_mask(struct pic *pic, int pin)
+{
+ evtchn_port_t evtchn = pin;
+
+ KASSERT(pic->pic_type == PIC_XEN);
+ KASSERT(evtchn < NR_EVENT_CHANNELS);
+
+ hypervisor_mask_event(evtchn);
+
+}
+
+static void
+xen_evtchn_unmask(struct pic *pic, int pin)
+{
+ evtchn_port_t evtchn = pin;
+
+ KASSERT(pic->pic_type == PIC_XEN);
+ KASSERT(evtchn < NR_EVENT_CHANNELS);
+
+ hypervisor_unmask_event(evtchn);
+
+}
+
+
+static void
+xen_evtchn_addroute(struct pic *pic, struct cpu_info *ci, int pin, int idt_vec, int type)
+{
+
+ evtchn_port_t evtchn = pin;
+
+ /* Events are simulated as level triggered interrupts */
+ KASSERT(type == IST_LEVEL);
+
+ KASSERT(evtchn < NR_EVENT_CHANNELS);
+#if notyet
+ evtchn_port_t boundport = idt_vec;
+#endif
+
+ KASSERT(pic->pic_type == PIC_XEN);
+
+ xen_atomic_set_bit(&ci->ci_evtmask[0], evtchn);
+
+}
+
+static void
+xen_evtchn_delroute(struct pic *pic, struct cpu_info *ci, int pin, int idt_vec, int type)
+{
+ /*
+ * XXX: In the future, this is a great place to
+ * 'unbind' events to underlying events and cpus.
+ * For now, just disable interrupt servicing on this cpu for
+ * this pin aka cpu.
+ */
+ evtchn_port_t evtchn = pin;
+
+ /* Events are simulated as level triggered interrupts */
+ KASSERT(type == IST_LEVEL);
+
+ KASSERT(evtchn < NR_EVENT_CHANNELS);
+#if notyet
+ evtchn_port_t boundport = idt_vec;
+#endif
+
+ KASSERT(pic->pic_type == PIC_XEN);
+
+ xen_atomic_clear_bit(&ci->ci_evtmask[0], evtchn);
+}
+
+static bool
+xen_evtchn_trymask(struct pic *pic, int pin)
+{
+ volatile shared_info_t *s = HYPERVISOR_shared_info;
+
+ /* Already masked! */
+ if (xen_atomic_test_bit(&s->evtchn_mask[0], pin))
+ return true;
+
+#if notyet // XXX: Whole thing needs review. mask and pending don't sync
+ /* Pending - bail! */
+ if (xen_atomic_test_bit(&s->evtchn_pending[0], pin))
+ return false;
+
+ /* XXX: There's a race here - anything we can do about this ? */
+#endif
+ /* Mask it */
+ xen_atomic_set_bit(&s->evtchn_mask[0], pin);
+ return true;
+}
+
evtchn_port_t
bind_vcpu_to_evtch(cpuid_t vcpu)
{
Index: arch/xen/xen/if_xennet_xenbus.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/xen/if_xennet_xenbus.c,v
retrieving revision 1.70
diff -u -r1.70 if_xennet_xenbus.c
--- arch/xen/xen/if_xennet_xenbus.c 4 Mar 2017 19:11:01 -0000 1.70
+++ arch/xen/xen/if_xennet_xenbus.c 20 Oct 2017 00:47:51 -0000
@@ -180,7 +180,8 @@
unsigned int sc_evtchn;
void *sc_softintr;
-
+ struct intrhand *sc_ih;
+
grant_ref_t sc_tx_ring_gntref;
grant_ref_t sc_rx_ring_gntref;
@@ -422,7 +423,7 @@
DPRINTF(("%s: xennet_xenbus_detach\n", device_xname(self)));
s0 = splnet();
xennet_stop(ifp, 1);
- event_remove_handler(sc->sc_evtchn, &xennet_handler, sc);
+ intr_disestablish(sc->sc_ih);
/* wait for pending TX to complete, and collect pending RX packets */
xennet_handler(sc);
while (sc->sc_tx_ring.sring->rsp_prod != sc->sc_tx_ring.rsp_cons) {
@@ -513,8 +514,9 @@
goto abort_resume;
aprint_verbose_dev(dev, "using event channel %d\n",
sc->sc_evtchn);
- event_set_handler(sc->sc_evtchn, &xennet_handler, sc,
- IPL_NET, device_xname(dev));
+ sc->sc_ih = intr_establish_xname(0, &xen_pic, sc->sc_evtchn, IST_LEVEL, IPL_NET,
+ &xennet_handler, sc, true, device_xname(dev));
+ KASSERT(sc->sc_ih != NULL);
return true;
abort_resume:
@@ -635,7 +637,7 @@
*/
sc->sc_backend_status = BEST_SUSPENDED;
- event_remove_handler(sc->sc_evtchn, &xennet_handler, sc);
+ intr_disestablish(sc->sc_ih);
splx(s);
Index: arch/xen/xen/xbd_xenbus.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/xen/xbd_xenbus.c,v
retrieving revision 1.76
diff -u -r1.76 xbd_xenbus.c
--- arch/xen/xen/xbd_xenbus.c 5 Mar 2017 23:07:12 -0000 1.76
+++ arch/xen/xen/xbd_xenbus.c 20 Oct 2017 00:47:51 -0000
@@ -123,6 +123,8 @@
struct dk_softc sc_dksc; /* Must be first in this struct */
struct xenbus_device *sc_xbusd;
+ struct intrhand *sc_ih; /* Interrupt handler for this instance. */
+
blkif_front_ring_t sc_ring;
unsigned int sc_evtchn;
@@ -368,7 +370,8 @@
}
hypervisor_mask_event(sc->sc_evtchn);
- event_remove_handler(sc->sc_evtchn, &xbd_handler, sc);
+ intr_disestablish(sc->sc_ih);
+
while (xengnt_status(sc->sc_ring_gntref)) {
tsleep(xbd_xenbus_detach, PRIBIO, "xbd_ref", hz/2);
}
@@ -397,7 +400,7 @@
hypervisor_mask_event(sc->sc_evtchn);
sc->sc_backend_status = BLKIF_STATE_SUSPENDED;
- event_remove_handler(sc->sc_evtchn, xbd_handler, sc);
+ intr_disestablish(sc->sc_ih);
splx(s);
@@ -449,8 +452,9 @@
aprint_verbose_dev(dev, "using event channel %d\n",
sc->sc_evtchn);
- event_set_handler(sc->sc_evtchn, &xbd_handler, sc,
- IPL_BIO, device_xname(dev));
+ sc->sc_ih = intr_establish_xname(0, &xen_pic, sc->sc_evtchn, IST_LEVEL, IPL_BIO, &xbd_handler, sc, true, "clock");
+
+ KASSERT(sc->sc_ih != NULL);
again:
xbt = xenbus_transaction_start();
Index: arch/xen/xen/xbdback_xenbus.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/xen/xbdback_xenbus.c,v
retrieving revision 1.63
diff -u -r1.63 xbdback_xenbus.c
--- arch/xen/xen/xbdback_xenbus.c 26 Dec 2016 08:16:28 -0000 1.63
+++ arch/xen/xen/xbdback_xenbus.c 20 Oct 2017 00:47:52 -0000
@@ -170,6 +170,7 @@
bool xbdi_ro; /* is device read-only ? */
/* parameters for the communication */
unsigned int xbdi_evtchn;
+ struct intrhand *xbdi_ih;
/* private parameters for communication */
blkif_back_ring_proto_t xbdi_ring;
enum xbdi_proto xbdi_proto;
@@ -636,8 +637,9 @@
XENPRINTF(("xbdback %s: connect evchannel %d\n", xbusd->xbusd_path, xbdi->xbdi_evtchn));
xbdi->xbdi_evtchn = evop.u.bind_interdomain.local_port;
- event_set_handler(xbdi->xbdi_evtchn, xbdback_evthandler,
- xbdi, IPL_BIO, xbdi->xbdi_name);
+ xbdi->xbdi_ih = intr_establish_xname(0, &xen_pic, xbdi->xbdi_evtchn, IST_LEVEL, IPL_BIO,
+ xbdback_evthandler, xbdi, true, xbdi->xbdi_name);
+ KASSERT(xbdi->xbdi_ih != NULL);
aprint_verbose("xbd backend domain %d handle %#x (%d) "
"using event channel %d, protocol %s\n", xbdi->xbdi_domid,
xbdi->xbdi_handle, xbdi->xbdi_handle, xbdi->xbdi_evtchn, proto);
@@ -681,8 +683,7 @@
return;
}
hypervisor_mask_event(xbdi->xbdi_evtchn);
- event_remove_handler(xbdi->xbdi_evtchn, xbdback_evthandler,
- xbdi);
+ intr_disestablish(xbdi->xbdi_ih);
/* signal thread that we want to disconnect, then wait for it */
xbdi->xbdi_status = DISCONNECTING;
Index: arch/xen/xen/xencons.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/xen/xencons.c,v
retrieving revision 1.41
diff -u -r1.41 xencons.c
--- arch/xen/xen/xencons.c 25 Jul 2014 08:10:35 -0000 1.41
+++ arch/xen/xen/xencons.c 20 Oct 2017 00:47:52 -0000
@@ -90,6 +90,7 @@
static int xencons_isconsole = 0;
static struct xencons_softc *xencons_console_device = NULL;
+static struct intrhand *ih;
#define XENCONS_UNIT(x) (minor(x))
#define XENCONS_BURST 128
@@ -216,13 +217,8 @@
if (!xendomain_is_dom0()) {
evtch = xen_start_info.console_evtchn;
hypervisor_mask_event(evtch);
- if (event_remove_handler(evtch, xencons_handler,
- xencons_console_device) != 0) {
- aprint_error_dev(dev,
- "can't remove handler: xencons_handler\n");
- }
-
- aprint_verbose_dev(dev, "removed event channel %d\n", evtch);
+ intr_disestablish(ih);
+ aprint_verbose_dev(dev, "removed event channel %d\n", ih->ih_pin);
}
return true;
@@ -237,13 +233,15 @@
/* dom0 console resume is required only during first start-up */
if (cold) {
evtch = bind_virq_to_evtch(VIRQ_CONSOLE);
- event_set_handler(evtch, xencons_intr,
- xencons_console_device, IPL_TTY, "xencons");
+ ih = intr_establish_xname(0, &xen_pic, evtch, IST_LEVEL, IPL_TTY,
+ xencons_intr, xencons_console_device, true, "xencons");
+ KASSERT(ih != NULL);
}
} else {
evtch = xen_start_info.console_evtchn;
- event_set_handler(evtch, xencons_handler,
- xencons_console_device, IPL_TTY, "xencons");
+ ih = intr_establish_xname(0, &xen_pic, evtch, IST_LEVEL, IPL_TTY,
+ xencons_handler, xencons_console_device, true, "xencons");
+ KASSERT(ih != NULL);
}
if (evtch != -1) {
Index: arch/xen/xen/xennetback_xenbus.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/xen/xennetback_xenbus.c,v
retrieving revision 1.58
diff -u -r1.58 xennetback_xenbus.c
--- arch/xen/xen/xennetback_xenbus.c 15 Dec 2016 09:28:04 -0000 1.58
+++ arch/xen/xen/xennetback_xenbus.c 20 Oct 2017 00:47:53 -0000
@@ -112,7 +112,8 @@
uint8_t xni_enaddr[ETHER_ADDR_LEN];
/* remote domain communication stuff */
- unsigned int xni_evtchn; /* our even channel */
+ unsigned int xni_evtchn; /* our event channel */
+ struct intrhand *xni_ih;
netif_tx_back_ring_t xni_txring;
netif_rx_back_ring_t xni_rxring;
grant_handle_t xni_tx_ring_handle; /* to unmap the ring */
@@ -389,7 +390,8 @@
#endif
aprint_verbose_ifnet(&xneti->xni_if, "disconnecting\n");
hypervisor_mask_event(xneti->xni_evtchn);
- event_remove_handler(xneti->xni_evtchn, xennetback_evthandler, xneti);
+ intr_disestablish(xneti->xni_ih);
+
if (xneti->xni_softintr) {
softint_disestablish(xneti->xni_softintr);
xneti->xni_softintr = NULL;
@@ -549,8 +551,9 @@
xneti->xni_status = CONNECTED;
xen_wmb();
- event_set_handler(xneti->xni_evtchn, xennetback_evthandler,
- xneti, IPL_NET, xneti->xni_if.if_xname);
+ xneti->xni_ih = intr_establish_xname(0, &xen_pic, xneti->xni_evtchn, IST_LEVEL, IPL_NET,
+ xennetback_evthandler, xneti, true, xneti->xni_if.if_xname);
+ KASSERT(xneti->xni_ih != NULL);
xennetback_ifinit(&xneti->xni_if);
hypervisor_enable_event(xneti->xni_evtchn);
hypervisor_notify_via_evtchn(xneti->xni_evtchn);
Index: arch/xen/xenbus/xenbus_comms.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/xenbus/xenbus_comms.c,v
retrieving revision 1.15
diff -u -r1.15 xenbus_comms.c
--- arch/xen/xenbus/xenbus_comms.c 7 Jul 2016 06:55:40 -0000 1.15
+++ arch/xen/xenbus/xenbus_comms.c 20 Oct 2017 00:47:53 -0000
@@ -40,6 +40,7 @@
#include <xen/xen.h> /* for xendomain_is_dom0() */
#include <xen/hypervisor.h>
+#include <xen/pic.h>
#include <xen/evtchn.h>
#include <xen/xenbus.h>
#include "xenbus_comms.h"
@@ -51,6 +52,7 @@
#define XENPRINTF(x)
#endif
+static struct intrhand *ih;
struct xenstore_domain_interface *xenstore_interface;
extern int xenstored_ready;
@@ -220,7 +222,9 @@
evtchn = xen_start_info.store_evtchn;
- event_set_handler(evtchn, wake_waiting, NULL, IPL_TTY, "xenbus");
+ ih = intr_establish_xname(0, &xen_pic, evtchn, IST_LEVEL, IPL_TTY,
+ wake_waiting, NULL, true, "xenbus");
+
hypervisor_enable_event(evtchn);
aprint_verbose_dev(dev, "using event channel %d\n", evtchn);
@@ -235,7 +239,7 @@
evtchn = xen_start_info.store_evtchn;
hypervisor_mask_event(evtchn);
- event_remove_handler(evtchn, wake_waiting, NULL);
+ intr_disestablish(ih);
aprint_verbose_dev(dev, "removed event channel %d\n", evtchn);
}
Index: arch/xen/x86/pintr.c
===================================================================
RCS file: arch/xen/x86/pintr.c
diff -N arch/xen/x86/pintr.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ arch/xen/x86/pintr.c 20 Oct 2017 09:36:39 -0000
@@ -0,0 +1,208 @@
+/* NetBSD: intr.c,v 1.15 2004/04/10 14:49:55 kochi Exp */
+
+/*
+ * Copyright 2002 (c) Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Frank van der Linden for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)isa.c 7.2 (Berkeley) 5/13/91
+ */
+/*-
+ * Copyright (c) 1993, 1994 Charles Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)isa.c 7.2 (Berkeley) 5/13/91
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.32 2017/07/16 06:14:24 cherry Exp $");
+
+#include "opt_multiprocessor.h"
+#include "opt_xen.h"
+#include "isa.h"
+#include "pci.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/errno.h>
+#include <sys/cpu.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/i8259.h>
+#include <machine/pio.h>
+#include <xen/evtchn.h>
+#include <xen/intr.h>
+
+#include "acpica.h"
+#include "ioapic.h"
+#include "opt_mpbios.h"
+
+#if NIOAPIC > 0
+/* XXX: todo - compat with lapic.c and XEN for x2apic */
+bool x2apic_mode __read_mostly = false;
+/* for x86/ioapic.c */
+//struct intrstub ioapic_edge_stubs[MAX_INTR_SOURCES] = {{0,0,0}};
+//struct intrstub ioapic_level_stubs[MAX_INTR_SOURCES] = {{0,0,0}};
+//struct intrstub x2apic_edge_stubs[MAX_INTR_SOURCES] = {{0,0,0}};
+//struct intrstub x2apic_level_stubs[MAX_INTR_SOURCES] = {{0,0,0}};
+#include <machine/i82093var.h>
+//int irq2vect[256] = {0};
+//int vect2irq[256] = {0};
+#endif /* NIOAPIC */
+#if NACPICA > 0
+#include <machine/mpconfig.h>
+#include <machine/mpacpi.h>
+#endif
+#ifdef MPBIOS
+#include <machine/mpbiosvar.h>
+#endif
+
+#if NPCI > 0
+#include <dev/pci/ppbreg.h>
+#endif
+
+int
+xen_pirq_alloc(intr_handle_t *pirq, int type)
+{
+ int irq = *pirq;
+#if NIOAPIC > 0
+ extern struct cpu_info phycpu_info_primary; /* XXX */
+ /*
+ * The hypervisor has already allocated vectors and IRQs for the
+ * devices. Reusing the same IRQ doesn't work because as we bind
+ * them for each devices, we can't then change the route entry
+ * of the next device if this one used this IRQ. The easiest is
+ * to allocate IRQs top-down, starting with a high number.
+ * 250 and 230 have been tried, but got rejected by Xen.
+ *
+ * Xen 3.5 also rejects 200. Try out all values until Xen accepts
+ * or none is available.
+ */
+ static int xen_next_irq = 200;
+ struct ioapic_softc *ioapic = ioapic_find(APIC_IRQ_APIC(*pirq));
+ struct pic *pic = &ioapic->sc_pic;
+ int pin = APIC_IRQ_PIN(*pirq);
+ physdev_op_t op;
+
+ if (*pirq & APIC_INT_VIA_APIC) {
+ irq = vect2irq[ioapic->sc_pins[pin].ip_vector];
+ if (ioapic->sc_pins[pin].ip_vector == 0 || irq == 0) {
+ /* allocate IRQ */
+ irq = APIC_IRQ_LEGACY_IRQ(*pirq);
+ if (irq <= 0 || irq > 15)
+ irq = xen_next_irq--;
+retry:
+ /* allocate vector and route interrupt */
+ op.cmd = PHYSDEVOP_ASSIGN_VECTOR;
+ op.u.irq_op.irq = irq;
+ if (HYPERVISOR_physdev_op(&op) < 0) {
+ irq = xen_next_irq--;
+ if (xen_next_irq == 15)
+ panic("PHYSDEVOP_ASSIGN_VECTOR irq %d", irq);
+ goto retry;
+ }
+ irq2vect[irq] = op.u.irq_op.vector;
+ vect2irq[op.u.irq_op.vector] = irq;
+ pic->pic_addroute(pic, &phycpu_info_primary, pin,
+ op.u.irq_op.vector, type);
+ }
+ *pirq &= ~0xff;
+ *pirq |= irq;
+ }
+#endif /* NIOAPIC */
+ return irq2port[irq];
+}
Home |
Main Index |
Thread Index |
Old Index