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