From eddf058e1e9f5e79d752bae97f94b6acce36c81d Mon Sep 17 00:00:00 2001 From: Ioannis Glaropoulos Date: Tue, 27 Aug 2019 17:31:38 +0200 Subject: [PATCH] arch: arm: be able to infer Z_ARCH_EXCEPT() for baseline SOCs This commit makes it possible to infer Z_ARCH_EXCEPT() calls in SVCs that escalate to HardFault due to being invoked from priority level equal or higher to the interrupt priority level of the SVC Handler. Signed-off-by: Ioannis Glaropoulos --- arch/arm/core/cortex_m/fault.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/arm/core/cortex_m/fault.c b/arch/arm/core/cortex_m/fault.c index dc1f573de1b..7943248368e 100644 --- a/arch/arm/core/cortex_m/fault.c +++ b/arch/arm/core/cortex_m/fault.c @@ -609,6 +609,30 @@ static u32_t HardFault(z_arch_esf_t *esf, bool *recoverable) PR_FAULT_INFO("***** HARD FAULT *****"); #if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) + /* Workaround for #18712: + * HardFault may be due to escalation, as a result of + * an SVC instruction that could not be executed; this + * can occur if Z_ARCH_EXCEPT() is called by an ISR, + * which executes at priority equal to the SVC handler + * priority. We handle the case of Kernel OOPS and Stack + * Fail here. + */ + u16_t *ret_addr = (u16_t *)esf->basic.pc; + /* SVC is a 16-bit instruction. On a synchronous SVC + * escalated to Hard Fault, the return address is the + * next instruction, i.e. after the SVC. + */ +#define _SVC_OPCODE 0xDF00 + + u16_t fault_insn = *(ret_addr - 1); + if (((fault_insn & 0xff00) == _SVC_OPCODE) && + ((fault_insn & 0x00ff) == _SVC_CALL_RUNTIME_EXCEPT)) { + + PR_EXC("Z_ARCH_EXCEPT with reason %x\n", esf->basic.r0); + reason = esf->basic.r0; + } +#undef _SVC_OPCODE + *recoverable = memory_fault_recoverable(esf); #elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) *recoverable = false;