[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen master] x86/irqs: move interrupt-stub generation out of C



commit e9706ae4cf6beb680583714f51ef8064fb2648b5
Author:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Mon May 19 14:24:04 2014 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Mon May 19 14:24:04 2014 +0200

    x86/irqs: move interrupt-stub generation out of C
    
    In addition, generate stubs for reserved exceptions.  These go through the
    standard handle_exception mechanism, although the C handler 
do_reserved_trap()
    is a terminal error path.
    
     * Move all automatic stub generation out of i8259.c and into entry.S.
     * Move patching of the master IDT into trap_init(). Provide ASSERT()s to
       ensure we have fully populated the IDT and don't accidentally clobbered 
any
       preexisting traps.
     * Demote TRAP_copro_seg and TRAP_spurious_int to being reserved exceptions
       and remove their custom entry points.
     * Point double_fault's exception_table entry at do_reserved_trap.  We do 
not
       ever expect to enter a real double fault this way.
     * Acquaint Xen with #VE but leave it reserved.
    
    Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
---
 xen/arch/x86/i8259.c            |   69 +--------------------------------------
 xen/arch/x86/traps.c            |   36 ++++++++++++++++----
 xen/arch/x86/x86_64/entry.S     |   67 ++++++++++++++++++++++++++++++-------
 xen/include/asm-x86/asm_defns.h |    5 ---
 xen/include/asm-x86/processor.h |    4 +-
 5 files changed, 85 insertions(+), 96 deletions(-)

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 136821f..8863334 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 exception"
     };
 
     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_trap(struct cpu_user_regs *regs)
+{
+    unsigned int trapnr = regs->entry_vector;
+
+    DEBUGGER_trap_fatal(trapnr, regs);
+    show_execution_state(regs);
+    panic("FATAL RESERVED TRAP %#x: %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,11 @@ 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);
 
@@ -3552,6 +3557,21 @@ void __init trap_init(void)
     /* Fast trap for int80 (faster than taking the #GP-fixup path). */
     _set_gate(idt_table + 0x80, SYS_DESC_trap_gate, 3, &int80_direct_trap);
 
+    for ( vector = 0; vector < NR_VECTORS; ++vector )
+    {
+        if ( autogen_entrypoints[vector] )
+        {
+            /* Found autogen entry: check we won't clobber an existing trap. */
+            ASSERT(idt_table[vector].b == 0);
+            set_intr_gate(vector, autogen_entrypoints[vector]);
+        }
+        else
+        {
+            /* No 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/entry.S b/xen/arch/x86/x86_64/entry.S
index 4796e65..a3ed216 100644
--- a/xen/arch/x86/x86_64/entry.S
+++ b/xen/arch/x86/x86_64/entry.S
@@ -586,11 +586,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 +606,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,18 +706,21 @@ 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 do_reserved_trap /* double_fault - has its own entry. */
+        .quad do_reserved_trap /* coproc_seg_overrun - Intel 387 only. */
         .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 do_reserved_trap /* Default PIC spurious irq - architecturally 
reserved. */
         .quad do_coprocessor_error
         .quad do_alignment_check
         .quad do_machine_check
         .quad do_simd_coprocessor_error
+        .rept TRAP_last_reserved + 1 - ((. - exception_table) / 8)
+        .quad do_reserved_trap /* Architecturally reserved exceptions. */
+        .endr
 
 ENTRY(hypercall_table)
         .quad do_set_trap_table     /*  0 */
@@ -824,3 +817,51 @@ ENTRY(hypercall_args_table)
         .rept NR_hypercalls-(.-hypercall_args_table)
         .byte 0 /* do_ni_hypercall      */
         .endr
+
+/* Table of automatically generated entry points.  One per vector. */
+        .section .init.rodata, "a", @progbits
+GLOBAL(autogen_entrypoints)
+        /* pop into the .init.rodata section and record an entry point. */
+        .macro entrypoint ent
+        .pushsection .init.rodata
+        .quad \ent
+        .popsection
+        .endm
+
+        .text
+autogen_stubs: /* Automatically generated stubs. */
+
+        vec = 0
+        .rept NR_VECTORS
+        ALIGN
+
+        /* Common interrupts, heading towards do_IRQ(). */
+        .if vec >= FIRST_DYNAMIC_VECTOR && vec != HYPERCALL_VECTOR && vec != 
LEGACY_SYSCALL_VECTOR
+
+1:      pushq $0
+        movb  $vec,4(%rsp)
+        jmp   common_interrupt
+
+        entrypoint 1b
+
+        /* Reserved exceptions, heading towards do_reserved_trap(). */
+        .elseif vec == TRAP_copro_seg || vec == TRAP_spurious_int || (vec > 
TRAP_simd_error && vec <= TRAP_last_reserved)
+
+1:      test  $8,%spl        /* 64bit exception frames are 16 byte aligned, 
but the word */
+        jz    2f             /* size is 8 bytes.  Check whether the processor 
gave us an */
+        pushq $0             /* error code, and insert an empty one if not.    
          */
+2:      movb  $vec,4(%rsp)
+        jmp   handle_exception
+
+        entrypoint 1b
+
+        /* Hand crafted entry points above. */
+        .else
+        entrypoint 0
+        .endif
+
+        vec = vec + 1
+        .endr
+
+        .section .init.rodata
+        .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/processor.h b/xen/include/asm-x86/processor.h
index 805ec34..4a60eb0 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_virtualisation   20
 #define TRAP_last_reserved    31
 
 /* Set for entry via SYSCALL. Informs return code to use SYSRETQ not IRETQ. */
@@ -503,7 +504,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);
@@ -514,12 +514,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_trap(struct cpu_user_regs *regs);
 
 void syscall_enter(void);
 void sysenter_entry(void);
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.