1 /*
2  * Copyright (c) 2021-2024, 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
psa_framework_version_thread_fn_call(void)39 uint32_t psa_framework_version_thread_fn_call(void)
40 {
41     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_client_psa_framework_version);
42 }
43 
44 __naked
psa_version_thread_fn_call(uint32_t sid)45 uint32_t psa_version_thread_fn_call(uint32_t sid)
46 {
47     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_client_psa_version);
48 }
49 
50 __naked
tfm_psa_call_pack_thread_fn_call(psa_handle_t handle,uint32_t ctrl_param,const psa_invec * in_vec,psa_outvec * out_vec)51 psa_status_t tfm_psa_call_pack_thread_fn_call(psa_handle_t handle,
52                                               uint32_t ctrl_param,
53                                               const psa_invec *in_vec,
54                                               psa_outvec *out_vec)
55 {
56     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_client_psa_call);
57 }
58 
59 __naked
psa_wait_thread_fn_call(psa_signal_t signal_mask,uint32_t timeout)60 psa_signal_t psa_wait_thread_fn_call(psa_signal_t signal_mask, uint32_t timeout)
61 {
62     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_wait);
63 }
64 
65 __naked
psa_get_thread_fn_call(psa_signal_t signal,psa_msg_t * msg)66 psa_status_t psa_get_thread_fn_call(psa_signal_t signal, psa_msg_t *msg)
67 {
68     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_get);
69 }
70 
71 __naked
psa_read_thread_fn_call(psa_handle_t msg_handle,uint32_t invec_idx,void * buffer,size_t num_bytes)72 size_t psa_read_thread_fn_call(psa_handle_t msg_handle, uint32_t invec_idx,
73                                void *buffer, size_t num_bytes)
74 {
75     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_read);
76 }
77 
78 __naked
psa_skip_thread_fn_call(psa_handle_t msg_handle,uint32_t invec_idx,size_t num_bytes)79 size_t psa_skip_thread_fn_call(psa_handle_t msg_handle,
80                                uint32_t invec_idx, size_t num_bytes)
81 {
82     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_skip);
83 }
84 
85 __naked
psa_write_thread_fn_call(psa_handle_t msg_handle,uint32_t outvec_idx,const void * buffer,size_t num_bytes)86 void psa_write_thread_fn_call(psa_handle_t msg_handle, uint32_t outvec_idx,
87                               const void *buffer, size_t num_bytes)
88 {
89     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_write);
90 }
91 
92 __naked
psa_reply_thread_fn_call(psa_handle_t msg_handle,psa_status_t status)93 void psa_reply_thread_fn_call(psa_handle_t msg_handle, psa_status_t status)
94 {
95     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_reply);
96 }
97 
98 #if CONFIG_TFM_DOORBELL_API == 1
99 __naked
psa_notify_thread_fn_call(int32_t partition_id)100 void psa_notify_thread_fn_call(int32_t partition_id)
101 {
102     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_notify);
103 }
104 
105 __naked
psa_clear_thread_fn_call(void)106 void psa_clear_thread_fn_call(void)
107 {
108     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_clear);
109 }
110 #endif /* CONFIG_TFM_DOORBELL_API == 1 */
111 
112 __naked
psa_panic_thread_fn_call(void)113 void psa_panic_thread_fn_call(void)
114 {
115     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_panic);
116 }
117 
118 __naked
psa_rot_lifecycle_state_thread_fn_call(void)119 uint32_t psa_rot_lifecycle_state_thread_fn_call(void)
120 {
121     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_get_lifecycle_state);
122 }
123 
124 /* Following PSA APIs are only needed by connection-based services */
125 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
126 
127 __naked
psa_connect_thread_fn_call(uint32_t sid,uint32_t version)128 psa_handle_t psa_connect_thread_fn_call(uint32_t sid, uint32_t version)
129 {
130     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_client_psa_connect);
131 }
132 
133 __naked
psa_close_thread_fn_call(psa_handle_t handle)134 void psa_close_thread_fn_call(psa_handle_t handle)
135 {
136     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_client_psa_close);
137 }
138 
139 __naked
psa_set_rhandle_thread_fn_call(psa_handle_t msg_handle,void * rhandle)140 void psa_set_rhandle_thread_fn_call(psa_handle_t msg_handle, void *rhandle)
141 {
142     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_set_rhandle);
143 }
144 
145 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
146 
147 #if (CONFIG_TFM_FLIH_API == 1) || (CONFIG_TFM_SLIH_API == 1)
148 __naked
psa_irq_enable_thread_fn_call(psa_signal_t irq_signal)149 void psa_irq_enable_thread_fn_call(psa_signal_t irq_signal)
150 {
151     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_irq_enable);
152 }
153 
154 __naked
psa_irq_disable_thread_fn_call(psa_signal_t irq_signal)155 psa_irq_status_t psa_irq_disable_thread_fn_call(psa_signal_t irq_signal)
156 {
157     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_irq_disable);
158 }
159 
160 /* This API is only used for FLIH. */
161 #if CONFIG_TFM_FLIH_API == 1
162 __naked
psa_reset_signal_thread_fn_call(psa_signal_t irq_signal)163 void psa_reset_signal_thread_fn_call(psa_signal_t irq_signal)
164 {
165     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_reset_signal);
166 }
167 #endif /* CONFIG_TFM_FLIH_API == 1 */
168 
169 /* This API is only used for SLIH. */
170 #if CONFIG_TFM_SLIH_API == 1
171 __naked
psa_eoi_thread_fn_call(psa_signal_t irq_signal)172 void psa_eoi_thread_fn_call(psa_signal_t irq_signal)
173 {
174     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_eoi);
175 }
176 #endif /* CONFIG_TFM_SLIH_API */
177 #endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
178 
179 #if PSA_FRAMEWORK_HAS_MM_IOVEC
180 
181 __naked
psa_map_invec_thread_fn_call(psa_handle_t msg_handle,uint32_t invec_idx)182 const void *psa_map_invec_thread_fn_call(psa_handle_t msg_handle, uint32_t invec_idx)
183 {
184     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_map_invec);
185 }
186 
187 __naked
psa_unmap_invec_thread_fn_call(psa_handle_t msg_handle,uint32_t invec_idx)188 void psa_unmap_invec_thread_fn_call(psa_handle_t msg_handle, uint32_t invec_idx)
189 {
190     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_unmap_invec);
191 }
192 
193 __naked
psa_map_outvec_thread_fn_call(psa_handle_t msg_handle,uint32_t outvec_idx)194 void *psa_map_outvec_thread_fn_call(psa_handle_t msg_handle, uint32_t outvec_idx)
195 {
196     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_map_outvec);
197 }
198 
199 __naked
psa_unmap_outvec_thread_fn_call(psa_handle_t msg_handle,uint32_t outvec_idx,size_t len)200 void psa_unmap_outvec_thread_fn_call(psa_handle_t msg_handle, uint32_t outvec_idx,
201                                      size_t len)
202 {
203     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_partition_psa_unmap_outvec);
204 }
205 
206 #endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
207 
208 #ifdef TFM_PARTITION_NS_AGENT_MAILBOX
209 __naked
agent_psa_call_thread_fn_call(psa_handle_t handle,uint32_t control,const struct client_params_t * params,const void * client_data_stateless)210 psa_status_t agent_psa_call_thread_fn_call(psa_handle_t handle,
211                                            uint32_t control,
212                                            const struct client_params_t *params,
213                                            const void *client_data_stateless)
214 {
215     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_agent_psa_call);
216 }
217 
218 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
219 __naked
agent_psa_connect_thread_fn_call(uint32_t sid,uint32_t version,int32_t ns_client_id,const void * client_data)220 psa_handle_t agent_psa_connect_thread_fn_call(uint32_t sid, uint32_t version,
221                                               int32_t ns_client_id,
222                                               const void *client_data)
223 {
224     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_agent_psa_connect);
225 }
226 
227 __naked
agent_psa_close_thread_fn_call(psa_handle_t handle,int32_t ns_client_id)228 psa_status_t agent_psa_close_thread_fn_call(psa_handle_t handle, int32_t ns_client_id)
229 {
230     TFM_THREAD_FN_CALL_ENTRY(tfm_spm_agent_psa_close);
231 }
232 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1 */
233 #endif /* TFM_PARTITION_NS_AGENT_MAILBOX */
234 
235 const struct psa_api_tbl_t psa_api_thread_fn_call = {
236                                 tfm_psa_call_pack_thread_fn_call,
237                                 psa_version_thread_fn_call,
238                                 psa_framework_version_thread_fn_call,
239                                 psa_wait_thread_fn_call,
240                                 psa_get_thread_fn_call,
241                                 psa_read_thread_fn_call,
242                                 psa_skip_thread_fn_call,
243                                 psa_write_thread_fn_call,
244                                 psa_reply_thread_fn_call,
245                                 psa_panic_thread_fn_call,
246                                 psa_rot_lifecycle_state_thread_fn_call,
247 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
248                                 psa_connect_thread_fn_call,
249                                 psa_close_thread_fn_call,
250                                 psa_set_rhandle_thread_fn_call,
251 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
252 #if CONFIG_TFM_DOORBELL_API == 1
253                                 psa_notify_thread_fn_call,
254                                 psa_clear_thread_fn_call,
255 #endif /* CONFIG_TFM_DOORBELL_API == 1 */
256 #if (CONFIG_TFM_FLIH_API == 1) || (CONFIG_TFM_SLIH_API == 1)
257                                 psa_irq_enable_thread_fn_call,
258                                 psa_irq_disable_thread_fn_call,
259 #if CONFIG_TFM_FLIH_API == 1
260                                 psa_reset_signal_thread_fn_call,
261 #endif /* CONFIG_TFM_FLIH_API == 1 */
262 #if CONFIG_TFM_SLIH_API == 1
263                                 psa_eoi_thread_fn_call,
264 #endif /* CONFIG_TFM_SLIH_API == 1 */
265 #endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
266 #if PSA_FRAMEWORK_HAS_MM_IOVEC
267                                 psa_map_invec_thread_fn_call,
268                                 psa_unmap_invec_thread_fn_call,
269                                 psa_map_outvec_thread_fn_call,
270                                 psa_unmap_outvec_thread_fn_call,
271 #endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
272 #ifdef TFM_PARTITION_NS_AGENT_MAILBOX
273                                 agent_psa_call_thread_fn_call,
274 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
275                                 agent_psa_connect_thread_fn_call,
276                                 agent_psa_close_thread_fn_call,
277 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1 */
278 #endif /* TFM_PARTITION_NS_AGENT_MAILBOX */
279                             };
280