]> xenbits.xensource.com Git - people/julieng/freebsd.git/commitdiff
Revert "xen/intr: Rework the event channels handler to make it generic"
authorJulien Grall <julien.grall@citrix.com>
Tue, 20 Oct 2015 15:09:28 +0000 (16:09 +0100)
committerJulien Grall <julien.grall@citrix.com>
Mon, 2 Nov 2015 11:53:19 +0000 (11:53 +0000)
This reverts commit 364f5ce83809e9b59fcd03d39c98f9ff2a83c3ff.

sys/xen/xen_intr.c

index 8063c10b612568d3690f0fccc0f68593b2611c92..014050631a749e45255b3a7793fe9e3a3d4ae194 100644 (file)
@@ -50,6 +50,8 @@ __FBSDID("$FreeBSD$");
 #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>
 
@@ -60,6 +62,7 @@ __FBSDID("$FreeBSD$");
 #include <xen/xen_intr.h>
 #include <xen/evtchn/evtchnvar.h>
 
+#include <dev/xen/xenpci/xenpcivar.h>
 #include <dev/pci/pcivar.h>
 
 #ifdef DDB
@@ -116,9 +119,10 @@ DPCPU_DECLARE(struct vcpu_info *, vcpu_info);
 #define        is_valid_evtchn(x)      ((x) != XEN_INVALID_EVTCHN)
 
 struct xenisrc {
-       struct intr_event *xi_event;
+       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;
@@ -131,10 +135,60 @@ struct xenisrc {
 
 #define ARRAY_SIZE(a)  (sizeof(a) / sizeof(a[0]))
 
-static void    xen_intr_enable_intr(void *arg);
-static void    xen_intr_disable_intr(void *arg);
+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);
 
-static int     xen_intr_assign_cpu(struct xenisrc *isrc, u_int to_cpu);
+/**
+ * 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;
@@ -198,16 +252,12 @@ xen_intr_intrcnt_add(u_int cpu)
        char buf[MAXCOMLEN + 1];
        struct xen_intr_pcpu_data *pcpu;
 
-       static u_long count = 0;
-
        pcpu = DPCPU_ID_PTR(cpu, xen_intr_pcpu);
        if (pcpu->evtchn_intrcnt != NULL)
                return;
 
        snprintf(buf, sizeof(buf), "cpu%d:xen", cpu);
-
-       /* TODO: handle correctly IRQ counter */
-       pcpu->evtchn_intrcnt = &count;
+       intrcnt_add(buf, &pcpu->evtchn_intrcnt);
 }
 
 /**
@@ -222,7 +272,6 @@ xen_intr_intrcnt_add(u_int cpu)
 static struct xenisrc *
 xen_intr_find_unused_isrc(enum evtchn_type type)
 {
-#if 0
        int isrc_idx;
 
        KASSERT(mtx_owned(&xen_intr_isrc_lock), ("Evtchn isrc lock not held"));
@@ -241,7 +290,6 @@ xen_intr_find_unused_isrc(enum evtchn_type type)
                        return (isrc);
                }
        }
-#endif
        return (NULL);
 }
 
@@ -258,7 +306,6 @@ xen_intr_alloc_isrc(enum evtchn_type type, int vector)
 {
        static int warned;
        struct xenisrc *isrc;
-       int error;
 
        KASSERT(mtx_owned(&xen_intr_isrc_lock), ("Evtchn alloc lock not held"));
 
@@ -275,24 +322,18 @@ 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;
-       /* TODO: Make the name of the event more accurate */
-       error = intr_event_create(&isrc->xi_event, isrc, 0, vector /* IRQ */,
-                                 xen_intr_disable_intr /* mask */,
-                                 xen_intr_enable_intr /* unmask */,
-                                 NULL /* EOI */,
-                                 NULL /* cpu assign */, "xen%d:", vector);
+       intr_register_source(&isrc->xi_intsrc);
        mtx_lock(&xen_intr_isrc_lock);
 
-       if (error) {
-               printf("%s: event creation failed (%d)\n",
-                      __FUNCTION__, error);
-               free(isrc, M_XENINTR);
-               isrc = NULL;
-       }
-
        return (isrc);
 }
 
