kernel: support log system for fatal errors
We introduce a new z_fatal_print() API and replace all occurrences of exception handling code to use it. This routes messages to the logging subsystem if enabled. Otherwise, messages are sent to printk(). Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
5623637a48
commit
8a9e8e0cd7
15 changed files with 289 additions and 270 deletions
|
@ -204,7 +204,7 @@ endmenu
|
||||||
config ARC_EXCEPTION_DEBUG
|
config ARC_EXCEPTION_DEBUG
|
||||||
bool "Unhandled exception debugging information"
|
bool "Unhandled exception debugging information"
|
||||||
default n
|
default n
|
||||||
depends on PRINTK
|
depends on PRINTK || LOG
|
||||||
help
|
help
|
||||||
Print human-readable information about exception vectors, cause codes,
|
Print human-readable information about exception vectors, cause codes,
|
||||||
and parameters, at a cost of code/data size for the human-readable
|
and parameters, at a cost of code/data size for the human-readable
|
||||||
|
|
|
@ -16,13 +16,12 @@
|
||||||
#include <offsets_short.h>
|
#include <offsets_short.h>
|
||||||
#include <toolchain.h>
|
#include <toolchain.h>
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
#include <sys/printk.h>
|
|
||||||
#include <logging/log_ctrl.h>
|
#include <logging/log_ctrl.h>
|
||||||
|
|
||||||
void z_arc_fatal_error(unsigned int reason, const NANO_ESF *esf)
|
void z_arc_fatal_error(unsigned int reason, const NANO_ESF *esf)
|
||||||
{
|
{
|
||||||
if (reason == K_ERR_CPU_EXCEPTION) {
|
if (reason == K_ERR_CPU_EXCEPTION) {
|
||||||
printk("Faulting instruction address = 0x%lx\n",
|
z_fatal_print("Faulting instruction address = 0x%lx",
|
||||||
z_arc_v2_aux_reg_read(_ARC_V2_ERET));
|
z_arc_v2_aux_reg_read(_ARC_V2_ERET));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <kernel_structs.h>
|
#include <kernel_structs.h>
|
||||||
#include <sys/printk.h>
|
|
||||||
#include <exc_handle.h>
|
#include <exc_handle.h>
|
||||||
#include <logging/log_ctrl.h>
|
#include <logging/log_ctrl.h>
|
||||||
|
|
||||||
|
@ -130,33 +129,25 @@ static u32_t z_check_thread_stack_fail(const u32_t fault_addr, u32_t sp)
|
||||||
* These codes and parameters do not have associated* names in
|
* These codes and parameters do not have associated* names in
|
||||||
* the technical manual, just switch on the values in Table 6-5
|
* the technical manual, just switch on the values in Table 6-5
|
||||||
*/
|
*/
|
||||||
static void dump_protv_access_err(u32_t parameter)
|
static const char *get_protv_access_err(u32_t parameter)
|
||||||
{
|
{
|
||||||
switch (parameter) {
|
switch (parameter) {
|
||||||
case 0x1:
|
case 0x1:
|
||||||
printk("code protection scheme");
|
return "code protection scheme";
|
||||||
break;
|
|
||||||
case 0x2:
|
case 0x2:
|
||||||
printk("stack checking scheme");
|
return "stack checking scheme";
|
||||||
break;
|
|
||||||
case 0x4:
|
case 0x4:
|
||||||
printk("MPU");
|
return "MPU";
|
||||||
break;
|
|
||||||
case 0x8:
|
case 0x8:
|
||||||
printk("MMU");
|
return "MMU";
|
||||||
break;
|
|
||||||
case 0x10:
|
case 0x10:
|
||||||
printk("NVM");
|
return "NVM";
|
||||||
break;
|
|
||||||
case 0x24:
|
case 0x24:
|
||||||
printk("Secure MPU");
|
return "Secure MPU";
|
||||||
break;
|
|
||||||
case 0x44:
|
case 0x44:
|
||||||
printk("Secure MPU with SID mismatch");
|
return "Secure MPU with SID mismatch";
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
printk("unknown");
|
return "unknown";
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,32 +155,32 @@ static void dump_protv_exception(u32_t cause, u32_t parameter)
|
||||||
{
|
{
|
||||||
switch (cause) {
|
switch (cause) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
printk("Instruction fetch violation: ");
|
z_fatal_print("Instruction fetch violation (%s)",
|
||||||
dump_protv_access_err(parameter);
|
get_protv_access_err(parameter));
|
||||||
break;
|
break;
|
||||||
case 0x1:
|
case 0x1:
|
||||||
printk("Memory read protection violation: ");
|
z_fatal_print("Memory read protection violation (%s)",
|
||||||
dump_protv_access_err(parameter);
|
get_protv_access_err(parameter));
|
||||||
break;
|
break;
|
||||||
case 0x2:
|
case 0x2:
|
||||||
printk("Memory write protection violation: ");
|
z_fatal_print("Memory write protection violation (%s)",
|
||||||
dump_protv_access_err(parameter);
|
get_protv_access_err(parameter));
|
||||||
break;
|
break;
|
||||||
case 0x3:
|
case 0x3:
|
||||||
printk("Memory read-modify-write violation: ");
|
z_fatal_print("Memory read-modify-write violation (%s)",
|
||||||
dump_protv_access_err(parameter);
|
get_protv_access_err(parameter));
|
||||||
break;
|
break;
|
||||||
case 0x10:
|
case 0x10:
|
||||||
printk("Normal vector table in secure memory");
|
z_fatal_print("Normal vector table in secure memory");
|
||||||
break;
|
break;
|
||||||
case 0x11:
|
case 0x11:
|
||||||
printk("NS handler code located in S memory");
|
z_fatal_print("NS handler code located in S memory");
|
||||||
break;
|
break;
|
||||||
case 0x12:
|
case 0x12:
|
||||||
printk("NSC Table Range Violation");
|
z_fatal_print("NSC Table Range Violation");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk("unknown");
|
z_fatal_print("unknown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,46 +189,46 @@ static void dump_machine_check_exception(u32_t cause, u32_t parameter)
|
||||||
{
|
{
|
||||||
switch (cause) {
|
switch (cause) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
printk("double fault");
|
z_fatal_print("double fault");
|
||||||
break;
|
break;
|
||||||
case 0x1:
|
case 0x1:
|
||||||
printk("overlapping TLB entries");
|
z_fatal_print("overlapping TLB entries");
|
||||||
break;
|
break;
|
||||||
case 0x2:
|
case 0x2:
|
||||||
printk("fatal TLB error");
|
z_fatal_print("fatal TLB error");
|
||||||
break;
|
break;
|
||||||
case 0x3:
|
case 0x3:
|
||||||
printk("fatal cache error");
|
z_fatal_print("fatal cache error");
|
||||||
break;
|
break;
|
||||||
case 0x4:
|
case 0x4:
|
||||||
printk("internal memory error on instruction fetch");
|
z_fatal_print("internal memory error on instruction fetch");
|
||||||
break;
|
break;
|
||||||
case 0x5:
|
case 0x5:
|
||||||
printk("internal memory error on data fetch");
|
z_fatal_print("internal memory error on data fetch");
|
||||||
break;
|
break;
|
||||||
case 0x6:
|
case 0x6:
|
||||||
printk("illegal overlapping MPU entries");
|
z_fatal_print("illegal overlapping MPU entries");
|
||||||
if (parameter == 0x1) {
|
if (parameter == 0x1) {
|
||||||
printk(" (jump and branch target)");
|
z_fatal_print(" - jump and branch target");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x10:
|
case 0x10:
|
||||||
printk("secure vector table not located in secure memory");
|
z_fatal_print("secure vector table not located in secure memory");
|
||||||
break;
|
break;
|
||||||
case 0x11:
|
case 0x11:
|
||||||
printk("NSC jump table not located in secure memory");
|
z_fatal_print("NSC jump table not located in secure memory");
|
||||||
break;
|
break;
|
||||||
case 0x12:
|
case 0x12:
|
||||||
printk("secure handler code not located in secure memory");
|
z_fatal_print("secure handler code not located in secure memory");
|
||||||
break;
|
break;
|
||||||
case 0x13:
|
case 0x13:
|
||||||
printk("NSC target address not located in secure memory");
|
z_fatal_print("NSC target address not located in secure memory");
|
||||||
break;
|
break;
|
||||||
case 0x80:
|
case 0x80:
|
||||||
printk("uncorrectable ECC or parity error in vector memory");
|
z_fatal_print("uncorrectable ECC or parity error in vector memory");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk("unknown");
|
z_fatal_print("unknown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,54 +237,54 @@ static void dump_privilege_exception(u32_t cause, u32_t parameter)
|
||||||
{
|
{
|
||||||
switch (cause) {
|
switch (cause) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
printk("Privilege violation");
|
z_fatal_print("Privilege violation");
|
||||||
break;
|
break;
|
||||||
case 0x1:
|
case 0x1:
|
||||||
printk("disabled extension");
|
z_fatal_print("disabled extension");
|
||||||
break;
|
break;
|
||||||
case 0x2:
|
case 0x2:
|
||||||
printk("action point hit");
|
z_fatal_print("action point hit");
|
||||||
break;
|
break;
|
||||||
case 0x10:
|
case 0x10:
|
||||||
switch (parameter) {
|
switch (parameter) {
|
||||||
case 0x1:
|
case 0x1:
|
||||||
printk("N to S return using incorrect return mechanism");
|
z_fatal_print("N to S return using incorrect return mechanism");
|
||||||
break;
|
break;
|
||||||
case 0x2:
|
case 0x2:
|
||||||
printk("N to S return with incorrect operating mode");
|
z_fatal_print("N to S return with incorrect operating mode");
|
||||||
break;
|
break;
|
||||||
case 0x3:
|
case 0x3:
|
||||||
printk("IRQ/exception return fetch from wrong mode");
|
z_fatal_print("IRQ/exception return fetch from wrong mode");
|
||||||
break;
|
break;
|
||||||
case 0x4:
|
case 0x4:
|
||||||
printk("attempt to halt secure processor in NS mode");
|
z_fatal_print("attempt to halt secure processor in NS mode");
|
||||||
break;
|
break;
|
||||||
case 0x20:
|
case 0x20:
|
||||||
printk("attempt to access secure resource from normal mode");
|
z_fatal_print("attempt to access secure resource from normal mode");
|
||||||
break;
|
break;
|
||||||
case 0x40:
|
case 0x40:
|
||||||
printk("SID violation on resource access (APEX/UAUX/key NVM)");
|
z_fatal_print("SID violation on resource access (APEX/UAUX/key NVM)");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk("unknown");
|
z_fatal_print("unknown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x13:
|
case 0x13:
|
||||||
switch (parameter) {
|
switch (parameter) {
|
||||||
case 0x20:
|
case 0x20:
|
||||||
printk("attempt to access secure APEX feature from NS mode");
|
z_fatal_print("attempt to access secure APEX feature from NS mode");
|
||||||
break;
|
break;
|
||||||
case 0x40:
|
case 0x40:
|
||||||
printk("SID violation on access to APEX feature");
|
z_fatal_print("SID violation on access to APEX feature");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk("unknown");
|
z_fatal_print("unknown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk("unknown");
|
z_fatal_print("unknown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,7 +292,7 @@ static void dump_privilege_exception(u32_t cause, u32_t parameter)
|
||||||
static void dump_exception_info(u32_t vector, u32_t cause, u32_t parameter)
|
static void dump_exception_info(u32_t vector, u32_t cause, u32_t parameter)
|
||||||
{
|
{
|
||||||
if (vector >= 0x10 && vector <= 0xFF) {
|
if (vector >= 0x10 && vector <= 0xFF) {
|
||||||
printk("interrupt %u\n", vector);
|
z_fatal_print("interrupt %u", vector);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,59 +301,57 @@ static void dump_exception_info(u32_t vector, u32_t cause, u32_t parameter)
|
||||||
*/
|
*/
|
||||||
switch (vector) {
|
switch (vector) {
|
||||||
case ARC_EV_RESET:
|
case ARC_EV_RESET:
|
||||||
printk("Reset");
|
z_fatal_print("Reset");
|
||||||
break;
|
break;
|
||||||
case ARC_EV_MEM_ERROR:
|
case ARC_EV_MEM_ERROR:
|
||||||
printk("Memory Error");
|
z_fatal_print("Memory Error");
|
||||||
break;
|
break;
|
||||||
case ARC_EV_INS_ERROR:
|
case ARC_EV_INS_ERROR:
|
||||||
printk("Instruction Error");
|
z_fatal_print("Instruction Error");
|
||||||
break;
|
break;
|
||||||
case ARC_EV_MACHINE_CHECK:
|
case ARC_EV_MACHINE_CHECK:
|
||||||
printk("EV_MachineCheck: ");
|
z_fatal_print("EV_MachineCheck");
|
||||||
dump_machine_check_exception(cause, parameter);
|
dump_machine_check_exception(cause, parameter);
|
||||||
break;
|
break;
|
||||||
case ARC_EV_TLB_MISS_I:
|
case ARC_EV_TLB_MISS_I:
|
||||||
printk("EV_TLBMissI");
|
z_fatal_print("EV_TLBMissI");
|
||||||
break;
|
break;
|
||||||
case ARC_EV_TLB_MISS_D:
|
case ARC_EV_TLB_MISS_D:
|
||||||
printk("EV_TLBMissD");
|
z_fatal_print("EV_TLBMissD");
|
||||||
break;
|
break;
|
||||||
case ARC_EV_PROT_V:
|
case ARC_EV_PROT_V:
|
||||||
printk("EV_ProtV: ");
|
z_fatal_print("EV_ProtV");
|
||||||
dump_protv_exception(cause, parameter);
|
dump_protv_exception(cause, parameter);
|
||||||
break;
|
break;
|
||||||
case ARC_EV_PRIVILEGE_V:
|
case ARC_EV_PRIVILEGE_V:
|
||||||
printk("EV_PrivilegeV: ");
|
z_fatal_print("EV_PrivilegeV");
|
||||||
dump_privilege_exception(cause, parameter);
|
dump_privilege_exception(cause, parameter);
|
||||||
break;
|
break;
|
||||||
case ARC_EV_SWI:
|
case ARC_EV_SWI:
|
||||||
printk("EV_SWI");
|
z_fatal_print("EV_SWI");
|
||||||
break;
|
break;
|
||||||
case ARC_EV_TRAP:
|
case ARC_EV_TRAP:
|
||||||
printk("EV_Trap");
|
z_fatal_print("EV_Trap");
|
||||||
break;
|
break;
|
||||||
case ARC_EV_EXTENSION:
|
case ARC_EV_EXTENSION:
|
||||||
printk("EV_Extension");
|
z_fatal_print("EV_Extension");
|
||||||
break;
|
break;
|
||||||
case ARC_EV_DIV_ZERO:
|
case ARC_EV_DIV_ZERO:
|
||||||
printk("EV_DivZero");
|
z_fatal_print("EV_DivZero");
|
||||||
break;
|
break;
|
||||||
case ARC_EV_DC_ERROR:
|
case ARC_EV_DC_ERROR:
|
||||||
printk("EV_DCError");
|
z_fatal_print("EV_DCError");
|
||||||
break;
|
break;
|
||||||
case ARC_EV_MISALIGNED:
|
case ARC_EV_MISALIGNED:
|
||||||
printk("EV_Misaligned");
|
z_fatal_print("EV_Misaligned");
|
||||||
break;
|
break;
|
||||||
case ARC_EV_VEC_UNIT:
|
case ARC_EV_VEC_UNIT:
|
||||||
printk("EV_VecUnit");
|
z_fatal_print("EV_VecUnit");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk("unknown");
|
z_fatal_print("unknown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printk("\n");
|
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_ARC_EXCEPTION_DEBUG */
|
#endif /* CONFIG_ARC_EXCEPTION_DEBUG */
|
||||||
|
|
||||||
|
@ -402,9 +391,9 @@ void _Fault(NANO_ESF *esf)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printk("***** Exception vector: 0x%x, cause code: 0x%x, parameter 0x%x\n",
|
z_fatal_print("***** Exception vector: 0x%x, cause code: 0x%x, parameter 0x%x",
|
||||||
vector, cause, parameter);
|
vector, cause, parameter);
|
||||||
printk("Address 0x%x\n", exc_addr);
|
z_fatal_print("Address 0x%x", exc_addr);
|
||||||
#ifdef CONFIG_ARC_EXCEPTION_DEBUG
|
#ifdef CONFIG_ARC_EXCEPTION_DEBUG
|
||||||
dump_exception_info(vector, cause, parameter);
|
dump_exception_info(vector, cause, parameter);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,12 +17,11 @@
|
||||||
|
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <kernel_structs.h>
|
#include <kernel_structs.h>
|
||||||
#include <sys/printk.h>
|
|
||||||
#include <logging/log_ctrl.h>
|
#include <logging/log_ctrl.h>
|
||||||
|
|
||||||
void z_arm_fatal_error(unsigned int reason, const NANO_ESF *esf)
|
void z_arm_fatal_error(unsigned int reason, const NANO_ESF *esf)
|
||||||
{
|
{
|
||||||
printk("Faulting instruction address = 0x%x\n",
|
z_fatal_print("Faulting instruction address = 0x%x",
|
||||||
esf->basic.pc);
|
esf->basic.pc);
|
||||||
z_fatal_error(reason, esf);
|
z_fatal_error(reason, esf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,13 @@
|
||||||
#include <exc_handle.h>
|
#include <exc_handle.h>
|
||||||
#include <logging/log_ctrl.h>
|
#include <logging/log_ctrl.h>
|
||||||
|
|
||||||
#ifdef CONFIG_PRINTK
|
#if defined(CONFIG_PRINTK) || defined(CONFIG_LOG)
|
||||||
#include <sys/printk.h>
|
#define PR_EXC(...) z_fatal_print(__VA_ARGS__)
|
||||||
#define PR_EXC(...) printk(__VA_ARGS__)
|
|
||||||
#define STORE_xFAR(reg_var, reg) u32_t reg_var = (u32_t)reg
|
#define STORE_xFAR(reg_var, reg) u32_t reg_var = (u32_t)reg
|
||||||
#else
|
#else
|
||||||
#define PR_EXC(...)
|
#define PR_EXC(...)
|
||||||
#define STORE_xFAR(reg_var, reg)
|
#define STORE_xFAR(reg_var, reg)
|
||||||
#endif /* CONFIG_PRINTK */
|
#endif /* CONFIG_PRINTK || CONFIG_LOG */
|
||||||
|
|
||||||
#if (CONFIG_FAULT_DUMP == 2)
|
#if (CONFIG_FAULT_DUMP == 2)
|
||||||
#define PR_FAULT_INFO(...) PR_EXC(__VA_ARGS__)
|
#define PR_FAULT_INFO(...) PR_EXC(__VA_ARGS__)
|
||||||
|
@ -139,13 +138,13 @@
|
||||||
#if (CONFIG_FAULT_DUMP == 1)
|
#if (CONFIG_FAULT_DUMP == 1)
|
||||||
static void FaultShow(const NANO_ESF *esf, int fault)
|
static void FaultShow(const NANO_ESF *esf, int fault)
|
||||||
{
|
{
|
||||||
PR_EXC("Fault! EXC #%d\n", fault);
|
PR_EXC("Fault! EXC #%d", fault);
|
||||||
|
|
||||||
#if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
#if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
|
||||||
PR_EXC("MMFSR: 0x%x, BFSR: 0x%x, UFSR: 0x%x\n",
|
PR_EXC("MMFSR: 0x%x, BFSR: 0x%x, UFSR: 0x%x",
|
||||||
SCB_MMFSR, SCB_BFSR, SCB_UFSR);
|
SCB_MMFSR, SCB_BFSR, SCB_UFSR);
|
||||||
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
|
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
|
||||||
PR_EXC("SFSR: 0x%x\n", SAU->SFSR);
|
PR_EXC("SFSR: 0x%x", SAU->SFSR);
|
||||||
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
|
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
|
||||||
#endif /* CONFIG_ARMV7_M_ARMV8_M_MAINLINE */
|
#endif /* CONFIG_ARMV7_M_ARMV8_M_MAINLINE */
|
||||||
}
|
}
|
||||||
|
@ -216,17 +215,17 @@ static u32_t MpuFault(NANO_ESF *esf, int fromHardFault, bool *recoverable)
|
||||||
u32_t reason = K_ERR_CPU_EXCEPTION;
|
u32_t reason = K_ERR_CPU_EXCEPTION;
|
||||||
u32_t mmfar = -EINVAL;
|
u32_t mmfar = -EINVAL;
|
||||||
|
|
||||||
PR_FAULT_INFO("***** MPU FAULT *****\n");
|
PR_FAULT_INFO("***** MPU FAULT *****");
|
||||||
|
|
||||||
if ((SCB->CFSR & SCB_CFSR_MSTKERR_Msk) != 0) {
|
if ((SCB->CFSR & SCB_CFSR_MSTKERR_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Stacking error (context area might be"
|
PR_FAULT_INFO(" Stacking error (context area might be"
|
||||||
" not valid)\n");
|
" not valid)");
|
||||||
}
|
}
|
||||||
if ((SCB->CFSR & SCB_CFSR_MUNSTKERR_Msk) != 0) {
|
if ((SCB->CFSR & SCB_CFSR_MUNSTKERR_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Unstacking error\n");
|
PR_FAULT_INFO(" Unstacking error");
|
||||||
}
|
}
|
||||||
if ((SCB->CFSR & SCB_CFSR_DACCVIOL_Msk) != 0) {
|
if ((SCB->CFSR & SCB_CFSR_DACCVIOL_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Data Access Violation\n");
|
PR_FAULT_INFO(" Data Access Violation");
|
||||||
/* In a fault handler, to determine the true faulting address:
|
/* In a fault handler, to determine the true faulting address:
|
||||||
* 1. Read and save the MMFAR value.
|
* 1. Read and save the MMFAR value.
|
||||||
* 2. Read the MMARVALID bit in the MMFSR.
|
* 2. Read the MMARVALID bit in the MMFSR.
|
||||||
|
@ -238,7 +237,7 @@ static u32_t MpuFault(NANO_ESF *esf, int fromHardFault, bool *recoverable)
|
||||||
mmfar = SCB->MMFAR;
|
mmfar = SCB->MMFAR;
|
||||||
|
|
||||||
if ((SCB->CFSR & SCB_CFSR_MMARVALID_Msk) != 0) {
|
if ((SCB->CFSR & SCB_CFSR_MMARVALID_Msk) != 0) {
|
||||||
PR_EXC(" MMFAR Address: 0x%x\n", mmfar);
|
PR_EXC(" MMFAR Address: 0x%x", mmfar);
|
||||||
if (fromHardFault) {
|
if (fromHardFault) {
|
||||||
/* clear SCB_MMAR[VALID] to reset */
|
/* clear SCB_MMAR[VALID] to reset */
|
||||||
SCB->CFSR &= ~SCB_CFSR_MMARVALID_Msk;
|
SCB->CFSR &= ~SCB_CFSR_MMARVALID_Msk;
|
||||||
|
@ -246,12 +245,12 @@ static u32_t MpuFault(NANO_ESF *esf, int fromHardFault, bool *recoverable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((SCB->CFSR & SCB_CFSR_IACCVIOL_Msk) != 0) {
|
if ((SCB->CFSR & SCB_CFSR_IACCVIOL_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Instruction Access Violation\n");
|
PR_FAULT_INFO(" Instruction Access Violation");
|
||||||
}
|
}
|
||||||
#if defined(CONFIG_ARMV7_M_ARMV8_M_FP)
|
#if defined(CONFIG_ARMV7_M_ARMV8_M_FP)
|
||||||
if ((SCB->CFSR & SCB_CFSR_MLSPERR_Msk) != 0) {
|
if ((SCB->CFSR & SCB_CFSR_MLSPERR_Msk) != 0) {
|
||||||
PR_FAULT_INFO(
|
PR_FAULT_INFO(
|
||||||
" Floating-point lazy state preservation error\n");
|
" Floating-point lazy state preservation error");
|
||||||
}
|
}
|
||||||
#endif /* !defined(CONFIG_ARMV7_M_ARMV8_M_FP) */
|
#endif /* !defined(CONFIG_ARMV7_M_ARMV8_M_FP) */
|
||||||
|
|
||||||
|
@ -338,16 +337,16 @@ static int BusFault(NANO_ESF *esf, int fromHardFault, bool *recoverable)
|
||||||
{
|
{
|
||||||
u32_t reason = K_ERR_CPU_EXCEPTION;
|
u32_t reason = K_ERR_CPU_EXCEPTION;
|
||||||
|
|
||||||
PR_FAULT_INFO("***** BUS FAULT *****\n");
|
PR_FAULT_INFO("***** BUS FAULT *****");
|
||||||
|
|
||||||
if (SCB->CFSR & SCB_CFSR_STKERR_Msk) {
|
if (SCB->CFSR & SCB_CFSR_STKERR_Msk) {
|
||||||
PR_FAULT_INFO(" Stacking error\n");
|
PR_FAULT_INFO(" Stacking error");
|
||||||
}
|
}
|
||||||
if (SCB->CFSR & SCB_CFSR_UNSTKERR_Msk) {
|
if (SCB->CFSR & SCB_CFSR_UNSTKERR_Msk) {
|
||||||
PR_FAULT_INFO(" Unstacking error\n");
|
PR_FAULT_INFO(" Unstacking error");
|
||||||
}
|
}
|
||||||
if (SCB->CFSR & SCB_CFSR_PRECISERR_Msk) {
|
if (SCB->CFSR & SCB_CFSR_PRECISERR_Msk) {
|
||||||
PR_FAULT_INFO(" Precise data bus error\n");
|
PR_FAULT_INFO(" Precise data bus error");
|
||||||
/* In a fault handler, to determine the true faulting address:
|
/* In a fault handler, to determine the true faulting address:
|
||||||
* 1. Read and save the BFAR value.
|
* 1. Read and save the BFAR value.
|
||||||
* 2. Read the BFARVALID bit in the BFSR.
|
* 2. Read the BFARVALID bit in the BFSR.
|
||||||
|
@ -359,7 +358,7 @@ static int BusFault(NANO_ESF *esf, int fromHardFault, bool *recoverable)
|
||||||
STORE_xFAR(bfar, SCB->BFAR);
|
STORE_xFAR(bfar, SCB->BFAR);
|
||||||
|
|
||||||
if ((SCB->CFSR & SCB_CFSR_BFARVALID_Msk) != 0) {
|
if ((SCB->CFSR & SCB_CFSR_BFARVALID_Msk) != 0) {
|
||||||
PR_EXC(" BFAR Address: 0x%x\n", bfar);
|
PR_EXC(" BFAR Address: 0x%x", bfar);
|
||||||
if (fromHardFault) {
|
if (fromHardFault) {
|
||||||
/* clear SCB_CFSR_BFAR[VALID] to reset */
|
/* clear SCB_CFSR_BFAR[VALID] to reset */
|
||||||
SCB->CFSR &= ~SCB_CFSR_BFARVALID_Msk;
|
SCB->CFSR &= ~SCB_CFSR_BFARVALID_Msk;
|
||||||
|
@ -367,15 +366,15 @@ static int BusFault(NANO_ESF *esf, int fromHardFault, bool *recoverable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (SCB->CFSR & SCB_CFSR_IMPRECISERR_Msk) {
|
if (SCB->CFSR & SCB_CFSR_IMPRECISERR_Msk) {
|
||||||
PR_FAULT_INFO(" Imprecise data bus error\n");
|
PR_FAULT_INFO(" Imprecise data bus error");
|
||||||
}
|
}
|
||||||
if ((SCB->CFSR & SCB_CFSR_IBUSERR_Msk) != 0) {
|
if ((SCB->CFSR & SCB_CFSR_IBUSERR_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Instruction bus error\n");
|
PR_FAULT_INFO(" Instruction bus error");
|
||||||
#if !defined(CONFIG_ARMV7_M_ARMV8_M_FP)
|
#if !defined(CONFIG_ARMV7_M_ARMV8_M_FP)
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
} else if (SCB->CFSR & SCB_CFSR_LSPERR_Msk) {
|
} else if (SCB->CFSR & SCB_CFSR_LSPERR_Msk) {
|
||||||
PR_FAULT_INFO(" Floating-point lazy state preservation error\n");
|
PR_FAULT_INFO(" Floating-point lazy state preservation error");
|
||||||
}
|
}
|
||||||
#endif /* !defined(CONFIG_ARMV7_M_ARMV8_M_FP) */
|
#endif /* !defined(CONFIG_ARMV7_M_ARMV8_M_FP) */
|
||||||
|
|
||||||
|
@ -393,13 +392,13 @@ static int BusFault(NANO_ESF *esf, int fromHardFault, bool *recoverable)
|
||||||
STORE_xFAR(edr, SYSMPU->SP[i].EDR);
|
STORE_xFAR(edr, SYSMPU->SP[i].EDR);
|
||||||
ear = SYSMPU->SP[i].EAR;
|
ear = SYSMPU->SP[i].EAR;
|
||||||
|
|
||||||
PR_FAULT_INFO(" NXP MPU error, port %d\n", i);
|
PR_FAULT_INFO(" NXP MPU error, port %d", i);
|
||||||
PR_FAULT_INFO(" Mode: %s, %s Address: 0x%x\n",
|
PR_FAULT_INFO(" Mode: %s, %s Address: 0x%x",
|
||||||
edr & BIT(2) ? "Supervisor" : "User",
|
edr & BIT(2) ? "Supervisor" : "User",
|
||||||
edr & BIT(1) ? "Data" : "Instruction",
|
edr & BIT(1) ? "Data" : "Instruction",
|
||||||
ear);
|
ear);
|
||||||
PR_FAULT_INFO(
|
PR_FAULT_INFO(
|
||||||
" Type: %s, Master: %d, Regions: 0x%x\n",
|
" Type: %s, Master: %d, Regions: 0x%x",
|
||||||
edr & BIT(0) ? "Write" : "Read",
|
edr & BIT(0) ? "Write" : "Read",
|
||||||
EMN(edr), EACD(edr));
|
EMN(edr), EACD(edr));
|
||||||
|
|
||||||
|
@ -464,7 +463,7 @@ static int BusFault(NANO_ESF *esf, int fromHardFault, bool *recoverable)
|
||||||
(void)ear;
|
(void)ear;
|
||||||
__ASSERT(0,
|
__ASSERT(0,
|
||||||
"Stacking error without stack guard"
|
"Stacking error without stack guard"
|
||||||
"or User-mode support\n");
|
"or User-mode support");
|
||||||
#endif /* CONFIG_MPU_STACK_GUARD || CONFIG_USERSPACE */
|
#endif /* CONFIG_MPU_STACK_GUARD || CONFIG_USERSPACE */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -492,18 +491,18 @@ static u32_t UsageFault(const NANO_ESF *esf)
|
||||||
{
|
{
|
||||||
u32_t reason = K_ERR_CPU_EXCEPTION;
|
u32_t reason = K_ERR_CPU_EXCEPTION;
|
||||||
|
|
||||||
PR_FAULT_INFO("***** USAGE FAULT *****\n");
|
PR_FAULT_INFO("***** USAGE FAULT *****");
|
||||||
|
|
||||||
/* bits are sticky: they stack and must be reset */
|
/* bits are sticky: they stack and must be reset */
|
||||||
if ((SCB->CFSR & SCB_CFSR_DIVBYZERO_Msk) != 0) {
|
if ((SCB->CFSR & SCB_CFSR_DIVBYZERO_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Division by zero\n");
|
PR_FAULT_INFO(" Division by zero");
|
||||||
}
|
}
|
||||||
if ((SCB->CFSR & SCB_CFSR_UNALIGNED_Msk) != 0) {
|
if ((SCB->CFSR & SCB_CFSR_UNALIGNED_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Unaligned memory access\n");
|
PR_FAULT_INFO(" Unaligned memory access");
|
||||||
}
|
}
|
||||||
#if defined(CONFIG_ARMV8_M_MAINLINE)
|
#if defined(CONFIG_ARMV8_M_MAINLINE)
|
||||||
if ((SCB->CFSR & SCB_CFSR_STKOF_Msk) != 0) {
|
if ((SCB->CFSR & SCB_CFSR_STKOF_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Stack overflow (context area not valid)\n");
|
PR_FAULT_INFO(" Stack overflow (context area not valid)");
|
||||||
#if defined(CONFIG_BUILTIN_STACK_GUARD)
|
#if defined(CONFIG_BUILTIN_STACK_GUARD)
|
||||||
/* Stack Overflows are always reported as stack corruption
|
/* Stack Overflows are always reported as stack corruption
|
||||||
* errors. Note that the built-in stack overflow mechanism
|
* errors. Note that the built-in stack overflow mechanism
|
||||||
|
@ -517,16 +516,16 @@ static u32_t UsageFault(const NANO_ESF *esf)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_ARMV8_M_MAINLINE */
|
#endif /* CONFIG_ARMV8_M_MAINLINE */
|
||||||
if ((SCB->CFSR & SCB_CFSR_NOCP_Msk) != 0) {
|
if ((SCB->CFSR & SCB_CFSR_NOCP_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" No coprocessor instructions\n");
|
PR_FAULT_INFO(" No coprocessor instructions");
|
||||||
}
|
}
|
||||||
if ((SCB->CFSR & SCB_CFSR_INVPC_Msk) != 0) {
|
if ((SCB->CFSR & SCB_CFSR_INVPC_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Illegal load of EXC_RETURN into PC\n");
|
PR_FAULT_INFO(" Illegal load of EXC_RETURN into PC");
|
||||||
}
|
}
|
||||||
if ((SCB->CFSR & SCB_CFSR_INVSTATE_Msk) != 0) {
|
if ((SCB->CFSR & SCB_CFSR_INVSTATE_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Illegal use of the EPSR\n");
|
PR_FAULT_INFO(" Illegal use of the EPSR");
|
||||||
}
|
}
|
||||||
if ((SCB->CFSR & SCB_CFSR_UNDEFINSTR_Msk) != 0) {
|
if ((SCB->CFSR & SCB_CFSR_UNDEFINSTR_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Attempt to execute undefined instruction\n");
|
PR_FAULT_INFO(" Attempt to execute undefined instruction");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clear UFSR sticky bits */
|
/* clear UFSR sticky bits */
|
||||||
|
@ -546,28 +545,28 @@ static u32_t UsageFault(const NANO_ESF *esf)
|
||||||
*/
|
*/
|
||||||
static void SecureFault(const NANO_ESF *esf)
|
static void SecureFault(const NANO_ESF *esf)
|
||||||
{
|
{
|
||||||
PR_FAULT_INFO("***** SECURE FAULT *****\n");
|
PR_FAULT_INFO("***** SECURE FAULT *****");
|
||||||
|
|
||||||
STORE_xFAR(sfar, SAU->SFAR);
|
STORE_xFAR(sfar, SAU->SFAR);
|
||||||
if ((SAU->SFSR & SAU_SFSR_SFARVALID_Msk) != 0) {
|
if ((SAU->SFSR & SAU_SFSR_SFARVALID_Msk) != 0) {
|
||||||
PR_EXC(" Address: 0x%x\n", sfar);
|
PR_EXC(" Address: 0x%x", sfar);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bits are sticky: they stack and must be reset */
|
/* bits are sticky: they stack and must be reset */
|
||||||
if ((SAU->SFSR & SAU_SFSR_INVEP_Msk) != 0) {
|
if ((SAU->SFSR & SAU_SFSR_INVEP_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Invalid entry point\n");
|
PR_FAULT_INFO(" Invalid entry point");
|
||||||
} else if ((SAU->SFSR & SAU_SFSR_INVIS_Msk) != 0) {
|
} else if ((SAU->SFSR & SAU_SFSR_INVIS_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Invalid integrity signature\n");
|
PR_FAULT_INFO(" Invalid integrity signature");
|
||||||
} else if ((SAU->SFSR & SAU_SFSR_INVER_Msk) != 0) {
|
} else if ((SAU->SFSR & SAU_SFSR_INVER_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Invalid exception return\n");
|
PR_FAULT_INFO(" Invalid exception return");
|
||||||
} else if ((SAU->SFSR & SAU_SFSR_AUVIOL_Msk) != 0) {
|
} else if ((SAU->SFSR & SAU_SFSR_AUVIOL_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Attribution unit violation\n");
|
PR_FAULT_INFO(" Attribution unit violation");
|
||||||
} else if ((SAU->SFSR & SAU_SFSR_INVTRAN_Msk) != 0) {
|
} else if ((SAU->SFSR & SAU_SFSR_INVTRAN_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Invalid transition\n");
|
PR_FAULT_INFO(" Invalid transition");
|
||||||
} else if ((SAU->SFSR & SAU_SFSR_LSPERR_Msk) != 0) {
|
} else if ((SAU->SFSR & SAU_SFSR_LSPERR_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Lazy state preservation\n");
|
PR_FAULT_INFO(" Lazy state preservation");
|
||||||
} else if ((SAU->SFSR & SAU_SFSR_LSERR_Msk) != 0) {
|
} else if ((SAU->SFSR & SAU_SFSR_LSERR_Msk) != 0) {
|
||||||
PR_FAULT_INFO(" Lazy state error\n");
|
PR_FAULT_INFO(" Lazy state error");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clear SFSR sticky bits */
|
/* clear SFSR sticky bits */
|
||||||
|
@ -588,7 +587,7 @@ static void DebugMonitor(const NANO_ESF *esf)
|
||||||
ARG_UNUSED(esf);
|
ARG_UNUSED(esf);
|
||||||
|
|
||||||
PR_FAULT_INFO(
|
PR_FAULT_INFO(
|
||||||
"***** Debug monitor exception (not implemented) *****\n");
|
"***** Debug monitor exception (not implemented) *****");
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -607,7 +606,7 @@ static u32_t HardFault(NANO_ESF *esf, bool *recoverable)
|
||||||
{
|
{
|
||||||
u32_t reason = K_ERR_CPU_EXCEPTION;
|
u32_t reason = K_ERR_CPU_EXCEPTION;
|
||||||
|
|
||||||
PR_FAULT_INFO("***** HARD FAULT *****\n");
|
PR_FAULT_INFO("***** HARD FAULT *****");
|
||||||
|
|
||||||
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
|
||||||
*recoverable = memory_fault_recoverable(esf);
|
*recoverable = memory_fault_recoverable(esf);
|
||||||
|
@ -615,9 +614,9 @@ static u32_t HardFault(NANO_ESF *esf, bool *recoverable)
|
||||||
*recoverable = false;
|
*recoverable = false;
|
||||||
|
|
||||||
if ((SCB->HFSR & SCB_HFSR_VECTTBL_Msk) != 0) {
|
if ((SCB->HFSR & SCB_HFSR_VECTTBL_Msk) != 0) {
|
||||||
PR_EXC(" Bus fault on vector table read\n");
|
PR_EXC(" Bus fault on vector table read");
|
||||||
} else if ((SCB->HFSR & SCB_HFSR_FORCED_Msk) != 0) {
|
} else if ((SCB->HFSR & SCB_HFSR_FORCED_Msk) != 0) {
|
||||||
PR_EXC(" Fault escalation (see below)\n");
|
PR_EXC(" Fault escalation (see below)");
|
||||||
if (SCB_MMFSR != 0) {
|
if (SCB_MMFSR != 0) {
|
||||||
reason = MpuFault(esf, 1, recoverable);
|
reason = MpuFault(esf, 1, recoverable);
|
||||||
} else if (SCB_BFSR != 0) {
|
} else if (SCB_BFSR != 0) {
|
||||||
|
@ -649,7 +648,7 @@ static void ReservedException(const NANO_ESF *esf, int fault)
|
||||||
{
|
{
|
||||||
ARG_UNUSED(esf);
|
ARG_UNUSED(esf);
|
||||||
|
|
||||||
PR_FAULT_INFO("***** %s %d) *****\n",
|
PR_FAULT_INFO("***** %s %d) *****",
|
||||||
fault < 16 ? "Reserved Exception (" : "Spurious interrupt (IRQ ",
|
fault < 16 ? "Reserved Exception (" : "Spurious interrupt (IRQ ",
|
||||||
fault - 16);
|
fault - 16);
|
||||||
}
|
}
|
||||||
|
@ -742,7 +741,7 @@ static void SecureStackDump(const NANO_ESF *secure_esf)
|
||||||
*/
|
*/
|
||||||
sec_ret_addr = *top_of_sec_stack;
|
sec_ret_addr = *top_of_sec_stack;
|
||||||
}
|
}
|
||||||
PR_FAULT_INFO(" S instruction address: 0x%x\n", sec_ret_addr);
|
PR_FAULT_INFO(" S instruction address: 0x%x", sec_ret_addr);
|
||||||
|
|
||||||
}
|
}
|
||||||
#define SECURE_STACK_DUMP(esf) SecureStackDump(esf)
|
#define SECURE_STACK_DUMP(esf) SecureStackDump(esf)
|
||||||
|
@ -818,13 +817,13 @@ void _Fault(NANO_ESF *esf, u32_t exc_return)
|
||||||
if (exc_return & EXC_RETURN_MODE_THREAD) {
|
if (exc_return & EXC_RETURN_MODE_THREAD) {
|
||||||
esf = (NANO_ESF *)__TZ_get_PSP_NS();
|
esf = (NANO_ESF *)__TZ_get_PSP_NS();
|
||||||
if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) == 0) {
|
if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) == 0) {
|
||||||
PR_EXC("RETTOBASE does not match EXC_RETURN\n");
|
PR_EXC("RETTOBASE does not match EXC_RETURN");
|
||||||
goto _exit_fatal;
|
goto _exit_fatal;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
esf = (NANO_ESF *)__TZ_get_MSP_NS();
|
esf = (NANO_ESF *)__TZ_get_MSP_NS();
|
||||||
if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) != 0) {
|
if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) != 0) {
|
||||||
PR_EXC("RETTOBASE does not match EXC_RETURN\n");
|
PR_EXC("RETTOBASE does not match EXC_RETURN");
|
||||||
goto _exit_fatal;
|
goto _exit_fatal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -850,7 +849,7 @@ void _Fault(NANO_ESF *esf, u32_t exc_return)
|
||||||
* inspection will indicate the Non-Secure instruction
|
* inspection will indicate the Non-Secure instruction
|
||||||
* that performed the branch to the Secure domain.
|
* that performed the branch to the Secure domain.
|
||||||
*/
|
*/
|
||||||
PR_FAULT_INFO("Exception occurred in Secure State\n");
|
PR_FAULT_INFO("Exception occurred in Secure State");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
(void) exc_return;
|
(void) exc_return;
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
#include <kernel_structs.h>
|
#include <kernel_structs.h>
|
||||||
#include <sys/printk.h>
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <logging/log_ctrl.h>
|
#include <logging/log_ctrl.h>
|
||||||
|
|
||||||
|
@ -22,24 +21,24 @@ FUNC_NORETURN void z_nios2_fatal_error(unsigned int reason,
|
||||||
* entry. We may want to introduce a config option to save and
|
* entry. We may want to introduce a config option to save and
|
||||||
* dump all registers, at the expense of some stack space.
|
* dump all registers, at the expense of some stack space.
|
||||||
*/
|
*/
|
||||||
printk("Faulting instruction: 0x%x\n"
|
z_fatal_print("Faulting instruction: 0x%08x", esf->instr - 4);
|
||||||
" r1: 0x%x r2: 0x%x r3: 0x%x r4: 0x%x\n"
|
z_fatal_print(" r1: 0x%08x r2: 0x%08x r3: 0x%08x r4: 0x%08x",
|
||||||
" r5: 0x%x r6: 0x%x r7: 0x%x r8: 0x%x\n"
|
esf->r1, esf->r2, esf->r3, esf->r4);
|
||||||
" r9: 0x%x r10: 0x%x r11: 0x%x r12: 0x%x\n"
|
z_fatal_print(" r5: 0x%08x r6: 0x%08x r7: 0x%08x r8: 0x%08x",
|
||||||
" r13: 0x%x r14: 0x%x r15: 0x%x ra: 0x%x\n"
|
esf->r5, esf->r6, esf->r7, esf->r8);
|
||||||
"estatus: %x\n", esf->instr - 4,
|
z_fatal_print(" r9: 0x%08x r10: 0x%08x r11: 0x%08x r12: 0x%08x",
|
||||||
esf->r1, esf->r2, esf->r3, esf->r4,
|
esf->r9, esf->r10, esf->r11, esf->r12);
|
||||||
esf->r5, esf->r6, esf->r7, esf->r8,
|
z_fatal_print(" r13: 0x%08x r14: 0x%08x r15: 0x%08x ra: 0x%08x",
|
||||||
esf->r9, esf->r10, esf->r11, esf->r12,
|
esf->r13, esf->r14, esf->r15, esf->ra);
|
||||||
esf->r13, esf->r14, esf->r15, esf->ra,
|
z_fatal_print("estatus: %08x", esf->estatus);
|
||||||
esf->estatus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
z_fatal_error(reason, esf);
|
z_fatal_error(reason, esf);
|
||||||
CODE_UNREACHABLE;
|
CODE_UNREACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_EXTRA_EXCEPTION_INFO) && defined(CONFIG_PRINTK) \
|
#if defined(CONFIG_EXTRA_EXCEPTION_INFO) && \
|
||||||
|
(defined(CONFIG_PRINTK) || defined(CONFIG_LOG)) \
|
||||||
&& defined(ALT_CPU_HAS_EXTRA_EXCEPTION_INFO)
|
&& defined(ALT_CPU_HAS_EXTRA_EXCEPTION_INFO)
|
||||||
static char *cause_str(u32_t cause_code)
|
static char *cause_str(u32_t cause_code)
|
||||||
{
|
{
|
||||||
|
@ -102,7 +101,7 @@ static char *cause_str(u32_t cause_code)
|
||||||
|
|
||||||
FUNC_NORETURN void _Fault(const NANO_ESF *esf)
|
FUNC_NORETURN void _Fault(const NANO_ESF *esf)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_PRINTK
|
#if defined(CONFIG_PRINTK) || defined(CONFIG_LOG)
|
||||||
/* Unfortunately, completely unavailable on Nios II/e cores */
|
/* Unfortunately, completely unavailable on Nios II/e cores */
|
||||||
#ifdef ALT_CPU_HAS_EXTRA_EXCEPTION_INFO
|
#ifdef ALT_CPU_HAS_EXTRA_EXCEPTION_INFO
|
||||||
u32_t exc_reg, badaddr_reg, eccftl;
|
u32_t exc_reg, badaddr_reg, eccftl;
|
||||||
|
@ -117,16 +116,16 @@ FUNC_NORETURN void _Fault(const NANO_ESF *esf)
|
||||||
cause = (exc_reg & NIOS2_EXCEPTION_REG_CAUSE_MASK)
|
cause = (exc_reg & NIOS2_EXCEPTION_REG_CAUSE_MASK)
|
||||||
>> NIOS2_EXCEPTION_REG_CAUSE_OFST;
|
>> NIOS2_EXCEPTION_REG_CAUSE_OFST;
|
||||||
|
|
||||||
printk("Exception cause: %d ECCFTL: 0x%x\n", cause, eccftl);
|
z_fatal_print("Exception cause: %d ECCFTL: 0x%x", cause, eccftl);
|
||||||
#if CONFIG_EXTRA_EXCEPTION_INFO
|
#if CONFIG_EXTRA_EXCEPTION_INFO
|
||||||
printk("reason: %s\n", cause_str(cause));
|
z_fatal_print("reason: %s", cause_str(cause));
|
||||||
#endif
|
#endif
|
||||||
if (BIT(cause) & NIOS2_BADADDR_CAUSE_MASK) {
|
if (BIT(cause) & NIOS2_BADADDR_CAUSE_MASK) {
|
||||||
badaddr_reg = z_nios2_creg_read(NIOS2_CR_BADADDR);
|
badaddr_reg = z_nios2_creg_read(NIOS2_CR_BADADDR);
|
||||||
printk("Badaddr: 0x%x\n", badaddr_reg);
|
z_fatal_print("Badaddr: 0x%x", badaddr_reg);
|
||||||
}
|
}
|
||||||
#endif /* ALT_CPU_HAS_EXTRA_EXCEPTION_INFO */
|
#endif /* ALT_CPU_HAS_EXTRA_EXCEPTION_INFO */
|
||||||
#endif /* CONFIG_PRINTK */
|
#endif /* CONFIG_PRINTK || CONFIG_LOG */
|
||||||
|
|
||||||
z_nios2_fatal_error(K_ERR_CPU_EXCEPTION, esf);
|
z_nios2_fatal_error(K_ERR_CPU_EXCEPTION, esf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include <kernel_structs.h>
|
#include <kernel_structs.h>
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
#include <irq.h>
|
#include <irq.h>
|
||||||
#include <sys/printk.h>
|
|
||||||
#include <sw_isr_table.h>
|
#include <sw_isr_table.h>
|
||||||
#include <ksched.h>
|
#include <ksched.h>
|
||||||
#include <kswap.h>
|
#include <kswap.h>
|
||||||
|
@ -24,7 +23,7 @@
|
||||||
FUNC_NORETURN void z_irq_spurious(void *unused)
|
FUNC_NORETURN void z_irq_spurious(void *unused)
|
||||||
{
|
{
|
||||||
ARG_UNUSED(unused);
|
ARG_UNUSED(unused);
|
||||||
printk("Spurious interrupt detected! ipending: %x\n",
|
z_fatal_print("Spurious interrupt detected! ipending: %x",
|
||||||
z_nios2_creg_read(NIOS2_CR_IPENDING));
|
z_nios2_creg_read(NIOS2_CR_IPENDING));
|
||||||
z_nios2_fatal_error(K_ERR_SPURIOUS_IRQ, NULL);
|
z_nios2_fatal_error(K_ERR_SPURIOUS_IRQ, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,24 +7,23 @@
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <kernel_structs.h>
|
#include <kernel_structs.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <sys/printk.h>
|
|
||||||
#include <logging/log_ctrl.h>
|
#include <logging/log_ctrl.h>
|
||||||
|
|
||||||
FUNC_NORETURN void z_riscv32_fatal_error(unsigned int reason,
|
FUNC_NORETURN void z_riscv32_fatal_error(unsigned int reason,
|
||||||
const NANO_ESF *esf)
|
const NANO_ESF *esf)
|
||||||
{
|
{
|
||||||
if (esf != NULL) {
|
if (esf != NULL) {
|
||||||
printk("Faulting instruction address = 0x%x\n"
|
z_fatal_print("Faulting instruction address = 0x%08x",
|
||||||
" ra: 0x%x gp: 0x%x tp: 0x%x t0: 0x%x\n"
|
esf->mepc);
|
||||||
" t1: 0x%x t2: 0x%x t3: 0x%x t4: 0x%x\n"
|
z_fatal_print(" ra: 0x%08x gp: 0x%08x tp: 0x%08x t0: 0x%08x",
|
||||||
" t5: 0x%x t6: 0x%x a0: 0x%x a1: 0x%x\n"
|
esf->ra, esf->gp, esf->tp, esf->t0);
|
||||||
" a2: 0x%x a3: 0x%x a4: 0x%x a5: 0x%x\n"
|
z_fatal_print(" t1: 0x%08x t2: 0x%08x t3: 0x%08x t4: 0x%08x",
|
||||||
" a6: 0x%x a7: 0x%x\n",
|
esf->t1, esf->t2, esf->t3, esf->t4);
|
||||||
esf->mepc,
|
z_fatal_print(" t5: 0x%08x t6: 0x%08x a0: 0x%08x a1: 0x%08x",
|
||||||
esf->ra, esf->gp, esf->tp, esf->t0,
|
esf->t5, esf->t6, esf->a0, esf->a1);
|
||||||
esf->t1, esf->t2, esf->t3, esf->t4,
|
z_fatal_print(" a2: 0x%08x a3: 0x%08x a4: 0x%08x a5: 0x%08x",
|
||||||
esf->t5, esf->t6, esf->a0, esf->a1,
|
esf->a2, esf->a3, esf->a4, esf->a5);
|
||||||
esf->a2, esf->a3, esf->a4, esf->a5,
|
z_fatal_print(" a6: 0x%08x a7: 0x%08x\n",
|
||||||
esf->a6, esf->a7);
|
esf->a6, esf->a7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +58,8 @@ FUNC_NORETURN void _Fault(const NANO_ESF *esf)
|
||||||
__asm__ volatile("csrr %0, mcause" : "=r" (mcause));
|
__asm__ volatile("csrr %0, mcause" : "=r" (mcause));
|
||||||
|
|
||||||
mcause &= SOC_MCAUSE_EXP_MASK;
|
mcause &= SOC_MCAUSE_EXP_MASK;
|
||||||
printk("Exception cause %s (%d)\n", cause_str(mcause), (int)mcause);
|
z_fatal_print("Exception cause %s (%d)", cause_str(mcause),
|
||||||
|
(int)mcause);
|
||||||
|
|
||||||
z_riscv32_fatal_error(K_ERR_CPU_EXCEPTION, esf);
|
z_riscv32_fatal_error(K_ERR_CPU_EXCEPTION, esf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include <toolchain.h>
|
#include <toolchain.h>
|
||||||
#include <kernel_structs.h>
|
#include <kernel_structs.h>
|
||||||
#include <sys/printk.h>
|
|
||||||
|
|
||||||
FUNC_NORETURN void z_irq_spurious(void *unused)
|
FUNC_NORETURN void z_irq_spurious(void *unused)
|
||||||
{
|
{
|
||||||
|
@ -18,10 +17,10 @@ FUNC_NORETURN void z_irq_spurious(void *unused)
|
||||||
|
|
||||||
mcause &= SOC_MCAUSE_EXP_MASK;
|
mcause &= SOC_MCAUSE_EXP_MASK;
|
||||||
|
|
||||||
printk("Spurious interrupt detected! IRQ: %d\n", (int)mcause);
|
z_fatal_print("Spurious interrupt detected! IRQ: %d", (int)mcause);
|
||||||
#if defined(CONFIG_RISCV_HAS_PLIC)
|
#if defined(CONFIG_RISCV_HAS_PLIC)
|
||||||
if (mcause == RISCV_MACHINE_EXT_IRQ) {
|
if (mcause == RISCV_MACHINE_EXT_IRQ) {
|
||||||
printk("PLIC interrupt line causing the IRQ: %d\n",
|
z_fatal_print("PLIC interrupt line causing the IRQ: %d",
|
||||||
riscv_plic_get_irq());
|
riscv_plic_get_irq());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <kernel_structs.h>
|
#include <kernel_structs.h>
|
||||||
#include <sys/printk.h>
|
|
||||||
#include <drivers/interrupt_controller/sysapic.h>
|
#include <drivers/interrupt_controller/sysapic.h>
|
||||||
#include <arch/x86/ia32/segmentation.h>
|
#include <arch/x86/ia32/segmentation.h>
|
||||||
#include <ia32/exception.h>
|
#include <ia32/exception.h>
|
||||||
|
@ -78,13 +77,13 @@ static void unwind_stack(u32_t base_ptr, u16_t cs)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (base_ptr == 0U) {
|
if (base_ptr == 0U) {
|
||||||
printk("NULL base ptr\n");
|
z_fatal_print("NULL base ptr");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < MAX_STACK_FRAMES; i++) {
|
for (i = 0; i < MAX_STACK_FRAMES; i++) {
|
||||||
if (base_ptr % sizeof(base_ptr) != 0U) {
|
if (base_ptr % sizeof(base_ptr) != 0U) {
|
||||||
printk("unaligned frame ptr\n");
|
z_fatal_print("unaligned frame ptr");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +97,7 @@ static void unwind_stack(u32_t base_ptr, u16_t cs)
|
||||||
* stack buffer
|
* stack buffer
|
||||||
*/
|
*/
|
||||||
if (check_stack_bounds((u32_t)frame, sizeof(*frame), cs)) {
|
if (check_stack_bounds((u32_t)frame, sizeof(*frame), cs)) {
|
||||||
printk(" corrupted? (bp=%p)\n", frame);
|
z_fatal_print(" corrupted? (bp=%p)", frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -107,9 +106,10 @@ static void unwind_stack(u32_t base_ptr, u16_t cs)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_X86_IAMCU
|
#ifdef CONFIG_X86_IAMCU
|
||||||
printk(" 0x%08x\n", frame->ret_addr);
|
z_fatal_print(" 0x%08x", frame->ret_addr);
|
||||||
#else
|
#else
|
||||||
printk(" 0x%08x (0x%x)\n", frame->ret_addr, frame->args);
|
z_fatal_print(" 0x%08x (0x%x)", frame->ret_addr,
|
||||||
|
frame->args);
|
||||||
#endif
|
#endif
|
||||||
base_ptr = frame->next;
|
base_ptr = frame->next;
|
||||||
}
|
}
|
||||||
|
@ -132,16 +132,17 @@ FUNC_NORETURN void z_arch_system_halt(unsigned int reason)
|
||||||
FUNC_NORETURN void z_x86_fatal_error(unsigned int reason, const NANO_ESF *esf)
|
FUNC_NORETURN void z_x86_fatal_error(unsigned int reason, const NANO_ESF *esf)
|
||||||
{
|
{
|
||||||
if (esf != NULL) {
|
if (esf != NULL) {
|
||||||
printk("eax: 0x%08x, ebx: 0x%08x, ecx: 0x%08x, edx: 0x%08x\n"
|
z_fatal_print("eax: 0x%08x, ebx: 0x%08x, ecx: 0x%08x, edx: 0x%08x",
|
||||||
"esi: 0x%08x, edi: 0x%08x, ebp: 0x%08x, esp: 0x%08x\n"
|
esf->eax, esf->ebx, esf->ecx, esf->edx);
|
||||||
"eflags: 0x%08x cs: 0x%04x\n"
|
z_fatal_print("esi: 0x%08x, edi: 0x%08x, ebp: 0x%08x, esp: 0x%08x",
|
||||||
|
esf->esi, esf->edi, esf->ebp, esf->esp);
|
||||||
|
z_fatal_print("eflags: 0x%08x cs: 0x%04x", esf->eflags,
|
||||||
|
esf->cs & 0xFFFFU);
|
||||||
|
|
||||||
#ifdef CONFIG_EXCEPTION_STACK_TRACE
|
#ifdef CONFIG_EXCEPTION_STACK_TRACE
|
||||||
"call trace:\n"
|
z_fatal_print("call trace:");
|
||||||
#endif
|
#endif
|
||||||
"eip: 0x%08x\n",
|
z_fatal_print("eip: 0x%08x", esf->eip);
|
||||||
esf->eax, esf->ebx, esf->ecx, esf->edx,
|
|
||||||
esf->esi, esf->edi, esf->ebp, esf->esp,
|
|
||||||
esf->eflags, esf->cs & 0xFFFFU, esf->eip);
|
|
||||||
#ifdef CONFIG_EXCEPTION_STACK_TRACE
|
#ifdef CONFIG_EXCEPTION_STACK_TRACE
|
||||||
unwind_stack(esf->ebp, esf->cs);
|
unwind_stack(esf->ebp, esf->cs);
|
||||||
#endif
|
#endif
|
||||||
|
@ -156,7 +157,7 @@ void z_x86_spurious_irq(const NANO_ESF *esf)
|
||||||
int vector = z_irq_controller_isr_vector_get();
|
int vector = z_irq_controller_isr_vector_get();
|
||||||
|
|
||||||
if (vector >= 0) {
|
if (vector >= 0) {
|
||||||
printk("IRQ vector: %d\n", vector);
|
z_fatal_print("IRQ vector: %d", vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
z_x86_fatal_error(K_ERR_SPURIOUS_IRQ, esf);
|
z_x86_fatal_error(K_ERR_SPURIOUS_IRQ, esf);
|
||||||
|
@ -209,20 +210,19 @@ NANO_CPU_INT_REGISTER(_kernel_oops_handler, NANO_SOFT_IRQ,
|
||||||
FUNC_NORETURN static void generic_exc_handle(unsigned int vector,
|
FUNC_NORETURN static void generic_exc_handle(unsigned int vector,
|
||||||
const NANO_ESF *pEsf)
|
const NANO_ESF *pEsf)
|
||||||
{
|
{
|
||||||
printk("***** ");
|
|
||||||
switch (vector) {
|
switch (vector) {
|
||||||
case IV_GENERAL_PROTECTION:
|
case IV_GENERAL_PROTECTION:
|
||||||
printk("General Protection Fault\n");
|
z_fatal_print("General Protection Fault");
|
||||||
break;
|
break;
|
||||||
case IV_DEVICE_NOT_AVAILABLE:
|
case IV_DEVICE_NOT_AVAILABLE:
|
||||||
printk("Floating point unit not enabled\n");
|
z_fatal_print("Floating point unit not enabled");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk("CPU exception %d\n", vector);
|
z_fatal_print("CPU exception %d", vector);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((BIT(vector) & _EXC_ERROR_CODE_FAULTS) != 0) {
|
if ((BIT(vector) & _EXC_ERROR_CODE_FAULTS) != 0) {
|
||||||
printk("***** Exception code: 0x%x\n", pEsf->errorCode);
|
z_fatal_print("Exception code: 0x%x", pEsf->errorCode);
|
||||||
}
|
}
|
||||||
z_x86_fatal_error(K_ERR_CPU_EXCEPTION, pEsf);
|
z_x86_fatal_error(K_ERR_CPU_EXCEPTION, pEsf);
|
||||||
}
|
}
|
||||||
|
@ -277,9 +277,9 @@ EXC_FUNC_NOCODE(IV_MACHINE_CHECK);
|
||||||
#define SGX BIT(15)
|
#define SGX BIT(15)
|
||||||
|
|
||||||
#ifdef CONFIG_X86_MMU
|
#ifdef CONFIG_X86_MMU
|
||||||
static void dump_entry_flags(x86_page_entry_data_t flags)
|
static void dump_entry_flags(const char *name, x86_page_entry_data_t flags)
|
||||||
{
|
{
|
||||||
printk("0x%x%x %s, %s, %s, %s\n", (u32_t)(flags>>32),
|
z_fatal_print("%s: 0x%x%x %s, %s, %s, %s", name, (u32_t)(flags>>32),
|
||||||
(u32_t)(flags),
|
(u32_t)(flags),
|
||||||
flags & (x86_page_entry_data_t)MMU_ENTRY_PRESENT ?
|
flags & (x86_page_entry_data_t)MMU_ENTRY_PRESENT ?
|
||||||
"Present" : "Non-present",
|
"Present" : "Non-present",
|
||||||
|
@ -297,11 +297,8 @@ static void dump_mmu_flags(struct x86_mmu_pdpt *pdpt, void *addr)
|
||||||
|
|
||||||
z_x86_mmu_get_flags(pdpt, addr, &pde_flags, &pte_flags);
|
z_x86_mmu_get_flags(pdpt, addr, &pde_flags, &pte_flags);
|
||||||
|
|
||||||
printk("PDE: ");
|
dump_entry_flags("PDE", pde_flags);
|
||||||
dump_entry_flags(pde_flags);
|
dump_entry_flags("PTE", pte_flags);
|
||||||
|
|
||||||
printk("PTE: ");
|
|
||||||
dump_entry_flags(pte_flags);
|
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_X86_MMU */
|
#endif /* CONFIG_X86_MMU */
|
||||||
|
|
||||||
|
@ -313,11 +310,12 @@ static void dump_page_fault(NANO_ESF *esf)
|
||||||
__asm__ ("mov %%cr2, %0" : "=r" (cr2));
|
__asm__ ("mov %%cr2, %0" : "=r" (cr2));
|
||||||
|
|
||||||
err = esf->errorCode;
|
err = esf->errorCode;
|
||||||
printk("***** CPU Page Fault (error code 0x%08x)\n", err);
|
z_fatal_print("***** CPU Page Fault (error code 0x%08x)", err);
|
||||||
|
|
||||||
printk("%s thread %s address 0x%08x\n",
|
z_fatal_print("%s thread %s address 0x%08x",
|
||||||
(err & US) != 0U ? "User" : "Supervisor",
|
(err & US) != 0U ? "User" : "Supervisor",
|
||||||
(err & ID) != 0U ? "executed" : ((err & WR) != 0U ? "wrote" :
|
(err & ID) != 0U ? "executed" : ((err & WR) != 0U ?
|
||||||
|
"wrote" :
|
||||||
"read"), cr2);
|
"read"), cr2);
|
||||||
|
|
||||||
#ifdef CONFIG_X86_MMU
|
#ifdef CONFIG_X86_MMU
|
||||||
|
@ -414,7 +412,7 @@ static __used void df_handler_bottom(void)
|
||||||
_df_tss.esp = (u32_t)(_df_stack + sizeof(_df_stack));
|
_df_tss.esp = (u32_t)(_df_stack + sizeof(_df_stack));
|
||||||
_df_tss.eip = (u32_t)df_handler_top;
|
_df_tss.eip = (u32_t)df_handler_top;
|
||||||
|
|
||||||
printk("***** Double Fault *****\n");
|
z_fatal_print("Double Fault");
|
||||||
#ifdef CONFIG_THREAD_STACK_INFO
|
#ifdef CONFIG_THREAD_STACK_INFO
|
||||||
if (check_stack_bounds(_df_esf.esp, 0, _df_esf.cs)) {
|
if (check_stack_bounds(_df_esf.esp, 0, _df_esf.cs)) {
|
||||||
reason = K_ERR_STACK_CHK_FAIL;
|
reason = K_ERR_STACK_CHK_FAIL;
|
||||||
|
|
|
@ -51,12 +51,12 @@ void z_unhandled_vector(int vector, int err, struct xuk_entry_frame *f)
|
||||||
/* Yes, there are five regsiters missing. See notes on
|
/* Yes, there are five regsiters missing. See notes on
|
||||||
* xuk_entry_frame/xuk_stack_frame.
|
* xuk_entry_frame/xuk_stack_frame.
|
||||||
*/
|
*/
|
||||||
printk("*** FATAL ERROR vector %d code %d\n", vector, err);
|
z_fatal_print("*** FATAL ERROR vector %d code %d", vector, err);
|
||||||
printk("*** RIP %d:0x%llx RSP %d:0x%llx RFLAGS 0x%llx\n",
|
z_fatal_print("*** RIP %d:0x%llx RSP %d:0x%llx RFLAGS 0x%llx",
|
||||||
(int)f->cs, f->rip, (int)f->ss, f->rsp, f->rflags);
|
(int)f->cs, f->rip, (int)f->ss, f->rsp, f->rflags);
|
||||||
printk("*** RAX 0x%llx RCX 0x%llx RDX 0x%llx RSI 0x%llx RDI 0x%llx\n",
|
z_fatal_print("*** RAX 0x%llx RCX 0x%llx RDX 0x%llx RSI 0x%llx RDI 0x%llx",
|
||||||
f->rax, f->rcx, f->rdx, f->rsi, f->rdi);
|
f->rax, f->rcx, f->rdx, f->rsi, f->rdi);
|
||||||
printk("*** R8 0x%llx R9 0x%llx R10 0x%llx R11 0x%llx\n",
|
z_fatal_print("*** R8 0x%llx R9 0x%llx R10 0x%llx R11 0x%llx",
|
||||||
f->r8, f->r9, f->r10, f->r11);
|
f->r8, f->r9, f->r10, f->r11);
|
||||||
|
|
||||||
/* FIXME: Why isn't xuk_entry_frame a NANO_ESF? */
|
/* FIXME: Why isn't xuk_entry_frame a NANO_ESF? */
|
||||||
|
|
|
@ -8,9 +8,7 @@
|
||||||
#include <kernel_structs.h>
|
#include <kernel_structs.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <kernel_arch_data.h>
|
#include <kernel_arch_data.h>
|
||||||
#include <sys/printk.h>
|
|
||||||
#include <xtensa/specreg.h>
|
#include <xtensa/specreg.h>
|
||||||
#include <logging/log_ctrl.h>
|
|
||||||
|
|
||||||
#ifdef XT_SIMULATOR
|
#ifdef XT_SIMULATOR
|
||||||
#include <xtensa/simcall.h>
|
#include <xtensa/simcall.h>
|
||||||
|
@ -27,7 +25,7 @@
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_PRINTK
|
#if defined(CONFIG_PRINTK) || defined(CONFIG_LOG)
|
||||||
static char *cause_str(unsigned int cause_code)
|
static char *cause_str(unsigned int cause_code)
|
||||||
{
|
{
|
||||||
switch (cause_code) {
|
switch (cause_code) {
|
||||||
|
@ -94,26 +92,26 @@ static inline unsigned int get_bits(int offset, int num_bits, unsigned int val)
|
||||||
|
|
||||||
static void dump_exc_state(void)
|
static void dump_exc_state(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_PRINTK
|
#if defined(CONFIG_PRINTK) || defined (CONFIG_LOG)
|
||||||
unsigned int cause, ps;
|
unsigned int cause, ps;
|
||||||
|
|
||||||
cause = get_sreg(EXCCAUSE);
|
cause = get_sreg(EXCCAUSE);
|
||||||
ps = get_sreg(PS);
|
ps = get_sreg(PS);
|
||||||
|
|
||||||
printk("Exception cause %d (%s):\n"
|
z_fatal_print("Exception cause %d (%s):", cause, cause_str(cause));
|
||||||
" EPC1 : 0x%08x EXCSAVE1 : 0x%08x EXCVADDR : 0x%08x\n",
|
z_fatal_print(" EPC1 : 0x%08x EXCSAVE1 : 0x%08x EXCVADDR : 0x%08x",
|
||||||
cause, cause_str(cause), get_sreg(EPC_1),
|
get_sreg(EPC_1), get_sreg(EXCSAVE_1), get_sreg(EXCVADDR));
|
||||||
get_sreg(EXCSAVE_1), get_sreg(EXCVADDR));
|
|
||||||
|
|
||||||
printk("Program state (PS):\n"
|
z_fatal_print("Program state (PS):");
|
||||||
" INTLEVEL : %02d EXCM : %d UM : %d RING : %d WOE : %d\n",
|
z_fatal_print(" INTLEVEL : %02d EXCM : %d UM : %d RING : %d WOE : %d",
|
||||||
get_bits(0, 4, ps), get_bits(4, 1, ps), get_bits(5, 1, ps),
|
get_bits(0, 4, ps), get_bits(4, 1, ps),
|
||||||
get_bits(6, 2, ps), get_bits(18, 1, ps));
|
get_bits(5, 1, ps), get_bits(6, 2, ps),
|
||||||
|
get_bits(18, 1, ps));
|
||||||
#ifndef __XTENSA_CALL0_ABI__
|
#ifndef __XTENSA_CALL0_ABI__
|
||||||
printk(" OWB : %02d CALLINC : %d\n",
|
z_fatal_print(" OWB : %02d CALLINC : %d",
|
||||||
get_bits(8, 4, ps), get_bits(16, 2, ps));
|
get_bits(8, 4, ps), get_bits(16, 2, ps));
|
||||||
#endif
|
#endif
|
||||||
#endif /* CONFIG_PRINTK */
|
#endif /* CONFIG_PRINTK || CONFIG_LOG */
|
||||||
}
|
}
|
||||||
|
|
||||||
XTENSA_ERR_NORET void z_xtensa_fatal_error(unsigned int reason,
|
XTENSA_ERR_NORET void z_xtensa_fatal_error(unsigned int reason,
|
||||||
|
@ -122,7 +120,7 @@ XTENSA_ERR_NORET void z_xtensa_fatal_error(unsigned int reason,
|
||||||
dump_exc_state();
|
dump_exc_state();
|
||||||
|
|
||||||
if (esf) {
|
if (esf) {
|
||||||
printk("Faulting instruction address = 0x%x\n", esf->pc);
|
z_fatal_print("Faulting instruction address = 0x%x", esf->pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
z_fatal_error(reason, esf);
|
z_fatal_error(reason, esf);
|
||||||
|
@ -135,8 +133,7 @@ XTENSA_ERR_NORET void FatalErrorHandler(void)
|
||||||
|
|
||||||
XTENSA_ERR_NORET void ReservedInterruptHandler(unsigned int intNo)
|
XTENSA_ERR_NORET void ReservedInterruptHandler(unsigned int intNo)
|
||||||
{
|
{
|
||||||
printk("INTENABLE = 0x%x\n"
|
z_fatal_print("INTENABLE = 0x%x INTERRUPT = 0x%x (%x)",
|
||||||
"INTERRUPT = 0x%x (%x)\n",
|
|
||||||
get_sreg(INTENABLE), (1 << intNo), intNo);
|
get_sreg(INTENABLE), (1 << intNo), intNo);
|
||||||
z_xtensa_fatal_error(K_ERR_SPURIOUS_IRQ, NULL);
|
z_xtensa_fatal_error(K_ERR_SPURIOUS_IRQ, NULL);
|
||||||
}
|
}
|
||||||
|
@ -152,7 +149,7 @@ void exit(int return_code)
|
||||||
: [code] "r" (return_code), [call] "i" (SYS_exit)
|
: [code] "r" (return_code), [call] "i" (SYS_exit)
|
||||||
: "a3", "a2");
|
: "a3", "a2");
|
||||||
#else
|
#else
|
||||||
printk("exit(%d)\n", return_code);
|
z_fatal_print("exit(%d)", return_code);
|
||||||
k_panic();
|
k_panic();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include <sys/printk.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <xtensa-asm2.h>
|
#include <xtensa-asm2.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
|
@ -85,7 +84,7 @@ void z_irq_spurious(void *arg)
|
||||||
|
|
||||||
__asm__ volatile("rsr.interrupt %0" : "=r"(irqs));
|
__asm__ volatile("rsr.interrupt %0" : "=r"(irqs));
|
||||||
__asm__ volatile("rsr.intenable %0" : "=r"(ie));
|
__asm__ volatile("rsr.intenable %0" : "=r"(ie));
|
||||||
printk(" ** Spurious INTERRUPT(s) %p, INTENABLE = %p\n",
|
z_fatal_print(" ** Spurious INTERRUPT(s) %p, INTENABLE = %p",
|
||||||
(void *)irqs, (void *)ie);
|
(void *)irqs, (void *)ie);
|
||||||
z_xtensa_fatal_error(K_ERR_SPURIOUS_IRQ, NULL);
|
z_xtensa_fatal_error(K_ERR_SPURIOUS_IRQ, NULL);
|
||||||
}
|
}
|
||||||
|
@ -95,37 +94,38 @@ static void dump_stack(int *stack)
|
||||||
{
|
{
|
||||||
int *bsa = *(int **)stack;
|
int *bsa = *(int **)stack;
|
||||||
|
|
||||||
printk(" ** A0 %p SP %p A2 %p A3 %p\n",
|
z_fatal_print(" ** A0 %p SP %p A2 %p A3 %p",
|
||||||
(void *)bsa[BSA_A0_OFF/4], ((char *)bsa) + BASE_SAVE_AREA_SIZE,
|
(void *)bsa[BSA_A0_OFF/4],
|
||||||
|
((char *)bsa) + BASE_SAVE_AREA_SIZE,
|
||||||
(void *)bsa[BSA_A2_OFF/4], (void *)bsa[BSA_A3_OFF/4]);
|
(void *)bsa[BSA_A2_OFF/4], (void *)bsa[BSA_A3_OFF/4]);
|
||||||
|
|
||||||
if (bsa - stack > 4) {
|
if (bsa - stack > 4) {
|
||||||
printk(" ** A4 %p A5 %p A6 %p A7 %p\n",
|
z_fatal_print(" ** A4 %p A5 %p A6 %p A7 %p",
|
||||||
(void *)bsa[-4], (void *)bsa[-3],
|
(void *)bsa[-4], (void *)bsa[-3],
|
||||||
(void *)bsa[-2], (void *)bsa[-1]);
|
(void *)bsa[-2], (void *)bsa[-1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bsa - stack > 8) {
|
if (bsa - stack > 8) {
|
||||||
printk(" ** A8 %p A9 %p A10 %p A11 %p\n",
|
z_fatal_print(" ** A8 %p A9 %p A10 %p A11 %p",
|
||||||
(void *)bsa[-8], (void *)bsa[-7],
|
(void *)bsa[-8], (void *)bsa[-7],
|
||||||
(void *)bsa[-6], (void *)bsa[-5]);
|
(void *)bsa[-6], (void *)bsa[-5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bsa - stack > 12) {
|
if (bsa - stack > 12) {
|
||||||
printk(" ** A12 %p A13 %p A14 %p A15 %p\n",
|
z_fatal_print(" ** A12 %p A13 %p A14 %p A15 %p",
|
||||||
(void *)bsa[-12], (void *)bsa[-11],
|
(void *)bsa[-12], (void *)bsa[-11],
|
||||||
(void *)bsa[-10], (void *)bsa[-9]);
|
(void *)bsa[-10], (void *)bsa[-9]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if XCHAL_HAVE_LOOPS
|
#if XCHAL_HAVE_LOOPS
|
||||||
printk(" ** LBEG %p LEND %p LCOUNT %p\n",
|
z_fatal_print(" ** LBEG %p LEND %p LCOUNT %p",
|
||||||
(void *)bsa[BSA_LBEG_OFF/4],
|
(void *)bsa[BSA_LBEG_OFF/4],
|
||||||
(void *)bsa[BSA_LEND_OFF/4],
|
(void *)bsa[BSA_LEND_OFF/4],
|
||||||
(void *)bsa[BSA_LCOUNT_OFF/4]);
|
(void *)bsa[BSA_LCOUNT_OFF/4]);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
printk(" ** SAR %p\n", (void *)bsa[BSA_SAR_OFF/4]);
|
z_fatal_print(" ** SAR %p", (void *)bsa[BSA_SAR_OFF/4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The wrapper code lives here instead of in the python script that
|
/* The wrapper code lives here instead of in the python script that
|
||||||
|
@ -173,7 +173,7 @@ void *xtensa_excint1_c(int *interrupted_stack)
|
||||||
} else if (cause == EXCCAUSE_SYSCALL) {
|
} else if (cause == EXCCAUSE_SYSCALL) {
|
||||||
|
|
||||||
/* Just report it to the console for now */
|
/* Just report it to the console for now */
|
||||||
printk(" ** SYSCALL PS %p PC %p\n",
|
z_fatal_print(" ** SYSCALL PS %p PC %p",
|
||||||
(void *)bsa[BSA_PS_OFF/4], (void *)bsa[BSA_PC_OFF/4]);
|
(void *)bsa[BSA_PS_OFF/4], (void *)bsa[BSA_PC_OFF/4]);
|
||||||
dump_stack(interrupted_stack);
|
dump_stack(interrupted_stack);
|
||||||
|
|
||||||
|
@ -189,8 +189,8 @@ void *xtensa_excint1_c(int *interrupted_stack)
|
||||||
/* Wouldn't hurt to translate EXCCAUSE to a string for
|
/* Wouldn't hurt to translate EXCCAUSE to a string for
|
||||||
* the user...
|
* the user...
|
||||||
*/
|
*/
|
||||||
printk(" ** FATAL EXCEPTION\n");
|
z_fatal_print(" ** FATAL EXCEPTION");
|
||||||
printk(" ** CPU %d EXCCAUSE %d PS %p PC %p VADDR %p\n",
|
z_fatal_print(" ** CPU %d EXCCAUSE %d PS %p PC %p VADDR %p",
|
||||||
z_arch_curr_cpu()->id, cause, (void *)bsa[BSA_PS_OFF/4],
|
z_arch_curr_cpu()->id, cause, (void *)bsa[BSA_PS_OFF/4],
|
||||||
(void *)bsa[BSA_PC_OFF/4], (void *)vaddr);
|
(void *)bsa[BSA_PC_OFF/4], (void *)vaddr);
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#define ZEPHYR_INCLUDE_FATAL_H
|
#define ZEPHYR_INCLUDE_FATAL_H
|
||||||
|
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
|
#include <toolchain.h>
|
||||||
|
|
||||||
enum k_fatal_error_reason {
|
enum k_fatal_error_reason {
|
||||||
/** Generic CPU exception, not covered by other codes */
|
/** Generic CPU exception, not covered by other codes */
|
||||||
|
@ -77,4 +78,27 @@ void k_sys_fatal_error_handler(unsigned int reason, const NANO_ESF *esf);
|
||||||
*/
|
*/
|
||||||
void z_fatal_error(unsigned int reason, const NANO_ESF *esf);
|
void z_fatal_error(unsigned int reason, const NANO_ESF *esf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print messages related to an exception
|
||||||
|
*
|
||||||
|
* This ensures the following:
|
||||||
|
* - The log system will enter panic mode if it is not already
|
||||||
|
* - Messages will be sent to printk() or the log subsystem if it is enabled
|
||||||
|
*
|
||||||
|
* Log subsystem filtering is disabled.
|
||||||
|
* To conform with log subsystem semantics, newlines are automatically
|
||||||
|
* appended, invoke this once per line.
|
||||||
|
*
|
||||||
|
* @param fmt Format string
|
||||||
|
* @param ... Optional list of format arguments
|
||||||
|
*
|
||||||
|
* FIXME: Implemented in C file to avoid #include loops, disentangle and
|
||||||
|
* make this a macro
|
||||||
|
*/
|
||||||
|
#if defined(CONFIG_LOG) || defined(CONFIG_PRINTK)
|
||||||
|
__printf_like(1, 2) void z_fatal_print(const char *fmt, ...);
|
||||||
|
#else
|
||||||
|
#define z_fatal_print(...) do { } while (false)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* ZEPHYR_INCLUDE_FATAL_H */
|
#endif /* ZEPHYR_INCLUDE_FATAL_H */
|
||||||
|
|
|
@ -10,8 +10,11 @@
|
||||||
#include <sys/__assert.h>
|
#include <sys/__assert.h>
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
#include <logging/log_ctrl.h>
|
#include <logging/log_ctrl.h>
|
||||||
|
#include <logging/log.h>
|
||||||
#include <fatal.h>
|
#include <fatal.h>
|
||||||
|
|
||||||
|
LOG_MODULE_DECLARE(os);
|
||||||
|
|
||||||
/* LCOV_EXCL_START */
|
/* LCOV_EXCL_START */
|
||||||
FUNC_NORETURN __weak void z_arch_system_halt(unsigned int reason)
|
FUNC_NORETURN __weak void z_arch_system_halt(unsigned int reason)
|
||||||
{
|
{
|
||||||
|
@ -35,13 +38,13 @@ __weak void k_sys_fatal_error_handler(unsigned int reason,
|
||||||
ARG_UNUSED(esf);
|
ARG_UNUSED(esf);
|
||||||
|
|
||||||
LOG_PANIC();
|
LOG_PANIC();
|
||||||
|
z_fatal_print("Halting system");
|
||||||
printk("Halting system.\n");
|
|
||||||
z_arch_system_halt(reason);
|
z_arch_system_halt(reason);
|
||||||
CODE_UNREACHABLE;
|
CODE_UNREACHABLE;
|
||||||
}
|
}
|
||||||
/* LCOV_EXCL_STOP */
|
/* LCOV_EXCL_STOP */
|
||||||
|
|
||||||
|
#if defined(CONFIG_LOG) || defined(CONFIG_PRINTK)
|
||||||
static const char *thread_name_get(struct k_thread *thread)
|
static const char *thread_name_get(struct k_thread *thread)
|
||||||
{
|
{
|
||||||
const char *thread_name = k_thread_name_get(thread);
|
const char *thread_name = k_thread_name_get(thread);
|
||||||
|
@ -71,18 +74,32 @@ static const char *reason_to_str(unsigned int reason)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void z_fatal_print(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
if (IS_ENABLED(CONFIG_LOG)) {
|
||||||
|
struct log_msg_ids src_level = {
|
||||||
|
.level = LOG_LEVEL_ERR,
|
||||||
|
.source_id = LOG_CURRENT_MODULE_ID(),
|
||||||
|
.domain_id = CONFIG_LOG_DOMAIN_ID
|
||||||
|
};
|
||||||
|
log_generic(src_level, fmt, ap);
|
||||||
|
} else {
|
||||||
|
printk("FATAL: ");
|
||||||
|
vprintk(fmt, ap);
|
||||||
|
printk("\n");
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_LOG || CONFIG_PRINTK */
|
||||||
|
|
||||||
void z_fatal_error(unsigned int reason, const NANO_ESF *esf)
|
void z_fatal_error(unsigned int reason, const NANO_ESF *esf)
|
||||||
{
|
{
|
||||||
struct k_thread *thread = k_current_get();
|
struct k_thread *thread = k_current_get();
|
||||||
|
|
||||||
/* TODO: Replace all printk()s here and in arch error handling code
|
z_fatal_print(">>> ZEPHYR FATAL ERROR %d: %s", reason,
|
||||||
* to some special printk_fatal() function, which enables panic
|
|
||||||
* mode and routes messages to printk or LOG subsystem appropriately
|
|
||||||
* based on configuration.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef CONFIG_PRINTK
|
|
||||||
printk(">>> ZEPHYR FATAL ERROR %d: %s\n", reason,
|
|
||||||
reason_to_str(reason));
|
reason_to_str(reason));
|
||||||
|
|
||||||
/* FIXME: This doesn't seem to work as expected on all arches.
|
/* FIXME: This doesn't seem to work as expected on all arches.
|
||||||
|
@ -96,8 +113,8 @@ void z_fatal_error(unsigned int reason, const NANO_ESF *esf)
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
printk("Current thread: %p (%s)\n", thread, thread_name_get(thread));
|
z_fatal_print("Current thread: %p (%s)", thread,
|
||||||
#endif /* CONFIG_PRINTK */
|
thread_name_get(thread));
|
||||||
|
|
||||||
k_sys_fatal_error_handler(reason, esf);
|
k_sys_fatal_error_handler(reason, esf);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue