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