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