diff options
Diffstat (limited to 'arch/x86/cpu/interrupts.c')
-rw-r--r-- | arch/x86/cpu/interrupts.c | 180 |
1 files changed, 74 insertions, 106 deletions
diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c index c777d3646fc..853c82f5a77 100644 --- a/arch/x86/cpu/interrupts.c +++ b/arch/x86/cpu/interrupts.c @@ -32,14 +32,76 @@ 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; unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; unsigned long d0, d1, d2, d3, d6, d7; unsigned long sp; + /* + * Some exceptions cause an error code to be saved on the current stack + * after the EIP value. We should extract CS/EIP/EFLAGS from different + * position on the stack based on the exception number. + */ + switch (regs->irq_id) { + case EXC_DF: + case EXC_TS: + case EXC_NP: + case EXC_SS: + case EXC_GP: + case EXC_PF: + case EXC_AC: + cs = regs->context.ctx2.xcs; + eip = regs->context.ctx2.eip; + eflags = regs->context.ctx2.eflags; + /* We should fix up the ESP due to error code */ + regs->esp += 4; + break; + default: + cs = regs->context.ctx1.xcs; + eip = regs->context.ctx1.eip; + eflags = regs->context.ctx1.eflags; + break; + } + printf("EIP: %04x:[<%08lx>] EFLAGS: %08lx\n", - (u16)regs->xcs, regs->eip, regs->eflags); + (u16)cs, eip, eflags); printf("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", regs->eax, regs->ebx, regs->ecx, regs->edx); @@ -85,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; @@ -201,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); } |