| .. | .. |
|---|
| 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 | } |
|---|