0001
0002
0003
0004
0005
0006 #include <linux/ptrace.h>
0007 #include <linux/module.h>
0008 #include <linux/mm.h>
0009 #include <linux/fs.h>
0010 #include <linux/kdev_t.h>
0011 #include <linux/proc_fs.h>
0012 #include <linux/file.h>
0013 #include <linux/sched/mm.h>
0014 #include <linux/sched/debug.h>
0015
0016 #include <asm/arcregs.h>
0017 #include <asm/irqflags.h>
0018
0019 #define ARC_PATH_MAX 256
0020
0021 static noinline void print_regs_scratch(struct pt_regs *regs)
0022 {
0023 pr_cont("BTA: 0x%08lx\n SP: 0x%08lx FP: 0x%08lx BLK: %pS\n",
0024 regs->bta, regs->sp, regs->fp, (void *)regs->blink);
0025 pr_cont("LPS: 0x%08lx\tLPE: 0x%08lx\tLPC: 0x%08lx\n",
0026 regs->lp_start, regs->lp_end, regs->lp_count);
0027
0028 pr_info("r00: 0x%08lx\tr01: 0x%08lx\tr02: 0x%08lx\n" \
0029 "r03: 0x%08lx\tr04: 0x%08lx\tr05: 0x%08lx\n" \
0030 "r06: 0x%08lx\tr07: 0x%08lx\tr08: 0x%08lx\n" \
0031 "r09: 0x%08lx\tr10: 0x%08lx\tr11: 0x%08lx\n" \
0032 "r12: 0x%08lx\t",
0033 regs->r0, regs->r1, regs->r2,
0034 regs->r3, regs->r4, regs->r5,
0035 regs->r6, regs->r7, regs->r8,
0036 regs->r9, regs->r10, regs->r11,
0037 regs->r12);
0038 }
0039
0040 static void print_regs_callee(struct callee_regs *regs)
0041 {
0042 pr_cont("r13: 0x%08lx\tr14: 0x%08lx\n" \
0043 "r15: 0x%08lx\tr16: 0x%08lx\tr17: 0x%08lx\n" \
0044 "r18: 0x%08lx\tr19: 0x%08lx\tr20: 0x%08lx\n" \
0045 "r21: 0x%08lx\tr22: 0x%08lx\tr23: 0x%08lx\n" \
0046 "r24: 0x%08lx\tr25: 0x%08lx\n",
0047 regs->r13, regs->r14,
0048 regs->r15, regs->r16, regs->r17,
0049 regs->r18, regs->r19, regs->r20,
0050 regs->r21, regs->r22, regs->r23,
0051 regs->r24, regs->r25);
0052 }
0053
0054 static void print_task_path_n_nm(struct task_struct *tsk)
0055 {
0056 char *path_nm = NULL;
0057 struct mm_struct *mm;
0058 struct file *exe_file;
0059 char buf[ARC_PATH_MAX];
0060
0061 mm = get_task_mm(tsk);
0062 if (!mm)
0063 goto done;
0064
0065 exe_file = get_mm_exe_file(mm);
0066 mmput(mm);
0067
0068 if (exe_file) {
0069 path_nm = file_path(exe_file, buf, ARC_PATH_MAX-1);
0070 fput(exe_file);
0071 }
0072
0073 done:
0074 pr_info("Path: %s\n", !IS_ERR(path_nm) ? path_nm : "?");
0075 }
0076
0077 static void show_faulting_vma(unsigned long address)
0078 {
0079 struct vm_area_struct *vma;
0080 struct mm_struct *active_mm = current->active_mm;
0081
0082
0083
0084
0085 mmap_read_lock(active_mm);
0086 vma = vma_lookup(active_mm, address);
0087
0088
0089
0090
0091 if (vma) {
0092 char buf[ARC_PATH_MAX];
0093 char *nm = "?";
0094
0095 if (vma->vm_file) {
0096 nm = file_path(vma->vm_file, buf, ARC_PATH_MAX-1);
0097 if (IS_ERR(nm))
0098 nm = "?";
0099 }
0100 pr_info(" @off 0x%lx in [%s] VMA: 0x%08lx to 0x%08lx\n",
0101 vma->vm_start < TASK_UNMAPPED_BASE ?
0102 address : address - vma->vm_start,
0103 nm, vma->vm_start, vma->vm_end);
0104 } else
0105 pr_info(" @No matching VMA found\n");
0106
0107 mmap_read_unlock(active_mm);
0108 }
0109
0110 static void show_ecr_verbose(struct pt_regs *regs)
0111 {
0112 unsigned int vec, cause_code;
0113 unsigned long address;
0114
0115
0116 address = current->thread.fault_address;
0117
0118 vec = regs->ecr_vec;
0119 cause_code = regs->ecr_cause;
0120
0121
0122 if (vec == ECR_V_DTLB_MISS) {
0123 pr_cont("Invalid %s @ 0x%08lx by insn @ %pS\n",
0124 (cause_code == 0x01) ? "Read" :
0125 ((cause_code == 0x02) ? "Write" : "EX"),
0126 address, (void *)regs->ret);
0127 } else if (vec == ECR_V_ITLB_MISS) {
0128 pr_cont("Insn could not be fetched\n");
0129 } else if (vec == ECR_V_MACH_CHK) {
0130 pr_cont("Machine Check (%s)\n", (cause_code == 0x0) ?
0131 "Double Fault" : "Other Fatal Err");
0132
0133 } else if (vec == ECR_V_PROTV) {
0134 if (cause_code == ECR_C_PROTV_INST_FETCH)
0135 pr_cont("Execute from Non-exec Page\n");
0136 else if (cause_code == ECR_C_PROTV_MISALIG_DATA &&
0137 IS_ENABLED(CONFIG_ISA_ARCOMPACT))
0138 pr_cont("Misaligned r/w from 0x%08lx\n", address);
0139 else
0140 pr_cont("%s access not allowed on page\n",
0141 (cause_code == 0x01) ? "Read" :
0142 ((cause_code == 0x02) ? "Write" : "EX"));
0143 } else if (vec == ECR_V_INSN_ERR) {
0144 pr_cont("Illegal Insn\n");
0145 #ifdef CONFIG_ISA_ARCV2
0146 } else if (vec == ECR_V_MEM_ERR) {
0147 if (cause_code == 0x00)
0148 pr_cont("Bus Error from Insn Mem\n");
0149 else if (cause_code == 0x10)
0150 pr_cont("Bus Error from Data Mem\n");
0151 else
0152 pr_cont("Bus Error, check PRM\n");
0153 } else if (vec == ECR_V_MISALIGN) {
0154 pr_cont("Misaligned r/w from 0x%08lx\n", address);
0155 #endif
0156 } else if (vec == ECR_V_TRAP) {
0157 if (regs->ecr_param == 5)
0158 pr_cont("gcc generated __builtin_trap\n");
0159 } else {
0160 pr_cont("Check Programmer's Manual\n");
0161 }
0162 }
0163
0164
0165
0166
0167
0168 void show_regs(struct pt_regs *regs)
0169 {
0170 struct task_struct *tsk = current;
0171 struct callee_regs *cregs = (struct callee_regs *)tsk->thread.callee_reg;
0172
0173
0174
0175
0176
0177 preempt_enable();
0178
0179 print_task_path_n_nm(tsk);
0180 show_regs_print_info(KERN_INFO);
0181
0182 show_ecr_verbose(regs);
0183
0184 if (user_mode(regs))
0185 show_faulting_vma(regs->ret);
0186
0187 pr_info("ECR: 0x%08lx EFA: 0x%08lx ERET: 0x%08lx\nSTAT: 0x%08lx",
0188 regs->event, current->thread.fault_address, regs->ret,
0189 regs->status32);
0190
0191 #define STS_BIT(r, bit) r->status32 & STATUS_##bit##_MASK ? #bit" " : ""
0192
0193 #ifdef CONFIG_ISA_ARCOMPACT
0194 pr_cont(" [%2s%2s%2s%2s%2s%2s%2s]",
0195 (regs->status32 & STATUS_U_MASK) ? "U " : "K ",
0196 STS_BIT(regs, DE), STS_BIT(regs, AE),
0197 STS_BIT(regs, A2), STS_BIT(regs, A1),
0198 STS_BIT(regs, E2), STS_BIT(regs, E1));
0199 #else
0200 pr_cont(" [%2s%2s%2s%2s] ",
0201 STS_BIT(regs, IE),
0202 (regs->status32 & STATUS_U_MASK) ? "U " : "K ",
0203 STS_BIT(regs, DE), STS_BIT(regs, AE));
0204 #endif
0205
0206 print_regs_scratch(regs);
0207 if (cregs)
0208 print_regs_callee(cregs);
0209
0210 preempt_disable();
0211 }
0212
0213 void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
0214 unsigned long address)
0215 {
0216 current->thread.fault_address = address;
0217
0218
0219 pr_info("\n%s\n", str);
0220
0221
0222 show_regs(regs);
0223
0224
0225 if (!user_mode(regs))
0226 show_stacktrace(current, regs, KERN_DEFAULT);
0227 }