]> xenbits.xensource.com Git - people/julieng/freebsd.git/commitdiff
xen/intr: Introduce xen_arch_intr.c
authorJulien Grall <julien.grall@citrix.com>
Tue, 20 Oct 2015 16:14:56 +0000 (17:14 +0100)
committerJulien Grall <julien.grall@citrix.com>
Mon, 2 Nov 2015 11:53:19 +0000 (11:53 +0000)
sys/amd64/include/xen/arch-intr.h [new file with mode: 0644]
sys/conf/files.amd64
sys/x86/include/xen/arch-intr.h [new file with mode: 0644]
sys/x86/xen/xen_arch_intr.c [new file with mode: 0644]
sys/xen/arch-intr.h [new file with mode: 0644]
sys/xen/evtchn/evtchnvar.h
sys/xen/xen_intr.c

diff --git a/sys/amd64/include/xen/arch-intr.h b/sys/amd64/include/xen/arch-intr.h
new file mode 100644 (file)
index 0000000..aadfd47
--- /dev/null
@@ -0,0 +1,6 @@
+/*-
+ * This file is in the public domain.
+ */
+/* $FreeBSD$ */
+
+#include <x86/xen/arch-intr.h>
index 3cb59cb9b90c291d33b5c66a3e87a65e428f2230..9132f7b56d3c6c6419e044bb642acfe332925d04 100644 (file)
@@ -617,6 +617,7 @@ x86/xen/hvm.c                       optional        xenhvm
 x86/xen/pv.c                   optional        xenhvm
 x86/xen/pvcpu_enum.c           optional        xenhvm
 x86/xen/xen_apic.c             optional        xenhvm
+x86/xen/xen_arch_intr.c                optional        xenhvm
 x86/xen/xen_nexus.c            optional        xenhvm
 x86/xen/xen_msi.c              optional        xenhvm
 x86/xen/xen_pci_bus.c          optional        xenhvm
