blob: 469e7f3713d044e962eb4d5aea4eb8d0e0685499 [file] [log] [blame]
Mingyang Sundeae45d2021-09-06 15:31:07 +08001/*
shejia01a0ea10c2022-06-27 13:56:00 +08002 * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
BohdanHunko749c9a52023-02-16 16:14:47 +02003 * Copyright (c) 2021-2023 Cypress Semiconductor Corporation (an Infineon
Chris Brandb4c2b002022-07-21 12:54:00 -07004 * company) or an affiliate of Cypress Semiconductor Corporation. All rights
5 * reserved.
Mingyang Sundeae45d2021-09-06 15:31:07 +08006 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 */
10
11#include <stdint.h>
Sherry Zhang049733e2022-04-20 21:37:51 +080012#include "aapcs_local.h"
Mingyang Sun620c8562021-11-10 11:44:58 +080013#include "critical_section.h"
Ken Liue07c3b72021-10-14 16:19:13 +080014#include "compiler_ext_defs.h"
Xinyu Zhangcdbe3622022-10-31 14:34:25 +080015#include "config_spm.h"
Summer Qin596f5552022-01-27 18:04:06 +080016#include "runtime_defs.h"
Chris Brand30106ba2022-01-13 13:48:50 -080017#include "ffm/stack_watermark.h"
Sherry Zhangc7147022023-02-03 11:21:10 +080018#include "spm.h"
Ken Liu62bae592021-10-19 22:15:43 +080019#include "tfm_hal_isolation.h"
Kevin Pengb288c522021-09-26 16:18:23 +080020#include "tfm_hal_platform.h"
Mingyang Sundeae45d2021-09-06 15:31:07 +080021#include "tfm_rpc.h"
Mingyang Sundeae45d2021-09-06 15:31:07 +080022#include "ffm/backend.h"
Ken Liu62bae592021-10-19 22:15:43 +080023#include "utilities.h"
Ken Liu71a79fe2023-03-01 16:27:23 +080024#include "cmsis_psa/memory_symbols.h"
Mingyang Sundeae45d2021-09-06 15:31:07 +080025#include "load/partition_defs.h"
26#include "load/service_defs.h"
27#include "load/spm_load_api.h"
28#include "psa/error.h"
Jianliang Shen9e389352023-02-09 16:58:08 +080029#include "internal_status_code.h"
Mingyang Sundeae45d2021-09-06 15:31:07 +080030
31/* Declare the global component list */
32struct partition_head_t partition_listhead;
33
Kevin Peng9f1a7542022-02-07 16:32:27 +080034#if CONFIG_TFM_PSA_API_CROSS_CALL == 1
Ken Liu63a176b2022-06-09 22:36:56 +080035/* Instance for SPM_THREAD_CONTEXT */
Ken Liue07c3b72021-10-14 16:19:13 +080036
Chris Brandfe5adca2022-11-08 17:44:07 -080037#ifdef CONFIG_TFM_USE_TRUSTZONE
38struct context_ctrl_t *p_spm_thread_context;
39#else
40/* If ns_agent_tz isn't used, we need to provide a stack for SPM to use */
Ken Liu63a176b2022-06-09 22:36:56 +080041static uint8_t spm_thread_stack[CONFIG_TFM_SPM_THREAD_STACK_SIZE] __aligned(8);
42ARCH_CLAIM_CTXCTRL_INSTANCE(spm_thread_context,
43 spm_thread_stack,
44 sizeof(spm_thread_stack));
45
Ken Liue07c3b72021-10-14 16:19:13 +080046struct context_ctrl_t *p_spm_thread_context = &spm_thread_context;
Ken Liue07c3b72021-10-14 16:19:13 +080047#endif
48
49#endif
50
Sherry Zhang049733e2022-04-20 21:37:51 +080051/* Indicator point to the partition meta */
52uintptr_t *partition_meta_indicator_pos;
53
54extern uint32_t scheduler_lock;
55
shejia0195a88bc2023-01-16 15:44:46 +080056/*
57 * Query the state of current thread.
58 */
59static uint32_t query_state(struct thread_t *p_thrd, uint32_t *p_retval)
60{
61 struct critical_section_t cs_signal = CRITICAL_SECTION_STATIC_INIT;
62 struct partition_t *p_pt = NULL;
63 uint32_t state = p_thrd->state;
64 psa_signal_t signal_ret = 0;
65
66 /* Get current partition of thread. */
67 p_pt = TO_CONTAINER(p_thrd->p_context_ctrl,
68 struct partition_t, ctx_ctrl);
69
70 CRITICAL_SECTION_ENTER(cs_signal);
71
72 signal_ret = p_pt->signals_waiting & p_pt->signals_asserted;
73
74 if (signal_ret) {
75 /*
76 * If the partition is waiting some signals and any of them is asserted,
77 * change thread to be THRD_STATE_RET_VAL_AVAIL and fill the retval. If
78 * the waiting signal is TFM_IPC_REPLY_SIGNAL, it means the Secure
79 * Partition is waiting for the services to be fulfilled, then the
80 * return value comes from the backend_replying() by the server
81 * Partition. For other waiting signals by psa_wait(), the return value
82 * is just the signal.
83 */
84 if (signal_ret == TFM_IPC_REPLY_SIGNAL) {
85 p_pt->signals_asserted &= ~TFM_IPC_REPLY_SIGNAL;
86 *p_retval = (uint32_t)p_pt->reply_value;
87 } else {
88 *p_retval = signal_ret;
89 }
90
91 p_pt->signals_waiting = 0;
92 state = THRD_STATE_RET_VAL_AVAIL;
93 } else if (p_pt->signals_waiting != 0) {
94 /*
95 * If the thread is waiting some signals but none of them is asserted,
96 * block the thread.
97 */
98 state = THRD_STATE_BLOCK;
99 }
100
101 CRITICAL_SECTION_LEAVE(cs_signal);
102 return state;
103}
104
Sherry Zhangef49b1d2023-02-07 14:08:40 +0800105extern struct psa_api_tbl_t psa_api_cross;
106extern struct psa_api_tbl_t psa_api_svc;
107
Summer Qin596f5552022-01-27 18:04:06 +0800108static void prv_process_metadata(struct partition_t *p_pt)
109{
Kevin Peng43160d52022-02-11 13:35:56 +0800110 const struct partition_load_info_t *p_pt_ldi;
111 const struct service_load_info_t *p_srv_ldi;
112 struct context_ctrl_t *ctx_ctrl;
113 struct runtime_metadata_t *p_rt_meta;
114 service_fn_t *p_sfn_table;
115 uint32_t allocate_size;
Summer Qin596f5552022-01-27 18:04:06 +0800116
Kevin Peng43160d52022-02-11 13:35:56 +0800117 p_pt_ldi = p_pt->p_ldinf;
Chris Brand1fb796d2022-10-18 16:54:25 -0700118 p_srv_ldi = LOAD_INFO_SERVICE(p_pt_ldi);
Kevin Peng43160d52022-02-11 13:35:56 +0800119 ctx_ctrl = &p_pt->ctx_ctrl;
120
121 /* common runtime metadata */
122 allocate_size = sizeof(*p_rt_meta);
123
124 if (!IS_PARTITION_IPC_MODEL(p_pt_ldi)) {
125 /* SFN specific metadata - SFN function table */
126 allocate_size += sizeof(service_fn_t) * p_pt_ldi->nservices;
Summer Qin596f5552022-01-27 18:04:06 +0800127 }
128
Kevin Peng43160d52022-02-11 13:35:56 +0800129 ARCH_CTXCTRL_ALLOCATE_STACK(ctx_ctrl, allocate_size);
130 p_rt_meta = (struct runtime_metadata_t *)
131 ARCH_CTXCTRL_ALLOCATED_PTR(ctx_ctrl);
132
133 p_rt_meta->entry = p_pt_ldi->entry;
Sherry Zhangef49b1d2023-02-07 14:08:40 +0800134#if TFM_LVL == 1
135 p_rt_meta->psa_fns = &psa_api_cross;
136#else
137 /* TODO: ABI for PRoT partitions needs to be updated based on implementations. */
138 p_rt_meta->psa_fns = &psa_api_svc;
139#endif
Kevin Peng43160d52022-02-11 13:35:56 +0800140 p_rt_meta->n_sfn = 0;
141 p_sfn_table = p_rt_meta->sfn_table;
142
143 if (!IS_PARTITION_IPC_MODEL(p_pt_ldi)) {
144 /* SFN table. The signal bit of the service is the same index of SFN. */
145 for (int i = 0; i < p_pt_ldi->nservices; i++) {
146 p_sfn_table[i] = (service_fn_t)p_srv_ldi[i].sfn;
147 }
148
149 p_rt_meta->n_sfn = p_pt_ldi->nservices;
150 }
151
152 p_pt->p_metadata = (void *)p_rt_meta;
Summer Qin596f5552022-01-27 18:04:06 +0800153}
154
Mingyang Sundeae45d2021-09-06 15:31:07 +0800155/*
156 * Send message and wake up the SP who is waiting on message queue, block the
Ken Liuf39d8eb2021-10-07 12:55:33 +0800157 * current thread and trigger scheduler.
Mingyang Sundeae45d2021-09-06 15:31:07 +0800158 */
Ken Liu995a9742022-05-18 19:28:30 +0800159psa_status_t backend_messaging(struct service_t *service,
Ken Liuc9313eb2023-02-22 15:45:54 +0800160 struct connection_t *handle)
Mingyang Sundeae45d2021-09-06 15:31:07 +0800161{
162 struct partition_t *p_owner = NULL;
163 psa_signal_t signal = 0;
Jianliang Shen9e389352023-02-09 16:58:08 +0800164 psa_status_t ret = PSA_SUCCESS;
Mingyang Sundeae45d2021-09-06 15:31:07 +0800165
Mingyang Suna09adda2022-02-16 18:11:33 +0800166 if (!handle || !service || !service->p_ldinf || !service->partition) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +0800167 return PSA_ERROR_PROGRAMMER_ERROR;
Mingyang Sundeae45d2021-09-06 15:31:07 +0800168 }
169
170 p_owner = service->partition;
171 signal = service->p_ldinf->signal;
172
Mingyang Suna09adda2022-02-16 18:11:33 +0800173 UNI_LIST_INSERT_AFTER(p_owner, handle, p_handles);
Mingyang Sundeae45d2021-09-06 15:31:07 +0800174
175 /* Messages put. Update signals */
Jianliang Shen9e389352023-02-09 16:58:08 +0800176 ret = backend_assert_signal(p_owner, signal);
Mingyang Sundeae45d2021-09-06 15:31:07 +0800177
178 /*
179 * If it is a NS request via RPC, it is unnecessary to block current
180 * thread.
181 */
182
Mingyang Suna09adda2022-02-16 18:11:33 +0800183 if (!is_tfm_rpc_msg(handle)) {
Jianliang Shen9e389352023-02-09 16:58:08 +0800184 ret = backend_wait_signals(handle->p_client, TFM_IPC_REPLY_SIGNAL);
185 } else {
186 ret = PSA_SUCCESS;
Mingyang Sundeae45d2021-09-06 15:31:07 +0800187 }
188
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800189 handle->status = TFM_HANDLE_STATUS_ACTIVE;
190
Jianliang Shen9e389352023-02-09 16:58:08 +0800191 return ret;
Mingyang Sundeae45d2021-09-06 15:31:07 +0800192}
193
Ken Liuc9313eb2023-02-22 15:45:54 +0800194psa_status_t backend_replying(struct connection_t *handle, int32_t status)
Ken Liu802a3702021-10-15 12:09:56 +0800195{
Mingyang Suna09adda2022-02-16 18:11:33 +0800196 if (is_tfm_rpc_msg(handle)) {
197 tfm_rpc_client_call_reply(handle, status);
Ken Liu802a3702021-10-15 12:09:56 +0800198 } else {
shejia0195a88bc2023-01-16 15:44:46 +0800199 handle->p_client->reply_value = (uintptr_t)status;
Jianliang Shen9e389352023-02-09 16:58:08 +0800200 return backend_assert_signal(handle->p_client, TFM_IPC_REPLY_SIGNAL);
Ken Liu802a3702021-10-15 12:09:56 +0800201 }
Ken Liuf39d8eb2021-10-07 12:55:33 +0800202
203 /*
204 * 'psa_reply' exists in IPC model only and returns 'void'. Return
205 * 'PSA_SUCCESS' here always since SPM does not forward the status
206 * to the caller.
207 */
208 return PSA_SUCCESS;
Ken Liu802a3702021-10-15 12:09:56 +0800209}
210
BohdanHunko749c9a52023-02-16 16:14:47 +0200211extern void common_sfn_thread(void);
Summer Qin596f5552022-01-27 18:04:06 +0800212
Mingyang Sundeae45d2021-09-06 15:31:07 +0800213/* Parameters are treated as assuredly */
Ken Liu995a9742022-05-18 19:28:30 +0800214void backend_init_comp_assuredly(struct partition_t *p_pt,
215 uint32_t service_setting)
Mingyang Sundeae45d2021-09-06 15:31:07 +0800216{
217 const struct partition_load_info_t *p_pldi = p_pt->p_ldinf;
BohdanHunko749c9a52023-02-16 16:14:47 +0200218 thrd_fn_t thrd_entry;
Mingyang Sundeae45d2021-09-06 15:31:07 +0800219
Kevin Peng613b4172022-02-15 14:41:44 +0800220#if CONFIG_TFM_DOORBELL_API == 1
221 p_pt->signals_allowed |= PSA_DOORBELL;
222#endif /* CONFIG_TFM_DOORBELL_API == 1 */
223
224 p_pt->signals_allowed |= service_setting;
Mingyang Sundeae45d2021-09-06 15:31:07 +0800225
Ken Liu0bed7e02022-02-10 12:38:07 +0800226 UNI_LISI_INIT_NODE(p_pt, p_handles);
Mingyang Sundeae45d2021-09-06 15:31:07 +0800227
Ken Liubf4681f2022-02-11 11:15:03 +0800228 ARCH_CTXCTRL_INIT(&p_pt->ctx_ctrl,
229 LOAD_ALLOCED_STACK_ADDR(p_pldi),
230 p_pldi->stack_size);
231
Chris Brand30106ba2022-01-13 13:48:50 -0800232 watermark_stack(p_pt);
233
Summer Qin596f5552022-01-27 18:04:06 +0800234 prv_process_metadata(p_pt);
235
Mingyang Sundeae45d2021-09-06 15:31:07 +0800236 THRD_INIT(&p_pt->thrd, &p_pt->ctx_ctrl,
237 TO_THREAD_PRIORITY(PARTITION_PRIORITY(p_pldi->flags)));
238
Chris Brandfe5adca2022-11-08 17:44:07 -0800239#if (CONFIG_TFM_PSA_API_CROSS_CALL == 1) && defined(CONFIG_TFM_USE_TRUSTZONE)
Chris Brandb4c2b002022-07-21 12:54:00 -0700240 if (IS_PARTITION_NS_AGENT(p_pldi)) {
Chris Brandfe5adca2022-11-08 17:44:07 -0800241 /* Get the context from ns_agent_tz */
242 if (p_pldi->pid == 0) {
243 SPM_THREAD_CONTEXT = &p_pt->ctx_ctrl;
244 }
Mingyang Sundeae45d2021-09-06 15:31:07 +0800245 }
Summer Qin95444822022-01-27 11:22:00 +0800246#endif
Mingyang Sundeae45d2021-09-06 15:31:07 +0800247
BohdanHunko749c9a52023-02-16 16:14:47 +0200248 if (IS_PARTITION_IPC_MODEL(p_pldi)) {
249 /* IPC Partition */
250 thrd_entry = POSITION_TO_ENTRY(p_pldi->entry, thrd_fn_t);
251 } else {
252 /* SFN Partition */
253 thrd_entry = POSITION_TO_ENTRY(common_sfn_thread, thrd_fn_t);
254 }
255
Mingyang Sundeae45d2021-09-06 15:31:07 +0800256 thrd_start(&p_pt->thrd,
BohdanHunko749c9a52023-02-16 16:14:47 +0200257 thrd_entry,
Ken Liubf4681f2022-02-11 11:15:03 +0800258 THRD_GENERAL_EXIT);
Mingyang Sundeae45d2021-09-06 15:31:07 +0800259}
260
Ken Liu995a9742022-05-18 19:28:30 +0800261uint32_t backend_system_run(void)
Mingyang Sundeae45d2021-09-06 15:31:07 +0800262{
Ken Liu62bae592021-10-19 22:15:43 +0800263 uint32_t control;
264 struct partition_t *p_cur_pt;
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800265 fih_int fih_rc = FIH_FAILURE;
Ken Liu62bae592021-10-19 22:15:43 +0800266
Sherry Zhang68681642022-06-24 13:36:33 +0800267#if CONFIG_TFM_PSA_API_CROSS_CALL == 1
Summer Qin1056d1c2022-10-19 16:07:15 +0800268 SPM_ASSERT(SPM_THREAD_CONTEXT);
Chris Brand3778bc12021-12-15 17:01:05 -0800269#endif
270
shejia0195a88bc2023-01-16 15:44:46 +0800271 /* Init thread callback function. */
272 thrd_set_query_callback(query_state);
273
Ken Liu71a79fe2023-03-01 16:27:23 +0800274 partition_meta_indicator_pos = (uintptr_t *)PART_LOCAL_STORAGE_PTR_POS;
Ken Liu62bae592021-10-19 22:15:43 +0800275 control = thrd_start_scheduler(&CURRENT_THREAD);
276
277 p_cur_pt = TO_CONTAINER(CURRENT_THREAD->p_context_ctrl,
278 struct partition_t, ctx_ctrl);
279
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800280 FIH_CALL(tfm_hal_activate_boundary, fih_rc, p_cur_pt->p_ldinf, p_cur_pt->boundary);
281 if (fih_not_eq(fih_rc, fih_int_encode(TFM_HAL_SUCCESS))) {
Ken Liu62bae592021-10-19 22:15:43 +0800282 tfm_core_panic();
283 }
284
285 return control;
Mingyang Sundeae45d2021-09-06 15:31:07 +0800286}
287
Jianliang Shen9e389352023-02-09 16:58:08 +0800288psa_status_t backend_wait_signals(struct partition_t *p_pt, psa_signal_t signals)
Kevin Pengdef92de2021-11-10 16:14:48 +0800289{
shejia0195a88bc2023-01-16 15:44:46 +0800290 struct critical_section_t cs_signal = CRITICAL_SECTION_STATIC_INIT;
Jianliang Shen9e389352023-02-09 16:58:08 +0800291 psa_status_t ret = PSA_SUCCESS;
Kevin Pengdef92de2021-11-10 16:14:48 +0800292
shejia0195a88bc2023-01-16 15:44:46 +0800293 if (!p_pt) {
294 tfm_core_panic();
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800295 }
shejia0195a88bc2023-01-16 15:44:46 +0800296
297 CRITICAL_SECTION_ENTER(cs_signal);
298
Jianliang Shen9e389352023-02-09 16:58:08 +0800299 ret = p_pt->signals_asserted & signals;
300 if (ret == 0) {
shejia0195a88bc2023-01-16 15:44:46 +0800301 p_pt->signals_waiting = signals;
Jianliang Shen9e389352023-02-09 16:58:08 +0800302 ret = STATUS_NEED_SCHEDULE;
shejia0195a88bc2023-01-16 15:44:46 +0800303 }
304
305 CRITICAL_SECTION_LEAVE(cs_signal);
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800306
Jianliang Shen9e389352023-02-09 16:58:08 +0800307 return ret;
Kevin Pengdef92de2021-11-10 16:14:48 +0800308}
309
Jianliang Shen9e389352023-02-09 16:58:08 +0800310psa_status_t backend_assert_signal(struct partition_t *p_pt, psa_signal_t signal)
Kevin Pengdef92de2021-11-10 16:14:48 +0800311{
shejia0195a88bc2023-01-16 15:44:46 +0800312 struct critical_section_t cs_signal = CRITICAL_SECTION_STATIC_INIT;
Jianliang Shen9e389352023-02-09 16:58:08 +0800313 psa_status_t ret = PSA_SUCCESS;
shejia0195a88bc2023-01-16 15:44:46 +0800314
315 if (!p_pt) {
316 tfm_core_panic();
shejia01a0ea10c2022-06-27 13:56:00 +0800317 }
shejia0195a88bc2023-01-16 15:44:46 +0800318
319 CRITICAL_SECTION_ENTER(cs_signal);
320 p_pt->signals_asserted |= signal;
Jianliang Shen9e389352023-02-09 16:58:08 +0800321
322 if (p_pt->signals_asserted & p_pt->signals_waiting) {
323 ret = STATUS_NEED_SCHEDULE;
324 }
shejia0195a88bc2023-01-16 15:44:46 +0800325 CRITICAL_SECTION_LEAVE(cs_signal);
326
Jianliang Shen9e389352023-02-09 16:58:08 +0800327 return ret;
Kevin Pengdef92de2021-11-10 16:14:48 +0800328}
329
Sherry Zhang049733e2022-04-20 21:37:51 +0800330uint64_t ipc_schedule(void)
331{
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800332 fih_int fih_rc = FIH_FAILURE;
Sherry Zhang049733e2022-04-20 21:37:51 +0800333 AAPCS_DUAL_U32_T ctx_ctrls;
334 struct partition_t *p_part_curr, *p_part_next;
335 struct context_ctrl_t *p_curr_ctx;
336 struct thread_t *pth_next = thrd_next();
337 struct critical_section_t cs = CRITICAL_SECTION_STATIC_INIT;
338
339 p_curr_ctx = (struct context_ctrl_t *)(CURRENT_THREAD->p_context_ctrl);
340
341 AAPCS_DUAL_U32_SET(ctx_ctrls, (uint32_t)p_curr_ctx, (uint32_t)p_curr_ctx);
342
343 p_part_curr = GET_CURRENT_COMPONENT();
344 p_part_next = GET_THRD_OWNER(pth_next);
345
346 if (scheduler_lock != SCHEDULER_LOCKED && pth_next != NULL &&
347 p_part_curr != p_part_next) {
348 /* Check if there is enough room on stack to save more context */
349 if ((p_curr_ctx->sp_limit +
350 sizeof(struct tfm_additional_context_t)) > __get_PSP()) {
351 tfm_core_panic();
352 }
353
354 CRITICAL_SECTION_ENTER(cs);
355 /*
356 * If required, let the platform update boundary based on its
357 * implementation. Change privilege, MPU or other configurations.
358 */
Chendi Sun0f7d2822022-10-28 12:24:12 +0800359 if (tfm_hal_boundary_need_switch(p_part_curr->boundary,
360 p_part_next->boundary)) {
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800361 FIH_CALL(tfm_hal_activate_boundary, fih_rc,
362 p_part_next->p_ldinf, p_part_next->boundary);
363 if (fih_not_eq(fih_rc, fih_int_encode(TFM_HAL_SUCCESS))) {
Sherry Zhang049733e2022-04-20 21:37:51 +0800364 tfm_core_panic();
365 }
366 }
367 ARCH_FLUSH_FP_CONTEXT();
368
369 AAPCS_DUAL_U32_SET_A1(ctx_ctrls, (uint32_t)pth_next->p_context_ctrl);
370
371 CURRENT_THREAD = pth_next;
372 CRITICAL_SECTION_LEAVE(cs);
373 }
374
375 /* Update meta indicator */
376 if (partition_meta_indicator_pos && (p_part_next->p_metadata)) {
377 *partition_meta_indicator_pos = (uintptr_t)(p_part_next->p_metadata);
378 }
379 return AAPCS_DUAL_U32_AS_U64(ctx_ctrls);
380}