x86: Simplify architecture defined exception handling in irq_llsr()
authorBin Meng <bmeng.cn@gmail.com>
Fri, 10 Jul 2015 02:51:23 +0000 (10:51 +0800)
committerSimon Glass <sjg@chromium.org>
Tue, 28 Jul 2015 16:36:21 +0000 (10:36 -0600)
Instead of using switch..case for architecture defined exceptions,
simply unify the handling by printing a message of exception name,
followed by registers dump then halt the CPU.

With this unification, it also fixes the wrong exception numbers
for #MF/#AC/#MC/#XM which should be 16/17/18/19 not 15/16/17/18.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Acked-by: Simon Glass <sjg@chromium.org>
arch/x86/cpu/interrupts.c

index 043a8d432d1b6063472b4da92f5c5caa9f6de756..853c82f5a7709105b822309abc2edcd44f6e7635 100644 (file)
@@ -32,6 +32,41 @@ DECLARE_GLOBAL_DATA_PTR;
        "pushl $"#x"\n" \
        "jmp irq_common_entry\n"
 
+static char *exceptions[] = {
+       "Divide Error",
+       "Debug",
+       "NMI Interrupt",
+       "Breakpoint",
+       "Overflow",
+       "BOUND Range Exceeded",
+       "Invalid Opcode (Undefined Opcode)",
+       "Device Not Avaiable (No Math Coprocessor)",
+       "Double Fault",
+       "Coprocessor Segment Overrun",
+       "Invalid TSS",
+       "Segment Not Present",
+       "Stack Segment Fault",
+       "Gerneral Protection",
+       "Page Fault",
+       "Reserved",
+       "x87 FPU Floating-Point Error",
+       "Alignment Check",
+       "Machine Check",
+       "SIMD Floating-Point Exception",
+       "Virtualization Exception",
+       "Reserved",
+       "Reserved",
+       "Reserved",
+       "Reserved",
+       "Reserved",
+       "Reserved",
+       "Reserved",
+       "Reserved",
+       "Reserved",
+       "Reserved",
+       "Reserved"
+};
+
 static void dump_regs(struct irq_regs *regs)
 {
        unsigned long cs, eip, eflags;
@@ -112,6 +147,13 @@ static void dump_regs(struct irq_regs *regs)
        }
 }
 
+static void do_exception(struct irq_regs *regs)
+{
+       printf("%s\n", exceptions[regs->irq_id]);
+       dump_regs(regs);
+       hang();
+}
+
 struct idt_entry {
        u16     base_low;
        u16     selector;
@@ -228,111 +270,10 @@ void irq_llsr(struct irq_regs *regs)
         * Order Number: 253665-029US, November 2008
         * Table 6-1. Exceptions and Interrupts
         */
-       switch (regs->irq_id) {
-       case 0x00:
-               printf("Divide Error (Division by zero)\n");
-               dump_regs(regs);
-               hang();
-               break;
-       case 0x01:
-               printf("Debug Interrupt (Single step)\n");
-               dump_regs(regs);
-               break;
-       case 0x02:
-               printf("NMI Interrupt\n");
-               dump_regs(regs);
-               break;
-       case 0x03:
-               printf("Breakpoint\n");
-               dump_regs(regs);
-               break;
-       case 0x04:
-               printf("Overflow\n");
-               dump_regs(regs);
-               hang();
-               break;
-       case 0x05:
-               printf("BOUND Range Exceeded\n");
-               dump_regs(regs);
-               hang();
-               break;
-       case 0x06:
-               printf("Invalid Opcode (UnDefined Opcode)\n");
-               dump_regs(regs);
-               hang();
-               break;
-       case 0x07:
-               printf("Device Not Available (No Math Coprocessor)\n");
-               dump_regs(regs);
-               hang();
-               break;
-       case 0x08:
-               printf("Double fault\n");
-               dump_regs(regs);
-               hang();
-               break;
-       case 0x09:
-               printf("Co-processor segment overrun\n");
-               dump_regs(regs);
-               hang();
-               break;
-       case 0x0a:
-               printf("Invalid TSS\n");
-               dump_regs(regs);
-               break;
-       case 0x0b:
-               printf("Segment Not Present\n");
-               dump_regs(regs);
-               hang();
-               break;
-       case 0x0c:
-               printf("Stack Segment Fault\n");
-               dump_regs(regs);
-               hang();
-               break;
-       case 0x0d:
-               printf("General Protection\n");
-               dump_regs(regs);
-               break;
-       case 0x0e:
-               printf("Page fault\n");
-               dump_regs(regs);
-               hang();
-               break;
-       case 0x0f:
-               printf("Floating-Point Error (Math Fault)\n");
-               dump_regs(regs);
-               break;
-       case 0x10:
-               printf("Alignment check\n");
-               dump_regs(regs);
-               break;
-       case 0x11:
-               printf("Machine Check\n");
-               dump_regs(regs);
-               break;
-       case 0x12:
-               printf("SIMD Floating-Point Exception\n");
-               dump_regs(regs);
-               break;
-       case 0x13:
-       case 0x14:
-       case 0x15:
-       case 0x16:
-       case 0x17:
-       case 0x18:
-       case 0x19:
-       case 0x1a:
-       case 0x1b:
-       case 0x1c:
-       case 0x1d:
-       case 0x1e:
-       case 0x1f:
-               printf("Reserved Exception\n");
-               dump_regs(regs);
-               break;
-
-       default:
+       if (regs->irq_id < 32) {
+               /* Architecture defined exception */
+               do_exception(regs);
+       } else {
                /* Hardware or User IRQ */
                do_irq(regs->irq_id);
        }