diff --git a/sys/x86/include/xen/arch-intr.h b/sys/x86/include/xen/arch-intr.h
new file mode 100644 (file)
index 0000000..522e9ea
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _MACHINE_X86_XEN_ARCH_INTR_H_
+#define _MACHINE_X86_XEN_ARCH_INTR_H_
+
+#include <machine/intr_machdep.h>
+
+typedef struct intsrc xen_arch_isrc_t;
+
+#endif /* _MACHINE_X86_XEN_ARCH_INTR_H_ */
diff --git a/sys/x86/xen/xen_arch_intr.c b/sys/x86/xen/xen_arch_intr.c
new file mode 100644 (file)
index 0000000..439ed04
--- /dev/null
@@ -0,0 +1,253 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/interrupt.h>
+#include <sys/pcpu.h>
+#include <sys/smp.h>
+
+#include <machine/intr_machdep.h>
+#include <x86/apicvar.h>
+
+#include <xen/xen-os.h>
+#include <xen/arch-intr.h>
+
+/********************************* EVTCHN PIC ********************************/
+
+static void
+xen_intr_pic_enable_source(struct intsrc *isrc)
+{
+
+       xen_intr_enable_source((struct xenisrc *)isrc);
+}
+
+static void
+xen_intr_pic_disable_source(struct intsrc *isrc, int eoi)
+{
+
+       xen_intr_disable_source((struct xenisrc *)isrc, eoi == PIC_EOI);
+}
+
+static void
+xen_intr_pic_eoi_source(struct intsrc *isrc)
+{
+
+       xen_intr_eoi_source((struct xenisrc *)isrc);
+}
+
+static void
+xen_intr_pic_enable_intr(struct intsrc *isrc)
+{
+
+       xen_intr_enable_intr((struct xenisrc *)isrc);
+}
+
+static void
+xen_intr_pic_disable_intr(struct intsrc *isrc)
+{
+
+       xen_intr_disable_intr((struct xenisrc *)isrc);
+}
+
+static int
+xen_intr_pic_vector(struct intsrc *isrc)
+{
+
+       return (xen_intr_vector((struct xenisrc *)isrc));
+}
+
+static int
+xen_intr_pic_source_pending(struct intsrc *isrc)
+{
+
+       return (xen_intr_source_pending((struct xenisrc *)isrc));
+}
+
+static void
+xen_intr_pic_suspend(struct pic *pic)
+{
+
+       xen_intr_suspend();
+}
+
+static void
+xen_intr_pic_resume(struct pic *pic, bool suspend_cancelled)
+{
+
+       xen_intr_resume(suspend_cancelled);
+}
+
+static int
+xen_intr_pic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
+    enum intr_polarity pol)
+{
+
+       return (xen_intr_config_intr((struct xenisrc *)isrc, trig, pol));
+}
+
+
+static int
+xen_intr_pic_assign_cpu(struct intsrc *isrc, u_int apic_id)
+{
+
+       return (xen_intr_assign_cpu((struct xenisrc *)isrc,
+           apic_cpuid(apic_id)));
+}
+
+/**
+ * PIC interface for all event channel port types except physical IRQs.
+ */
+static struct pic xen_intr_pic = {
+       .pic_enable_source  = xen_intr_pic_enable_source,
+       .pic_disable_source = xen_intr_pic_disable_source,
+       .pic_eoi_source     = xen_intr_pic_eoi_source,
+       .pic_enable_intr    = xen_intr_pic_enable_intr,
+       .pic_disable_intr   = xen_intr_pic_disable_intr,
+       .pic_vector         = xen_intr_pic_vector,
+       .pic_source_pending = xen_intr_pic_source_pending,
+       .pic_suspend        = xen_intr_pic_suspend,
+       .pic_resume         = xen_intr_pic_resume,
+       .pic_config_intr    = xen_intr_pic_config_intr,
+       .pic_assign_cpu     = xen_intr_pic_assign_cpu
+};
+
+/****************************** PIRQ PIC *************************************/
+
+static void
+xen_intr_pirq_pic_enable_source(struct intsrc *isrc)
+{
+
+       xen_intr_pirq_enable_source((struct xenisrc *)isrc);
+}
+
+static void
+xen_intr_pirq_pic_disable_source(struct intsrc *isrc, int eoi)
+{
+
+       xen_intr_pirq_disable_source((struct xenisrc *)isrc, eoi == PIC_EOI);
+}
+
+static void
+xen_intr_pirq_pic_eoi_source(struct intsrc *isrc)
+{
+
+       xen_intr_pirq_eoi_source((struct xenisrc *)isrc);
+}
+
+static void
+xen_intr_pirq_pic_enable_intr(struct intsrc *isrc)
+{
+
+       xen_intr_pirq_enable_intr((struct xenisrc *)isrc);
+}
+
+static void
+xen_intr_pirq_pic_disable_intr(struct intsrc *isrc)
+{
+
+       xen_intr_pirq_disable_intr((struct xenisrc *)isrc);
+}
+
+static int
+xen_intr_pirq_pic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
+    enum intr_polarity pol)
+{
+
+       return (xen_intr_pirq_config_intr((struct xenisrc *)isrc, trig, pol));
+}
+
+/**
+ * PIC interface for all event channel representing
+ * physical interrupt sources.
+ */
+static struct pic xen_intr_pirq_pic = {
+       .pic_enable_source  = xen_intr_pirq_pic_enable_source,
+       .pic_disable_source = xen_intr_pirq_pic_disable_source,
+       .pic_eoi_source     = xen_intr_pirq_pic_eoi_source,
+       .pic_enable_intr    = xen_intr_pirq_pic_enable_intr,
+       .pic_disable_intr   = xen_intr_pirq_pic_disable_intr,
+       .pic_vector         = xen_intr_pic_vector,
+       .pic_source_pending = xen_intr_pic_source_pending,
+       .pic_config_intr    = xen_intr_pirq_pic_config_intr,
+       .pic_assign_cpu     = xen_intr_pic_assign_cpu
+};
+
+/****************************** ARCH wrappers ********************************/
+
+void
+xen_arch_intr_init(void)
+{
+
+       intr_register_pic(&xen_intr_pic);
+       intr_register_pic(&xen_intr_pirq_pic);
+}
+
+int
+xen_arch_intr_setup(struct xenisrc *isrc)
+{
+
+       KASSERT((intr_lookup_source(isrc->xi_vector) == NULL),
+           ("Trying to use an already allocated vector"));
+
+       if (isrc->xi_type == EVTCHN_TYPE_PIRQ)
+               isrc->xi_intsrc.is_pic = &xen_intr_pirq_pic;
+       else
+               isrc->xi_intsrc.is_pic = &xen_intr_pic;
+
+       return (intr_register_source(&isrc->xi_intsrc));
+}
+
+struct xenisrc *
+xen_arch_intr_lookup_source(int vector)
+{
+
+       return ((struct xenisrc *)intr_lookup_source(vector));
+}
+
+bool
+xen_arch_intr_has_handlers(struct xenisrc *isrc)
+{
+
+       return (isrc->xi_intsrc.is_handlers != 0);
+}
+
+void
+xen_arch_intr_execute_handlers(struct xenisrc *isrc, struct trapframe *frame)
+{
+
+       intr_execute_handlers(&isrc->xi_intsrc, frame);
+}
+
+int
+xen_arch_intr_add_handler(device_t dev, driver_filter_t filter,
+    driver_intr_t handler, void *arg, enum intr_type flags,
+    struct xenisrc *isrc)
+{
+       return (intr_add_handler(device_get_nameunit(dev), isrc->xi_vector,
+           filter, handler, arg, flags, &isrc->xi_cookie));
+}
+
+int
+xen_arch_intr_describe(struct xenisrc *isrc, const char *descr)
+{
+       return (intr_describe(isrc->xi_vector, isrc->xi_cookie, descr));
+}
+
+int
+xen_arch_intr_remove_handler(struct xenisrc *isrc)
+{
+       return (intr_remove_handler(isrc->xi_cookie));
+}
+
+int
+xen_arch_intr_event_bind(struct xenisrc *isrc, u_int cpu)
+{
+       return (intr_event_bind(isrc->xi_intsrc.is_event, cpu));
+}
diff --git a/sys/xen/arch-intr.h b/sys/xen/arch-intr.h
new file mode 100644 (file)
index 0000000..a1b65e2
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef _XEN_ARCH_INTR_H_
+#define _XEN_ARCH_INTR_H_
+
+#include <machine/xen/arch-intr.h>
+
+#include <xen/evtchn/evtchnvar.h>
+
+struct xenisrc {
+       xen_arch_isrc_t         xi_intsrc;
+       enum evtchn_type        xi_type;
+       int                     xi_cpu;         /* VCPU for delivery */
+       int                     xi_vector;      /* Global isrc vector number */
+       evtchn_port_t           xi_port;
+       int                     xi_pirq;
+       int                     xi_virq;
+       void                    *xi_cookie;
+       u_int                   xi_close:1;     /* close on unbind? */
+       u_int                   xi_activehi:1;
+       u_int                   xi_edgetrigger:1;
+       u_int                   xi_masked:1;
+};
+
+/***************** Functions called by the architecture code *****************/
+
+void   xen_intr_suspend(void);
+void   xen_intr_resume(bool suspend_cancelled);
+void   xen_intr_enable_source(struct xenisrc *isrc);
+void   xen_intr_disable_source(struct xenisrc *isrc, bool need_eoi);
+void   xen_intr_eoi_source(struct xenisrc *isrc);
+void   xen_intr_enable_intr(struct xenisrc *isrc);
+void   xen_intr_disable_intr(struct xenisrc *isrc);
+int    xen_intr_vector(struct xenisrc *isrc);
+int    xen_intr_source_pending(struct xenisrc *isrc);
+int    xen_intr_config_intr(struct xenisrc *isrc,
+            enum intr_trigger trig, enum intr_polarity pol);
+int    xen_intr_assign_cpu(struct xenisrc *isrc, u_int to_cpu);
+
+void   xen_intr_pirq_enable_source(struct xenisrc *isrc);
+void   xen_intr_pirq_disable_source(struct xenisrc *isrc, bool need_eoi);
+void   xen_intr_pirq_eoi_source(struct xenisrc *isrc);
+void   xen_intr_pirq_enable_intr(struct xenisrc *isrc);
+void   xen_intr_pirq_disable_intr(struct xenisrc *isrc);
+int    xen_intr_pirq_config_intr(struct xenisrc *isrc,
+           enum intr_trigger trig, enum intr_polarity pol);
+
+/******************* Functions implemented by each architecture **************/
+
+void   xen_arch_intr_init(void);
+int    xen_arch_intr_setup(struct xenisrc *isrc);
+struct xenisrc *xen_arch_intr_lookup_source(int vector);
+bool   xen_arch_intr_has_handlers(struct xenisrc *isrc);
+void   xen_arch_intr_execute_handlers(struct xenisrc *isrc,
+           struct trapframe *frame);
+int    xen_arch_intr_add_handler(device_t dev, driver_filter_t filter,
+           driver_intr_t handler, void *arg, enum intr_type flags,
+           struct xenisrc *isrc);
+int    xen_arch_intr_describe(struct xenisrc *isrc, const char *descr);
+int    xen_arch_intr_remove_handler(struct xenisrc *isrc);
+int    xen_arch_intr_event_bind(struct xenisrc *isrc, u_int cpu);
+
+#endif /* _XEN_ARCH_INTR_H_ */
index 8008d23297d3f8a4976bbc9a90f90c7b64b82d18..0da62aab0167b56741bea16cc1280b5b99f60fe2 100644 (file)
@@ -37,6 +37,8 @@
 #include <xen/hypervisor.h>
 #include <xen/interface/event_channel.h>
 
