Line data Source code
1 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_ */
|