1 /* 2 * (C) Copyright 2013 3 * David Feng <fenghua@phytium.com.cn> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <linux/compiler.h> 10 #include <efi_loader.h> 11 #include <iomem.h> 12 #include <stacktrace.h> 13 #ifdef CONFIG_ROCKCHIP_MINIDUMP 14 #include <rk_mini_dump.h> 15 #endif 16 17 DECLARE_GLOBAL_DATA_PTR; 18 19 #if !CONFIG_IS_ENABLED(IRQ) 20 int interrupt_init(void) 21 { 22 return 0; 23 } 24 25 void enable_interrupts(void) 26 { 27 return; 28 } 29 30 int disable_interrupts(void) 31 { 32 return 0; 33 } 34 #endif 35 36 #define REG_BITS(val, shift, mask) (((val) >> (shift)) & (mask)) 37 38 #ifndef CONFIG_SPL_BUILD 39 void show_regs(struct pt_regs *regs) 40 { 41 int el = current_el(); 42 int i; 43 44 const char *esr_bits_ec[] = { 45 [0] = "an unknown reason", 46 [1] = "a WFI or WFE instruction", 47 [3] = "an MCR or MRC access", 48 [4] = "an MCRR or MRRC access", 49 [5] = "an MCR or MRC access", 50 [6] = "an LDC or STC access to CP14", 51 [7] = "an access to an Advanced SIMD or floating-point register, resulting from CPACR_EL1.FPEN or CPTR_ELx.TFP", 52 [8] = "an MCR or MRC access", 53 [12] = "an MCRR or MRRC access", 54 [14] = "an Illegal execution state, or a PC or SP alignment fault", 55 [10] = "HVC or SVC instruction execution", 56 [18] = "HVC or SVC instruction execution", 57 [19] = "SMC instruction execution in AArch32 state", 58 [21] = "HVC or SVC instruction execution", 59 [22] = "HVC or SVC instruction execution", 60 [23] = "SMC instruction execution in AArch64 state", 61 [24] = "MSR, MRS, or System instruction execution in AArch64 state", 62 [31] = "IMPLEMENTATION DEFINED exception to EL3", 63 [32] = "an Instruction abort", 64 [33] = "an Instruction abort", 65 [34] = "an Illegal execution state, or a PC or SP alignment fault", 66 [36] = "a Data abort, from lower exception level", 67 [37] = "a Data abort, from current exception level", 68 [38] = "an Illegal execution state, or a PC or SP alignment fault", 69 [40] = "a trapped Floating-point exception", 70 [44] = "a trapped Floating-point exception", 71 [47] = "SError interrupt", 72 [48] = "a Breakpoint or Vector Catch debug event", 73 [49] = "a Breakpoint or Vector Catch debug event", 74 [50] = "a Software Step debug event", 75 [51] = "a Software Step debug event", 76 [52] = "a Watchpoint debug event", 77 [53] = "a Watchpoint debug event", 78 [56] = "execution of a Software Breakpoint instructio", 79 }; 80 81 printf("\n"); 82 83 /* PC/LR/SP ... */ 84 printf("* Reason: Exception from %s\n", esr_bits_ec[REG_BITS(regs->esr, 26, 0x3f)]); 85 if (gd->flags & GD_FLG_RELOC) { 86 printf("* PC = %016lx\n", regs->elr - gd->reloc_off); 87 printf("* LR = %016lx\n", regs->regs[30] - gd->reloc_off); 88 } else { 89 printf("* ELR(PC) = %016lx\n", regs->elr); 90 printf("* LR = %016lx\n", regs->regs[30]); 91 } 92 printf("* SP = %016lx\n", regs->sp); 93 printf("* ESR_EL%d = %016lx\n", el, regs->esr); 94 printf("* Reloc Off = %016lx\n\n", gd->reloc_off); 95 96 /* CPU */ 97 for (i = 0; i < 29; i += 2) 98 printf("x%-2d: %016lx x%-2d: %016lx\n", 99 i, regs->regs[i], i+1, regs->regs[i+1]); 100 printf("\n"); 101 102 /* SoC */ 103 #ifdef CONFIG_ROCKCHIP_CRASH_DUMP 104 iomem_show_by_compatible("-cru", 0, 0x400); 105 iomem_show_by_compatible("-pmucru", 0, 0x400); 106 iomem_show_by_compatible("-grf", 0, 0x400); 107 iomem_show_by_compatible("-pmugrf", 0, 0x400); 108 #endif 109 /* Call trace */ 110 dump_core_stack(regs); 111 } 112 113 #else 114 void show_regs(struct pt_regs *regs) 115 { 116 int i; 117 118 if (gd->flags & GD_FLG_RELOC) { 119 printf("ELR: %lx\n", regs->elr - gd->reloc_off); 120 printf("LR: %lx\n", regs->regs[30] - gd->reloc_off); 121 } else { 122 printf("ELR: %lx\n", regs->elr); 123 printf("LR: %lx\n", regs->regs[30]); 124 } 125 126 printf("ESR: %lx (ec=%ld)\n", regs->esr, REG_BITS(regs->esr, 26, 0x3f)); 127 128 for (i = 0; i < 29; i += 2) 129 printf("x%-2d: %016lx x%-2d: %016lx\n", 130 i, regs->regs[i], i+1, regs->regs[i+1]); 131 printf("\n"); 132 133 dump_core_stack(regs); 134 } 135 #endif 136 137 /* 138 * do_bad_sync handles the impossible case in the Synchronous Abort vector. 139 */ 140 void do_bad_sync(struct pt_regs *pt_regs, unsigned int esr) 141 { 142 efi_restore_gd(); 143 printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08x\n", esr); 144 show_regs(pt_regs); 145 panic("Resetting CPU ...\n"); 146 } 147 148 /* 149 * do_bad_irq handles the impossible case in the Irq vector. 150 */ 151 void do_bad_irq(struct pt_regs *pt_regs, unsigned int esr) 152 { 153 efi_restore_gd(); 154 printf("Bad mode in \"Irq\" handler, esr 0x%08x\n", esr); 155 show_regs(pt_regs); 156 panic("Resetting CPU ...\n"); 157 } 158 159 /* 160 * do_bad_fiq handles the impossible case in the Fiq vector. 161 */ 162 void do_bad_fiq(struct pt_regs *pt_regs, unsigned int esr) 163 { 164 efi_restore_gd(); 165 printf("Bad mode in \"Fiq\" handler, esr 0x%08x\n", esr); 166 show_regs(pt_regs); 167 panic("Resetting CPU ...\n"); 168 } 169 170 /* 171 * do_bad_error handles the impossible case in the Error vector. 172 */ 173 void do_bad_error(struct pt_regs *pt_regs, unsigned int esr) 174 { 175 efi_restore_gd(); 176 printf("Bad mode in \"Error\" handler, esr 0x%08x\n", esr); 177 show_regs(pt_regs); 178 panic("Resetting CPU ...\n"); 179 } 180 181 /* 182 * do_sync handles the Synchronous Abort exception. 183 */ 184 void do_sync(struct pt_regs *pt_regs, unsigned int esr) 185 { 186 efi_restore_gd(); 187 #ifdef CONFIG_ROCKCHIP_MINIDUMP 188 if (md_no_fault_handler(pt_regs, esr)) { 189 /* Return to next instruction */ 190 pt_regs->elr += 4; 191 return; 192 } 193 #endif 194 printf("\"Synchronous Abort\" handler, esr 0x%08x\n", esr); 195 show_regs(pt_regs); 196 panic("Resetting CPU ...\n"); 197 } 198 199 #if !CONFIG_IS_ENABLED(IRQ) 200 /* 201 * do_irq handles the Irq exception. 202 */ 203 void do_irq(struct pt_regs *pt_regs, unsigned int esr) 204 { 205 efi_restore_gd(); 206 printf("\"Irq\" handler, esr 0x%08x\n", esr); 207 show_regs(pt_regs); 208 panic("Resetting CPU ...\n"); 209 } 210 #endif 211 212 /* 213 * do_fiq handles the Fiq exception. 214 */ 215 void do_fiq(struct pt_regs *pt_regs, unsigned int esr) 216 { 217 efi_restore_gd(); 218 printf("\"Fiq\" handler, esr 0x%08x\n", esr); 219 show_regs(pt_regs); 220 panic("Resetting CPU ...\n"); 221 } 222 223 /* 224 * do_error handles the Error exception. 225 * Errors are more likely to be processor specific, 226 * it is defined with weak attribute and can be redefined 227 * in processor specific code. 228 */ 229 void __weak do_error(struct pt_regs *pt_regs, unsigned int esr) 230 { 231 efi_restore_gd(); 232 #ifdef CONFIG_ROCKCHIP_MINIDUMP 233 if (md_no_fault_handler(pt_regs, esr)) { 234 /* Return to next instruction */ 235 pt_regs->elr += 4; 236 return; 237 } 238 #endif 239 printf("\"Error\" handler, esr 0x%08x\n", esr); 240 show_regs(pt_regs); 241 panic("Resetting CPU ...\n"); 242 } 243