+#include <machine/xen/synch_bitops.h>
+
 enum evtchn_type {
        EVTCHN_TYPE_UNBOUND,
        EVTCHN_TYPE_PIRQ,
index 014050631a749e45255b3a7793fe9e3a3d4ae194..0cba754940d3418fa1e9416a36b5e8a2cba4732a 100644 (file)
@@ -49,18 +49,16 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm.h>
 #include <vm/pmap.h>
 
-#include <machine/intr_machdep.h>
-#include <x86/apicvar.h>
-#include <x86/apicreg.h>
 #include <machine/smp.h>
 #include <machine/stdarg.h>
+#include <machine/intr_machdep.h>
 
+#include <xen/xen-os.h>
+#include <xen/arch-intr.h>
 #include <machine/xen/synch_bitops.h>
-#include <machine/xen/xen-os.h>
 
 #include <xen/hypervisor.h>
 #include <xen/xen_intr.h>
-#include <xen/evtchn/evtchnvar.h>
 
 #include <dev/xen/xenpci/xenpcivar.h>
 #include <dev/pci/pcivar.h>
@@ -118,78 +116,8 @@ DPCPU_DECLARE(struct vcpu_info *, vcpu_info);
 
 #define        is_valid_evtchn(x)      ((x) != XEN_INVALID_EVTCHN)
 
-struct xenisrc {
-       struct intsrc   xi_intsrc;
-       enum evtchn_type xi_type;
-       int             xi_cpu;         /* VCPU for delivery. */
-       int             xi_vector;      /* Global isrc vector number. */
-       evtchn_port_t   xi_port;
-       int             xi_pirq;
-       int             xi_virq;
-       void            *xi_cookie;
-       u_int           xi_close:1;     /* close on unbind? */
-       u_int           xi_activehi:1;
-       u_int           xi_edgetrigger:1;
-       u_int           xi_masked:1;
-};
-
 #define ARRAY_SIZE(a)  (sizeof(a) / sizeof(a[0]))
 
-static void    xen_intr_suspend(struct pic *);
-static void    xen_intr_resume(struct pic *, bool suspend_cancelled);
-static void    xen_intr_enable_source(struct intsrc *isrc);
-static void    xen_intr_disable_source(struct intsrc *isrc, int eoi);
-static void    xen_intr_eoi_source(struct intsrc *isrc);
-static void    xen_intr_enable_intr(struct intsrc *isrc);
-static void    xen_intr_disable_intr(struct intsrc *isrc);
-static int     xen_intr_vector(struct intsrc *isrc);
-static int     xen_intr_source_pending(struct intsrc *isrc);
-static int     xen_intr_config_intr(struct intsrc *isrc,
-                    enum intr_trigger trig, enum intr_polarity pol);
-static int     xen_intr_assign_cpu(struct intsrc *isrc, u_int to_cpu);
-static int     xen_pic_assign_cpu(struct intsrc *isrc, u_int apic_id);
-
-static void    xen_intr_pirq_enable_source(struct intsrc *isrc);
-static void    xen_intr_pirq_disable_source(struct intsrc *isrc, int eoi);
-static void    xen_intr_pirq_eoi_source(struct intsrc *isrc);
-static void    xen_intr_pirq_enable_intr(struct intsrc *isrc);
-static void    xen_intr_pirq_disable_intr(struct intsrc *isrc);
-static int     xen_intr_pirq_config_intr(struct intsrc *isrc,
-                    enum intr_trigger trig, enum intr_polarity pol);
-
-/**
- * PIC interface for all event channel port types except physical IRQs.
- */
-struct pic xen_intr_pic = {
-       .pic_enable_source  = xen_intr_enable_source,
-       .pic_disable_source = xen_intr_disable_source,
-       .pic_eoi_source     = xen_intr_eoi_source,
-       .pic_enable_intr    = xen_intr_enable_intr,
-       .pic_disable_intr   = xen_intr_disable_intr,
-       .pic_vector         = xen_intr_vector,
-       .pic_source_pending = xen_intr_source_pending,
-       .pic_suspend        = xen_intr_suspend,
-       .pic_resume         = xen_intr_resume,
-       .pic_config_intr    = xen_intr_config_intr,
-       .pic_assign_cpu     = xen_pic_assign_cpu
-};
-
-/**
- * PIC interface for all event channel representing
- * physical interrupt sources.
- */
-struct pic xen_intr_pirq_pic = {
-       .pic_enable_source  = xen_intr_pirq_enable_source,
-       .pic_disable_source = xen_intr_pirq_disable_source,
-       .pic_eoi_source     = xen_intr_pirq_eoi_source,
-       .pic_enable_intr    = xen_intr_pirq_enable_intr,
-       .pic_disable_intr   = xen_intr_pirq_disable_intr,
-       .pic_vector         = xen_intr_vector,
-       .pic_source_pending = xen_intr_source_pending,
-       .pic_config_intr    = xen_intr_pirq_config_intr,
-       .pic_assign_cpu     = xen_pic_assign_cpu
-};
-
 static struct mtx       xen_intr_isrc_lock;
 static int              xen_intr_auto_vector_count;
 static struct xenisrc  *xen_intr_port_to_isrc[NR_EVENT_CHANNELS];
@@ -241,6 +169,11 @@ evtchn_cpu_unmask_port(u_int cpu, evtchn_port_t port)
        BIT_SET_ATOMIC(ENABLED_SETSIZE, port, &pcpu->evtchn_enabled);
 }
 
