x86: Display correct CS/EIP/EFLAGS when there is an error code
authorBin Meng <bmeng.cn@gmail.com>
Fri, 10 Jul 2015 02:38:32 +0000 (10:38 +0800)
committerSimon Glass <sjg@chromium.org>
Tue, 28 Jul 2015 16:36:21 +0000 (10:36 -0600)
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.

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

index c777d3646fca7e1db142216b3449e737aba0752a..043a8d432d1b6063472b4da92f5c5caa9f6de756 100644 (file)
@@ -34,12 +34,39 @@ DECLARE_GLOBAL_DATA_PTR;
 
 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);
index 00cbe07ed186381c2d63f9e1d73f6b6a0743d022..fcd766ba9b6a255f916a17639541554385a9acf1 100644 (file)
 
 #include <asm/types.h>
 
+/* Architecture defined exceptions */
+enum x86_exception {
+       EXC_DE = 0,
+       EXC_DB,
+       EXC_NMI,
+       EXC_BP,
+       EXC_OF,
+       EXC_BR,
+       EXC_UD,
+       EXC_NM,
+       EXC_DF,
+       EXC_CSO,
+       EXC_TS,
+       EXC_NP,
+       EXC_SS,
+       EXC_GP,
+       EXC_PF,
+       EXC_MF = 16,
+       EXC_AC,
+       EXC_MC,
+       EXC_XM,
+       EXC_VE
+};
+
 /* arch/x86/cpu/interrupts.c */
 void set_vector(u8 intnum, void *routine);
 
index a727dbfb0577d50d905c5ef6e6e3b4c19948fa58..3849bc075663c9d568a431eccc9eca7285d69fd0 100644 (file)
@@ -63,9 +63,19 @@ struct irq_regs {
        /* Pushed by vector handler (irq_<num>) */
        long irq_id;
        /* Pushed by cpu in response to interrupt */
-       long eip;
-       long xcs;
-       long eflags;
+       union {
+               struct {
+                       long eip;
+                       long xcs;
+                       long eflags;
+               } ctx1;
+               struct {
+                       long err;
+                       long eip;
+                       long xcs;
+                       long eflags;
+               } ctx2;
+       } context;
 }  __attribute__ ((packed));
 
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */