Index: sys/amd64/amd64/apic_vector.S =================================================================== --- sys/amd64/amd64/apic_vector.S +++ sys/amd64/amd64/apic_vector.S @@ -159,7 +159,7 @@ INTR_HANDLER xen_intr_upcall KMSAN_ENTER movq %rsp, %rdi - call xen_intr_handle_upcall + call xen_arch_intr_handle_upcall KMSAN_LEAVE jmp doreti #endif Index: sys/dev/xen/xenpci/xenpci.c =================================================================== --- sys/dev/xen/xenpci/xenpci.c +++ sys/dev/xen/xenpci/xenpci.c @@ -57,13 +57,6 @@ */ static devclass_t xenpci_devclass; -static int -xenpci_intr_filter(void *trap_frame) -{ - xen_intr_handle_upcall(trap_frame); - return (FILTER_HANDLED); -} - static int xenpci_irq_init(device_t device, struct xenpci_softc *scp) { @@ -71,7 +64,7 @@ error = BUS_SETUP_INTR(device_get_parent(device), device, scp->res_irq, INTR_MPSAFE|INTR_TYPE_MISC, - xenpci_intr_filter, NULL, /*trap_frame*/NULL, + xen_intr_handle_upcall, NULL, NULL, &scp->intr_cookie); if (error) return error; Index: sys/i386/i386/apic_vector.s =================================================================== --- sys/i386/i386/apic_vector.s +++ sys/i386/i386/apic_vector.s @@ -183,7 +183,7 @@ cld KENTER pushl %esp - movl $xen_intr_handle_upcall, %eax + movl $xen_arch_intr_handle_upcall, %eax call *%eax add $4, %esp jmp doreti Index: sys/x86/xen/xen_arch_intr.c =================================================================== --- sys/x86/xen/xen_arch_intr.c +++ sys/x86/xen/xen_arch_intr.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -48,6 +49,11 @@ #include #include +/* + * Pointers to the interrupt counters + */ +DPCPU_DEFINE_STATIC(u_long *, pintrcnt); + /* * Lock for x86-related structures. Notably modifying * xen_intr_auto_vector_count, and allocating interrupts require this lock be @@ -60,6 +66,75 @@ static u_int xen_intr_auto_vector_count; +/* + * Transition from assembly language, called from + * sys/{amd64/amd64|i386/i386}/apic_vector.[Ss] + */ +extern void xen_arch_intr_handle_upcall(struct trapframe *); +void +xen_arch_intr_handle_upcall(struct trapframe *trap_frame) +{ + struct trapframe *old; + + /* + * Disable preemption in order to always check and fire events + * on the right vCPU + */ + critical_enter(); + + ++*DPCPU_GET(pintrcnt); + + ++curthread->td_intr_nesting_level; + old = curthread->td_intr_frame; + curthread->td_intr_frame = trap_frame; + + xen_intr_handle_upcall(NULL); + + curthread->td_intr_frame = old; + --curthread->td_intr_nesting_level; + + if (xen_evtchn_needs_ack) + lapic_eoi(); + + critical_exit(); +} + +/** + * Allocate and register a per-cpu Xen upcall interrupt counter. + * + * \param cpu The cpu for which to register this interrupt count. + */ +static void +xen_intr_intrcnt_add(const u_int cpu) +{ + char buf[MAXCOMLEN + 1]; + u_long **ppintrcnt; + + ppintrcnt = DPCPU_ID_PTR(cpu, pintrcnt); + if (ppintrcnt != NULL) + return; + + snprintf(buf, sizeof(buf), "cpu%d:xen", cpu); + intrcnt_add(buf, ppintrcnt); +} + +static void +xen_intrcnt_init(void *dummy __unused) +{ + unsigned int i; + + if (!xen_domain()) + return; + + /* + * Register interrupt count manually as we aren't guaranteed to see a + * call to xen_intr_assign_cpu() before our first interrupt. + */ + CPU_FOREACH(i) + xen_intr_intrcnt_add(i); +} +SYSINIT(xen_intrcnt_init, SI_SUB_INTR, SI_ORDER_MIDDLE, xen_intrcnt_init, NULL); + void xen_intr_alloc_irqs(void) { Index: sys/xen/xen_intr.h =================================================================== --- sys/xen/xen_intr.h +++ sys/xen/xen_intr.h @@ -38,7 +38,10 @@ /** Registered Xen interrupt callback handle. */ typedef void * xen_intr_handle_t; -void xen_intr_handle_upcall(struct trapframe *trap_frame); +/* + * Main handler for Xen event channel interrupts + */ +extern driver_filter_t xen_intr_handle_upcall; /** * Associate an already allocated local event channel port an interrupt Index: sys/xen/xen_intr.c =================================================================== --- sys/xen/xen_intr.c +++ sys/xen/xen_intr.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -88,9 +89,6 @@ */ u_int last_processed_l2i; - /** Pointer to this CPU's interrupt statistic counter. */ - u_long *evtchn_intrcnt; - /** * A bitmap of ports that can be serviced from this CPU. * A set bit means interrupt handling is enabled. @@ -199,25 +197,6 @@ xen_set_bit(port, pcpu->evtchn_enabled); } -/** - * Allocate and register a per-cpu Xen upcall interrupt counter. - * - * \param cpu The cpu for which to register this interrupt count. - */ -static void -xen_intr_intrcnt_add(u_int cpu) -{ - char buf[MAXCOMLEN + 1]; - struct xen_intr_pcpu_data *pcpu; - - 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); -} - /** * Attempt to free an active Xen interrupt source object. * @@ -371,9 +350,10 @@ * * \param trap_frame The trap frame context for the current interrupt. */ -void -xen_intr_handle_upcall(struct trapframe *trap_frame) +int +xen_intr_handle_upcall(void *unused __unused) { + struct trapframe *trap_frame = curthread->td_intr_frame; u_int l1i, l2i, port, cpu; u_long masked_l1, masked_l2; struct xenisrc *isrc; @@ -382,11 +362,7 @@ struct xen_intr_pcpu_data *pc; u_long l1, l2; - /* - * Disable preemption in order to always check and fire events - * on the right vCPU - */ - critical_enter(); + int handled = FILTER_STRAY; cpu = PCPU_GET(cpuid); pc = DPCPU_PTR(xen_intr_pcpu); @@ -410,7 +386,6 @@ l1i = pc->last_processed_l1i; l2i = pc->last_processed_l2i; - (*pc->evtchn_intrcnt)++; while (l1 != 0) { l1i = (l1i + 1) % LONG_BIT; @@ -453,7 +428,8 @@ ("Received unexpected event on vCPU#%d, event bound to vCPU#%u", PCPU_GET(cpuid), isrc->xi_cpu)); - xen_arch_intr_execute_handlers(isrc, trap_frame); + if (xen_arch_intr_execute_handlers(isrc, trap_frame)) + handled = FILTER_HANDLED; /* * If this is the final port processed, @@ -474,10 +450,7 @@ } } - if (xen_evtchn_needs_ack) - lapic_eoi(); - - critical_exit(); + return (handled); } static int @@ -514,23 +487,6 @@ } SYSINIT(xen_intr_init, SI_SUB_INTR, SI_ORDER_SECOND, xen_intr_init, NULL); -static void -xen_intrcnt_init(void *dummy __unused) -{ - unsigned int i; - - if (!xen_domain()) - return; - - /* - * Register interrupt count manually as we aren't guaranteed to see a - * call to xen_intr_assign_cpu() before our first interrupt. - */ - CPU_FOREACH(i) - xen_intr_intrcnt_add(i); -} -SYSINIT(xen_intrcnt_init, SI_SUB_INTR, SI_ORDER_MIDDLE, xen_intrcnt_init, NULL); - /*--------------------------- Common PIC Functions ---------------------------*/ /** * Prepare this PIC for system suspension.