+/*
+ * XXX: FIXME. Use the arch intrcnt counter
+ */
+static DPCPU_DEFINE(u_long, xen_intrcnt);
+
 /**
  * Allocate and register a per-cpu Xen upcall interrupt counter.
  *
@@ -249,15 +182,21 @@ evtchn_cpu_unmask_port(u_int cpu, evtchn_port_t port)
 static void
 xen_intr_intrcnt_add(u_int cpu)
 {
+#if 0
        char buf[MAXCOMLEN + 1];
+#endif
        struct xen_intr_pcpu_data *pcpu;
 
        pcpu = DPCPU_ID_PTR(cpu, xen_intr_pcpu);
        if (pcpu->evtchn_intrcnt != NULL)
                return;
 
+       pcpu->evtchn_intrcnt = DPCPU_ID_PTR(cpu, xen_intrcnt);
+
+#if 0
        snprintf(buf, sizeof(buf), "cpu%d:xen", cpu);
        intrcnt_add(buf, &pcpu->evtchn_intrcnt);
+#endif
 }
 
 /**
@@ -281,10 +220,10 @@ xen_intr_find_unused_isrc(enum evtchn_type type)
                u_int vector;
 
                vector = FIRST_EVTCHN_INT + isrc_idx;
-               isrc = (struct xenisrc *)intr_lookup_source(vector);
+               isrc = xen_arch_intr_lookup_source(vector);
                if (isrc != NULL
                 && isrc->xi_type == EVTCHN_TYPE_UNBOUND) {
-                       KASSERT(isrc->xi_intsrc.is_handlers == 0,
+                       KASSERT(xen_arch_intr_has_handlers(isrc),
                            ("Free evtchn still has handlers"));
                        isrc->xi_type = type;
                        return (isrc);
@@ -306,6 +245,7 @@ xen_intr_alloc_isrc(enum evtchn_type type, int vector)
 {
        static int warned;
        struct xenisrc *isrc;
+       int ret;
 
        KASSERT(mtx_owned(&xen_intr_isrc_lock), ("Evtchn alloc lock not held"));
 
@@ -322,18 +262,21 @@ xen_intr_alloc_isrc(enum evtchn_type type, int vector)
                xen_intr_auto_vector_count++;
        }
 
-       KASSERT((intr_lookup_source(vector) == NULL),
-           ("Trying to use an already allocated vector"));
-
        mtx_unlock(&xen_intr_isrc_lock);
        isrc = malloc(sizeof(*isrc), M_XENINTR, M_WAITOK | M_ZERO);
-       isrc->xi_intsrc.is_pic =
-           (type == EVTCHN_TYPE_PIRQ) ? &xen_intr_pirq_pic : &xen_intr_pic;
        isrc->xi_vector = vector;
        isrc->xi_type = type;
-       intr_register_source(&isrc->xi_intsrc);
+
+       ret = xen_arch_intr_setup(isrc);
+
        mtx_lock(&xen_intr_isrc_lock);
 
+       if (!ret) {
+               printf("xen_intr_alloc: Unable to setup the interrupt\n");
+               free(isrc, M_XENINTR);
+               return (NULL);
+       }
+
        return (isrc);
 }
 
@@ -349,7 +292,7 @@ xen_intr_release_isrc(struct xenisrc *isrc)
 {
 
        mtx_lock(&xen_intr_isrc_lock);
-       if (isrc->xi_intsrc.is_handlers != 0) {
+       if (xen_arch_intr_has_handlers(isrc)) {
                mtx_unlock(&xen_intr_isrc_lock);
                return (EBUSY);
        }
@@ -435,7 +378,7 @@ xen_intr_bind_isrc(struct xenisrc **isrcp, evtchn_port_t local_port,
                 * unless specified otherwise, so shuffle them to balance
                 * the interrupt load.
                 */
