[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


 


Rackspace

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