1 /*
2 * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include <stdint.h>
9
10 #include "cmsis_compiler.h"
11 #include "compiler_ext_defs.h"
12 #include "config_impl.h"
13 #include "security_defs.h"
14 #include "svc_num.h"
15 #include "tfm_psa_call_pack.h"
16 #include "utilities.h"
17 #include "psa/client.h"
18 #include "psa/service.h"
19 #include "tfm_arch.h"
20
21 /*
22 * This is the veneers of FF-M Client APIs for Armv8.0-m.
23 * The interfaces are written in assembly, and the reasons:
24 *
25 * - On the 8.0 version of Armv8-M with security extension, a mandatory
26 * software solution needs to be applied because hardware reentrant
27 * detection was not involved until 8.1. It requires TF-M to take full
28 * control of stack usage to perform reentrant detection. Therefore
29 * TF-M shall implement these veneers in the assembly code.
30 *
31 * - The non-secure context is pushed in the stack. When SPM API returns,
32 * the pushed non-secure context is popped and overrides the returned
33 * context before returning to NSPE. Therefore it is unnecessary to
34 * explicitly clean up the context.
35 */
36
37 #if defined(__ICCARM__)
38
39 #pragma required = psa_framework_version
40 #pragma required = psa_panic
41 #pragma required = psa_version
42 #pragma required = tfm_psa_call_pack
43 /* Following PSA APIs are only needed by connection-based services */
44 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
45 #pragma required = psa_connect
46 #pragma required = psa_close
47 #endif
48
49 #endif
50
51 __attribute__((naked, used))
clear_caller_context(void)52 static void clear_caller_context(void)
53 {
54 __ASM volatile(
55 #if (CONFIG_TFM_FLOAT_ABI >= 1)
56 " vmov.f32 s0, #1.0 \n"
57 " vmov.f32 s1, #1.0 \n"
58 " vmov.f32 s2, #1.0 \n"
59 " vmov.f32 s3, #1.0 \n"
60 " vmov.f32 s4, #1.0 \n"
61 " vmov.f32 s5, #1.0 \n"
62 " vmov.f32 s6, #1.0 \n"
63 " vmov.f32 s7, #1.0 \n"
64 " vmov.f32 s8, #1.0 \n"
65 " vmov.f32 s9, #1.0 \n"
66 " vmov.f32 s10, #1.0 \n"
67 " vmov.f32 s11, #1.0 \n"
68 " vmov.f32 s12, #1.0 \n"
69 " vmov.f32 s13, #1.0 \n"
70 " vmov.f32 s14, #1.0 \n"
71 " vmov.f32 s15, #1.0 \n"
72 " vmrs r12, fpscr \n"
73 " movw r1, #0x009f \n"
74 " movt r1, #0xf000 \n"
75 " bics r12, r1 \n"
76 " vmsr fpscr, r12 \n"
77 #endif
78 " movs r3, #0x0 \n"
79 " msr APSR_nzcvq, r3 \n"
80 " bx lr \n"
81 );
82 }
83
84 __tz_naked_veneer
tfm_psa_framework_version_veneer(void)85 uint32_t tfm_psa_framework_version_veneer(void)
86 {
87 __ASM volatile(
88 SYNTAX_UNIFIED
89 #if CONFIG_TFM_SECURE_THREAD_MASK_NS_INTERRUPT == 1
90 " ldr r2, ="M2S(SECURE_THREAD_EXECUTION_PRIORITY)"\n"
91 " msr basepri, r2 \n"
92 #endif
93 " ldr r2, [sp] \n"
94 " ldr r3, ="M2S(STACK_SEAL_PATTERN)" \n"
95 " cmp r2, r3 \n"
96 " bne reent_panic1 \n"
97 " push {r4, lr} \n"
98 " bl "M2S(psa_framework_version)" \n"
99 " bl clear_caller_context \n"
100 " pop {r1, r2} \n"
101 " mov lr, r2 \n"
102 " mov r4, r1 \n"
103 #if CONFIG_TFM_SECURE_THREAD_MASK_NS_INTERRUPT == 1
104 " ldr r1, =0x00 \n"
105 " msr basepri, r1 \n"
106 #endif
107 " bxns lr \n"
108
109 "reent_panic1: \n"
110 " bl psa_panic \n"
111 );
112 }
113
114 __tz_naked_veneer
tfm_psa_version_veneer(uint32_t sid)115 uint32_t tfm_psa_version_veneer(uint32_t sid)
116 {
117 __ASM volatile(
118 SYNTAX_UNIFIED
119 #if CONFIG_TFM_SECURE_THREAD_MASK_NS_INTERRUPT == 1
120 " ldr r2, ="M2S(SECURE_THREAD_EXECUTION_PRIORITY)"\n"
121 " msr basepri, r2 \n"
122 #endif
123 " ldr r2, [sp] \n"
124 " ldr r3, ="M2S(STACK_SEAL_PATTERN)" \n"
125 " cmp r2, r3 \n"
126 " bne reent_panic2 \n"
127
128 " push {r4, lr} \n"
129 " bl "M2S(psa_version)" \n"
130 " bl clear_caller_context \n"
131 " pop {r1, r2} \n"
132 " mov lr, r2 \n"
133 " mov r4, r1 \n"
134 #if CONFIG_TFM_SECURE_THREAD_MASK_NS_INTERRUPT == 1
135 " ldr r1, =0x00 \n"
136 " msr basepri, r1 \n"
137 #endif
138 " bxns lr \n"
139
140 "reent_panic2: \n"
141 " bl psa_panic \n"
142 );
143 }
144
145 __tz_naked_veneer
tfm_psa_call_veneer(psa_handle_t handle,uint32_t ctrl_param,const psa_invec * in_vec,psa_outvec * out_vec)146 psa_status_t tfm_psa_call_veneer(psa_handle_t handle,
147 uint32_t ctrl_param,
148 const psa_invec *in_vec,
149 psa_outvec *out_vec)
150 {
151 __ASM volatile(
152 SYNTAX_UNIFIED
153 " push {r2, r3} \n"
154 #if CONFIG_TFM_SECURE_THREAD_MASK_NS_INTERRUPT == 1
155 " ldr r2, ="M2S(SECURE_THREAD_EXECUTION_PRIORITY)"\n"
156 " msr basepri, r2 \n"
157 #endif
158 " ldr r2, [sp, #8] \n"
159 " ldr r3, ="M2S(STACK_SEAL_PATTERN)" \n"
160 " cmp r2, r3 \n"
161 " bne reent_panic4 \n"
162 " ldr r3, ="M2S(NS_VEC_DESC_BIT)" \n"
163 " orrs r1, r3 \n"
164 " pop {r2, r3} \n"
165 " push {r4, lr} \n"
166 " bl "M2S(tfm_psa_call_pack)" \n"
167 " bl clear_caller_context \n"
168 " pop {r1, r2} \n"
169 " mov lr, r2 \n"
170 " mov r4, r1 \n"
171 #if CONFIG_TFM_SECURE_THREAD_MASK_NS_INTERRUPT == 1
172 " ldr r1, =0x00 \n"
173 " msr basepri, r1 \n"
174 #endif
175 " bxns lr \n"
176
177 "reent_panic4: \n"
178 " bl psa_panic \n"
179 );
180 }
181
182 /* Following veneers are only needed by connection-based services */
183 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
184
185 __tz_naked_veneer
tfm_psa_connect_veneer(uint32_t sid,uint32_t version)186 psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t version)
187 {
188 __ASM volatile(
189 SYNTAX_UNIFIED
190 #if CONFIG_TFM_SECURE_THREAD_MASK_NS_INTERRUPT == 1
191 " ldr r2, ="M2S(SECURE_THREAD_EXECUTION_PRIORITY)"\n"
192 " msr basepri, r2 \n"
193 #endif
194 " ldr r2, [sp] \n"
195 " ldr r3, ="M2S(STACK_SEAL_PATTERN)" \n"
196 " cmp r2, r3 \n"
197 " bne reent_panic3 \n"
198 " push {r4, lr} \n"
199 " bl "M2S(psa_connect)" \n"
200 " bl clear_caller_context \n"
201 " pop {r1, r2} \n"
202 " mov lr, r2 \n"
203 " mov r4, r1 \n"
204 #if CONFIG_TFM_SECURE_THREAD_MASK_NS_INTERRUPT == 1
205 " ldr r1, =0x00 \n"
206 " msr basepri, r1 \n"
207 #endif
208 " bxns lr \n"
209
210 "reent_panic3: \n"
211 " bl psa_panic \n"
212 );
213 }
214
215 __tz_naked_veneer
tfm_psa_close_veneer(psa_handle_t handle)216 void tfm_psa_close_veneer(psa_handle_t handle)
217 {
218 __ASM volatile(
219 SYNTAX_UNIFIED
220 #if CONFIG_TFM_SECURE_THREAD_MASK_NS_INTERRUPT == 1
221 " ldr r2, ="M2S(SECURE_THREAD_EXECUTION_PRIORITY)"\n"
222 " msr basepri, r2 \n"
223 #endif
224 " ldr r2, [sp] \n"
225 " ldr r3, ="M2S(STACK_SEAL_PATTERN)" \n"
226 " cmp r2, r3 \n"
227 " bne reent_panic5 \n"
228
229 " push {r4, lr} \n"
230 " bl "M2S(psa_close)" \n"
231 " bl clear_caller_context \n"
232 " pop {r1, r2} \n"
233 " mov lr, r2 \n"
234 " mov r4, r1 \n"
235 #if CONFIG_TFM_SECURE_THREAD_MASK_NS_INTERRUPT == 1
236 " ldr r1, =0x00 \n"
237 " msr basepri, r1 \n"
238 #endif
239 " bxns lr \n"
240
241 "reent_panic5: \n"
242 " bl psa_panic \n"
243 );
244 }
245
246 #else /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
247
248 /*
249 * Define a constant to enable naked tfm_psa_connect_veneer() to return the error code.
250 * It is not supported to directly return the error code in psa_status_t type in Basic Asm via
251 * M2S.
252 * This is defined as a const in order to be placed in .rodata section which
253 * normally has least strict protection requirements and can be freely accessed
254 * during a call to "tfm_psa_connect_veneer()".
255 */
256 __used const int32_t ret_err = (int32_t)PSA_ERROR_NOT_SUPPORTED;
257 #if defined(__ICCARM__)
258 #pragma required = ret_err
259 #endif
260
261 __tz_naked_veneer
tfm_psa_connect_veneer(uint32_t sid,uint32_t version)262 psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t version)
263 {
264 __ASM volatile(
265 SYNTAX_UNIFIED
266 " ldr r2, [sp] \n"
267 " ldr r3, ="M2S(STACK_SEAL_PATTERN)" \n"
268 " cmp r2, r3 \n"
269 " bne reent_panic3 \n"
270
271 " ldr r1, =ret_err \n"
272 " ldr r0, [r1] \n"
273 " bxns lr \n"
274
275 "reent_panic3: \n"
276 " bl psa_panic \n"
277 );
278 }
279
280 __tz_naked_veneer
tfm_psa_close_veneer(psa_handle_t handle)281 void tfm_psa_close_veneer(psa_handle_t handle)
282 {
283 __ASM volatile(
284 SYNTAX_UNIFIED
285 " ldr r2, [sp] \n"
286 " ldr r3, ="M2S(STACK_SEAL_PATTERN)" \n"
287 " cmp r2, r3 \n"
288 " bne reent_panic5 \n"
289
290 " bxns lr \n"
291
292 "reent_panic5: \n"
293 " bl psa_panic \n"
294 );
295 }
296
297 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
298