We're going to support two ways of delivering the combined
Xen interrupt that later fans out into event port specific
(device specific) interrupts: IDT method and a PCI device
method.

This diff adds a Xen IDT vector the same way LAPIC timer and
IPIs are implemented.  The additional machinery is there to
be able to mask Xen interrupt (it's installed as an IPL_NET|
IPL_MPSAFE interrupt) via standard mechanisms (e.g. splnet).

The LAPIC_XEN_VECTOR is set to be the first of the IPL_NET
group in the IDT.  The next IPL_NET interrupt will be
assigned 0x71 and so on.

OK?

---
 sys/arch/amd64/amd64/intr.c        | 16 +++++++++++++++-
 sys/arch/amd64/amd64/lapic.c       |  7 +++++++
 sys/arch/amd64/amd64/vector.S      | 37 ++++++++++++++++++++++++++++++++++++-
 sys/arch/amd64/include/i82489var.h |  7 +++++++
 sys/arch/amd64/include/intrdefs.h  |  1 +
 5 files changed, 66 insertions(+), 2 deletions(-)

diff --git sys/arch/amd64/amd64/intr.c sys/arch/amd64/amd64/intr.c
index 022ae1f..b24e872 100644
--- sys/arch/amd64/amd64/intr.c
+++ sys/arch/amd64/amd64/intr.c
@@ -52,10 +52,11 @@
 #include <machine/pio.h>
 #include <machine/cpufunc.h>
 
 #include "ioapic.h"
 #include "lapic.h"
+#include "xen.h"
 
 #if NIOAPIC > 0
 #include <machine/mpbiosvar.h>
 #endif
 
@@ -547,10 +548,13 @@ intr_handler(struct intrframe *frame, struct intrhand *ih)
 struct intrhand fake_softclock_intrhand;
 struct intrhand fake_softnet_intrhand;
 struct intrhand fake_softtty_intrhand;
 struct intrhand fake_timer_intrhand;
 struct intrhand fake_ipi_intrhand;
+#if NXEN > 0
+struct intrhand fake_xen_intrhand;
+#endif
 
 #if NLAPIC > 0 && defined(MULTIPROCESSOR) && 0
 static char *x86_ipi_names[X86_NIPI] = X86_IPI_NAMES;
 #endif
 
@@ -611,13 +615,23 @@ cpu_intr_init(struct cpu_info *ci)
        isp->is_resume = Xresume_lapic_ipi;
        fake_ipi_intrhand.ih_level = IPL_IPI;
        isp->is_handlers = &fake_ipi_intrhand;
        isp->is_pic = &local_pic;
        ci->ci_isources[LIR_IPI] = isp;
-
 #endif
+#if NXEN > 0
+       isp = malloc(sizeof (struct intrsource), M_DEVBUF, M_NOWAIT|M_ZERO);
+       if (isp == NULL)
+               panic("can't allocate fixed interrupt source");
+       isp->is_recurse = Xrecurse_xen_upcall;
+       isp->is_resume = Xresume_xen_upcall;
+       fake_xen_intrhand.ih_level = IPL_NET;
+       isp->is_handlers = &fake_xen_intrhand;
+       isp->is_pic = &local_pic;
+       ci->ci_isources[LIR_XEN] = isp;
 #endif
+#endif /* NLAPIC */
 
        intr_calculatemasks(ci);
 
 }
 
diff --git sys/arch/amd64/amd64/lapic.c sys/arch/amd64/amd64/lapic.c
index 29a8a6c..f810aed 100644
--- sys/arch/amd64/amd64/lapic.c
+++ sys/arch/amd64/amd64/lapic.c
@@ -53,10 +53,11 @@
 #include <machine/i82489var.h>
 
 #include <dev/ic/i8253reg.h>
 
 #include "ioapic.h"
+#include "xen.h"
 
 #if NIOAPIC > 0
 #include <machine/i82093var.h>
 #endif
 
@@ -351,10 +352,16 @@ lapic_boot_init(paddr_t lapic_base)
        idt_vec_set(LAPIC_SPURIOUS_VECTOR, Xintrspurious);
 
        idt_allocmap[LAPIC_TIMER_VECTOR] = 1;
        idt_vec_set(LAPIC_TIMER_VECTOR, Xintr_lapic_ltimer);
 
