1 /*
2 * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7 #ifndef __TFM_ARCH_V8M_H__
8 #define __TFM_ARCH_V8M_H__
9
10 #include <stdint.h>
11 #include <stdbool.h>
12
13 #include "cmsis_compiler.h"
14 #include "tfm_core_trustzone.h"
15 #include "utilities.h"
16
17 #define EXC_RETURN_RES1 (0x1FFFFUL << 7)
18
19 /* Initial EXC_RETURN value in LR when a thread is loaded at the first time */
20 #define EXC_RETURN_THREAD_PSP \
21 EXC_RETURN_PREFIX | EXC_RETURN_RES1 | \
22 EXC_RETURN_S | EXC_RETURN_DCRS | \
23 EXC_RETURN_FTYPE | EXC_RETURN_MODE | \
24 EXC_RETURN_SPSEL | EXC_RETURN_ES
25
26 #define EXC_RETURN_THREAD_MSP \
27 EXC_RETURN_PREFIX | EXC_RETURN_RES1 | \
28 EXC_RETURN_S | EXC_RETURN_DCRS | \
29 EXC_RETURN_FTYPE | EXC_RETURN_MODE | \
30 EXC_RETURN_ES
31
32 #define EXC_RETURN_HANDLER \
33 EXC_RETURN_PREFIX | EXC_RETURN_RES1 | \
34 EXC_RETURN_S | EXC_RETURN_DCRS | \
35 EXC_RETURN_FTYPE | EXC_RETURN_ES
36
37 /* Exception numbers */
38 #define EXC_NUM_THREAD_MODE (0)
39 #define EXC_NUM_SVCALL (11)
40 #define EXC_NUM_PENDSV (14)
41
42 #define SCB_ICSR_ADDR (0xE000ED04)
43 #define SCB_ICSR_PENDSVSET_BIT (0x10000000)
44
45 /* Disable NS exceptions by setting NS PRIMASK to 1 */
46 #define TFM_NS_EXC_DISABLE() __TZ_set_PRIMASK_NS(1)
47 /* Enable NS exceptions by setting NS PRIMASK to 0 */
48 #define TFM_NS_EXC_ENABLE() __TZ_set_PRIMASK_NS(0)
49
50 extern uint64_t __STACK_SEAL;
51
52 /**
53 * \brief Check whether Secure or Non-secure stack is used to restore stack
54 * frame on exception return.
55 *
56 * \param[in] lr LR register containing the EXC_RETURN value.
57 *
58 * \retval true Secure stack is used to restore stack frame on
59 * exception return.
60 * \retval false Non-secure stack is used to restore stack frame on
61 * exception return.
62 */
is_return_secure_stack(uint32_t lr)63 __STATIC_INLINE bool is_return_secure_stack(uint32_t lr)
64 {
65 return (lr & EXC_RETURN_S) ? true : false;
66 }
67
68 /**
69 * \brief Check whether the default stacking rules apply, or whether the
70 * Additional state context, also known as callee registers,
71 * are already on the stack.
72 * DCRS bit is only present from V8M and above.
73 * If DCRS is 1 then Stack contains:
74 * r0, r1, r2, r3, r12, r14 (lr), the return address and xPSR
75 *
76 * If DCRS is 0 then the stack contains the following too before
77 * the caller-saved registers:
78 * Integrity signature, res, r4, r5, r6, r7, r8, r9, r10, r11
79 *
80 * \param[in] lr LR register containing the EXC_RETURN value.
81 *
82 * \retval true Default rules for stacking the Additional state
83 * context registers followed.
84 * \retval false Stacking of the Additional state context
85 * registers skipped.
86 */
is_default_stacking_rules_apply(uint32_t lr)87 __STATIC_INLINE bool is_default_stacking_rules_apply(uint32_t lr)
88 {
89 return (lr & EXC_RETURN_DCRS) ? true : false;
90 }
91
92 /**
93 * \brief Check whether the stack frame for this exception has space allocated
94 * for Floating Point(FP) state information.
95 *
96 * \param[in] lr LR register containing the EXC_RETURN value.
97 *
98 * \retval true The stack allocates space for FP information
99 * \retval false The stack doesn't allocate space for FP information
100 */
is_stack_alloc_fp_space(uint32_t lr)101 __STATIC_INLINE bool is_stack_alloc_fp_space(uint32_t lr)
102 {
103 return (lr & EXC_RETURN_FTYPE) ? false : true;
104 }
105
106 /**
107 * \brief Set PSPLIM register.
108 *
109 * \param[in] psplim Register value to be written into PSPLIM.
110 */
tfm_arch_set_psplim(uint32_t psplim)111 __STATIC_INLINE void tfm_arch_set_psplim(uint32_t psplim)
112 {
113 __set_PSPLIM(psplim);
114 }
115
116 /**
117 * \brief Set MSP limit value.
118 *
119 * \param[in] msplim MSP limit value to be written.
120 */
tfm_arch_set_msplim(uint32_t msplim)121 __STATIC_INLINE void tfm_arch_set_msplim(uint32_t msplim)
122 {
123 __set_MSPLIM(msplim);
124 }
125
126 /**
127 * \brief Seal the thread stack.
128 *
129 * This function must be called only when the caller is using MSP.
130 *
131 * \param[in] stk Thread stack address.
132 *
133 * \retval stack Updated thread stack address.
134 */
arch_seal_thread_stack(uintptr_t stk)135 __STATIC_INLINE uintptr_t arch_seal_thread_stack(uintptr_t stk)
136 {
137 SPM_ASSERT((stk & 0x7) == 0);
138 stk -= TFM_STACK_SEALED_SIZE;
139
140 *((uint32_t *)stk) = TFM_STACK_SEAL_VALUE;
141 *((uint32_t *)(stk + 4)) = TFM_STACK_SEAL_VALUE;
142
143 return stk;
144 }
145
146 /**
147 * \brief Check MSP sealing.
148 *
149 * Sealing must be done in the Reset_Handler() on a 8 byte region
150 * (__STACK_SEAL) defined in the linker scripts.
151 * (It is a CMSIS recommendation)
152 *
153 */
tfm_arch_check_msp_sealing(void)154 __STATIC_INLINE void tfm_arch_check_msp_sealing(void)
155 {
156 SPM_ASSERT(*(uint64_t *)(&__STACK_SEAL) == __TZ_STACK_SEAL_VALUE);
157 }
158
159 #endif
160