]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
powerpc: Save Come-From Address Register (CFAR) in exception frame
authorPaul Mackerras <paulus@samba.org>
Sun, 1 May 2011 19:48:20 +0000 (19:48 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 4 May 2011 05:22:09 +0000 (15:22 +1000)
Recent 64-bit server processors (POWER6 and POWER7) have a "Come-From
Address Register" (CFAR), that records the address of the most recent
branch or rfid (return from interrupt) instruction for debugging purposes.

This saves the value of the CFAR in the exception entry code and stores
it in the exception frame.  We also make xmon print the CFAR value in
its register dump code.

Rather than extend the pt_regs struct at this time, we steal the orig_gpr3
field, which is only used for system calls, and use it for the CFAR value
for all exceptions/interrupts other than system calls.  This means we
don't save the CFAR on system calls, which is not a great problem since
system calls tend not to happen unexpectedly, and also avoids adding the
overhead of reading the CFAR to the system call entry path.

Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/include/asm/paca.h
arch/powerpc/include/asm/reg.h
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/xmon/xmon.c

index a3e1a9e96a7f2f60c99f6c017a1085c885e90163..4efbfb3f325463ba53c80add9975f8c77ddcb8bf 100644 (file)
@@ -180,6 +180,7 @@ extern const char *powerpc_base_platform;
 
 
 #define CPU_FTR_HVMODE_206             LONG_ASM_CONST(0x0000000800000000)
+#define CPU_FTR_CFAR                   LONG_ASM_CONST(0x0000001000000000)
 #define CPU_FTR_IABR                   LONG_ASM_CONST(0x0000002000000000)
 #define CPU_FTR_MMCRA                  LONG_ASM_CONST(0x0000004000000000)
 #define CPU_FTR_CTRL                   LONG_ASM_CONST(0x0000008000000000)
@@ -412,7 +413,7 @@ extern const char *powerpc_base_platform;
            CPU_FTR_COHERENT_ICACHE | \
            CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
            CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD | \
-           CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB)
+           CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_CFAR)
 #define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_HVMODE_206 |\
            CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -420,7 +421,7 @@ extern const char *powerpc_base_platform;
            CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
            CPU_FTR_DSCR | CPU_FTR_SAO  | CPU_FTR_ASYM_SMT | \
            CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
-           CPU_FTR_ICSWX)
+           CPU_FTR_ICSWX | CPU_FTR_CFAR)
 #define CPU_FTRS_CELL  (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
index 96ccef136ca9d7ab56aac962fb5ad96b7e2243f0..f5dfe3411f64d3bf74dbcf7c6b4a331c8cac0809 100644 (file)
@@ -46,6 +46,7 @@
 #define EX_CCR         60
 #define EX_R3          64
 #define EX_LR          72
+#define EX_CFAR                80
 
 /*
  * We're short on space and time in the exception prolog, so we can't
        std     r10,area+EX_R10(r13);                                   \
        std     r11,area+EX_R11(r13);                                   \
        std     r12,area+EX_R12(r13);                                   \
+       BEGIN_FTR_SECTION_NESTED(66);                                   \
+       mfspr   r10,SPRN_CFAR;                                          \
+       std     r10,area+EX_CFAR(r13);                                  \
+       END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66);         \
        GET_SCRATCH0(r9);                                               \
        std     r9,area+EX_R13(r13);                                    \
        mfcr    r9
        std     r9,GPR11(r1);                                              \
        std     r10,GPR12(r1);                                             \
        std     r11,GPR13(r1);                                             \
+       BEGIN_FTR_SECTION_NESTED(66);                                      \
+       ld      r10,area+EX_CFAR(r13);                                     \
+       std     r10,ORIG_GPR3(r1);                                         \
+       END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66);            \
        ld      r2,PACATOC(r13);        /* get kernel TOC into r2       */ \
        mflr    r9;                     /* save LR in stackframe        */ \
        std     r9,_LINK(r1);                                              \
index 65c13c48db43201a57ce74cb720aabd1301757ea..74126765106adda381b48700f0e68d49602d5653 100644 (file)
@@ -92,9 +92,9 @@ struct paca_struct {
         * Now, starting in cacheline 2, the exception save areas
         */
        /* used for most interrupts/exceptions */
-       u64 exgen[10] __attribute__((aligned(0x80)));
-       u64 exmc[10];           /* used for machine checks */
-       u64 exslb[10];          /* used for SLB/segment table misses
+       u64 exgen[11] __attribute__((aligned(0x80)));
+       u64 exmc[11];           /* used for machine checks */
+       u64 exslb[11];          /* used for SLB/segment table misses
                                 * on the linear mapping */
        /* SLB related definitions */
        u16 vmalloc_sllp;
index 632e78e144418ec64162a22da9fbe763d6e89518..fdec5933305362ac6984fef87dd2c618618e190e 100644 (file)
 
 #define SPRN_CTR       0x009   /* Count Register */
 #define SPRN_DSCR      0x11
+#define SPRN_CFAR      0x1c    /* Come From Address Register */
 #define SPRN_ACOP      0x1F    /* Available Coprocessor Register */
 #define SPRN_CTRLF     0x088
 #define SPRN_CTRLT     0x098
index 27ca8b7c6002bea41c3d5937709a78f1836e802f..0ec3b42717d7ea2694a069b1fa8162023e2ec136 100644 (file)
@@ -474,6 +474,10 @@ bad_stack:
        std     r9,GPR11(r1)
        std     r10,GPR12(r1)
        std     r11,GPR13(r1)
+BEGIN_FTR_SECTION
+       ld      r10,EX_CFAR(r3)
+       std     r10,ORIG_GPR3(r1)
+END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
        SAVE_8GPRS(14,r1)
        SAVE_10GPRS(22,r1)
        lhz     r12,PACA_TRAP_SAVE(r13)
index 60593ad861e803938956b352135c2028ea93de08..909804aaeebb56f90798f3ef08ab606f0ece7fcf 100644 (file)
@@ -1497,6 +1497,10 @@ static void prregs(struct pt_regs *fp)
 #endif
        printf("pc  = ");
        xmon_print_symbol(fp->nip, " ", "\n");
+       if (TRAP(fp) != 0xc00 && cpu_has_feature(CPU_FTR_CFAR)) {
+               printf("cfar= ");
+               xmon_print_symbol(fp->orig_gpr3, " ", "\n");
+       }
        printf("lr  = ");
        xmon_print_symbol(fp->link, " ", "\n");
        printf("msr = "REG"   cr  = %.8lx\n", fp->msr, fp->ccr);