1 /* 2 * Copyright (c) 2013-2014 Wind River Systems, Inc. 3 * Copyright (c) 2023 Arm Limited 4 * 5 * SPDX-License-Identifier: Apache-2.0 6 */ 7 8 /** 9 * @file 10 * @brief ARM AArch32 public error handling 11 * 12 * ARM AArch32-specific kernel error handling interface. Included by 13 * arm/arch.h. 14 */ 15 16 #ifndef ZEPHYR_INCLUDE_ARCH_ARM_ERROR_H_ 17 #define ZEPHYR_INCLUDE_ARCH_ARM_ERROR_H_ 18 19 #include <zephyr/arch/arm/syscall.h> 20 #include <zephyr/arch/arm/exception.h> 21 #include <stdbool.h> 22 23 #ifdef __cplusplus 24 extern "C" { 25 #endif 26 27 #if defined(CONFIG_CPU_CORTEX_M) 28 /* ARMv6 will hard-fault if SVC is called with interrupts locked. Just 29 * force them unlocked, the thread is in an undefined state anyway 30 * 31 * On ARMv7m we won't get a HardFault, but if interrupts were locked the 32 * thread will continue executing after the exception and forbid PendSV to 33 * schedule a new thread until they are unlocked which is not what we want. 34 * Force them unlocked as well. 35 */ 36 #define ARCH_EXCEPT(reason_p) \ 37 do {\ 38 arch_irq_unlock(0); \ 39 __asm__ volatile( \ 40 "mov r0, %[_reason]\n" \ 41 "svc %[id]\n" \ 42 :: [_reason] "r" (reason_p), [id] "i" (_SVC_CALL_RUNTIME_EXCEPT) \ 43 : "r0", "memory"); \ 44 } while (false) 45 #elif defined(CONFIG_ARMV7_R) || defined(CONFIG_AARCH32_ARMV8_R) \ 46 || defined(CONFIG_ARMV7_A) 47 /* 48 * In order to support using svc for an exception while running in an 49 * isr, stack $lr_svc before calling svc. While exiting the isr, 50 * z_check_stack_sentinel is called. $lr_svc contains the return address. 51 * If the sentinel is wrong, it calls svc to cause an oops. This svc 52 * call will overwrite $lr_svc, losing the return address from the 53 * z_check_stack_sentinel call if it is not stacked before the svc. 54 */ 55 #define ARCH_EXCEPT(reason_p) \ 56 register uint32_t r0 __asm__("r0") = reason_p; \ 57 do { \ 58 __asm__ volatile ( \ 59 "push {lr}\n\t" \ 60 "cpsie i\n\t" \ 61 "svc %[id]\n\t" \ 62 "pop {lr}\n\t" \ 63 : \ 64 : "r" (r0), [id] "i" (_SVC_CALL_RUNTIME_EXCEPT) \ 65 : "memory"); \ 66 } while (false) 67 #else 68 #error Unknown ARM architecture 69 #endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ 70 71 #ifdef __cplusplus 72 } 73 #endif 74 75 #endif /* ZEPHYR_INCLUDE_ARCH_ARM_ERROR_H_ */ 76