+#if NXEN > 0
+       /* Xen HVM Event Channel Interrupt Vector */
+       idt_allocmap[LAPIC_XEN_VECTOR] = 1;
+       idt_vec_set(LAPIC_XEN_VECTOR, Xintr_xen_upcall);
+#endif
+
        evcount_attach(&clk_count, "clock", &clk_irq);
 #ifdef MULTIPROCESSOR
        evcount_attach(&ipi_count, "ipi", &ipi_irq);
 #endif
 }
diff --git sys/arch/amd64/amd64/vector.S sys/arch/amd64/amd64/vector.S
index 3d752ab..2874734 100644
--- sys/arch/amd64/amd64/vector.S
+++ sys/arch/amd64/amd64/vector.S
@@ -81,10 +81,11 @@
 #include <machine/specialreg.h>
 
 #include "ioapic.h"
 #include "lapic.h"
 #include "assym.h"
+#include "xen.h"
 
 /*****************************************************************************/
 
 /*
  * Trap and fault vector routines
@@ -433,12 +434,46 @@ IDTVEC(resume_lapic_ltimer)
        jmp     _C_LABEL(Xdoreti)
 2:
        movq    $(1 << LIR_TIMER),%rax
        orq     %rax,CPUVAR(IPENDING)
        INTRFASTEXIT
-#endif /* NLAPIC > 0 */
 
+#if NXEN > 0
+/*
+ * Xen event channel upcall interrupt handler.
+ * Only used when the hypervisor supports direct vector callbacks.
+ */
+IDTVEC(recurse_xen_upcall)
+       INTR_RECURSE_HWFRAME
+       pushq   $0
+       subq    $8,%rsp                 /* unused __if_trapno */
+       INTRENTRY
+       jmp     1f
+IDTVEC(intr_xen_upcall)
+       pushq   $0
+       subq    $8,%rsp                 /* unused __if_trapno */
+       INTRENTRY
+       call    _C_LABEL(xen_intr_ack)
+       movl    CPUVAR(ILEVEL),%ebx
+       cmpl    $IPL_NET,%ebx
+       jae     2f
+IDTVEC(resume_xen_upcall)
+1:
+       incl    CPUVAR(IDEPTH)
+       movl    $IPL_NET,CPUVAR(ILEVEL)
+       sti
+       cld
+       pushq   %rbx
+       call    _C_LABEL(xen_intr)
+       jmp     _C_LABEL(Xdoreti)
+2:
+       movq    $(1 << LIR_XEN),%rax
+       orq     %rax,CPUVAR(IPENDING)
+3:
+       INTRFASTEXIT
+#endif /* NXEN > 0 */
+#endif /* NLAPIC > 0 */
 
 #define voidop(num)
 
 
 /*
diff --git sys/arch/amd64/include/i82489var.h sys/arch/amd64/include/i82489var.h
index 4eb1999..0ac0dcc 100644
--- sys/arch/amd64/include/i82489var.h
+++ sys/arch/amd64/include/i82489var.h
@@ -97,10 +97,17 @@ extern void Xintr_lapic0(void);
 extern void Xintr_lapic2(void);
 extern void Xintr_lapic3(void);
 extern void Xintr_lapic4(void);
 extern void Xintr_lapic5(void);
 
+/*
+ * Vector used for Xen HVM Event Channel Interrupts.
+ */
+extern void Xintr_xen_upcall(void);
+extern void Xresume_xen_upcall(void);
+extern void Xrecurse_xen_upcall(void);
+#define LAPIC_XEN_VECTOR               0x70
 
 struct cpu_info;
 
 extern void lapic_boot_init(paddr_t);
 extern void lapic_set_lvt(void);
diff --git sys/arch/amd64/include/intrdefs.h sys/arch/amd64/include/intrdefs.h
index 0d15286..c8db1e9 100644
--- sys/arch/amd64/include/intrdefs.h
+++ sys/arch/amd64/include/intrdefs.h
@@ -52,10 +52,11 @@
 /* Soft interrupt masks. */
 #define        SIR_CLOCK       61
 #define        SIR_NET         60
 #define        SIR_TTY         59
 
+#define        LIR_XEN         58
 
 /*
  * Maximum # of interrupt sources per CPU. 64 to fit in one word.
  * ioapics can theoretically produce more, but it's not likely to
  * happen. For multiple ioapics, things can be routed to different
-- 
2.6.3

Reply via email to