]> xenbits.xensource.com Git - people/julieng/freebsd.git/commitdiff
xen/intr: Rework the event channels handler to make it generic
authorJulien Grall <julien.grall@linaro.org>
Tue, 14 Jan 2014 01:41:04 +0000 (01:41 +0000)
committerJulien Grall <julien.grall@citrix.com>
Mon, 5 Oct 2015 17:55:13 +0000 (18:55 +0100)
The current code to handle the event channels was x86-specific. I think
we can use safely generic function to handle interrupt.

This code was not yet tested/compiled on x86.

TODO:
- There is some #if 0 in the code. Mainly for suspend/resume

sys/xen/xen_intr.c

index f1221d6ad8e6cf6e50d3ee6849a51f92b5777d5e..e5c12af89ce761084481283634723629046518a9 100644 (file)
@@ -50,8 +50,6 @@ __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>
 
@@ -62,7 +60,6 @@ __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,10 +113,9 @@ DPCPU_DECLARE(struct vcpu_info *, vcpu_info);
 #define        is_valid_evtchn(x)      ((x) != XEN_INVALID_EVTCHN)
 
 struct xenisrc {
-       struct intsrc   xi_intsrc;
+       struct intr_event *xi_event;
        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;
@@ -132,60 +128,10 @@ struct xenisrc {
 
 #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);
+static void    xen_intr_enable_intr(void *arg);
+static void    xen_intr_disable_intr(void *arg);
 
-/**
- * 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 int     xen_intr_assign_cpu(struct xenisrc *isrc, u_int to_cpu);
 
 static struct mtx       xen_intr_isrc_lock;
 static int              xen_intr_auto_vector_count;
@@ -249,12 +195,16 @@ 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);
-       intrcnt_add(buf, &pcpu->evtchn_intrcnt);
+
+       /* TODO: handle correctly IRQ counter */
+       pcpu->evtchn_intrcnt = &count;
 }
 
 /**
@@ -269,6 +219,7 @@ 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"));
@@ -287,6 +238,7 @@ xen_intr_find_unused_isrc(enum evtchn_type type)
                        return (isrc);
                }
        }
+#endif
        return (NULL);
 }
 
@@ -303,6 +255,7 @@ 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"));
 
@@ -319,18 +272,24 @@ 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);
+       /* 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);
        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);
 }
 
@@ -346,7 +305,8 @@ xen_intr_release_isrc(struct xenisrc *isrc)
 {
 
        mtx_lock(&xen_intr_isrc_lock);
-       if (isrc->xi_intsrc.is_handlers != 0) {
+
+       if (!TAILQ_EMPTY(&isrc->xi_event->ie_handlers)) {
                mtx_unlock(&xen_intr_isrc_lock);
                return (EBUSY);
        }
@@ -357,6 +317,8 @@ 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))
@@ -511,12 +473,13 @@ void
 xen_intr_handle_upcall(struct trapframe *trap_frame)
 {
        u_int l1i, l2i, port, cpu;
-       u_long masked_l1, masked_l2;
+       xen_ulong_t masked_l1, masked_l2;
        struct xenisrc *isrc;
        shared_info_t *s;
        vcpu_info_t *v;
        struct xen_intr_pcpu_data *pc;
-       u_long l1, l2;
+       xen_ulong_t l1, l2;
+       int error;
 
        /*
         * Disable preemption in order to always check and fire events
@@ -535,14 +498,11 @@ xen_intr_handle_upcall(struct trapframe *trap_frame)
 
        v->evtchn_upcall_pending = 0;
 
-#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);
+       /*
+        * 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);
 
        l1i = pc->last_processed_l1i;
        l2i = pc->last_processed_l2i;
@@ -590,7 +550,9 @@ 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);
+                       error = intr_event_handle(isrc->xi_event, trap_frame);
+                       if ( error != 0 )
+                               printf("stray evchn%d: %d\n", port, error);
 
                        /*
                         * If this is the final port processed,
@@ -641,7 +603,7 @@ xen_intr_init(void *dummy __unused)
        }
 
        for (i = 0; i < nitems(s->evtchn_mask); i++)
-               atomic_store_rel_long(&s->evtchn_mask[i], ~0);
+               atomic_store_rel_xen_ulong(&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);
@@ -652,9 +614,6 @@ 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");
 
@@ -663,9 +622,8 @@ 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.
- */
+
+#if 0
 static void
 xen_intr_suspend(struct pic *unused)
 {
@@ -780,6 +738,7 @@ xen_intr_resume(struct pic *unused, bool suspend_cancelled)
                }
        }
 }