-               xen_intr_assign_cpu(&isrc->xi_intsrc, intr_next_cpu());
+               xen_intr_assign_cpu(isrc, intr_next_cpu());
        }
 #endif
 
@@ -593,7 +536,7 @@ xen_intr_handle_upcall(struct trapframe *trap_frame)
                                ("Received unexpected event on vCPU#%d, event bound to vCPU#%d",
                                PCPU_GET(cpuid), isrc->xi_cpu));
 
-                       intr_execute_handlers(&isrc->xi_intsrc, trap_frame);
+                       xen_arch_intr_execute_handlers(isrc, trap_frame);
 
                        /*
                         * If this is the final port processed,
@@ -657,8 +600,7 @@ xen_intr_init(void *dummy __unused)
        else
                xen_intr_pirq_eoi_map_enabled = true;
 
-       intr_register_pic(&xen_intr_pic);
-       intr_register_pic(&xen_intr_pirq_pic);
+       xen_arch_intr_init();
 
        if (bootverbose)
                printf("Xen interrupt system initialized\n");
@@ -668,12 +610,10 @@ xen_intr_init(void *dummy __unused)
 SYSINIT(xen_intr_init, SI_SUB_INTR, SI_ORDER_SECOND, xen_intr_init, NULL);
 
 /*--------------------------- Common PIC Functions ---------------------------*/
-/**
- * Prepare this PIC for system suspension.
- */
-static void
-xen_intr_suspend(struct pic *unused)
+void
+xen_intr_suspend(void)
 {
+       /* Nothing to do on suspend */
 }
 
 static void
@@ -694,7 +634,7 @@ xen_rebind_ipi(struct xenisrc *isrc)
        isrc->xi_cpu = 0;
        xen_intr_port_to_isrc[bind_ipi.port] = isrc;
 
