.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify |
---|
5 | | - * it under the terms of the GNU General Public License version 2 as |
---|
6 | 4 | */ |
---|
7 | 5 | |
---|
8 | 6 | #include <linux/ptrace.h> |
---|
.. | .. |
---|
20 | 18 | |
---|
21 | 19 | #define ARC_PATH_MAX 256 |
---|
22 | 20 | |
---|
23 | | -/* |
---|
24 | | - * Common routine to print scratch regs (r0-r12) or callee regs (r13-r25) |
---|
25 | | - * -Prints 3 regs per line and a CR. |
---|
26 | | - * -To continue, callee regs right after scratch, special handling of CR |
---|
27 | | - */ |
---|
28 | | -static noinline void print_reg_file(long *reg_rev, int start_num) |
---|
| 21 | +static noinline void print_regs_scratch(struct pt_regs *regs) |
---|
29 | 22 | { |
---|
30 | | - unsigned int i; |
---|
31 | | - char buf[512]; |
---|
32 | | - int n = 0, len = sizeof(buf); |
---|
| 23 | + pr_cont("BTA: 0x%08lx\n SP: 0x%08lx FP: 0x%08lx BLK: %pS\n", |
---|
| 24 | + regs->bta, regs->sp, regs->fp, (void *)regs->blink); |
---|
| 25 | + pr_cont("LPS: 0x%08lx\tLPE: 0x%08lx\tLPC: 0x%08lx\n", |
---|
| 26 | + regs->lp_start, regs->lp_end, regs->lp_count); |
---|
33 | 27 | |
---|
34 | | - for (i = start_num; i < start_num + 13; i++) { |
---|
35 | | - n += scnprintf(buf + n, len - n, "r%02u: 0x%08lx\t", |
---|
36 | | - i, (unsigned long)*reg_rev); |
---|
37 | | - |
---|
38 | | - if (((i + 1) % 3) == 0) |
---|
39 | | - n += scnprintf(buf + n, len - n, "\n"); |
---|
40 | | - |
---|
41 | | - /* because pt_regs has regs reversed: r12..r0, r25..r13 */ |
---|
42 | | - if (is_isa_arcv2() && start_num == 0) |
---|
43 | | - reg_rev++; |
---|
44 | | - else |
---|
45 | | - reg_rev--; |
---|
46 | | - } |
---|
47 | | - |
---|
48 | | - if (start_num != 0) |
---|
49 | | - n += scnprintf(buf + n, len - n, "\n\n"); |
---|
50 | | - |
---|
51 | | - /* To continue printing callee regs on same line as scratch regs */ |
---|
52 | | - if (start_num == 0) |
---|
53 | | - pr_info("%s", buf); |
---|
54 | | - else |
---|
55 | | - pr_cont("%s\n", buf); |
---|
| 28 | + pr_info("r00: 0x%08lx\tr01: 0x%08lx\tr02: 0x%08lx\n" \ |
---|
| 29 | + "r03: 0x%08lx\tr04: 0x%08lx\tr05: 0x%08lx\n" \ |
---|
| 30 | + "r06: 0x%08lx\tr07: 0x%08lx\tr08: 0x%08lx\n" \ |
---|
| 31 | + "r09: 0x%08lx\tr10: 0x%08lx\tr11: 0x%08lx\n" \ |
---|
| 32 | + "r12: 0x%08lx\t", |
---|
| 33 | + regs->r0, regs->r1, regs->r2, |
---|
| 34 | + regs->r3, regs->r4, regs->r5, |
---|
| 35 | + regs->r6, regs->r7, regs->r8, |
---|
| 36 | + regs->r9, regs->r10, regs->r11, |
---|
| 37 | + regs->r12); |
---|
56 | 38 | } |
---|
57 | 39 | |
---|
58 | | -static void show_callee_regs(struct callee_regs *cregs) |
---|
| 40 | +static void print_regs_callee(struct callee_regs *regs) |
---|
59 | 41 | { |
---|
60 | | - print_reg_file(&(cregs->r13), 13); |
---|
| 42 | + pr_cont("r13: 0x%08lx\tr14: 0x%08lx\n" \ |
---|
| 43 | + "r15: 0x%08lx\tr16: 0x%08lx\tr17: 0x%08lx\n" \ |
---|
| 44 | + "r18: 0x%08lx\tr19: 0x%08lx\tr20: 0x%08lx\n" \ |
---|
| 45 | + "r21: 0x%08lx\tr22: 0x%08lx\tr23: 0x%08lx\n" \ |
---|
| 46 | + "r24: 0x%08lx\tr25: 0x%08lx\n", |
---|
| 47 | + regs->r13, regs->r14, |
---|
| 48 | + regs->r15, regs->r16, regs->r17, |
---|
| 49 | + regs->r18, regs->r19, regs->r20, |
---|
| 50 | + regs->r21, regs->r22, regs->r23, |
---|
| 51 | + regs->r24, regs->r25); |
---|
61 | 52 | } |
---|
62 | 53 | |
---|
63 | 54 | static void print_task_path_n_nm(struct task_struct *tsk) |
---|
.. | .. |
---|
91 | 82 | /* can't use print_vma_addr() yet as it doesn't check for |
---|
92 | 83 | * non-inclusive vma |
---|
93 | 84 | */ |
---|
94 | | - down_read(&active_mm->mmap_sem); |
---|
| 85 | + mmap_read_lock(active_mm); |
---|
95 | 86 | vma = find_vma(active_mm, address); |
---|
96 | 87 | |
---|
97 | 88 | /* check against the find_vma( ) behaviour which returns the next VMA |
---|
.. | .. |
---|
106 | 97 | if (IS_ERR(nm)) |
---|
107 | 98 | nm = "?"; |
---|
108 | 99 | } |
---|
109 | | - pr_info(" @off 0x%lx in [%s]\n" |
---|
110 | | - " VMA: 0x%08lx to 0x%08lx\n", |
---|
| 100 | + pr_info(" @off 0x%lx in [%s] VMA: 0x%08lx to 0x%08lx\n", |
---|
111 | 101 | vma->vm_start < TASK_UNMAPPED_BASE ? |
---|
112 | 102 | address : address - vma->vm_start, |
---|
113 | 103 | nm, vma->vm_start, vma->vm_end); |
---|
114 | 104 | } else |
---|
115 | 105 | pr_info(" @No matching VMA found\n"); |
---|
116 | 106 | |
---|
117 | | - up_read(&active_mm->mmap_sem); |
---|
| 107 | + mmap_read_unlock(active_mm); |
---|
118 | 108 | } |
---|
119 | 109 | |
---|
120 | 110 | static void show_ecr_verbose(struct pt_regs *regs) |
---|
121 | 111 | { |
---|
122 | 112 | unsigned int vec, cause_code; |
---|
123 | 113 | unsigned long address; |
---|
124 | | - |
---|
125 | | - pr_info("\n[ECR ]: 0x%08lx => ", regs->event); |
---|
126 | 114 | |
---|
127 | 115 | /* For Data fault, this is data address not instruction addr */ |
---|
128 | 116 | address = current->thread.fault_address; |
---|
.. | .. |
---|
132 | 120 | |
---|
133 | 121 | /* For DTLB Miss or ProtV, display the memory involved too */ |
---|
134 | 122 | if (vec == ECR_V_DTLB_MISS) { |
---|
135 | | - pr_cont("Invalid %s @ 0x%08lx by insn @ 0x%08lx\n", |
---|
| 123 | + pr_cont("Invalid %s @ 0x%08lx by insn @ %pS\n", |
---|
136 | 124 | (cause_code == 0x01) ? "Read" : |
---|
137 | 125 | ((cause_code == 0x02) ? "Write" : "EX"), |
---|
138 | | - address, regs->ret); |
---|
| 126 | + address, (void *)regs->ret); |
---|
139 | 127 | } else if (vec == ECR_V_ITLB_MISS) { |
---|
140 | 128 | pr_cont("Insn could not be fetched\n"); |
---|
141 | 129 | } else if (vec == ECR_V_MACH_CHK) { |
---|
.. | .. |
---|
145 | 133 | } else if (vec == ECR_V_PROTV) { |
---|
146 | 134 | if (cause_code == ECR_C_PROTV_INST_FETCH) |
---|
147 | 135 | pr_cont("Execute from Non-exec Page\n"); |
---|
148 | | - else if (cause_code == ECR_C_PROTV_MISALIG_DATA) |
---|
| 136 | + else if (cause_code == ECR_C_PROTV_MISALIG_DATA && |
---|
| 137 | + IS_ENABLED(CONFIG_ISA_ARCOMPACT)) |
---|
149 | 138 | pr_cont("Misaligned r/w from 0x%08lx\n", address); |
---|
150 | 139 | else |
---|
151 | 140 | pr_cont("%s access not allowed on page\n", |
---|
.. | .. |
---|
161 | 150 | pr_cont("Bus Error from Data Mem\n"); |
---|
162 | 151 | else |
---|
163 | 152 | pr_cont("Bus Error, check PRM\n"); |
---|
| 153 | + } else if (vec == ECR_V_MISALIGN) { |
---|
| 154 | + pr_cont("Misaligned r/w from 0x%08lx\n", address); |
---|
164 | 155 | #endif |
---|
165 | 156 | } else if (vec == ECR_V_TRAP) { |
---|
166 | 157 | if (regs->ecr_param == 5) |
---|
.. | .. |
---|
177 | 168 | void show_regs(struct pt_regs *regs) |
---|
178 | 169 | { |
---|
179 | 170 | struct task_struct *tsk = current; |
---|
180 | | - struct callee_regs *cregs; |
---|
| 171 | + struct callee_regs *cregs = (struct callee_regs *)tsk->thread.callee_reg; |
---|
181 | 172 | |
---|
182 | 173 | /* |
---|
183 | 174 | * generic code calls us with preemption disabled, but some calls |
---|
.. | .. |
---|
190 | 181 | |
---|
191 | 182 | show_ecr_verbose(regs); |
---|
192 | 183 | |
---|
193 | | - pr_info("[EFA ]: 0x%08lx\n[BLINK ]: %pS\n[ERET ]: %pS\n", |
---|
194 | | - current->thread.fault_address, |
---|
195 | | - (void *)regs->blink, (void *)regs->ret); |
---|
196 | | - |
---|
197 | 184 | if (user_mode(regs)) |
---|
198 | 185 | show_faulting_vma(regs->ret); /* faulting code, not data */ |
---|
199 | 186 | |
---|
200 | | - pr_info("[STAT32]: 0x%08lx", regs->status32); |
---|
| 187 | + pr_info("ECR: 0x%08lx EFA: 0x%08lx ERET: 0x%08lx\nSTAT: 0x%08lx", |
---|
| 188 | + regs->event, current->thread.fault_address, regs->ret, |
---|
| 189 | + regs->status32); |
---|
201 | 190 | |
---|
202 | 191 | #define STS_BIT(r, bit) r->status32 & STATUS_##bit##_MASK ? #bit" " : "" |
---|
203 | 192 | |
---|
204 | 193 | #ifdef CONFIG_ISA_ARCOMPACT |
---|
205 | | - pr_cont(" : %2s%2s%2s%2s%2s%2s%2s\n", |
---|
| 194 | + pr_cont(" [%2s%2s%2s%2s%2s%2s%2s]", |
---|
206 | 195 | (regs->status32 & STATUS_U_MASK) ? "U " : "K ", |
---|
207 | 196 | STS_BIT(regs, DE), STS_BIT(regs, AE), |
---|
208 | 197 | STS_BIT(regs, A2), STS_BIT(regs, A1), |
---|
209 | 198 | STS_BIT(regs, E2), STS_BIT(regs, E1)); |
---|
210 | 199 | #else |
---|
211 | | - pr_cont(" : %2s%2s%2s%2s\n", |
---|
| 200 | + pr_cont(" [%2s%2s%2s%2s] ", |
---|
212 | 201 | STS_BIT(regs, IE), |
---|
213 | 202 | (regs->status32 & STATUS_U_MASK) ? "U " : "K ", |
---|
214 | 203 | STS_BIT(regs, DE), STS_BIT(regs, AE)); |
---|
215 | 204 | #endif |
---|
216 | | - pr_info("BTA: 0x%08lx\t SP: 0x%08lx\t FP: 0x%08lx\n", |
---|
217 | | - regs->bta, regs->sp, regs->fp); |
---|
218 | | - pr_info("LPS: 0x%08lx\tLPE: 0x%08lx\tLPC: 0x%08lx\n", |
---|
219 | | - regs->lp_start, regs->lp_end, regs->lp_count); |
---|
220 | 205 | |
---|
221 | | - /* print regs->r0 thru regs->r12 |
---|
222 | | - * Sequential printing was generating horrible code |
---|
223 | | - */ |
---|
224 | | - print_reg_file(&(regs->r0), 0); |
---|
225 | | - |
---|
226 | | - /* If Callee regs were saved, display them too */ |
---|
227 | | - cregs = (struct callee_regs *)current->thread.callee_reg; |
---|
| 206 | + print_regs_scratch(regs); |
---|
228 | 207 | if (cregs) |
---|
229 | | - show_callee_regs(cregs); |
---|
| 208 | + print_regs_callee(cregs); |
---|
230 | 209 | |
---|
231 | 210 | preempt_disable(); |
---|
232 | 211 | } |
---|
.. | .. |
---|
244 | 223 | |
---|
245 | 224 | /* Show stack trace if this Fatality happened in kernel mode */ |
---|
246 | 225 | if (!user_mode(regs)) |
---|
247 | | - show_stacktrace(current, regs); |
---|
| 226 | + show_stacktrace(current, regs, KERN_DEFAULT); |
---|
248 | 227 | } |
---|