diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2013-03-22 07:46:49 -0400 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2013-05-07 04:13:54 -0400 |
commit | bd3c8b11eccddd311c9e6a56aa00c1af24ea5958 (patch) | |
tree | 0f3374e644f51d63cd9744718a7a65d9f480b896 /arch | |
parent | 68e4790ec4383c57224d69ed9e0a94e4ef005f35 (diff) |
ARC: Debug/crash-printing Improvements
* Remove the line-break between scratch/callee-regs (sneaked in when we
converted from printk to pr_*
* Use %pS to print the symbol names of faulting PC (ret pseudo register)
and BLINK (call return register)
* Don't print user-vma for a kernel crash (only do it for
print-fatal-signals based regfile dump)
* Verbose print the Interrupt/Exception Enable/Active state
* for main executable link address is 0x10000 based (vs. 0) thus offset
of faulting PC needs to be adjusted
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arc/kernel/troubleshoot.c | 50 |
1 files changed, 32 insertions, 18 deletions
diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c index 7c10873c311f..a39d5812cc09 100644 --- a/arch/arc/kernel/troubleshoot.c +++ b/arch/arc/kernel/troubleshoot.c | |||
@@ -26,7 +26,6 @@ static noinline void print_reg_file(long *reg_rev, int start_num) | |||
26 | char buf[512]; | 26 | char buf[512]; |
27 | int n = 0, len = sizeof(buf); | 27 | int n = 0, len = sizeof(buf); |
28 | 28 | ||
29 | /* weird loop because pt_regs regs rev r12..r0, r25..r13 */ | ||
30 | for (i = start_num; i < start_num + 13; i++) { | 29 | for (i = start_num; i < start_num + 13; i++) { |
31 | n += scnprintf(buf + n, len - n, "r%02u: 0x%08lx\t", | 30 | n += scnprintf(buf + n, len - n, "r%02u: 0x%08lx\t", |
32 | i, (unsigned long)*reg_rev); | 31 | i, (unsigned long)*reg_rev); |
@@ -34,13 +33,18 @@ static noinline void print_reg_file(long *reg_rev, int start_num) | |||
34 | if (((i + 1) % 3) == 0) | 33 | if (((i + 1) % 3) == 0) |
35 | n += scnprintf(buf + n, len - n, "\n"); | 34 | n += scnprintf(buf + n, len - n, "\n"); |
36 | 35 | ||
36 | /* because pt_regs has regs reversed: r12..r0, r25..r13 */ | ||
37 | reg_rev--; | 37 | reg_rev--; |
38 | } | 38 | } |
39 | 39 | ||
40 | if (start_num != 0) | 40 | if (start_num != 0) |
41 | n += scnprintf(buf + n, len - n, "\n\n"); | 41 | n += scnprintf(buf + n, len - n, "\n\n"); |
42 | 42 | ||
43 | pr_info("%s", buf); | 43 | /* To continue printing callee regs on same line as scratch regs */ |
44 | if (start_num == 0) | ||
45 | pr_info("%s", buf); | ||
46 | else | ||
47 | pr_cont("%s\n", buf); | ||
44 | } | 48 | } |
45 | 49 | ||
46 | static void show_callee_regs(struct callee_regs *cregs) | 50 | static void show_callee_regs(struct callee_regs *cregs) |
@@ -83,6 +87,10 @@ static void show_faulting_vma(unsigned long address, char *buf) | |||
83 | dev_t dev = 0; | 87 | dev_t dev = 0; |
84 | char *nm = buf; | 88 | char *nm = buf; |
85 | 89 | ||
90 | /* can't use print_vma_addr() yet as it doesn't check for | ||
91 | * non-inclusive vma | ||
92 | */ | ||
93 | |||
86 | vma = find_vma(current->active_mm, address); | 94 | vma = find_vma(current->active_mm, address); |
87 | 95 | ||
88 | /* check against the find_vma( ) behaviour which returns the next VMA | 96 | /* check against the find_vma( ) behaviour which returns the next VMA |
@@ -98,10 +106,13 @@ static void show_faulting_vma(unsigned long address, char *buf) | |||
98 | ino = inode->i_ino; | 106 | ino = inode->i_ino; |
99 | } | 107 | } |
100 | pr_info(" @off 0x%lx in [%s]\n" | 108 | pr_info(" @off 0x%lx in [%s]\n" |
101 | " VMA: 0x%08lx to 0x%08lx\n\n", | 109 | " VMA: 0x%08lx to 0x%08lx\n", |
102 | address - vma->vm_start, nm, vma->vm_start, vma->vm_end); | 110 | vma->vm_start < TASK_UNMAPPED_BASE ? |
103 | } else | 111 | address : address - vma->vm_start, |
112 | nm, vma->vm_start, vma->vm_end); | ||
113 | } else { | ||
104 | pr_info(" @No matching VMA found\n"); | 114 | pr_info(" @No matching VMA found\n"); |
115 | } | ||
105 | } | 116 | } |
106 | 117 | ||
107 | static void show_ecr_verbose(struct pt_regs *regs) | 118 | static void show_ecr_verbose(struct pt_regs *regs) |
@@ -110,7 +121,7 @@ static void show_ecr_verbose(struct pt_regs *regs) | |||
110 | unsigned long address; | 121 | unsigned long address; |
111 | 122 | ||
112 | cause_reg = current->thread.cause_code; | 123 | cause_reg = current->thread.cause_code; |
113 | pr_info("\n[ECR]: 0x%08x => ", cause_reg); | 124 | pr_info("\n[ECR ]: 0x%08x => ", cause_reg); |
114 | 125 | ||
115 | /* For Data fault, this is data address not instruction addr */ | 126 | /* For Data fault, this is data address not instruction addr */ |
116 | address = current->thread.fault_address; | 127 | address = current->thread.fault_address; |
@@ -120,7 +131,7 @@ static void show_ecr_verbose(struct pt_regs *regs) | |||
120 | 131 | ||
121 | /* For DTLB Miss or ProtV, display the memory involved too */ | 132 | /* For DTLB Miss or ProtV, display the memory involved too */ |
122 | if (vec == ECR_V_DTLB_MISS) { | 133 | if (vec == ECR_V_DTLB_MISS) { |
123 | pr_cont("Invalid (%s) @ 0x%08lx by insn @ 0x%08lx\n", | 134 | pr_cont("Invalid %s 0x%08lx by insn @ 0x%08lx\n", |
124 | (cause_code == 0x01) ? "Read From" : | 135 | (cause_code == 0x01) ? "Read From" : |
125 | ((cause_code == 0x02) ? "Write to" : "EX"), | 136 | ((cause_code == 0x02) ? "Write to" : "EX"), |
126 | address, regs->ret); | 137 | address, regs->ret); |
@@ -167,20 +178,23 @@ void show_regs(struct pt_regs *regs) | |||
167 | if (current->thread.cause_code) | 178 | if (current->thread.cause_code) |
168 | show_ecr_verbose(regs); | 179 | show_ecr_verbose(regs); |
169 | 180 | ||
170 | pr_info("[EFA]: 0x%08lx\n", current->thread.fault_address); | 181 | pr_info("[EFA ]: 0x%08lx\n[BLINK ]: %pS\n[ERET ]: %pS\n", |
171 | pr_info("[ERET]: 0x%08lx (PC of Faulting Instr)\n", regs->ret); | 182 | current->thread.fault_address, |
183 | (void *)regs->blink, (void *)regs->ret); | ||
172 | 184 | ||
173 | show_faulting_vma(regs->ret, buf); /* faulting code, not data */ | 185 | if (user_mode(regs)) |
186 | show_faulting_vma(regs->ret, buf); /* faulting code, not data */ | ||
174 | 187 | ||
175 | /* can't use print_vma_addr() yet as it doesn't check for | 188 | pr_info("[STAT32]: 0x%08lx", regs->status32); |
176 | * non-inclusive vma | 189 | |
177 | */ | 190 | #define STS_BIT(r, bit) r->status32 & STATUS_##bit##_MASK ? #bit : "" |
191 | if (!user_mode(regs)) | ||
192 | pr_cont(" : %2s %2s %2s %2s %2s\n", | ||
193 | STS_BIT(regs, AE), STS_BIT(regs, A2), STS_BIT(regs, A1), | ||
194 | STS_BIT(regs, E2), STS_BIT(regs, E1)); | ||
178 | 195 | ||
179 | /* print special regs */ | 196 | pr_info("BTA: 0x%08lx\t SP: 0x%08lx\t FP: 0x%08lx\n", |
180 | pr_info("status32: 0x%08lx\n", regs->status32); | 197 | regs->bta, regs->sp, regs->fp); |
181 | pr_info(" SP: 0x%08lx\tFP: 0x%08lx\n", regs->sp, regs->fp); | ||
182 | pr_info("BTA: 0x%08lx\tBLINK: 0x%08lx\n", | ||
183 | regs->bta, regs->blink); | ||
184 | pr_info("LPS: 0x%08lx\tLPE: 0x%08lx\tLPC: 0x%08lx\n", | 198 | pr_info("LPS: 0x%08lx\tLPE: 0x%08lx\tLPC: 0x%08lx\n", |
185 | regs->lp_start, regs->lp_end, regs->lp_count); | 199 | regs->lp_start, regs->lp_end, regs->lp_count); |
186 | 200 | ||