+#endif
 
 /**
  * Disable a Xen interrupt source.
@@ -787,13 +746,14 @@ 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)
+xen_intr_disable_intr(void *arg)
 {
-       struct xenisrc *isrc = (struct xenisrc *)base_isrc;
+       struct xenisrc *isrc = arg;
 
        evtchn_mask_port(isrc->xi_port);
 }
 
+#if 0
 /**
  * Determine the global interrupt vector number for
  * a Xen interrupt source.
@@ -845,6 +805,8 @@ xen_intr_config_intr(struct intsrc *isrc, enum intr_trigger trig,
        return (ENODEV);
 }
 
+#endif
+
 /**
  * Configure CPU affinity for interrupt source event delivery.
  *
@@ -854,11 +816,10 @@ 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)
+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;
 
@@ -868,7 +829,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);
@@ -915,14 +875,8 @@ 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.
  *
@@ -974,19 +928,21 @@ 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(struct intsrc *base_isrc)
+xen_intr_enable_intr(void *arg)
 {
-       struct xenisrc *isrc = (struct xenisrc *)base_isrc;
+       struct xenisrc *isrc = arg;
 
        evtchn_unmask_port(isrc->xi_port);
 }
 
+#if 0
 /*------------------ Physical Interrupt Source PIC Functions -----------------*/
 /*
  * Mask a level triggered interrupt source.
@@ -1164,6 +1120,7 @@ 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 -------*/
@@ -1290,7 +1247,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 = intr_event_bind(isrc->xi_event, cpu);
 #endif
 
        if (error != 0) {
@@ -1310,7 +1267,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
 
@@ -1352,7 +1309,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 = intr_event_bind(isrc->xi_event, cpu);
 
        if (error != 0) {
                evtchn_close_t close = { .port = bind_ipi.port };
@@ -1370,7 +1327,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);
        }
 
        /*
@@ -1458,6 +1415,7 @@ xen_register_msi(device_t dev, int vector, int count)
        return (0);
 }
 
+#if 0
 int
 xen_release_msi(int vector)
 {
@@ -1478,6 +1436,7 @@ xen_release_msi(int vector)
 
        return (0);
 }
+#endif
 
 int
 xen_intr_describe(xen_intr_handle_t port_handle, const char *fmt, ...)
@@ -1493,7 +1452,9 @@ 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 (intr_event_describe_handler(isrc->xi_event, port_handle,
+                                           descr));
 }
 
 void
@@ -1510,7 +1471,7 @@ xen_intr_unbind(xen_intr_handle_t *port_handlep)
                return;
 
        if (isrc->xi_cookie != NULL)
-               intr_remove_handler(isrc->xi_cookie);
+               intr_event_remove_handler(isrc->xi_cookie);
        xen_intr_release_isrc(isrc);
 }
 
@@ -1553,8 +1514,11 @@ 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 = intr_event_add_handler(isrc->xi_event,
+                                      device_get_nameunit(dev),
+                                      filter, handler, arg,
+                                      intr_priority(flags), flags|INTR_EXCL,
+                                      isrc->xi_cookie);
        if (error != 0) {
                device_printf(dev,
                    "xen_intr_add_handler: intr_add_handler failed: %d\n",