@@ -308,8 +349,7 @@ xen_intr_release_isrc(struct xenisrc *isrc)
 {
 
        mtx_lock(&xen_intr_isrc_lock);
-
-       if (!TAILQ_EMPTY(&isrc->xi_event->ie_handlers)) {
+       if (isrc->xi_intsrc.is_handlers != 0) {
                mtx_unlock(&xen_intr_isrc_lock);
                return (EBUSY);
        }
@@ -320,8 +360,6 @@ xen_intr_release_isrc(struct xenisrc *isrc)
        evtchn_cpu_mask_port(isrc->xi_cpu, isrc->xi_port);
        evtchn_cpu_unmask_port(0, isrc->xi_port);
 
-       intr_event_destroy(isrc->xi_event);
-
        if (isrc->xi_close != 0 && is_valid_evtchn(isrc->xi_port)) {
                struct evtchn_close close = { .port = isrc->xi_port };
                if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
@@ -397,7 +435,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, intr_next_cpu());
+               xen_intr_assign_cpu(&isrc->xi_intsrc, intr_next_cpu());
        }
 #endif
 
@@ -476,13 +514,12 @@ void
 xen_intr_handle_upcall(struct trapframe *trap_frame)
 {
        u_int l1i, l2i, port, cpu;
-       xen_ulong_t masked_l1, masked_l2;
+       u_long masked_l1, masked_l2;
        struct xenisrc *isrc;
        shared_info_t *s;
        vcpu_info_t *v;
        struct xen_intr_pcpu_data *pc;
-       xen_ulong_t l1, l2;
-       int error;
+       u_long l1, l2;
 
        /*
         * Disable preemption in order to always check and fire events
@@ -501,11 +538,14 @@ xen_intr_handle_upcall(struct trapframe *trap_frame)
 
        v->evtchn_upcall_pending = 0;
 
-       /*
-        * Clear master flags /before/ clearing selector flag.
-        * atomic_readandclear_xen_ulong must contain an appropriate barrier
-        */
-       l1 = atomic_readandclear_xen_ulong(&v->evtchn_pending_sel);
+#if 0
+#ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
+       /* Clear master flag /before/ clearing selector flag. */
+       wmb();
+#endif
+#endif
+
+       l1 = atomic_readandclear_long(&v->evtchn_pending_sel);
 
        l1i = pc->last_processed_l1i;
        l2i = pc->last_processed_l2i;
@@ -553,9 +593,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));
 
-                       error = intr_event_handle(isrc->xi_event, trap_frame);
-                       if ( error != 0 )
-                               printf("stray evchn%d: %d\n", port, error);
+                       intr_execute_handlers(&isrc->xi_intsrc, trap_frame);
 
                        /*
                         * If this is the final port processed,
@@ -608,7 +646,7 @@ xen_intr_init(void *dummy __unused)
        }
 
        for (i = 0; i < nitems(s->evtchn_mask); i++)
-               atomic_store_rel_xen_ulong(&s->evtchn_mask[i], ~0);
+               atomic_store_rel_long(&s->evtchn_mask[i], ~0);
 
        /* Try to register PIRQ EOI map */
        xen_intr_pirq_eoi_map = malloc(PAGE_SIZE, M_XENINTR, M_WAITOK | M_ZERO);
@@ -619,6 +657,9 @@ 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);
+
        if (bootverbose)
                printf("Xen interrupt system initialized\n");
 
@@ -627,8 +668,9 @@ xen_intr_init(void *dummy __unused)
 SYSINIT(xen_intr_init, SI_SUB_INTR, SI_ORDER_SECOND, xen_intr_init, NULL);
 
 /*--------------------------- Common PIC Functions ---------------------------*/
-
-#if 0
+/**
+ * Prepare this PIC for system suspension.
+ */
 static void
 xen_intr_suspend(struct pic *unused)
 {
@@ -746,7 +788,6 @@ xen_intr_resume(struct pic *unused, bool suspend_cancelled)
                }
        }
 }
-#endif
 
 /**
  * Disable a Xen interrupt source.
@@ -754,14 +795,13 @@ xen_intr_resume(struct pic *unused, bool suspend_cancelled)
  * \param isrc  The interrupt source to disable.
  */
 static void
-xen_intr_disable_intr(void *arg)
+xen_intr_disable_intr(struct intsrc *base_isrc)
 {
-       struct xenisrc *isrc = arg;
+       struct xenisrc *isrc = (struct xenisrc *)base_isrc;
 
        evtchn_mask_port(isrc->xi_port);
 }
 
