|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC 8/9] x86/irqs: Move interrupt-stub generation out of C
Also generate stubs for reserved exceptions, which find their way to
do_reserved_exception() along with their entry vector for informative
purposes.
* Move all automatic stub generation out of i8259.c and into irqgen.S.
* Move patching of the master IDT into trap_init(), and provide ASSERT()s to
ensure we have fully populated the IDT, and unexpectedly clobbered any
traps.
* Demote TRAP_copro_seg and TRAP_spurious_int to being reserved exceptions,
and remove their custom entry points.
* Introduce BAD_VIRT_ADDR as a virtual address guaranteed to cause a #GP
fault if followed, and use it in preference to NULL pointers in the
exception table.
* Acquaint Xen with #VE but leave it reserved.
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CC: Keir Fraser <keir@xxxxxxx>
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Tim Deegan <tim@xxxxxxx>
---
The .macro hackary in irqgen.S is very ugly, and I dislike it. This is the
only way I can find of getting a literal number out of 'vec'. If anyone knows
how to beat GAS into submission, I will very happily accept improvements.
---
xen/arch/x86/i8259.c | 69 +------------------------------------
xen/arch/x86/traps.c | 39 ++++++++++++++++-----
xen/arch/x86/x86_64/Makefile | 1 +
xen/arch/x86/x86_64/entry.S | 22 +++++-------
xen/arch/x86/x86_64/irqgen.S | 72 +++++++++++++++++++++++++++++++++++++++
xen/include/asm-x86/asm_defns.h | 5 ---
xen/include/asm-x86/config.h | 1 +
xen/include/asm-x86/processor.h | 4 +--
8 files changed, 117 insertions(+), 96 deletions(-)
create mode 100644 xen/arch/x86/x86_64/irqgen.S
diff --git a/xen/arch/x86/i8259.c b/xen/arch/x86/i8259.c
index 9fec490..9f99995 100644
--- a/xen/arch/x86/i8259.c
+++ b/xen/arch/x86/i8259.c
@@ -23,65 +23,6 @@
#include <io_ports.h>
/*
- * Common place to define all x86 IRQ vectors
- *
- * This builds up the IRQ handler stubs using some ugly macros in irq.h
- *
- * These macros create the low-level assembly IRQ routines that save
- * register context and call do_IRQ(). do_IRQ() then does all the
- * operations that are needed to keep the AT (or SMP IOAPIC)
- * interrupt-controller happy.
- */
-
-__asm__(".section .text");
-
-#define IRQ_NAME(nr) VEC##nr##_interrupt
-
-#define BI(nr) \
-void IRQ_NAME(nr)(void); \
-__asm__( \
-".if " STR(0x##nr) " >= " STR(FIRST_DYNAMIC_VECTOR) "\n" \
-__ALIGN_STR "\n" \
-STR(IRQ_NAME(nr)) ":\n\t" \
-BUILD_IRQ(0x##nr) "\n" \
-".else\n" \
-".equ " STR(IRQ_NAME(nr)) ", 0\n" \
-".endif\n")
-
-#define BUILD_16_IRQS(x) \
- BI(x##0); BI(x##1); BI(x##2); BI(x##3); \
- BI(x##4); BI(x##5); BI(x##6); BI(x##7); \
- BI(x##8); BI(x##9); BI(x##a); BI(x##b); \
- BI(x##c); BI(x##d); BI(x##e); BI(x##f)
-
-BUILD_16_IRQS(0); BUILD_16_IRQS(1); BUILD_16_IRQS(2); BUILD_16_IRQS(3);
-BUILD_16_IRQS(4); BUILD_16_IRQS(5); BUILD_16_IRQS(6); BUILD_16_IRQS(7);
-BUILD_16_IRQS(8); BUILD_16_IRQS(9); BUILD_16_IRQS(a); BUILD_16_IRQS(b);
-BUILD_16_IRQS(c); BUILD_16_IRQS(d); BUILD_16_IRQS(e); BUILD_16_IRQS(f);
-
-#undef BUILD_16_IRQS
-#undef BI
-
-
-#define IRQ(x,y) IRQ_NAME(x##y)
-
-#define IRQLIST_16(x) \
- IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), \
- IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), \
- IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
- IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
-
-static void (*__initdata interrupt[NR_VECTORS])(void) = {
- IRQLIST_16(0), IRQLIST_16(1), IRQLIST_16(2), IRQLIST_16(3),
- IRQLIST_16(4), IRQLIST_16(5), IRQLIST_16(6), IRQLIST_16(7),
- IRQLIST_16(8), IRQLIST_16(9), IRQLIST_16(a), IRQLIST_16(b),
- IRQLIST_16(c), IRQLIST_16(d), IRQLIST_16(e), IRQLIST_16(f)
-};
-
-#undef IRQ
-#undef IRQLIST_16
-
-/*
* This is the 'legacy' 8259A Programmable Interrupt Controller,
* present in the majority of PC/AT boxes.
* plus some generic x86 specific things if generic specifics makes
@@ -395,7 +336,7 @@ static struct irqaction __read_mostly cascade = {
no_action, "cascade", NULL};
void __init init_IRQ(void)
{
- int vector, irq, cpu = smp_processor_id();
+ int irq, cpu = smp_processor_id();
init_bsp_APIC();
@@ -403,14 +344,6 @@ void __init init_IRQ(void)
BUG_ON(init_irq_data() < 0);
- for ( vector = FIRST_DYNAMIC_VECTOR; vector < NR_VECTORS; vector++ )
- {
- if (vector == HYPERCALL_VECTOR || vector == LEGACY_SYSCALL_VECTOR)
- continue;
- BUG_ON(!interrupt[vector]);
- set_intr_gate(vector, interrupt[vector]);
- }
-
for (irq = 0; platform_legacy_irq(irq); irq++) {
struct irq_desc *desc = irq_to_desc(irq);
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 41a9d77..4dfcf4f 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -383,7 +383,7 @@ static const char *trapstr(unsigned int trapnr)
"coprocessor segment", "invalid tss", "segment not found",
"stack error", "general protection fault", "page fault",
"spurious interrupt", "coprocessor error", "alignment check",
- "machine check", "simd error"
+ "machine check", "simd error", "virtualisation error"
};
return trapnr < ARRAY_SIZE(strings) ? strings[trapnr] : "???";
@@ -534,6 +534,15 @@ int set_guest_nmi_trapbounce(void)
return !null_trap_bounce(v, tb);
}
+void do_reserved_exception(struct cpu_user_regs *regs)
+{
+ unsigned int trapnr = regs->entry_vector;
+
+ DEBUGGER_trap_fatal(trapnr, regs);
+ show_execution_state(regs);
+ panic("FATAL RESERVED TRAP: vector = %d (%s)", trapnr, trapstr(trapnr));
+}
+
static void do_trap(struct cpu_user_regs *regs, int use_error_code)
{
struct vcpu *curr = current;
@@ -589,7 +598,6 @@ void do_##name(struct cpu_user_regs *regs) \
DO_ERROR_NOCODE(divide_error)
DO_ERROR_NOCODE(overflow)
DO_ERROR_NOCODE(bounds)
-DO_ERROR_NOCODE(coprocessor_segment_overrun)
DO_ERROR( invalid_TSS)
DO_ERROR( segment_not_present)
DO_ERROR( stack_segment)
@@ -3414,10 +3422,6 @@ void do_debug(struct cpu_user_regs *regs)
return;
}
-void do_spurious_interrupt_bug(struct cpu_user_regs *regs)
-{
-}
-
static void __set_intr_gate(unsigned int n, uint32_t dpl, void *addr)
{
int i;
@@ -3516,13 +3520,11 @@ void __init init_idt_traps(void)
set_intr_gate(TRAP_invalid_op,&invalid_op);
set_intr_gate(TRAP_no_device,&device_not_available);
set_intr_gate(TRAP_double_fault, &double_fault);
- set_intr_gate(TRAP_copro_seg,&coprocessor_segment_overrun);
set_intr_gate(TRAP_invalid_tss,&invalid_TSS);
set_intr_gate(TRAP_no_segment,&segment_not_present);
set_intr_gate(TRAP_stack_error,&stack_segment);
set_intr_gate(TRAP_gp_fault,&general_protection);
set_intr_gate(TRAP_page_fault,&early_page_fault);
- set_intr_gate(TRAP_spurious_int,&spurious_interrupt_bug);
set_intr_gate(TRAP_copro_error,&coprocessor_error);
set_intr_gate(TRAP_alignment_check,&alignment_check);
set_intr_gate(TRAP_machine_check,&machine_check);
@@ -3540,8 +3542,12 @@ void __init init_idt_traps(void)
this_cpu(compat_gdt_table) = boot_cpu_compat_gdt_table;
}
+extern void (*__initconst autogen_entrypoints[NR_VECTORS])(void);
void __init trap_init(void)
{
+ unsigned int vector;
+
+ /* Replace early pagefault with real pagefault handler */
set_intr_gate(TRAP_page_fault, &page_fault);
/* The 32-on-64 hypercall entry vector is only accessible from ring 1. */
@@ -3550,6 +3556,23 @@ void __init trap_init(void)
/* Fast trap for int80 (faster than taking the #GP-fixup path). */
_set_gate(idt_table+0x80, DESC_TYPE_trap_gate, 3, &int80_direct_trap);
+ for ( vector = 0; vector < NR_VECTORS; vector++ )
+ {
+ if ( autogen_entrypoints[vector] )
+ {
+ /* Found autogenerated entry point - confirm we won't clobber an
+ * existing trap. */
+ ASSERT(idt_table[vector].b == 0);
+ set_intr_gate(vector, autogen_entrypoints[vector]);
+ }
+ else
+ {
+ /* No autogenerated entry point - confirm we have an existing
+ * trap in place. */
+ ASSERT(idt_table[vector].b != 0);
+ }
+ }
+
percpu_traps_init();
cpu_init();
diff --git a/xen/arch/x86/x86_64/Makefile b/xen/arch/x86/x86_64/Makefile
index 7f8fb3d..4b23d89 100644
--- a/xen/arch/x86/x86_64/Makefile
+++ b/xen/arch/x86/x86_64/Makefile
@@ -1,6 +1,7 @@
subdir-y += compat
obj-bin-y += entry.o
+obj-bin-y += irqgen.o
obj-bin-y += gpr_switch.o
obj-y += mm.o
obj-y += traps.o
diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
index 4796e65..1bd4ee4 100644
--- a/xen/arch/x86/x86_64/entry.S
+++ b/xen/arch/x86/x86_64/entry.S
@@ -475,6 +475,12 @@ ENTRY(common_interrupt)
callq do_IRQ
jmp ret_from_intr
+ENTRY(reserved_exception)
+ SAVE_ALL CLAC
+ movq %rsp,%rdi
+ callq do_reserved_exception
+ jmp ret_from_intr
+
/* No special register assumptions. */
ENTRY(ret_from_intr)
GET_CURRENT(%rbx)
@@ -586,11 +592,6 @@ ENTRY(invalid_op)
movl $TRAP_invalid_op,4(%rsp)
jmp handle_exception
-ENTRY(coprocessor_segment_overrun)
- pushq $0
- movl $TRAP_copro_seg,4(%rsp)
- jmp handle_exception
-
ENTRY(invalid_TSS)
movl $TRAP_invalid_tss,4(%rsp)
jmp handle_exception
@@ -611,11 +612,6 @@ ENTRY(alignment_check)
movl $TRAP_alignment_check,4(%rsp)
jmp handle_exception
-ENTRY(spurious_interrupt_bug)
- pushq $0
- movl $TRAP_spurious_int,4(%rsp)
- jmp handle_exception
-
ENTRY(double_fault)
movl $TRAP_double_fault,4(%rsp)
/* Set AC to reduce chance of further SMAP faults */
@@ -716,14 +712,14 @@ ENTRY(exception_table)
.quad do_bounds
.quad do_invalid_op
.quad do_device_not_available
- .quad 0 # double_fault
- .quad do_coprocessor_segment_overrun
+ .quad BAD_VIRT_ADDR # double_fault
+ .quad BAD_VIRT_ADDR # coproc_seg_overrun, reserved
.quad do_invalid_TSS
.quad do_segment_not_present
.quad do_stack_segment
.quad do_general_protection
.quad do_page_fault
- .quad do_spurious_interrupt_bug
+ .quad BAD_VIRT_ADDR # IRQ7 spurious, reserved
.quad do_coprocessor_error
.quad do_alignment_check
.quad do_machine_check
diff --git a/xen/arch/x86/x86_64/irqgen.S b/xen/arch/x86/x86_64/irqgen.S
new file mode 100644
index 0000000..6389b4e
--- /dev/null
+++ b/xen/arch/x86/x86_64/irqgen.S
@@ -0,0 +1,72 @@
+/* Automatically generated interrupt entry points */
+
+#include <xen/config.h>
+#include <asm/asm_defns.h>
+#include <irq_vectors.h>
+
+.altmacro
+
+/* Make a symbol by evaluating num for a real number */
+.macro mksym name, num
+ __mksym \name, %num
+.endm
+.macro __mksym, name, num
+ \name\num:
+.endm
+
+/* Equate a symbol with 0 by evaluating num for a real number */
+.macro nullsym name, num
+ __nullsym \name, %num
+.endm
+.macro __nullsym, name, num
+ .equ \name\num\(), 0
+.endm
+
+/* Create a .quad of a symbol evaluating num for a real number */
+.macro mkquad name, num
+ __mkquad \name, %num
+.endm
+.macro __mkquad name, num
+ .quad \name\num
+.endm
+
+/* Automatically generate stub entry points */
+vec = 0
+.rept NR_VECTORS
+ ALIGN
+
+ /* Common interrupts, heading towards do_IRQ() */
+ .if vec >= FIRST_DYNAMIC_VECTOR && vec != HYPERCALL_VECTOR && vec !=
LEGACY_SYSCALL_VECTOR
+ mksym autogen_vec_, vec
+ pushq $0
+ movb $(vec),4(%rsp)
+ jmp common_interrupt
+
+ /* Reserved exceptions, heading towards do_reserved_exception() */
+ .elseif vec == TRAP_copro_seg || vec == TRAP_spurious_int || (vec >
TRAP_simd_error && vec <= TRAP_last_reserved)
+ mksym autogen_vec_, vec
+ pushq $0
+ movb $(vec),4(%rsp)
+ jmp reserved_exception
+
+ /* Hand generated in entry.S */
+ .else
+ nullsym autogen_vec_, vec
+ .endif
+
+vec = vec + 1
+.endr
+
+
+.section ".init.rodata", "a", @progbits
+
+/* Entry points of automatically generated subs from above */
+GLOBAL(autogen_entrypoints)
+ vec = 0
+
+ .rept NR_VECTORS
+ mkquad autogen_vec_, vec
+ vec = vec + 1
+ .endr
+
+ .size autogen_entrypoints, . - autogen_entrypoints
diff --git a/xen/include/asm-x86/asm_defns.h b/xen/include/asm-x86/asm_defns.h
index df4873b..87a462f 100644
--- a/xen/include/asm-x86/asm_defns.h
+++ b/xen/include/asm-x86/asm_defns.h
@@ -357,9 +357,4 @@ static inline void stac(void)
#define REX64_PREFIX "rex64/"
#endif
-#define BUILD_IRQ(nr) \
- "pushq $0\n\t" \
- "movl $"#nr",4(%rsp)\n\t" \
- "jmp common_interrupt"
-
#endif /* __X86_ASM_DEFNS_H__ */
diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h
index 02ab1fc..5df2fe2 100644
--- a/xen/include/asm-x86/config.h
+++ b/xen/include/asm-x86/config.h
@@ -106,6 +106,7 @@
/* Return value for zero-size _xmalloc(), distinguished from NULL. */
#define ZERO_BLOCK_PTR ((void *)0xBAD0BAD0BAD0BAD0UL)
+#define BAD_VIRT_ADDR _AC(0x8000000000000000,UL)
#ifndef __ASSEMBLY__
extern unsigned long trampoline_phys;
diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
index c9051be..13ee755 100644
--- a/xen/include/asm-x86/processor.h
+++ b/xen/include/asm-x86/processor.h
@@ -113,6 +113,7 @@
#define TRAP_alignment_check 17
#define TRAP_machine_check 18
#define TRAP_simd_error 19
+#define TRAP_virt_error 20
#define TRAP_last_reserved 31
/* Set for entry via SYSCALL. Informs return code to use SYSRETQ not IRETQ. */
@@ -501,7 +502,6 @@ DECLARE_TRAP_HANDLER(bounds);
DECLARE_TRAP_HANDLER(invalid_op);
DECLARE_TRAP_HANDLER(device_not_available);
DECLARE_TRAP_HANDLER(double_fault);
-DECLARE_TRAP_HANDLER(coprocessor_segment_overrun);
DECLARE_TRAP_HANDLER(invalid_TSS);
DECLARE_TRAP_HANDLER(segment_not_present);
DECLARE_TRAP_HANDLER(stack_segment);
@@ -512,12 +512,12 @@ DECLARE_TRAP_HANDLER(coprocessor_error);
DECLARE_TRAP_HANDLER(simd_coprocessor_error);
DECLARE_TRAP_HANDLER(machine_check);
DECLARE_TRAP_HANDLER(alignment_check);
-DECLARE_TRAP_HANDLER(spurious_interrupt_bug);
#undef DECLARE_TRAP_HANDLER
void trap_nop(void);
void enable_nmis(void);
void noreturn do_nmi_crash(struct cpu_user_regs *regs);
+void do_reserved_exception(struct cpu_user_regs *regs);
void syscall_enter(void);
void sysenter_entry(void);
--
1.7.10.4
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |