1 /*
2  * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 #ifndef __TFM_ARCH_V6M_V7M_H__
8 #define __TFM_ARCH_V6M_V7M_H__
9 
10 #include <stdint.h>
11 #include <stdbool.h>
12 #include <assert.h>
13 #include "cmsis_compiler.h"
14 #include "utilities.h"
15 
16 #if !TFM_MULTI_CORE_TOPOLOGY
17 #error "Armv6-M/Armv7-M can only support multi-core TF-M now."
18 #endif
19 
20 extern uint32_t psp_limit;
21 
22 #if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
23 #define EXC_RETURN_FTYPE                        (1 << 4)
24 #endif
25 
26 /* Exception return behavior */
27 
28 /* stack pointer used to restore context: 0=MSP 1=PSP. */
29 #define EXC_RETURN_SPSEL                        (1UL << 2)
30 /* processor mode for return: 0=Handler mode 1=Thread mod. */
31 #define EXC_RETURN_MODE                         (1UL << 3)
32 
33 /* Exception numbers */
34 #define EXC_NUM_THREAD_MODE                     (0)
35 #define EXC_NUM_SVCALL                          (11)
36 #define EXC_NUM_PENDSV                          (14)
37 
38 #define SCB_ICSR_ADDR                           (0xE000ED04)
39 #define SCB_ICSR_PENDSVSET_BIT                  (0x10000000)
40 
41 /**
42  * \brief Check whether Secure or Non-secure stack is used to restore stack
43  *        frame on exception return.
44  *
45  * \param[in] lr            LR register containing the EXC_RETURN value.
46  *
47  * \retval true             Always return to Secure stack on secure core in
48  *                          multi-core topology.
49  */
is_return_secure_stack(uint32_t lr)50 __STATIC_INLINE bool is_return_secure_stack(uint32_t lr)
51 {
52     (void)lr;
53 
54     return true;
55 }
56 
57 /**
58  * \brief Check whether the default stacking rules apply, or whether the
59  *        Additional state context, also known as callee registers,
60  *        are already on the stack.
61  *
62  * \param[in] lr            LR register containing the EXC_RETURN value.
63  *
64  * \retval true             Always use default stacking rules on
65  *                          v6m/v7m architectures.
66  */
is_default_stacking_rules_apply(uint32_t lr)67 __STATIC_INLINE bool is_default_stacking_rules_apply(uint32_t lr)
68 {
69     (void)lr;
70 
71     return true;
72 }
73 
74 #if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
75 /**
76  * \brief Check whether the stack frame for this exception has space allocated
77  *        for Floating Point(FP) state information.
78  *
79  * \param[in] lr            LR register containing the EXC_RETURN value.
80  *
81  * \retval true             The stack allocates space for FP information
82  * \retval false            The stack doesn't allocate space for FP information
83  */
is_stack_alloc_fp_space(uint32_t lr)84 __STATIC_INLINE bool is_stack_alloc_fp_space(uint32_t lr)
85 {
86     return (lr & EXC_RETURN_FTYPE) ? false : true;
87 }
88 #elif defined(__ARM_ARCH_6M__)
89 /**
90  * \brief Check whether the stack frame for this exception has space allocated
91  *        for Floating Point(FP) state information.
92  *
93  * \param[in] lr            LR register containing the EXC_RETURN value.
94  *
95  * \retval false            The stack doesn't allocate space for FP information
96  */
is_stack_alloc_fp_space(uint32_t lr)97 __STATIC_INLINE bool is_stack_alloc_fp_space(uint32_t lr)
98 {
99     (void)lr;
100 
101     return false;
102 }
103 #endif
104 
105 /**
106  * \brief Get PSP Limit.
107  *
108  * \retval psp limit        Limit of PSP stack.
109  */
tfm_arch_get_psplim(void)110 __STATIC_INLINE uint32_t tfm_arch_get_psplim(void)
111 {
112     return psp_limit;
113 }
114 
115 /**
116  * \brief Set PSP limit value.
117  *
118  * \param[in] psplim        PSP limit value to be written.
119  */
tfm_arch_set_psplim(uint32_t psplim)120 __STATIC_INLINE void tfm_arch_set_psplim(uint32_t psplim)
121 {
122     psp_limit = psplim;
123 }
124 
125 /**
126  * \brief Set MSP limit value.
127  *
128  * \param[in] msplim        MSP limit value to be written.
129  */
tfm_arch_set_msplim(uint32_t msplim)130 __STATIC_INLINE void tfm_arch_set_msplim(uint32_t msplim)
131 {
132     /*
133      * Defined as an empty function now.
134      * The MSP limit value can be used in more strict memory check.
135      */
136     (void)msplim;
137 }
138 
139 /**
140  * \brief Seal the thread stack.
141  *
142  * \param[in] stk        Thread stack address.
143  *
144  * \retval stack         Updated thread stack address.
145  */
arch_seal_thread_stack(uintptr_t stk)146 __STATIC_INLINE uintptr_t arch_seal_thread_stack(uintptr_t stk)
147 {
148     assert((stk & 0x7) == 0);
149     return stk;
150 }
151 
152 /**
153  * \brief Check MSP sealing.
154  */
tfm_arch_check_msp_sealing(void)155 __STATIC_INLINE void tfm_arch_check_msp_sealing(void)
156 {
157 }
158 
159 /*
160  * Update thread stack to architecture registers.
161  * The stack 'bottom' is higher address in this architecture,
162  * and 'toplimit' is the limit of top which is lower address.
163  */
arch_update_process_sp(uint32_t bottom,uint32_t toplimit)164 __STATIC_INLINE void arch_update_process_sp(uint32_t bottom,
165                                             uint32_t toplimit)
166 {
167     __set_PSP(bottom);
168     psp_limit = toplimit;
169     __ISB();
170 }
171 
172 /**
173  * \brief Empty implementation for branch protection.
174  *        PACBTI applies for v8.1M Main Extension onwards.
175  */
tfm_arch_config_branch_protection(void)176 __STATIC_INLINE void tfm_arch_config_branch_protection(void)
177 {
178 }
179 
180 #endif /* __TFM_ARCH_V6M_V7M_H__ */
181