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