-#if 0
 /**
  * Determine the global interrupt vector number for
  * a Xen interrupt source.
@@ -813,8 +853,6 @@ xen_intr_config_intr(struct intsrc *isrc, enum intr_trigger trig,
        return (ENODEV);
 }
 
-#endif
-
 /**
  * Configure CPU affinity for interrupt source event delivery.
  *
@@ -824,12 +862,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 xenisrc *isrc, u_int to_cpu)
+xen_intr_assign_cpu(struct intsrc *base_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, masked;
+       int error;
 
        if (!xen_support_evtchn_rebind())
                return (EOPNOTSUPP);
@@ -837,6 +876,7 @@ xen_intr_assign_cpu(struct xenisrc *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);
@@ -883,8 +923,14 @@ 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 -----------------*/
-#if 0
 /*
  * Mask a level triggered interrupt source.
  *
@@ -936,21 +982,19 @@ xen_intr_eoi_source(struct intsrc *base_isrc)
 {
 }
 
-#endif
 /*
  * Enable and unmask the interrupt source.
  *
  * \param isrc  The interrupt source to enable.
  */
 static void
-xen_intr_enable_intr(void *arg)
+xen_intr_enable_intr(struct intsrc *base_isrc)
 {
-       struct xenisrc *isrc = arg;
+       struct xenisrc *isrc = (struct xenisrc *)base_isrc;
 
        evtchn_unmask_port(isrc->xi_port);
 }
 
-#if 0
 /*------------------ Physical Interrupt Source PIC Functions -----------------*/
 /*
  * Mask a level triggered interrupt source.
@@ -1128,7 +1172,6 @@ xen_intr_pirq_config_intr(struct intsrc *base_isrc, enum intr_trigger trig,
 
        return (0);
 }
-#endif
 
 /*--------------------------- Public Functions -------------------------------*/
 /*------- API comments for these methods can be found in xen/xenintr.h -------*/
@@ -1255,7 +1298,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_event, cpu);
+               error = intr_event_bind(isrc->xi_intsrc.is_event, cpu);
 #endif
 
        if (error != 0) {
@@ -1275,7 +1318,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, cpu);
+               xen_intr_assign_cpu(&isrc->xi_intsrc, cpu);
        }
 #endif
 
@@ -1317,7 +1360,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_event, cpu);
+               error = intr_event_bind(isrc->xi_intsrc.is_event, cpu);
 
        if (error != 0) {
                evtchn_close_t close = { .port = bind_ipi.port };
@@ -1335,7 +1378,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, cpu);
+               xen_intr_assign_cpu(&isrc->xi_intsrc, cpu);
        }
 
        /*
@@ -1423,7 +1466,6 @@ xen_register_msi(device_t dev, int vector, int count)
        return (0);
 }
 
-#if 0
 int
 xen_release_msi(int vector)
 {
@@ -1444,7 +1486,6 @@ xen_release_msi(int vector)
 
        return (0);
 }
-#endif
 
 int
 xen_intr_describe(xen_intr_handle_t port_handle, const char *fmt, ...)
@@ -1460,9 +1501,7 @@ 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_event_describe_handler(isrc->xi_event, port_handle,
-                                           descr));
+       return (intr_describe(isrc->xi_vector, isrc->xi_cookie, descr));
 }
 
 void
@@ -1479,7 +1518,7 @@ xen_intr_unbind(xen_intr_handle_t *port_handlep)
                return;
 
        if (isrc->xi_cookie != NULL)
-               intr_event_remove_handler(isrc->xi_cookie);
+               intr_remove_handler(isrc->xi_cookie);
        xen_intr_release_isrc(isrc);
 }
 
@@ -1522,11 +1561,8 @@ xen_intr_add_handler(device_t dev, driver_filter_t filter,
        if (isrc == NULL || isrc->xi_cookie != NULL)
                return (EINVAL);
 
-       error = intr_event_add_handler(isrc->xi_event,
-                                      device_get_nameunit(dev),
-                                      filter, handler, arg,
-                                      intr_priority(flags), flags|INTR_EXCL,
-                                      isrc->xi_cookie);
+       error = intr_add_handler(device_get_nameunit(dev), isrc->xi_vector,
+           filter, handler, arg, flags|INTR_EXCL, &isrc->xi_cookie);
        if (error != 0) {
                device_printf(dev,
                    "xen_intr_add_handler: intr_add_handler failed: %d\n",