-       error = xen_intr_assign_cpu(&isrc->xi_intsrc, cpu);
+       error = xen_intr_assign_cpu(isrc, cpu);
        if (error)
                panic("unable to bind xen IPI to CPU#%d: %d",
                      cpu, error);
@@ -724,7 +664,7 @@ xen_rebind_virq(struct xenisrc *isrc)
        xen_intr_port_to_isrc[bind_virq.port] = isrc;
 
 #ifdef SMP
-       error = xen_intr_assign_cpu(&isrc->xi_intsrc, cpu);
+       error = xen_intr_assign_cpu(isrc, cpu);
        if (error)
                panic("unable to bind xen VIRQ#%d to CPU#%d: %d",
                      isrc->xi_virq, cpu, error);
@@ -733,11 +673,8 @@ xen_rebind_virq(struct xenisrc *isrc)
        evtchn_unmask_port(bind_virq.port);
 }
 
-/**
- * Return this PIC to service after being suspended.
- */
-static void
-xen_intr_resume(struct pic *unused, bool suspend_cancelled)
+void
+xen_intr_resume(bool suspend_cancelled)
 {
        shared_info_t *s = HYPERVISOR_shared_info;
        struct xenisrc *isrc;
@@ -771,7 +708,7 @@ xen_intr_resume(struct pic *unused, bool suspend_cancelled)
                u_int vector;
 
                vector = FIRST_EVTCHN_INT + isrc_idx;
-               isrc = (struct xenisrc *)intr_lookup_source(vector);
+               isrc = xen_arch_intr_lookup_source(vector);
                if (isrc != NULL) {
                        isrc->xi_port = 0;
                        switch (isrc->xi_type) {
@@ -794,10 +731,9 @@ xen_intr_resume(struct pic *unused, bool suspend_cancelled)
  *
  * \param isrc  The interrupt source to disable.
  */
-static void
-xen_intr_disable_intr(struct intsrc *base_isrc)
+void
+xen_intr_disable_intr(struct xenisrc *isrc)
 {
-       struct xenisrc *isrc = (struct xenisrc *)base_isrc;
 
        evtchn_mask_port(isrc->xi_port);
 }
@@ -810,10 +746,9 @@ xen_intr_disable_intr(struct intsrc *base_isrc)
  *
  * \return  The vector number corresponding to the given interrupt source.
  */
-static int
-xen_intr_vector(struct intsrc *base_isrc)
+int
+xen_intr_vector(struct xenisrc *isrc)
 {
-       struct xenisrc *isrc = (struct xenisrc *)base_isrc;
 
        return (isrc->xi_vector);
 }
@@ -826,8 +761,8 @@ xen_intr_vector(struct intsrc *base_isrc)
  *
  * \returns  0 if no events are pending, otherwise non-zero.
  */
-static int
-xen_intr_source_pending(struct intsrc *isrc)
+int
+xen_intr_source_pending(struct xenisrc *isrc)
 {
        /*
         * EventChannels are edge triggered and never masked.
@@ -845,8 +780,8 @@ xen_intr_source_pending(struct intsrc *isrc)
  *
  * \returns  0 if no events are pending, otherwise non-zero.
  */
-static int
-xen_intr_config_intr(struct intsrc *isrc, enum intr_trigger trig,
+int
+xen_intr_config_intr(struct xenisrc *isrc, enum intr_trigger trig,
     enum intr_polarity pol)
 {
        /* Configuration is only possible via the evtchn apis. */
@@ -861,14 +796,13 @@ xen_intr_config_intr(struct intsrc *isrc, enum intr_trigger trig,
  *
  * \returns  0 if successful, otherwise an errno.
  */
-static int
-xen_intr_assign_cpu(struct intsrc *base_isrc, u_int to_cpu)
+int
+xen_intr_assign_cpu(struct xenisrc *isrc, u_int to_cpu)
 {
 #ifdef SMP
        struct evtchn_bind_vcpu bind_vcpu;
-       struct xenisrc *isrc;
        u_int vcpu_id = cpu_to_vcpu_id(to_cpu);
-       int error;
+       int error, masked;
 
        if (!xen_support_evtchn_rebind())
                return (EOPNOTSUPP);
@@ -876,7 +810,6 @@ xen_intr_assign_cpu(struct intsrc *base_isrc, u_int to_cpu)
        xen_intr_intrcnt_add(to_cpu);
 
        mtx_lock(&xen_intr_isrc_lock);
-       isrc = (struct xenisrc *)base_isrc;
        if (!is_valid_evtchn(isrc->xi_port)) {
                mtx_unlock(&xen_intr_isrc_lock);
                return (EINVAL);
@@ -923,27 +856,17 @@ out:
 #endif
 }
 
-/* Wrapper of xen_intr_assign_cpu to use as pic callbacks */
-static int
-xen_pic_assign_cpu(struct intsrc *isrc, u_int apic_id)
-{
-       return xen_intr_assign_cpu(isrc, apic_cpuid(apic_id));
-}
-
 /*------------------- Virtual Interrupt Source PIC Functions -----------------*/
 /*
  * Mask a level triggered interrupt source.
  *
- * \param isrc  The interrupt source to mask (if necessary).
- * \param eoi   If non-zero, perform any necessary end-of-interrupt
- *              acknowledgements.
+ * \param isrc         The interrupt source to mask (if necessary).
+ * \param need_eoi     If true, perform any necessary end-of-interrupt
+ *                     acknowledgements.
  */
-static void
-xen_intr_disable_source(struct intsrc *base_isrc, int eoi)
+void
+xen_intr_disable_source(struct xenisrc *isrc, bool need_eoi)
 {
-       struct xenisrc *isrc;
-
-       isrc = (struct xenisrc *)base_isrc;
 
        /*
         * NB: checking if the event channel is already masked is
@@ -961,13 +884,9 @@ xen_intr_disable_source(struct intsrc *base_isrc, int eoi)
  *
  * \param isrc  The interrupt source to unmask (if necessary).
  */
-static void
-xen_intr_enable_source(struct intsrc *base_isrc)
+void
+xen_intr_enable_source(struct xenisrc *isrc)
 {
-       struct xenisrc *isrc;
-
-       isrc = (struct xenisrc *)base_isrc;
-
        if (isrc->xi_masked == 0)
                evtchn_unmask_port(isrc->xi_port);
 }
@@ -977,8 +896,8 @@ xen_intr_enable_source(struct intsrc *base_isrc)
  *
  * \param isrc  The interrupt source to EOI.
  */
-static void
-xen_intr_eoi_source(struct intsrc *base_isrc)
+void
+xen_intr_eoi_source(struct xenisrc *isrc)
 {
 }
 
@@ -987,10 +906,9 @@ xen_intr_eoi_source(struct intsrc *base_isrc)
  *
  * \param isrc  The interrupt source to enable.
  */
-static void
-xen_intr_enable_intr(struct intsrc *base_isrc)
+void
+xen_intr_enable_intr(struct xenisrc *isrc)
 {
-       struct xenisrc *isrc = (struct xenisrc *)base_isrc;
 
        evtchn_unmask_port(isrc->xi_port);
 }
@@ -1000,20 +918,17 @@ xen_intr_enable_intr(struct intsrc *base_isrc)
  * Mask a level triggered interrupt source.
  *
  * \param isrc  The interrupt source to mask (if necessary).
- * \param eoi   If non-zero, perform any necessary end-of-interrupt
+ * \param need_eoi  If true, perform any necessary end-of-interrupt
  *              acknowledgements.
  */
-static void
-xen_intr_pirq_disable_source(struct intsrc *base_isrc, int eoi)
+void
+xen_intr_pirq_disable_source(struct xenisrc *isrc, bool need_eoi)
 {
-       struct xenisrc *isrc;
-
-       isrc = (struct xenisrc *)base_isrc;
 
        if (isrc->xi_edgetrigger == 0)
                evtchn_mask_port(isrc->xi_port);
-       if (eoi == PIC_EOI)
-               xen_intr_pirq_eoi_source(base_isrc);
+       if (need_eoi)
+               xen_intr_pirq_eoi_source(isrc);
 }
 
 /*
@@ -1021,12 +936,9 @@ xen_intr_pirq_disable_source(struct intsrc *base_isrc, int eoi)
  *
  * \param isrc  The interrupt source to unmask (if necessary).
  */
-static void
-xen_intr_pirq_enable_source(struct intsrc *base_isrc)
+void
+xen_intr_pirq_enable_source(struct xenisrc *isrc)
 {
-       struct xenisrc *isrc;
-
-       isrc = (struct xenisrc *)base_isrc;
 
        if (isrc->xi_edgetrigger == 0)
                evtchn_unmask_port(isrc->xi_port);
@@ -1037,14 +949,11 @@ xen_intr_pirq_enable_source(struct intsrc *base_isrc)
  *
  * \param isrc  The interrupt source to EOI.
  */
-static void
-xen_intr_pirq_eoi_source(struct intsrc *base_isrc)
+void
+xen_intr_pirq_eoi_source(struct xenisrc *isrc)
 {
-       struct xenisrc *isrc;
        int error;
 
-       isrc = (struct xenisrc *)base_isrc;
-
        if (xen_test_bit(isrc->xi_pirq, xen_intr_pirq_eoi_map)) {
                struct physdev_eoi eoi = { .irq = isrc->xi_pirq };
 
@@ -1060,16 +969,13 @@ xen_intr_pirq_eoi_source(struct intsrc *base_isrc)
  *
  * \param isrc  The interrupt source to enable.
  */
-static void
-xen_intr_pirq_enable_intr(struct intsrc *base_isrc)
+void
+xen_intr_pirq_enable_intr(struct xenisrc *isrc)
 {
-       struct xenisrc *isrc;
        struct evtchn_bind_pirq bind_pirq;
        struct physdev_irq_status_query irq_status;
        int error;
 
-       isrc = (struct xenisrc *)base_isrc;
-
        if (!xen_intr_pirq_eoi_map_enabled) {
                irq_status.irq = isrc->xi_pirq;
                error = HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query,
@@ -1108,15 +1014,12 @@ xen_intr_pirq_enable_intr(struct intsrc *base_isrc)
  *
  * \param isrc  The interrupt source to disable.
  */
-static void
-xen_intr_pirq_disable_intr(struct intsrc *base_isrc)
+void
+xen_intr_pirq_disable_intr(struct xenisrc *isrc)
 {
-       struct xenisrc *isrc;
        struct evtchn_close close;
        int error;
 
-       isrc = (struct xenisrc *)base_isrc;
-
        evtchn_mask_port(isrc->xi_port);
 
        close.port = isrc->xi_port;
@@ -1141,11 +1044,10 @@ xen_intr_pirq_disable_intr(struct intsrc *base_isrc)
  *
  * \returns  0 if no events are pending, otherwise non-zero.
  */
-static int
-xen_intr_pirq_config_intr(struct intsrc *base_isrc, enum intr_trigger trig,
+int
+xen_intr_pirq_config_intr(struct xenisrc *isrc, enum intr_trigger trig,
     enum intr_polarity pol)
 {
-       struct xenisrc *isrc = (struct xenisrc *)base_isrc;
        struct physdev_setup_gsi setup_gsi;
        int error;
 
@@ -1298,7 +1200,7 @@ xen_intr_bind_virq(device_t dev, u_int virq, u_int cpu,
 
 #ifdef SMP
        if (error == 0)
-               error = intr_event_bind(isrc->xi_intsrc.is_event, cpu);
+               error = xen_arch_intr_event_bind(isrc, cpu);
 #endif
 
        if (error != 0) {
@@ -1318,7 +1220,7 @@ xen_intr_bind_virq(device_t dev, u_int virq, u_int cpu,
                 * masks manually so events can't fire on the wrong cpu
                 * during AP startup.
                 */
-               xen_intr_assign_cpu(&isrc->xi_intsrc, cpu);
+               xen_intr_assign_cpu(isrc, cpu);
        }
 #endif
 
@@ -1360,7 +1262,7 @@ xen_intr_alloc_and_bind_ipi(device_t dev, u_int cpu,
                                   dev, filter, NULL, NULL, flags,
                                   port_handlep);
        if (error == 0)
-               error = intr_event_bind(isrc->xi_intsrc.is_event, cpu);
+               error = xen_arch_intr_event_bind(isrc, cpu);
 
        if (error != 0) {
                evtchn_close_t close = { .port = bind_ipi.port };
@@ -1378,7 +1280,7 @@ xen_intr_alloc_and_bind_ipi(device_t dev, u_int cpu,
                 * masks manually so events can't fire on the wrong cpu
                 * during AP startup.
                 */
-               xen_intr_assign_cpu(&isrc->xi_intsrc, cpu);
+               xen_intr_assign_cpu(isrc, cpu);
        }
 
        /*
@@ -1473,7 +1375,7 @@ xen_release_msi(int vector)
        struct xenisrc *isrc;
        int ret;
 
-       isrc = (struct xenisrc *)intr_lookup_source(vector);
+       isrc = xen_arch_intr_lookup_source(vector);
        if (isrc == NULL)
                return (ENXIO);
 
@@ -1501,7 +1403,8 @@ xen_intr_describe(xen_intr_handle_t port_handle, const char *fmt, ...)
        va_start(ap, fmt);
        vsnprintf(descr, sizeof(descr), fmt, ap);
        va_end(ap);
-       return (intr_describe(isrc->xi_vector, isrc->xi_cookie, descr));
+
+       return (xen_arch_intr_describe(isrc, descr));
 }
 
 void
@@ -1518,7 +1421,7 @@ xen_intr_unbind(xen_intr_handle_t *port_handlep)
                return;
 
        if (isrc->xi_cookie != NULL)
-               intr_remove_handler(isrc->xi_cookie);
+               xen_arch_intr_remove_handler(isrc);
        xen_intr_release_isrc(isrc);
 }
 
@@ -1545,7 +1448,7 @@ xen_intr_port(xen_intr_handle_t handle)
        isrc = xen_intr_isrc(handle);
        if (isrc == NULL)
                return (0);
-       
+
        return (isrc->xi_port);
 }
 
@@ -1561,8 +1464,8 @@ xen_intr_add_handler(device_t dev, driver_filter_t filter,
        if (isrc == NULL || isrc->xi_cookie != NULL)
                return (EINVAL);
 
-       error = intr_add_handler(device_get_nameunit(dev), isrc->xi_vector,
-           filter, handler, arg, flags|INTR_EXCL, &isrc->xi_cookie);
+       error = xen_arch_intr_add_handler(dev, filter, handler, arg,
+           flags | INTR_EXCL, isrc);
        if (error != 0) {
                device_printf(dev,
                    "xen_intr_add_handler: intr_add_handler failed: %d\n",