diff --git a/arch/arm64/src/common/arm64_fatal.c b/arch/arm64/src/common/arm64_fatal.c index 5c1b5241904..3486fe1d5d1 100644 --- a/arch/arm64/src/common/arm64_fatal.c +++ b/arch/arm64/src/common/arm64_fatal.c @@ -39,7 +39,6 @@ #include #include "sched/sched.h" #include "irq/irq.h" - #include "arm64_arch.h" #include "arm64_internal.h" #include "arm64_fatal.h" @@ -51,528 +50,327 @@ #include "arm64_fpu.h" #endif -/**************************************************************************** - * Private Type Declarations - ****************************************************************************/ - -struct fatal_handle_info -{ - fatal_handle_func_t handle_fn; - const char *name; -}; - -/**************************************************************************** - * Private Functions Declarations - ****************************************************************************/ - -/* Default callback handler for debug and fatal event - * Can be override by other handler - */ - -static int default_debug_handler(struct regs_context *regs, - uint64_t far, uint64_t esr); -static int default_fatal_handler(struct regs_context *regs, - uint64_t far, uint64_t esr); - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -static const char *g_esr_class_str[] = -{ - [0 ... ESR_ELX_EC_MAX] = "UNRECOGNIZED EC", - [ESR_ELX_EC_UNKNOWN] = "Unknown/Uncategorized", - [ESR_ELX_EC_WFX] = "WFI/WFE", - [ESR_ELX_EC_CP15_32] = "CP15 MCR/MRC", - [ESR_ELX_EC_CP15_64] = "CP15 MCRR/MRRC", - [ESR_ELX_EC_CP14_MR] = "CP14 MCR/MRC", - [ESR_ELX_EC_CP14_LS] = "CP14 LDC/STC", - [ESR_ELX_EC_FP_ASIMD] = "ASIMD", - [ESR_ELX_EC_CP10_ID] = "CP10 MRC/VMRS", - [ESR_ELX_EC_PAC] = "PAC", - [ESR_ELX_EC_CP14_64] = "CP14 MCRR/MRRC", - [ESR_ELX_EC_BTI] = "BTI", - [ESR_ELX_EC_ILL] = "PSTATE.IL", - [ESR_ELX_EC_SVC32] = "SVC (AArch32)", - [ESR_ELX_EC_HVC32] = "HVC (AArch32)", - [ESR_ELX_EC_SMC32] = "SMC (AArch32)", - [ESR_ELX_EC_SVC64] = "SVC (AArch64)", - [ESR_ELX_EC_HVC64] = "HVC (AArch64)", - [ESR_ELX_EC_SMC64] = "SMC (AArch64)", - [ESR_ELX_EC_SYS64] = "MSR/MRS (AArch64)", - [ESR_ELX_EC_SVE] = "SVE", - [ESR_ELX_EC_ERET] = "ERET/ERETAA/ERETAB", - [ESR_ELX_EC_FPAC] = "FPAC", - [ESR_ELX_EC_SME] = "SME", - [ESR_ELX_EC_IMP_DEF] = "EL3 IMP DEF", - [ESR_ELX_EC_IABT_LOW] = "IABT (lower EL)", - [ESR_ELX_EC_IABT_CUR] = "IABT (current EL)", - [ESR_ELX_EC_PC_ALIGN] = "PC Alignment", - [ESR_ELX_EC_DABT_LOW] = "DABT (lower EL)", - [ESR_ELX_EC_DABT_CUR] = "DABT (current EL)", - [ESR_ELX_EC_SP_ALIGN] = "SP Alignment", - [ESR_ELX_EC_MOPS] = "MOPS", - [ESR_ELX_EC_FP_EXC32] = "FP (AArch32)", - [ESR_ELX_EC_FP_EXC64] = "FP (AArch64)", - [ESR_ELX_EC_SERROR] = "SError", - [ESR_ELX_EC_BREAKPT_LOW] = "Breakpoint (lower EL)", - [ESR_ELX_EC_BREAKPT_CUR] = "Breakpoint (current EL)", - [ESR_ELX_EC_SOFTSTP_LOW] = "Software Step (lower EL)", - [ESR_ELX_EC_SOFTSTP_CUR] = "Software Step (current EL)", - [ESR_ELX_EC_WATCHPT_LOW] = "Watchpoint (lower EL)", - [ESR_ELX_EC_WATCHPT_CUR] = "Watchpoint (current EL)", - [ESR_ELX_EC_BKPT32] = "BKPT (AArch32)", - [ESR_ELX_EC_VECTOR32] = "Vector catch (AArch32)", - [ESR_ELX_EC_BRK64] = "BRK (AArch64)", -}; - -static const char *g_esr_desc_str[] = -{ - [0 ... ESR_ELX_EC_MAX] = "UNRECOGNIZED EC", - [ESR_ELX_EC_UNKNOWN] = "Unknown/Uncategorized", - [ESR_ELX_EC_WFX] = "Trapped WFI or WFE instruction execution", - [ESR_ELX_EC_CP15_32] = "Trapped MCR or MRC access with" - "(coproc==0b1111) " - "that is not reported using EC 0b000000", - [ESR_ELX_EC_CP15_64] = "Trapped MCRR or MRRC access with" - "(coproc==0b1111) " - "that is not reported using EC 0b000000", - [ESR_ELX_EC_CP14_MR] = "Trapped MCR or MRC access with (coproc==0b1110)", - [ESR_ELX_EC_CP14_LS] = "Trapped LDC or STC access", - [ESR_ELX_EC_FP_ASIMD] = "Trapped access to SVE, Advanced SIMD, or " - "floating-point functionality", - [ESR_ELX_EC_CP10_ID] = "CP10 MRC/VMRS", - [ESR_ELX_EC_PAC] = "PAC", - [ESR_ELX_EC_CP14_64] = "Trapped MRRC access with (coproc==0b1110)", - [ESR_ELX_EC_BTI] = "Branch Target Exception", - [ESR_ELX_EC_ILL] = "Illegal Execution state", - [ESR_ELX_EC_SVC32] = "SVC instruction execution in AArch32 state", - [ESR_ELX_EC_HVC32] = "HVC (AArch32)", - [ESR_ELX_EC_SMC32] = "SMC (AArch32)", - [ESR_ELX_EC_SVC64] = "SVC (AArch64)", - [ESR_ELX_EC_HVC64] = "HVC (AArch64)", - [ESR_ELX_EC_SMC64] = "SMC (AArch64)", - [ESR_ELX_EC_SYS64] = "Trapped MSR, MRS or System instruction " - "execution in AArch64 state, that is not " - "reported using EC 0b000000, 0b000001 or 0b000111", - [ESR_ELX_EC_SVE] = "Trapped access to SVE functionality", - [ESR_ELX_EC_ERET] = "ERET/ERETAA/ERETAB", - [ESR_ELX_EC_FPAC] = "Exception from a Pointer Authentication " - "instruction authentication failure", - [ESR_ELX_EC_SME] = "SME", - [ESR_ELX_EC_IMP_DEF] = "EL3 IMP DEF", - [ESR_ELX_EC_IABT_LOW] = "Instruction Abort from a lower Exception level, " - "that might be using AArch32 or AArch64", - [ESR_ELX_EC_IABT_CUR] = "Instruction Abort taken without a change " - "in Exception level", - [ESR_ELX_EC_PC_ALIGN] = "PC alignment fault exception.", - [ESR_ELX_EC_DABT_LOW] = "Data Abort from a lower Exception level, " - "that might be using AArch32 or AArch64", - [ESR_ELX_EC_DABT_CUR] = "Data Abort taken without a change in " - "Exception level", - [ESR_ELX_EC_SP_ALIGN] = "SP alignment fault exception", - [ESR_ELX_EC_MOPS] = "MOPS", - [ESR_ELX_EC_FP_EXC32] = "Trapped floating-point exception taken from " - "AArch32 state", - [ESR_ELX_EC_FP_EXC64] = "Trapped floating-point exception taken from " - "AArch64 state", - [ESR_ELX_EC_SERROR] = "SError interrupt", - [ESR_ELX_EC_BREAKPT_LOW] = "Breakpoint exception from a lower " - "Exception level, " - "that might be using AArch32 or AArch64", - [ESR_ELX_EC_BREAKPT_CUR] = "Breakpoint exception taken without a change " - "in Exception level", - [ESR_ELX_EC_SOFTSTP_LOW] = "Software Step exception from a lower " - "Exception level," - "that might be using AArch32 or AArch64", - [ESR_ELX_EC_SOFTSTP_CUR] = "Software Step exception taken without a " - "change in Exception level", - [ESR_ELX_EC_WATCHPT_LOW] = "Watchpoint exception from a lower " - "Exception level, " - "that might be using AArch32 or AArch64", - [ESR_ELX_EC_WATCHPT_CUR] = "Watchpoint exception taken without " - "a change in Exception level.", - [ESR_ELX_EC_BKPT32] = "BKPT instruction execution in AArch32 state", - [ESR_ELX_EC_VECTOR32] = "Vector catch (AArch32)", - [ESR_ELX_EC_BRK64] = "BRK instruction execution in AArch64 state.", -}; - -static struct fatal_handle_info g_fatal_handler[] = -{ - { default_fatal_handler, "ttbr address size fault" }, - { default_fatal_handler, "level 1 address size fault" }, - { default_fatal_handler, "level 2 address size fault" }, - { default_fatal_handler, "level 3 address size fault" }, - { default_fatal_handler, "level 0 translation fault" }, - { default_fatal_handler, "level 1 translation fault" }, - { default_fatal_handler, "level 2 translation fault" }, - { default_fatal_handler, "level 3 translation fault" }, - { default_fatal_handler, "unknown 8" }, - { default_fatal_handler, "level 1 access flag fault" }, - { default_fatal_handler, "level 2 access flag fault" }, - { default_fatal_handler, "level 3 access flag fault" }, - { default_fatal_handler, "unknown 12" }, - { default_fatal_handler, "level 1 permission fault" }, - { default_fatal_handler, "level 2 permission fault" }, - { default_fatal_handler, "level 3 permission fault" }, - { default_fatal_handler, "synchronous external abort" }, - { default_fatal_handler, "synchronous tag check fault" }, - { default_fatal_handler, "unknown 18" }, - { default_fatal_handler, "unknown 19" }, - { default_fatal_handler, "level 0 (translation table walk)" }, - { default_fatal_handler, "level 1 (translation table walk)" }, - { default_fatal_handler, "level 2 (translation table walk)" }, - { default_fatal_handler, "level 3 (translation table walk)" }, - { default_fatal_handler, "synchronous parity or ECC error" }, - { default_fatal_handler, "unknown 25" }, - { default_fatal_handler, "unknown 26" }, - { default_fatal_handler, "unknown 27" }, - { default_fatal_handler, "level 0 synchronous parity " - "error (translation table walk)" }, - { default_fatal_handler, "level 1 synchronous parity " - "error (translation table walk)" }, - { default_fatal_handler, "level 2 synchronous parity " - "error (translation table walk)" }, - { default_fatal_handler, "level 3 synchronous parity " - "error (translation table walk)" }, - { default_fatal_handler, "unknown 32" }, - { default_fatal_handler, "alignment fault" }, - { default_fatal_handler, "unknown 34" }, - { default_fatal_handler, "unknown 35" }, - { default_fatal_handler, "unknown 36" }, - { default_fatal_handler, "unknown 37" }, - { default_fatal_handler, "unknown 38" }, - { default_fatal_handler, "unknown 39" }, - { default_fatal_handler, "unknown 40" }, - { default_fatal_handler, "unknown 41" }, - { default_fatal_handler, "unknown 42" }, - { default_fatal_handler, "unknown 43" }, - { default_fatal_handler, "unknown 44" }, - { default_fatal_handler, "unknown 45" }, - { default_fatal_handler, "unknown 46" }, - { default_fatal_handler, "unknown 47" }, - { default_fatal_handler, "TLB conflict abort" }, - { default_fatal_handler, "Unsupported atomic hardware update fault" }, - { default_fatal_handler, "unknown 50" }, - { default_fatal_handler, "unknown 51" }, - { default_fatal_handler, "implementation fault (lockdown abort)" }, - { default_fatal_handler, "implementation fault (unsupported exclusive)" }, - { default_fatal_handler, "unknown 54" }, - { default_fatal_handler, "unknown 55" }, - { default_fatal_handler, "unknown 56" }, - { default_fatal_handler, "unknown 57" }, - { default_fatal_handler, "unknown 58" }, - { default_fatal_handler, "unknown 59" }, - { default_fatal_handler, "unknown 60" }, - { default_fatal_handler, "section domain fault" }, - { default_fatal_handler, "page domain fault" }, - { default_fatal_handler, "unknown 63" }, -}; - -static struct fatal_handle_info g_debug_handler[] = -{ - { default_debug_handler, "hardware breakpoint" }, - { default_debug_handler, "hardware single-step" }, - { default_debug_handler, "hardware watchpoint" }, - { default_debug_handler, "unknown 3" }, - { default_debug_handler, "aarch32 BKPT" }, - { default_debug_handler, "aarch32 vector catch" }, - { default_debug_handler, "aarch64 BRK" }, - { default_debug_handler, "unknown 7" }, -}; - /**************************************************************************** * Private Functions ****************************************************************************/ -static const char *esr_get_class_string(uint64_t esr) -{ - uint32_t ec = ESR_ELX_EC(esr); - - return g_esr_class_str[ec]; -} - -static const char *esr_get_desc_string(uint64_t esr) -{ - uint32_t ec = ESR_ELX_EC(esr); - - return g_esr_desc_str[ec]; -} +/**************************************************************************** + * Name: print_ec_cause + ****************************************************************************/ static void print_ec_cause(uint64_t esr) { - sinfo("%s\n", esr_get_class_string(esr)); - sinfo("%s\n", esr_get_desc_string(esr)); -} - -static int default_fatal_handler(struct regs_context *regs, - uint64_t far, uint64_t esr) -{ - struct fatal_handle_info *inf = g_fatal_handler + (esr & ESR_ELX_FSC); - - /* Data Fault Status Code. */ - - sinfo("(IFSC/DFSC) for Data/Instruction aborts: %s\n", inf->name); - - return -EINVAL; /* "fault" */ -} - -static int default_debug_handler(struct regs_context *regs, - uint64_t far, uint64_t esr) -{ - struct fatal_handle_info *inf = g_debug_handler + DBG_ESR_EVT(esr); - - sinfo("Default Debug Handler: %s\n", inf->name); - return -1; /* "fault" */ -} - -static int arm64_el1_abort(struct regs_context *regs, uint64_t esr) -{ - uint64_t far = read_sysreg(far_el1); - struct fatal_handle_info *inf = g_fatal_handler + (esr & ESR_ELX_FSC); - - return inf->handle_fn(regs, far, esr); -} - -static int arm64_el1_pc(struct regs_context *regs, uint64_t esr) -{ - uint64_t far = read_sysreg(far_el1); - - sinfo("SP/PC alignment exception at 0x%" PRIx64 "\n", far); - return -EINVAL; /* "fault" */ -} - -static int arm64_el1_bti(struct regs_context *regs, uint64_t esr) -{ - uint64_t far = read_sysreg(far_el1); - - sinfo("BTI exception at 0x%" PRIx64 "\n", far); - return -EINVAL; /* "fault" */ -} - -static int arm64_el1_undef(struct regs_context *regs, uint64_t esr) -{ - uint32_t insn; - - sinfo("Undefined instruction at 0x%" PRIx64 ", dump:\n", regs->elr); - memcpy(&insn, (void *)(regs->elr - 8), 4); - sinfo("0x%" PRIx64 " : 0x%" PRIx32 "\n", regs->elr - 8, insn); - memcpy(&insn, (void *)(regs->elr - 4), 4); - sinfo("0x%" PRIx64 " : 0x%" PRIx32 "\n", regs->elr - 4, insn); - memcpy(&insn, (void *)(regs->elr), 4); - sinfo("0x%" PRIx64 " : 0x%" PRIx32 "\n", regs->elr, insn); - memcpy(&insn, (void *)(regs->elr + 4), 4); - sinfo("0x%" PRIx64 " : 0x%" PRIx32 "\n", regs->elr + 4, insn); - memcpy(&insn, (void *)(regs->elr + 8), 4); - sinfo("0x%" PRIx64 " : 0x%" PRIx32 "\n", regs->elr + 8, insn); - - return -1; -} - -static int arm64_el1_fpac(struct regs_context *regs, uint64_t esr) -{ - uint64_t far = read_sysreg(far_el1); - - /* Unexpected FPAC exception in the kernel. */ - - sinfo("Unexpected FPAC exception at 0x%" PRIx64 "\n", far); - return -EINVAL; -} - -static int arm64_el1_dbg(struct regs_context *regs, uint64_t esr) -{ - uint64_t far = read_sysreg(far_el1); - struct fatal_handle_info *inf = g_debug_handler + DBG_ESR_EVT(esr); - - return inf->handle_fn(regs, far, esr); -} - -static int arm64_el1_exception_handler(uint64_t esr, - struct regs_context *regs) -{ - uint32_t ec = ESR_ELX_EC(esr); - int ret; + uint32_t ec = (uint32_t)esr >> 26; switch (ec) { - /* Data/Instruction Abort at EL1 */ - - case ESR_ELX_EC_DABT_CUR: - case ESR_ELX_EC_IABT_CUR: + case 0b000000: { - ret = arm64_el1_abort(regs, esr); + sinfo("Unknown reason\n"); break; } - /* PC alignment fault exception. */ - - case ESR_ELX_EC_PC_ALIGN: + case 0b000001: { - ret = arm64_el1_pc(regs, esr); + sinfo("Trapped WFI or WFE instruction execution\n"); break; } - /* Trapped MSR, MRS or System instruction execution - * in AArch64 state - */ - - case ESR_ELX_EC_SYS64: - case ESR_ELX_EC_UNKNOWN: + case 0b000011: { - ret = arm64_el1_undef(regs, esr); + sinfo( + "Trapped MCR or MRC access with (coproc==0b1111) that " + "is not reported using EC 0b000000\n"); break; } - /* Branch Target Exception */ - - case ESR_ELX_EC_BTI: + case 0b000100: { - ret = arm64_el1_bti(regs, esr); + sinfo( + "Trapped MCRR or MRRC access with (coproc==0b1111) " + "that is not reported using EC 0b000000\n"); break; } - case ESR_ELX_EC_BREAKPT_CUR: - - /* Breakpoint exception taken in current Exception level */ - - case ESR_ELX_EC_SOFTSTP_CUR: - - /* Software Step exception taken in current Exception level */ - - case ESR_ELX_EC_WATCHPT_CUR: - - /* Watchpoint exception taken in current Exception level */ - - case ESR_ELX_EC_BRK64: + case 0b000101: { - /* BRK instruction execution in AArch64 state */ - - ret = arm64_el1_dbg(regs, esr); + sinfo("Trapped MCR or MRC access with (coproc==0b1110)\n"); break; } - case ESR_ELX_EC_FPAC: + case 0b000110: { - /* Exception from a Pointer Authentication - * instruction authentication failure - */ + sinfo("Trapped LDC or STC access\n"); + break; + } - ret = arm64_el1_fpac(regs, esr); + case 0b000111: + { + sinfo( + "Trapped access to SVE, Advanced SIMD, or " + "floating-point functionality\n"); + break; + } + + case 0b001100: + { + sinfo("Trapped MRRC access with (coproc==0b1110)\n"); + break; + } + + case 0b001101: + { + sinfo("Branch Target Exception\n"); + break; + } + + case 0b001110: + { + sinfo("Illegal Execution state\n"); + break; + } + + case 0b010001: + { + sinfo("SVC instruction execution in AArch32 state\n"); + break; + } + + case 0b011000: + { + sinfo( + "Trapped MSR, MRS or System instruction execution in " + "AArch64 state, that is not reported using EC " + "0b000000, 0b000001 or 0b000111\n"); + break; + } + + case 0b011001: + { + sinfo("Trapped access to SVE functionality\n"); + break; + } + + case 0b100000: + { + sinfo( + "Instruction Abort from a lower Exception level, that " + "might be using AArch32 or AArch64\n"); + break; + } + + case 0b100001: + { + sinfo( + "Instruction Abort taken without a change " + "in Exception level.\n"); + break; + } + + case 0b100010: + { + sinfo("PC alignment fault exception.\n"); + break; + } + + case 0b100100: + { + sinfo( + "Data Abort from a lower Exception level, that might " + "be using AArch32 or AArch64\n"); + break; + } + + case 0b100101: + { + sinfo("Data Abort taken without a change in Exception level\n"); + break; + } + + case 0b100110: + { + sinfo("SP alignment fault exception\n"); + break; + } + + case 0b101000: + { + sinfo( + "Trapped floating-point exception " + "taken from AArch32 state\n"); + break; + } + + case 0b101100: + { + sinfo( + "Trapped floating-point exception " + "taken from AArch64 state.\n"); + break; + } + + case 0b101111: + { + sinfo("SError interrupt\n"); + break; + } + + case 0b110000: + { + sinfo( + "Breakpoint exception from a lower Exception level, " + "that might be using AArch32 or AArch64\n"); + break; + } + + case 0b110001: + { + sinfo( + "Breakpoint exception taken without a change in " + "Exception level\n"); + break; + } + + case 0b110010: + { + sinfo( + "Software Step exception from a lower Exception level, " + "that might be using AArch32 or AArch64\n"); + break; + } + + case 0b110011: + { + sinfo( + "Software Step exception taken without a change in " + "Exception level\n"); + break; + } + + case 0b110100: + { + sinfo( + "Watchpoint exception from a lower Exception level, " + "that might be using AArch32 or AArch64\n"); + break; + } + + case 0b110101: + { + sinfo( + "Watchpoint exception taken without a change in " + "Exception level.\n"); + break; + } + + case 0b111000: + { + sinfo("BKPT instruction execution in AArch32 state\n"); + break; + } + + case 0b111100: + { + sinfo("BRK instruction execution in AArch64 state.\n"); break; } default: - { - sinfo("64-bit el1h sync, esr = 0x%x", ec); - ret = -EINVAL; - } - } - - return ret; -} - -static int arm64_exception_handler(struct regs_context *regs) -{ - uint64_t el; - uint64_t esr; - uint64_t elr; - uint64_t far; - const char *el_str; - int ret = -EINVAL; - - el = arm64_current_el(); - - switch (el) - { - case MODE_EL1: - { - el_str = "MODE_EL1"; - esr = read_sysreg(esr_el1); - far = read_sysreg(far_el1); - elr = read_sysreg(elr_el1); - ret = arm64_el1_exception_handler(esr, regs); - break; + break; } - - case MODE_EL2: - { - el_str = "MODE_EL2"; - esr = read_sysreg(esr_el2); - far = read_sysreg(far_el2); - elr = read_sysreg(elr_el2); - break; - } - -#ifdef CONFIG_ARCH_HAVE_EL3 - case MODE_EL3: - { - el_str = "MODE_EL3"; - esr = read_sysreg(esr_el3); - far = read_sysreg(far_el3); - elr = read_sysreg(elr_el3); - break; - } - -#endif - default: - { - el_str = "Unknown"; - - /* Just to keep the compiler happy */ - - esr = elr = far = 0; - break; - } - } - - if (ret != 0) - { - sinfo("CurrentEL: %s\n", el_str); - sinfo("ESR_ELn: 0x%" PRIx64 "\n", esr); - sinfo("FAR_ELn: 0x%" PRIx64 "\n", far); - sinfo("ELR_ELn: 0x%" PRIx64 "\n", elr); - - print_ec_cause(esr); - } - - return ret; } /**************************************************************************** * Public Functions ****************************************************************************/ -void arm64_fatal_handler(struct regs_context *regs) +/**************************************************************************** + * Name: up_mdelay + ****************************************************************************/ + +void up_mdelay(unsigned int milliseconds) { - int ret; + volatile unsigned int i; + volatile unsigned int j; - /* Nested exception are not supported */ - - DEBUGASSERT(up_current_regs() == NULL); - - up_set_current_regs((uint64_t *)regs); - - ret = arm64_exception_handler(regs); - - if (ret != 0) + for (i = 0; i < milliseconds; i++) { - /* The fatal is not handled, print error and hung */ + for (j = 0; j < CONFIG_BOARD_LOOPSPERMSEC; j++) + { + } + } +} - PANIC_WITH_REGS("panic", regs); +/**************************************************************************** + * Name: arm64_fatal_error + * + * Description: + * + ****************************************************************************/ + +void arm64_fatal_error(unsigned int reason, struct regs_context * reg) +{ + uint64_t el, esr, elr, far; + + sinfo("reason = %d\n", reason); + + up_set_current_regs((uint64_t *)reg); + + if (reason != K_ERR_SPURIOUS_IRQ) + { + __asm__ volatile ("mrs %0, CurrentEL" : "=r" (el)); + + switch (GET_EL(el)) + { + case MODE_EL1: + { + sinfo("CurrentEL: MODE_EL1\n"); + __asm__ volatile ("mrs %0, esr_el1" : "=r" (esr)); + __asm__ volatile ("mrs %0, far_el1" : "=r" (far)); + __asm__ volatile ("mrs %0, elr_el1" : "=r" (elr)); + break; + } + + case MODE_EL2: + { + sinfo("CurrentEL: MODE_EL2\n"); + __asm__ volatile ("mrs %0, esr_el2" : "=r" (esr)); + __asm__ volatile ("mrs %0, far_el2" : "=r" (far)); + __asm__ volatile ("mrs %0, elr_el2" : "=r" (elr)); + break; + } + +#ifdef CONFIG_ARCH_HAVE_EL3 + case MODE_EL3: + { + sinfo("CurrentEL: MODE_EL3\n"); + __asm__ volatile ("mrs %0, esr_el3" : "=r" (esr)); + __asm__ volatile ("mrs %0, far_el3" : "=r" (far)); + __asm__ volatile ("mrs %0, elr_el3" : "=r" (elr)); + break; + } +#endif + + default: + { + sinfo("CurrentEL: unknown\n"); + + /* Just to keep the compiler happy */ + + esr = elr = far = 0; + break; + } + } + + if (GET_EL(el) != MODE_EL0) + { + sinfo("ESR_ELn: 0x%"PRIx64"\n", esr); + sinfo("FAR_ELn: 0x%"PRIx64"\n", far); + sinfo("ELR_ELn: 0x%"PRIx64"\n", elr); + + print_ec_cause(esr); + } } - /* Set CURRENT_REGS to NULL to indicate that we are no longer in an - * Exception handler. - */ - - up_set_current_regs(NULL); -} - -void arm64_register_debug_hook(int nr, fatal_handle_func_t fn) -{ - DEBUGVERIFY(nr > 0 && nr <= nitems(g_debug_handler)); - - /* Override the default handler */ - - g_debug_handler[nr].handle_fn = fn; + PANIC_WITH_REGS("panic", reg); } diff --git a/arch/arm64/src/common/arm64_fatal.h b/arch/arm64/src/common/arm64_fatal.h index 301e158f000..360a28e8fa9 100644 --- a/arch/arm64/src/common/arm64_fatal.h +++ b/arch/arm64/src/common/arm64_fatal.h @@ -21,6 +21,12 @@ #ifndef __ARCH_ARM64_SRC_COMMON_ARM64_FATAL_H #define __ARCH_ARM64_SRC_COMMON_ARM64_FATAL_H +/* Fatal error APIs */ + +#define K_ERR_CPU_EXCEPTION (0) +#define K_ERR_CPU_MODE32 (1) +#define K_ERR_SPURIOUS_IRQ (2) + #ifndef __ASSEMBLY__ /**************************************************************************** @@ -37,123 +43,6 @@ * Pre-processor Definitions ****************************************************************************/ -#define ESR_ELX_EC_UNKNOWN (0x00) -#define ESR_ELX_EC_WFX (0x01) - -/* Unallocated EC: 0x02 */ - -#define ESR_ELX_EC_CP15_32 (0x03) -#define ESR_ELX_EC_CP15_64 (0x04) -#define ESR_ELX_EC_CP14_MR (0x05) -#define ESR_ELX_EC_CP14_LS (0x06) -#define ESR_ELX_EC_FP_ASIMD (0x07) -#define ESR_ELX_EC_CP10_ID (0x08) /* EL2 only */ -#define ESR_ELX_EC_PAC (0x09) /* EL2 and above */ - -/* Unallocated EC: 0x0A - 0x0B */ - -#define ESR_ELX_EC_CP14_64 (0x0C) -#define ESR_ELX_EC_BTI (0x0D) -#define ESR_ELX_EC_ILL (0x0E) - -/* Unallocated EC: 0x0F - 0x10 */ - -#define ESR_ELX_EC_SVC32 (0x11) -#define ESR_ELX_EC_HVC32 (0x12) /* EL2 only */ -#define ESR_ELX_EC_SMC32 (0x13) /* EL2 and above */ - -/* Unallocated EC: 0x14 */ - -#define ESR_ELX_EC_SVC64 (0x15) -#define ESR_ELX_EC_HVC64 (0x16) /* EL2 and above */ -#define ESR_ELX_EC_SMC64 (0x17) /* EL2 and above */ -#define ESR_ELX_EC_SYS64 (0x18) -#define ESR_ELX_EC_SVE (0x19) -#define ESR_ELX_EC_ERET (0x1a) /* EL2 only */ - -/* Unallocated EC: 0x1B */ - -#define ESR_ELX_EC_FPAC (0x1C) /* EL1 and above */ -#define ESR_ELX_EC_SME (0x1D) - -/* Unallocated EC: 0x1D - 0x1E */ - -#define ESR_ELX_EC_IMP_DEF (0x1f) /* EL3 only */ -#define ESR_ELX_EC_IABT_LOW (0x20) -#define ESR_ELX_EC_IABT_CUR (0x21) -#define ESR_ELX_EC_PC_ALIGN (0x22) - -/* Unallocated EC: 0x23 */ - -#define ESR_ELX_EC_DABT_LOW (0x24) -#define ESR_ELX_EC_DABT_CUR (0x25) -#define ESR_ELX_EC_SP_ALIGN (0x26) -#define ESR_ELX_EC_MOPS (0x27) -#define ESR_ELX_EC_FP_EXC32 (0x28) - -/* Unallocated EC: 0x29 - 0x2B */ - -#define ESR_ELX_EC_FP_EXC64 (0x2C) - -/* Unallocated EC: 0x2D - 0x2E */ - -#define ESR_ELX_EC_SERROR (0x2F) -#define ESR_ELX_EC_BREAKPT_LOW (0x30) -#define ESR_ELX_EC_BREAKPT_CUR (0x31) -#define ESR_ELX_EC_SOFTSTP_LOW (0x32) -#define ESR_ELX_EC_SOFTSTP_CUR (0x33) -#define ESR_ELX_EC_WATCHPT_LOW (0x34) -#define ESR_ELX_EC_WATCHPT_CUR (0x35) - -/* Unallocated EC: 0x36 - 0x37 */ - -#define ESR_ELX_EC_BKPT32 (0x38) - -/* Unallocated EC: 0x39 */ - -#define ESR_ELX_EC_VECTOR32 (0x3A) /* EL2 only */ - -/* Unallocated EC: 0x3B */ - -#define ESR_ELX_EC_BRK64 (0x3C) - -/* Unallocated EC: 0x3D - 0x3F */ - -#define ESR_ELX_EC_MAX (0x3F) - -#define ESR_ELX_EC_SHIFT (26) -#define ESR_ELX_EC_WIDTH (6) -#define ESR_ELX_EC_MASK (0x3F << ESR_ELX_EC_SHIFT) -#define ESR_ELX_EC(esr) (((esr) & ESR_ELX_EC_MASK) \ - >> ESR_ELX_EC_SHIFT) - -/* Shared ISS fault status code(IFSC/DFSC) for Data/Instruction aborts */ - -#define ESR_ELX_FSC (0x3F) -#define ESR_ELX_FSC_TYPE (0x3C) -#define ESR_ELX_FSC_LEVEL (0x03) -#define ESR_ELX_FSC_EXTABT (0x10) -#define ESR_ELX_FSC_MTE (0x11) -#define ESR_ELX_FSC_SERROR (0x11) -#define ESR_ELX_FSC_ACCESS (0x08) -#define ESR_ELX_FSC_FAULT (0x04) -#define ESR_ELX_FSC_PERM (0x0C) -#define ESR_ELX_FSC_SEA_TTW0 (0x14) -#define ESR_ELX_FSC_SEA_TTW1 (0x15) -#define ESR_ELX_FSC_SEA_TTW2 (0x16) -#define ESR_ELX_FSC_SEA_TTW3 (0x17) -#define ESR_ELX_FSC_SECC (0x18) -#define ESR_ELX_FSC_SECC_TTW0 (0x1c) -#define ESR_ELX_FSC_SECC_TTW1 (0x1d) -#define ESR_ELX_FSC_SECC_TTW2 (0x1e) -#define ESR_ELX_FSC_SECC_TTW3 (0x1f) - -#define DBG_ESR_EVT(x) (((x) >> 27) & 0x7) -#define DBG_ESR_EVT_HWBP (0x0) -#define DBG_ESR_EVT_HWSS (0x1) -#define DBG_ESR_EVT_HWWP (0x2) -#define DBG_ESR_EVT_BRK (0x6) - #define __builtin_unreachable() \ do \ { \ @@ -162,49 +51,28 @@ } while (true) /**************************************************************************** - * Public Type Declarations + * Public Data ****************************************************************************/ -typedef int (*fatal_handle_func_t)(struct regs_context *regs, - uint64_t far, uint64_t esr); - /**************************************************************************** * Public Function Prototypes ****************************************************************************/ /**************************************************************************** - * Name: arm64_fatal_handler + * Name: arm64_fatal_error * * Description: - * Fatal handle for arm64 + * fatal error handle for arm64 * Input Parameters: + * reason: error reason * reg: exception stack reg context * - * Returned Value: None - * If the function return, the exception has been handled + * Returned Value: * ****************************************************************************/ -void arm64_fatal_handler(struct regs_context *reg); - -/**************************************************************************** - * Name: arm64_register_debug_hook - * - * Description: - * Register a hook function for DEBUG event - * Input Parameters: - * nr: DEBUG event - * DBG_ESR_EVT_HWBP : Hardware BreakPoint - * DBG_ESR_EVT_HWSS : Hardware SingleStep - * DBG_ESR_EVT_HWWP : Hardware WatchPoint - * DBG_ESR_EVT_BRK : Brk instruction trigger - * fn: hook function - * - * Returned Value: none - * - ****************************************************************************/ - -void arm64_register_debug_hook(int nr, fatal_handle_func_t fn); +void arm64_fatal_error(unsigned int reason, struct regs_context * reg); +void arm64_dump_fatal(struct regs_context * reg); #endif /* __ASSEMBLY__ */ diff --git a/arch/arm64/src/common/arm64_vector_table.S b/arch/arm64/src/common/arm64_vector_table.S index 1c05814c876..fa81c4e888e 100644 --- a/arch/arm64/src/common/arm64_vector_table.S +++ b/arch/arm64/src/common/arm64_vector_table.S @@ -216,25 +216,25 @@ SECTION_SUBSEC_FUNC(exc_vector_table,_vector_table_section,_vector_table) .align 7 arm64_enter_exception x0, x1 - b arm64_mode32_handler + b arm64_mode32_error /* Lower EL using AArch32 / IRQ */ .align 7 arm64_enter_exception x0, x1 - b arm64_mode32_handler + b arm64_mode32_error /* Lower EL using AArch32 / FIQ */ .align 7 arm64_enter_exception x0, x1 - b arm64_mode32_handler + b arm64_mode32_error /* Lower EL using AArch32 / SError */ .align 7 arm64_enter_exception x0, x1 - b arm64_mode32_handler + b arm64_mode32_error /* Restore Corruptible Registers and exception context * from the task stack. diff --git a/arch/arm64/src/common/arm64_vectors.S b/arch/arm64/src/common/arm64_vectors.S index 26aa2888b97..d2d1e5c95a3 100644 --- a/arch/arm64/src/common/arm64_vectors.S +++ b/arch/arm64/src/common/arm64_vectors.S @@ -355,13 +355,16 @@ save_context: b arm64_exit_exception exc_handle: - mov x0, sp + arm64_exception_context_save x0 x1 sp + mov x0, #K_ERR_CPU_EXCEPTION + mov x1, sp - /* void arm64_fatal_handler(struct regs_context * reg); - * x0 = Exception stack frame + /* void arm64_fatal_error(unsigned int reason, const uint64_t *regs) + * x0 = reason + * x1 = Exception stack frame */ - bl arm64_fatal_handler + bl arm64_fatal_error /* Return here only in case of recoverable error */ @@ -442,20 +445,28 @@ irq_context_switch: irq_exit: b arm64_exit_exception -/* TODO: if the arm64_fatal_handler return success, maybe need context switch */ +/* TODO: if the arm64_fatal_error return success, maybe need context switch */ GTEXT(arm64_serror_handler) SECTION_FUNC(text, arm64_serror_handler) - mov x0, sp - bl arm64_fatal_handler + arm64_exception_context_save x0 x1 sp + + mov x0, #K_ERR_CPU_EXCEPTION + mov x1, sp + + bl arm64_fatal_error /* Return here only in case of recoverable error */ b arm64_exit_exception -GTEXT(arm64_mode32_handler) -SECTION_FUNC(text, arm64_mode32_handler) - mov x0, sp - bl arm64_fatal_handler +GTEXT(arm64_mode32_error) +SECTION_FUNC(text, arm64_mode32_error) + arm64_exception_context_save x0 x1 sp + + mov x1, sp + mov x0, #K_ERR_CPU_MODE32 + + bl arm64_fatal_error /* Return here only in case of recoverable error */ b arm64_exit_exception @@ -463,9 +474,12 @@ SECTION_FUNC(text, arm64_mode32_handler) GTEXT(arm64_fiq_handler) SECTION_FUNC(text, arm64_fiq_handler) #ifndef CONFIG_ARM64_DECODEFIQ + arm64_exception_context_save x0 x1 sp - mov x0, sp - bl arm64_fatal_handler + mov x1, sp + mov x0, #K_ERR_SPURIOUS_IRQ /* K_ERR_SPURIOUS_IRQ */ + + bl arm64_fatal_error /* Return here only in case of recoverable error */