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