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