[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 |