aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2011-05-01 15:48:20 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-05-04 01:22:09 -0400
commit48404f2e95ef0ffd8134d89c8abcd1a15e15f1b0 (patch)
treec1f55c2b59f4c32848152a4bdc23aac8537b8cbb /arch/powerpc
parent1977b502120d44b9b4897703adfb2e2fab346880 (diff)
powerpc: Save Come-From Address Register (CFAR) in exception frame
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>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/cputable.h5
-rw-r--r--arch/powerpc/include/asm/exception-64s.h9
-rw-r--r--arch/powerpc/include/asm/paca.h6
-rw-r--r--arch/powerpc/include/asm/reg.h1
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S4
-rw-r--r--arch/powerpc/xmon/xmon.c4
6 files changed, 24 insertions, 5 deletions
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index a3e1a9e96a7..4efbfb3f325 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -180,6 +180,7 @@ extern const char *powerpc_base_platform;
180 180
181 181
182#define CPU_FTR_HVMODE_206 LONG_ASM_CONST(0x0000000800000000) 182#define CPU_FTR_HVMODE_206 LONG_ASM_CONST(0x0000000800000000)
183#define CPU_FTR_CFAR LONG_ASM_CONST(0x0000001000000000)
183#define CPU_FTR_IABR LONG_ASM_CONST(0x0000002000000000) 184#define CPU_FTR_IABR LONG_ASM_CONST(0x0000002000000000)
184#define CPU_FTR_MMCRA LONG_ASM_CONST(0x0000004000000000) 185#define CPU_FTR_MMCRA LONG_ASM_CONST(0x0000004000000000)
185#define CPU_FTR_CTRL LONG_ASM_CONST(0x0000008000000000) 186#define CPU_FTR_CTRL LONG_ASM_CONST(0x0000008000000000)
@@ -412,7 +413,7 @@ extern const char *powerpc_base_platform;
412 CPU_FTR_COHERENT_ICACHE | \ 413 CPU_FTR_COHERENT_ICACHE | \
413 CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ 414 CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
414 CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD | \ 415 CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD | \
415 CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB) 416 CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_CFAR)
416#define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ 417#define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
417 CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_HVMODE_206 |\ 418 CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_HVMODE_206 |\
418 CPU_FTR_MMCRA | CPU_FTR_SMT | \ 419 CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -420,7 +421,7 @@ extern const char *powerpc_base_platform;
420 CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ 421 CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
421 CPU_FTR_DSCR | CPU_FTR_SAO | CPU_FTR_ASYM_SMT | \ 422 CPU_FTR_DSCR | CPU_FTR_SAO | CPU_FTR_ASYM_SMT | \
422 CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ 423 CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
423 CPU_FTR_ICSWX) 424 CPU_FTR_ICSWX | CPU_FTR_CFAR)
424#define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ 425#define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
425 CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ 426 CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
426 CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ 427 CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
index 96ccef136ca..f5dfe3411f6 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -46,6 +46,7 @@
46#define EX_CCR 60 46#define EX_CCR 60
47#define EX_R3 64 47#define EX_R3 64
48#define EX_LR 72 48#define EX_LR 72
49#define EX_CFAR 80
49 50
50/* 51/*
51 * We're short on space and time in the exception prolog, so we can't 52 * We're short on space and time in the exception prolog, so we can't
@@ -66,6 +67,10 @@
66 std r10,area+EX_R10(r13); \ 67 std r10,area+EX_R10(r13); \
67 std r11,area+EX_R11(r13); \ 68 std r11,area+EX_R11(r13); \
68 std r12,area+EX_R12(r13); \ 69 std r12,area+EX_R12(r13); \
70 BEGIN_FTR_SECTION_NESTED(66); \
71 mfspr r10,SPRN_CFAR; \
72 std r10,area+EX_CFAR(r13); \
73 END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66); \
69 GET_SCRATCH0(r9); \ 74 GET_SCRATCH0(r9); \
70 std r9,area+EX_R13(r13); \ 75 std r9,area+EX_R13(r13); \
71 mfcr r9 76 mfcr r9
@@ -130,6 +135,10 @@
130 std r9,GPR11(r1); \ 135 std r9,GPR11(r1); \
131 std r10,GPR12(r1); \ 136 std r10,GPR12(r1); \
132 std r11,GPR13(r1); \ 137 std r11,GPR13(r1); \
138 BEGIN_FTR_SECTION_NESTED(66); \
139 ld r10,area+EX_CFAR(r13); \
140 std r10,ORIG_GPR3(r1); \
141 END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66); \
133 ld r2,PACATOC(r13); /* get kernel TOC into r2 */ \ 142 ld r2,PACATOC(r13); /* get kernel TOC into r2 */ \
134 mflr r9; /* save LR in stackframe */ \ 143 mflr r9; /* save LR in stackframe */ \
135 std r9,_LINK(r1); \ 144 std r9,_LINK(r1); \
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 65c13c48db4..74126765106 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -92,9 +92,9 @@ struct paca_struct {
92 * Now, starting in cacheline 2, the exception save areas 92 * Now, starting in cacheline 2, the exception save areas
93 */ 93 */
94 /* used for most interrupts/exceptions */ 94 /* used for most interrupts/exceptions */
95 u64 exgen[10] __attribute__((aligned(0x80))); 95 u64 exgen[11] __attribute__((aligned(0x80)));
96 u64 exmc[10]; /* used for machine checks */ 96 u64 exmc[11]; /* used for machine checks */
97 u64 exslb[10]; /* used for SLB/segment table misses 97 u64 exslb[11]; /* used for SLB/segment table misses
98 * on the linear mapping */ 98 * on the linear mapping */
99 /* SLB related definitions */ 99 /* SLB related definitions */
100 u16 vmalloc_sllp; 100 u16 vmalloc_sllp;
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 632e78e1444..fdec5933305 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -188,6 +188,7 @@
188 188
189#define SPRN_CTR 0x009 /* Count Register */ 189#define SPRN_CTR 0x009 /* Count Register */
190#define SPRN_DSCR 0x11 190#define SPRN_DSCR 0x11
191#define SPRN_CFAR 0x1c /* Come From Address Register */
191#define SPRN_ACOP 0x1F /* Available Coprocessor Register */ 192#define SPRN_ACOP 0x1F /* Available Coprocessor Register */
192#define SPRN_CTRLF 0x088 193#define SPRN_CTRLF 0x088
193#define SPRN_CTRLT 0x098 194#define SPRN_CTRLT 0x098
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 27ca8b7c600..0ec3b42717d 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -474,6 +474,10 @@ bad_stack:
474 std r9,GPR11(r1) 474 std r9,GPR11(r1)
475 std r10,GPR12(r1) 475 std r10,GPR12(r1)
476 std r11,GPR13(r1) 476 std r11,GPR13(r1)
477BEGIN_FTR_SECTION
478 ld r10,EX_CFAR(r3)
479 std r10,ORIG_GPR3(r1)
480END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
477 SAVE_8GPRS(14,r1) 481 SAVE_8GPRS(14,r1)
478 SAVE_10GPRS(22,r1) 482 SAVE_10GPRS(22,r1)
479 lhz r12,PACA_TRAP_SAVE(r13) 483 lhz r12,PACA_TRAP_SAVE(r13)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 60593ad861e..909804aaeeb 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -1497,6 +1497,10 @@ static void prregs(struct pt_regs *fp)
1497#endif 1497#endif
1498 printf("pc = "); 1498 printf("pc = ");
1499 xmon_print_symbol(fp->nip, " ", "\n"); 1499 xmon_print_symbol(fp->nip, " ", "\n");
1500 if (TRAP(fp) != 0xc00 && cpu_has_feature(CPU_FTR_CFAR)) {
1501 printf("cfar= ");
1502 xmon_print_symbol(fp->orig_gpr3, " ", "\n");
1503 }
1500 printf("lr = "); 1504 printf("lr = ");
1501 xmon_print_symbol(fp->link, " ", "\n"); 1505 xmon_print_symbol(fp->link, " ", "\n");
1502 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr); 1506 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);