1 /* 2 * Copyright (c) 2013-2014 Wind River Systems, Inc. 3 * Copyright 2023, 2025 Arm Limited and/or its affiliates <open-source-office@arm.com> 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/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 IF_ENABLED(CONFIG_ARM_BTI, ("bti\n")) \ 43 :: [_reason] "r" (reason_p), [id] "i" (_SVC_CALL_RUNTIME_EXCEPT) \ 44 : "r0", "memory"); \ 45 } while (false) 46 #elif defined(CONFIG_ARMV7_R) || defined(CONFIG_AARCH32_ARMV8_R) \ 47 || defined(CONFIG_ARMV7_A) 48 /* 49 * In order to support using svc for an exception while running in an 50 * isr, stack $lr_svc before calling svc. While exiting the isr, 51 * z_check_stack_sentinel is called. $lr_svc contains the return address. 52 * If the sentinel is wrong, it calls svc to cause an oops. This svc 53 * call will overwrite $lr_svc, losing the return address from the 54 * z_check_stack_sentinel call if it is not stacked before the svc. 55 */ 56 #define ARCH_EXCEPT(reason_p) \ 57 do { \ 58 register uint32_t r0 __asm__("r0") = reason_p; \ 59 __asm__ volatile ( \ 60 "push {lr}\n\t" \ 61 "cpsie i\n\t" \ 62 "svc %[id]\n\t" \ 63 IF_ENABLED(CONFIG_ARM_BTI, ("bti\n\t")) \ 64 "pop {lr}\n\t" \ 65 : \ 66 : "r" (r0), [id] "i" (_SVC_CALL_RUNTIME_EXCEPT) \ 67 : "memory"); \ 68 } while (false) 69 #else 70 #error Unknown ARM architecture 71 #endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ 72 73 #ifdef __cplusplus 74 } 75 #endif 76 77 #endif /* ZEPHYR_INCLUDE_ARCH_ARM_ERROR_H_ */ 78