10ae76531SDavid Feng /* 20ae76531SDavid Feng * (C) Copyright 2013 30ae76531SDavid Feng * David Feng <fenghua@phytium.com.cn> 40ae76531SDavid Feng * 50ae76531SDavid Feng * SPDX-License-Identifier: GPL-2.0+ 60ae76531SDavid Feng */ 70ae76531SDavid Feng 80ae76531SDavid Feng #include <common.h> 90ae76531SDavid Feng #include <linux/compiler.h> 1064982915SAlexander Graf #include <efi_loader.h> 1158d85a14SJoseph Chen #include <iomem.h> 12d554a7b2SJoseph Chen #include <stacktrace.h> 130ae76531SDavid Feng 145e076729SPeng Fan DECLARE_GLOBAL_DATA_PTR; 153fe16d46SJoseph Chen 16*7cef7918SJoseph Chen #if !CONFIG_IS_ENABLED(IRQ) 170ae76531SDavid Feng int interrupt_init(void) 180ae76531SDavid Feng { 190ae76531SDavid Feng return 0; 200ae76531SDavid Feng } 210ae76531SDavid Feng 220ae76531SDavid Feng void enable_interrupts(void) 230ae76531SDavid Feng { 240ae76531SDavid Feng return; 250ae76531SDavid Feng } 260ae76531SDavid Feng 270ae76531SDavid Feng int disable_interrupts(void) 280ae76531SDavid Feng { 290ae76531SDavid Feng return 0; 300ae76531SDavid Feng } 31fa40f8a0SJoseph Chen #endif 320ae76531SDavid Feng 33faa7eb0fSJoseph Chen #define REG_BITS(val, shift, mask) (((val) >> (shift)) & (mask)) 34faa7eb0fSJoseph Chen 35*7cef7918SJoseph Chen #ifndef CONFIG_SPL_BUILD 36faa7eb0fSJoseph Chen void show_regs(struct pt_regs *regs) 37faa7eb0fSJoseph Chen { 38faa7eb0fSJoseph Chen int el = current_el(); 3974ab8aa2SJoseph Chen int i; 4074ab8aa2SJoseph Chen 41faa7eb0fSJoseph Chen const char *esr_bits_ec[] = { 4274ab8aa2SJoseph Chen [0] = "an unknown reason", 4374ab8aa2SJoseph Chen [1] = "a WFI or WFE instruction", 4474ab8aa2SJoseph Chen [3] = "an MCR or MRC access", 4574ab8aa2SJoseph Chen [4] = "an MCRR or MRRC access", 4674ab8aa2SJoseph Chen [5] = "an MCR or MRC access", 4774ab8aa2SJoseph Chen [6] = "an LDC or STC access to CP14", 4874ab8aa2SJoseph Chen [7] = "an access to an Advanced SIMD or floating-point register, resulting from CPACR_EL1.FPEN or CPTR_ELx.TFP", 4974ab8aa2SJoseph Chen [8] = "an MCR or MRC access", 5074ab8aa2SJoseph Chen [12] = "an MCRR or MRRC access", 5174ab8aa2SJoseph Chen [14] = "an Illegal execution state, or a PC or SP alignment fault", 5274ab8aa2SJoseph Chen [10] = "HVC or SVC instruction execution", 5374ab8aa2SJoseph Chen [18] = "HVC or SVC instruction execution", 5474ab8aa2SJoseph Chen [19] = "SMC instruction execution in AArch32 state", 5574ab8aa2SJoseph Chen [21] = "HVC or SVC instruction execution", 5674ab8aa2SJoseph Chen [22] = "HVC or SVC instruction execution", 5774ab8aa2SJoseph Chen [23] = "SMC instruction execution in AArch64 state", 5874ab8aa2SJoseph Chen [24] = "MSR, MRS, or System instruction execution in AArch64 state", 5974ab8aa2SJoseph Chen [31] = "IMPLEMENTATION DEFINED exception to EL3", 6074ab8aa2SJoseph Chen [32] = "an Instruction abort", 6174ab8aa2SJoseph Chen [33] = "an Instruction abort", 6274ab8aa2SJoseph Chen [34] = "an Illegal execution state, or a PC or SP alignment fault", 6374ab8aa2SJoseph Chen [36] = "a Data abort, from lower exception level", 6474ab8aa2SJoseph Chen [37] = "a Data abort, from current exception level", 6574ab8aa2SJoseph Chen [38] = "an Illegal execution state, or a PC or SP alignment fault", 6674ab8aa2SJoseph Chen [40] = "a trapped Floating-point exception", 6774ab8aa2SJoseph Chen [44] = "a trapped Floating-point exception", 6874ab8aa2SJoseph Chen [47] = "SError interrupt", 6974ab8aa2SJoseph Chen [48] = "a Breakpoint or Vector Catch debug event", 7074ab8aa2SJoseph Chen [49] = "a Breakpoint or Vector Catch debug event", 7174ab8aa2SJoseph Chen [50] = "a Software Step debug event", 7274ab8aa2SJoseph Chen [51] = "a Software Step debug event", 7374ab8aa2SJoseph Chen [52] = "a Watchpoint debug event", 7474ab8aa2SJoseph Chen [53] = "a Watchpoint debug event", 7574ab8aa2SJoseph Chen [56] = "execution of a Software Breakpoint instructio", 76faa7eb0fSJoseph Chen }; 77faa7eb0fSJoseph Chen 7874ab8aa2SJoseph Chen printf("\n"); 79faa7eb0fSJoseph Chen 8074ab8aa2SJoseph Chen /* PC/LR/SP ... */ 8174ab8aa2SJoseph Chen printf("* Reason: Exception from %s\n", esr_bits_ec[REG_BITS(regs->esr, 26, 0x3f)]); 82faa7eb0fSJoseph Chen if (gd->flags & GD_FLG_RELOC) { 8374ab8aa2SJoseph Chen printf("* PC = %016lx\n", regs->elr - gd->reloc_off); 84faa7eb0fSJoseph Chen printf("* LR = %016lx\n", regs->regs[30] - gd->reloc_off); 85faa7eb0fSJoseph Chen } else { 86faa7eb0fSJoseph Chen printf("* ELR(PC) = %016lx\n", regs->elr); 87faa7eb0fSJoseph Chen printf("* LR = %016lx\n", regs->regs[30]); 88faa7eb0fSJoseph Chen } 89faa7eb0fSJoseph Chen printf("* SP = %016lx\n", regs->sp); 90faa7eb0fSJoseph Chen printf("* ESR_EL%d = %016lx\n", el, regs->esr); 9174ab8aa2SJoseph Chen printf("* Reloc Off = %016lx\n\n", gd->reloc_off); 92faa7eb0fSJoseph Chen 9374ab8aa2SJoseph Chen /* CPU */ 94faa7eb0fSJoseph Chen for (i = 0; i < 29; i += 2) 95faa7eb0fSJoseph Chen printf("x%-2d: %016lx x%-2d: %016lx\n", 96faa7eb0fSJoseph Chen i, regs->regs[i], i+1, regs->regs[i+1]); 97faa7eb0fSJoseph Chen printf("\n"); 9824cd8f36SJoseph Chen 9974ab8aa2SJoseph Chen /* SoC */ 10024cd8f36SJoseph Chen #ifdef CONFIG_ROCKCHIP_CRASH_DUMP 10124cd8f36SJoseph Chen iomem_show_by_compatible("-cru", 0, 0x400); 10224cd8f36SJoseph Chen iomem_show_by_compatible("-pmucru", 0, 0x400); 10324cd8f36SJoseph Chen iomem_show_by_compatible("-grf", 0, 0x400); 10424cd8f36SJoseph Chen iomem_show_by_compatible("-pmugrf", 0, 0x400); 10524cd8f36SJoseph Chen #endif 10674ab8aa2SJoseph Chen /* Call trace */ 107d554a7b2SJoseph Chen dump_core_stack(regs); 108faa7eb0fSJoseph Chen } 109faa7eb0fSJoseph Chen 110faa7eb0fSJoseph Chen #else 1110ae76531SDavid Feng void show_regs(struct pt_regs *regs) 1120ae76531SDavid Feng { 1130ae76531SDavid Feng int i; 1140ae76531SDavid Feng 1155e076729SPeng Fan if (gd->flags & GD_FLG_RELOC) { 1165e076729SPeng Fan printf("ELR: %lx\n", regs->elr - gd->reloc_off); 1175e076729SPeng Fan printf("LR: %lx\n", regs->regs[30] - gd->reloc_off); 1185e076729SPeng Fan } else { 1190ae76531SDavid Feng printf("ELR: %lx\n", regs->elr); 1200ae76531SDavid Feng printf("LR: %lx\n", regs->regs[30]); 1215e076729SPeng Fan } 1223fe16d46SJoseph Chen 1233fe16d46SJoseph Chen printf("ESR: %lx (ec=%ld)\n", regs->esr, REG_BITS(regs->esr, 26, 0x3f)); 1243fe16d46SJoseph Chen 1250ae76531SDavid Feng for (i = 0; i < 29; i += 2) 1260ae76531SDavid Feng printf("x%-2d: %016lx x%-2d: %016lx\n", 1270ae76531SDavid Feng i, regs->regs[i], i+1, regs->regs[i+1]); 1280ae76531SDavid Feng printf("\n"); 129d554a7b2SJoseph Chen 130d554a7b2SJoseph Chen dump_core_stack(regs); 1310ae76531SDavid Feng } 132faa7eb0fSJoseph Chen #endif 1330ae76531SDavid Feng 1340ae76531SDavid Feng /* 1350ae76531SDavid Feng * do_bad_sync handles the impossible case in the Synchronous Abort vector. 1360ae76531SDavid Feng */ 1370ae76531SDavid Feng void do_bad_sync(struct pt_regs *pt_regs, unsigned int esr) 1380ae76531SDavid Feng { 13964982915SAlexander Graf efi_restore_gd(); 1400ae76531SDavid Feng printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08x\n", esr); 1410ae76531SDavid Feng show_regs(pt_regs); 1420ae76531SDavid Feng panic("Resetting CPU ...\n"); 1430ae76531SDavid Feng } 1440ae76531SDavid Feng 1450ae76531SDavid Feng /* 1460ae76531SDavid Feng * do_bad_irq handles the impossible case in the Irq vector. 1470ae76531SDavid Feng */ 1480ae76531SDavid Feng void do_bad_irq(struct pt_regs *pt_regs, unsigned int esr) 1490ae76531SDavid Feng { 15064982915SAlexander Graf efi_restore_gd(); 1510ae76531SDavid Feng printf("Bad mode in \"Irq\" handler, esr 0x%08x\n", esr); 1520ae76531SDavid Feng show_regs(pt_regs); 1530ae76531SDavid Feng panic("Resetting CPU ...\n"); 1540ae76531SDavid Feng } 1550ae76531SDavid Feng 1560ae76531SDavid Feng /* 1570ae76531SDavid Feng * do_bad_fiq handles the impossible case in the Fiq vector. 1580ae76531SDavid Feng */ 1590ae76531SDavid Feng void do_bad_fiq(struct pt_regs *pt_regs, unsigned int esr) 1600ae76531SDavid Feng { 16164982915SAlexander Graf efi_restore_gd(); 1620ae76531SDavid Feng printf("Bad mode in \"Fiq\" handler, esr 0x%08x\n", esr); 1630ae76531SDavid Feng show_regs(pt_regs); 1640ae76531SDavid Feng panic("Resetting CPU ...\n"); 1650ae76531SDavid Feng } 1660ae76531SDavid Feng 1670ae76531SDavid Feng /* 1680ae76531SDavid Feng * do_bad_error handles the impossible case in the Error vector. 1690ae76531SDavid Feng */ 1700ae76531SDavid Feng void do_bad_error(struct pt_regs *pt_regs, unsigned int esr) 1710ae76531SDavid Feng { 17264982915SAlexander Graf efi_restore_gd(); 1730ae76531SDavid Feng printf("Bad mode in \"Error\" handler, esr 0x%08x\n", esr); 1740ae76531SDavid Feng show_regs(pt_regs); 1750ae76531SDavid Feng panic("Resetting CPU ...\n"); 1760ae76531SDavid Feng } 1770ae76531SDavid Feng 1780ae76531SDavid Feng /* 1790ae76531SDavid Feng * do_sync handles the Synchronous Abort exception. 1800ae76531SDavid Feng */ 1810ae76531SDavid Feng void do_sync(struct pt_regs *pt_regs, unsigned int esr) 1820ae76531SDavid Feng { 18364982915SAlexander Graf efi_restore_gd(); 1840ae76531SDavid Feng printf("\"Synchronous Abort\" handler, esr 0x%08x\n", esr); 1850ae76531SDavid Feng show_regs(pt_regs); 1860ae76531SDavid Feng panic("Resetting CPU ...\n"); 1870ae76531SDavid Feng } 1880ae76531SDavid Feng 189*7cef7918SJoseph Chen #if !CONFIG_IS_ENABLED(IRQ) 1900ae76531SDavid Feng /* 1910ae76531SDavid Feng * do_irq handles the Irq exception. 1920ae76531SDavid Feng */ 1930ae76531SDavid Feng void do_irq(struct pt_regs *pt_regs, unsigned int esr) 1940ae76531SDavid Feng { 19564982915SAlexander Graf efi_restore_gd(); 1960ae76531SDavid Feng printf("\"Irq\" handler, esr 0x%08x\n", esr); 1970ae76531SDavid Feng show_regs(pt_regs); 1980ae76531SDavid Feng panic("Resetting CPU ...\n"); 1990ae76531SDavid Feng } 200fa40f8a0SJoseph Chen #endif 2010ae76531SDavid Feng 2020ae76531SDavid Feng /* 2030ae76531SDavid Feng * do_fiq handles the Fiq exception. 2040ae76531SDavid Feng */ 2050ae76531SDavid Feng void do_fiq(struct pt_regs *pt_regs, unsigned int esr) 2060ae76531SDavid Feng { 20764982915SAlexander Graf efi_restore_gd(); 2080ae76531SDavid Feng printf("\"Fiq\" handler, esr 0x%08x\n", esr); 2090ae76531SDavid Feng show_regs(pt_regs); 2100ae76531SDavid Feng panic("Resetting CPU ...\n"); 2110ae76531SDavid Feng } 2120ae76531SDavid Feng 2130ae76531SDavid Feng /* 2140ae76531SDavid Feng * do_error handles the Error exception. 2150ae76531SDavid Feng * Errors are more likely to be processor specific, 2160ae76531SDavid Feng * it is defined with weak attribute and can be redefined 2170ae76531SDavid Feng * in processor specific code. 2180ae76531SDavid Feng */ 2190ae76531SDavid Feng void __weak do_error(struct pt_regs *pt_regs, unsigned int esr) 2200ae76531SDavid Feng { 22164982915SAlexander Graf efi_restore_gd(); 2220ae76531SDavid Feng printf("\"Error\" handler, esr 0x%08x\n", esr); 2230ae76531SDavid Feng show_regs(pt_regs); 2240ae76531SDavid Feng panic("Resetting CPU ...\n"); 2250ae76531SDavid Feng } 226