1 /*
2  * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <stdint.h>
9 #include "compiler_ext_defs.h"
10 #include "config_spm.h"
11 #include "ffm/psa_api.h"
12 #include "spm.h"
13 #include "svc_num.h"
14 #include "tfm_psa_call_pack.h"
15 #include "psa/client.h"
16 #include "psa/lifecycle.h"
17 #include "psa/service.h"
18 #include "runtime_defs.h"
19 #include "tfm_arch.h"
20 
21 #if defined(__ICCARM__)
22 #pragma required = tfm_arch_thread_fn_call
23 #endif
24 
25 /*
26  * Restore target psa api to R12 and step to tfm_arch_thread_fn_call.
27  */
28 #define TFM_THREAD_FN_CALL_ENTRY(target_psa_api)      \
29     __asm volatile(                                   \
30         SYNTAX_UNIFIED                                \
31         "push   {r4, lr}                   \n"        \
32         "ldr    r4, ="M2S(target_psa_api)" \n"        \
33         "mov    r12, r4                    \n"        \
34         "bl     tfm_arch_thread_fn_call    \n"        \
35         "pop    {r4, pc}                   \n"        \
36     )
37 
38 __naked
39 __section(".psa_interface_thread_fn_call")
psa_framework_version_thread_fn_call(void)40 uint32_t psa_framework_version_thread_fn_call(void)
41 {
42     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_client_psa_framework_version);
43 }
44 
45 __naked
46 __section(".psa_interface_thread_fn_call")
psa_version_thread_fn_call(uint32_t sid)47 uint32_t psa_version_thread_fn_call(uint32_t sid)
48 {
49     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_client_psa_version);
50 }
51 
52 __naked
53 __section(".psa_interface_thread_fn_call")
tfm_psa_call_pack_thread_fn_call(psa_handle_t handle,uint32_t ctrl_param,const psa_invec * in_vec,psa_outvec * out_vec)54 psa_status_t tfm_psa_call_pack_thread_fn_call(psa_handle_t handle,
55                                               uint32_t ctrl_param,
56                                               const psa_invec *in_vec,
57                                               psa_outvec *out_vec)
58 {
59     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_client_psa_call);
60 }
61 
62 __naked
63 __section(".psa_interface_thread_fn_call")
psa_wait_thread_fn_call(psa_signal_t signal_mask,uint32_t timeout)64 psa_signal_t psa_wait_thread_fn_call(psa_signal_t signal_mask, uint32_t timeout)
65 {
66     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_wait);
67 }
68 
69 __naked
70 __section(".psa_interface_thread_fn_call")
psa_get_thread_fn_call(psa_signal_t signal,psa_msg_t * msg)71 psa_status_t psa_get_thread_fn_call(psa_signal_t signal, psa_msg_t *msg)
72 {
73     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_get);
74 }
75 
76 __naked
77 __section(".psa_interface_thread_fn_call")
psa_read_thread_fn_call(psa_handle_t msg_handle,uint32_t invec_idx,void * buffer,size_t num_bytes)78 size_t psa_read_thread_fn_call(psa_handle_t msg_handle, uint32_t invec_idx,
79                                void *buffer, size_t num_bytes)
80 {
81     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_read);
82 }
83 
84 __naked
85 __section(".psa_interface_thread_fn_call")
psa_skip_thread_fn_call(psa_handle_t msg_handle,uint32_t invec_idx,size_t num_bytes)86 size_t psa_skip_thread_fn_call(psa_handle_t msg_handle,
87                                uint32_t invec_idx, size_t num_bytes)
88 {
89     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_skip);
90 }
91 
92 __naked
93 __section(".psa_interface_thread_fn_call")
psa_write_thread_fn_call(psa_handle_t msg_handle,uint32_t outvec_idx,const void * buffer,size_t num_bytes)94 void psa_write_thread_fn_call(psa_handle_t msg_handle, uint32_t outvec_idx,
95                               const void *buffer, size_t num_bytes)
96 {
97     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_write);
98 }
99 
100 __naked
101 __section(".psa_interface_thread_fn_call")
psa_reply_thread_fn_call(psa_handle_t msg_handle,psa_status_t status)102 void psa_reply_thread_fn_call(psa_handle_t msg_handle, psa_status_t status)
103 {
104     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_reply);
105 }
106 
107 #if CONFIG_TFM_DOORBELL_API == 1
108 __naked
109 __section(".psa_interface_thread_fn_call")
psa_notify_thread_fn_call(int32_t partition_id)110 void psa_notify_thread_fn_call(int32_t partition_id)
111 {
112     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_notify);
113 }
114 
115 __naked
116 __section(".psa_interface_thread_fn_call")
psa_clear_thread_fn_call(void)117 void psa_clear_thread_fn_call(void)
118 {
119     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_clear);
120 }
121 #endif /* CONFIG_TFM_DOORBELL_API == 1 */
122 
123 __naked
124 __section(".psa_interface_thread_fn_call")
psa_panic_thread_fn_call(void)125 void psa_panic_thread_fn_call(void)
126 {
127     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_panic);
128 }
129 
130 __naked
131 __section(".psa_interface_thread_fn_call")
psa_rot_lifecycle_state_thread_fn_call(void)132 uint32_t psa_rot_lifecycle_state_thread_fn_call(void)
133 {
134     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_get_lifecycle_state);
135 }
136 
137 /* Following PSA APIs are only needed by connection-based services */
138 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
139 
140 __naked
141 __section(".psa_interface_thread_fn_call")
psa_connect_thread_fn_call(uint32_t sid,uint32_t version)142 psa_handle_t psa_connect_thread_fn_call(uint32_t sid, uint32_t version)
143 {
144     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_client_psa_connect);
145 }
146 
147 __naked
148 __section(".psa_interface_thread_fn_call")
psa_close_thread_fn_call(psa_handle_t handle)149 void psa_close_thread_fn_call(psa_handle_t handle)
150 {
151     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_client_psa_close);
152 }
153 
154 __naked
155 __section(".psa_interface_thread_fn_call")
psa_set_rhandle_thread_fn_call(psa_handle_t msg_handle,void * rhandle)156 void psa_set_rhandle_thread_fn_call(psa_handle_t msg_handle, void *rhandle)
157 {
158     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_set_rhandle);
159 }
160 
161 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
162 
163 #if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
164 __naked
165 __section(".psa_interface_thread_fn_call")
psa_irq_enable_thread_fn_call(psa_signal_t irq_signal)166 void psa_irq_enable_thread_fn_call(psa_signal_t irq_signal)
167 {
168     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_irq_enable);
169 }
170 
171 __naked
172 __section(".psa_interface_thread_fn_call")
psa_irq_disable_thread_fn_call(psa_signal_t irq_signal)173 psa_irq_status_t psa_irq_disable_thread_fn_call(psa_signal_t irq_signal)
174 {
175     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_irq_disable);
176 }
177 
178 /* This API is only used for FLIH. */
179 #if CONFIG_TFM_FLIH_API == 1
180 __naked
181 __section(".psa_interface_thread_fn_call")
psa_reset_signal_thread_fn_call(psa_signal_t irq_signal)182 void psa_reset_signal_thread_fn_call(psa_signal_t irq_signal)
183 {
184     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_reset_signal);
185 }
186 #endif /* CONFIG_TFM_FLIH_API == 1 */
187 
188 /* This API is only used for SLIH. */
189 #if CONFIG_TFM_SLIH_API == 1
190 __naked
191 __section(".psa_interface_thread_fn_call")
psa_eoi_thread_fn_call(psa_signal_t irq_signal)192 void psa_eoi_thread_fn_call(psa_signal_t irq_signal)
193 {
194     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_eoi);
195 }
196 #endif /* CONFIG_TFM_SLIH_API */
197 #endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
198 
199 #if PSA_FRAMEWORK_HAS_MM_IOVEC
200 
201 __naked
202 __section(".psa_interface_thread_fn_call")
psa_map_invec_thread_fn_call(psa_handle_t msg_handle,uint32_t invec_idx)203 const void *psa_map_invec_thread_fn_call(psa_handle_t msg_handle, uint32_t invec_idx)
204 {
205     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_map_invec);
206 }
207 
208 __naked
209 __section(".psa_interface_thread_fn_call")
psa_unmap_invec_thread_fn_call(psa_handle_t msg_handle,uint32_t invec_idx)210 void psa_unmap_invec_thread_fn_call(psa_handle_t msg_handle, uint32_t invec_idx)
211 {
212     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_unmap_invec);
213 }
214 
215 __naked
216 __section(".psa_interface_thread_fn_call")
psa_map_outvec_thread_fn_call(psa_handle_t msg_handle,uint32_t outvec_idx)217 void *psa_map_outvec_thread_fn_call(psa_handle_t msg_handle, uint32_t outvec_idx)
218 {
219     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_map_outvec);
220 }
221 
222 __naked
223 __section(".psa_interface_thread_fn_call")
psa_unmap_outvec_thread_fn_call(psa_handle_t msg_handle,uint32_t outvec_idx,size_t len)224 void psa_unmap_outvec_thread_fn_call(psa_handle_t msg_handle, uint32_t outvec_idx,
225                                      size_t len)
226 {
227     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_unmap_outvec);
228 }
229 
230 #endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
231 
232 #ifdef TFM_PARTITION_NS_AGENT_MAILBOX
233 __naked
234 __section(".psa_interface_thread_fn_call")
agent_psa_call_thread_fn_call(psa_handle_t handle,uint32_t control,const struct client_params_t * params,const void * client_data_stateless)235 psa_status_t agent_psa_call_thread_fn_call(psa_handle_t handle,
236                                            uint32_t control,
237                                            const struct client_params_t *params,
238                                            const void *client_data_stateless)
239 {
240     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_agent_psa_call);
241 }
242 
243 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
244 __naked
245 __section(".psa_interface_thread_fn_call")
agent_psa_connect_thread_fn_call(uint32_t sid,uint32_t version,int32_t ns_client_id,const void * client_data)246 psa_handle_t agent_psa_connect_thread_fn_call(uint32_t sid, uint32_t version,
247                                               int32_t ns_client_id,
248                                               const void *client_data)
249 {
250     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_agent_psa_connect);
251 }
252 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1 */
253 #endif /* TFM_PARTITION_NS_AGENT_MAILBOX */
254 
255 const struct psa_api_tbl_t psa_api_thread_fn_call = {
256                                 tfm_psa_call_pack_thread_fn_call,
257                                 psa_version_thread_fn_call,
258                                 psa_framework_version_thread_fn_call,
259                                 psa_wait_thread_fn_call,
260                                 psa_get_thread_fn_call,
261                                 psa_read_thread_fn_call,
262                                 psa_skip_thread_fn_call,
263                                 psa_write_thread_fn_call,
264                                 psa_reply_thread_fn_call,
265                                 psa_panic_thread_fn_call,
266                                 psa_rot_lifecycle_state_thread_fn_call,
267 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
268                                 psa_connect_thread_fn_call,
269                                 psa_close_thread_fn_call,
270                                 psa_set_rhandle_thread_fn_call,
271 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
272 #if CONFIG_TFM_DOORBELL_API == 1
273                                 psa_notify_thread_fn_call,
274                                 psa_clear_thread_fn_call,
275 #endif /* CONFIG_TFM_DOORBELL_API == 1 */
276 #if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
277                                 psa_irq_enable_thread_fn_call,
278                                 psa_irq_disable_thread_fn_call,
279 #if CONFIG_TFM_FLIH_API == 1
280                                 psa_reset_signal_thread_fn_call,
281 #endif /* CONFIG_TFM_FLIH_API == 1 */
282 #if CONFIG_TFM_SLIH_API == 1
283                                 psa_eoi_thread_fn_call,
284 #endif /* CONFIG_TFM_SLIH_API == 1 */
285 #endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
286 #if PSA_FRAMEWORK_HAS_MM_IOVEC
287                                 psa_map_invec_thread_fn_call,
288                                 psa_unmap_invec_thread_fn_call,
289                                 psa_map_outvec_thread_fn_call,
290                                 psa_unmap_outvec_thread_fn_call,
291 #endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
292 #ifdef TFM_PARTITION_NS_AGENT_MAILBOX
293                                 agent_psa_call_thread_fn_call,
294 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
295                                 agent_psa_connect_thread_fn_call,
296 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1 */
297 #endif /* TFM_PARTITION_NS_AGENT_MAILBOX */
298                             };
299