blob: b05ec81b40a3cc1c67b68b0f490c2d53e18f353e [file] [log] [blame]
Edison Ai764d41f2018-09-21 15:56:36 +08001/*
2 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
Mingyang Sunda01a972019-07-12 17:32:59 +08007
8/* All the APIs defined in this file are used for IPC model. */
9
Edison Ai764d41f2018-09-21 15:56:36 +080010#include <inttypes.h>
Summer Qin2bfd2a02018-09-26 17:10:41 +080011#include <limits.h>
Edison Ai764d41f2018-09-21 15:56:36 +080012#include <stdbool.h>
Edison Ai764d41f2018-09-21 15:56:36 +080013#include <stdlib.h>
Jamie Foxcc31d402019-01-28 17:13:52 +000014#include "psa/client.h"
15#include "psa/service.h"
Edison Ai764d41f2018-09-21 15:56:36 +080016#include "tfm_utils.h"
Mingyang Sunf3d29892019-07-10 17:50:23 +080017#include "tfm_spm_hal.h"
Edison Ai764d41f2018-09-21 15:56:36 +080018#include "spm_api.h"
19#include "spm_db.h"
David Hu326f3972019-08-06 14:16:51 +080020#include "tfm_core_mem_check.h"
Edison Ai764d41f2018-09-21 15:56:36 +080021#include "tfm_internal_defines.h"
22#include "tfm_wait.h"
23#include "tfm_message_queue.h"
24#include "tfm_list.h"
25#include "tfm_pools.h"
Edison Ai764d41f2018-09-21 15:56:36 +080026#include "tfm_thread.h"
Summer Qin2bfd2a02018-09-26 17:10:41 +080027#include "region_defs.h"
Edison Ai764d41f2018-09-21 15:56:36 +080028#include "tfm_nspm.h"
Edison Ai807fedb2019-03-07 11:22:03 +080029#include "tfm_memory_utils.h"
Edison Ai764d41f2018-09-21 15:56:36 +080030
Edison Ai764d41f2018-09-21 15:56:36 +080031/* Extern SPM variable */
32extern struct spm_partition_db_t g_spm_partition_db;
33
Mate Toth-Palc430b992019-05-09 21:01:14 +020034/* Extern secure lock variable */
35extern int32_t tfm_secure_lock;
Mingyang Sunf3d29892019-07-10 17:50:23 +080036
Edison Ai764d41f2018-09-21 15:56:36 +080037/* Pools */
38TFM_POOL_DECLARE(conn_handle_pool, sizeof(struct tfm_conn_handle_t),
39 TFM_CONN_HANDLE_MAX_NUM);
40TFM_POOL_DECLARE(spm_service_pool, sizeof(struct tfm_spm_service_t),
41 TFM_SPM_MAX_ROT_SERV_NUM);
42TFM_POOL_DECLARE(msg_db_pool, sizeof(struct tfm_msg_body_t),
43 TFM_MSG_QUEUE_MAX_MSG_NUM);
44
45static struct tfm_spm_service_db_t g_spm_service_db[] = {
46 #include "secure_fw/services/tfm_service_list.inc"
47};
48
49/********************** SPM functions for handler mode ***********************/
50
51/* Service handle management functions */
52psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service)
53{
54 struct tfm_conn_handle_t *node;
55
56 TFM_ASSERT(service);
57
58 /* Get buffer for handle list structure from handle pool */
59 node = (struct tfm_conn_handle_t *)tfm_pool_alloc(conn_handle_pool);
60 if (!node) {
61 return PSA_NULL_HANDLE;
62 }
63
64 /* Global unique handle, use handle buffer address directly */
65 node->handle = (psa_handle_t)node;
66
67 /* Add handle node to list for next psa functions */
68 tfm_list_add_tail(&service->handle_list, &node->list);
69
70 return node->handle;
71}
72
73static struct tfm_conn_handle_t *
Mingyang Sun5e13aa72019-07-10 10:30:16 +080074 tfm_spm_find_conn_handle_node(struct tfm_spm_service_t *service,
75 psa_handle_t conn_handle)
Edison Ai764d41f2018-09-21 15:56:36 +080076{
77 struct tfm_conn_handle_t *handle_node;
78 struct tfm_list_node_t *node, *head;
79
80 TFM_ASSERT(service);
81
82 head = &service->handle_list;
83 TFM_LIST_FOR_EACH(node, head) {
84 handle_node = TFM_GET_CONTAINER_PTR(node, struct tfm_conn_handle_t,
85 list);
86 if (handle_node->handle == conn_handle) {
87 return handle_node;
88 }
89 }
90 return NULL;
91}
92
93int32_t tfm_spm_free_conn_handle(struct tfm_spm_service_t *service,
94 psa_handle_t conn_handle)
95{
96 struct tfm_conn_handle_t *node;
97
98 TFM_ASSERT(service);
99
100 /* There are many handles for each RoT Service */
101 node = tfm_spm_find_conn_handle_node(service, conn_handle);
102 if (!node) {
103 tfm_panic();
104 }
105
106 /* Remove node from handle list */
107 tfm_list_del_node(&node->list);
108
109 /* Back handle buffer to pool */
110 tfm_pool_free(node);
111 return IPC_SUCCESS;
112}
113
114int32_t tfm_spm_set_rhandle(struct tfm_spm_service_t *service,
115 psa_handle_t conn_handle,
116 void *rhandle)
117{
118 struct tfm_conn_handle_t *node;
119
120 TFM_ASSERT(service);
121 /* Set reverse handle value only be allowed for a connected handle */
122 TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
123
124 /* There are many handles for each RoT Service */
125 node = tfm_spm_find_conn_handle_node(service, conn_handle);
126 if (!node) {
127 tfm_panic();
128 }
129
130 node->rhandle = rhandle;
131 return IPC_SUCCESS;
132}
133
134void *tfm_spm_get_rhandle(struct tfm_spm_service_t *service,
135 psa_handle_t conn_handle)
136{
137 struct tfm_conn_handle_t *node;
138
139 TFM_ASSERT(service);
140 /* Get reverse handle value only be allowed for a connected handle */
141 TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
142
143 /* There are many handles for each RoT Service */
144 node = tfm_spm_find_conn_handle_node(service, conn_handle);
145 if (!node) {
146 tfm_panic();
147 }
148
149 return node->rhandle;
150}
151
152/* Partition management functions */
153struct tfm_spm_service_t *
Mingyang Sunf3d29892019-07-10 17:50:23 +0800154 tfm_spm_get_service_by_signal(struct spm_partition_desc_t *partition,
155 psa_signal_t signal)
Edison Ai764d41f2018-09-21 15:56:36 +0800156{
157 struct tfm_list_node_t *node, *head;
158 struct tfm_spm_service_t *service;
159
160 TFM_ASSERT(partition);
161
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800162 if (tfm_list_is_empty(&partition->runtime_data.service_list)) {
Edison Ai764d41f2018-09-21 15:56:36 +0800163 tfm_panic();
164 }
165
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800166 head = &partition->runtime_data.service_list;
Edison Ai764d41f2018-09-21 15:56:36 +0800167 TFM_LIST_FOR_EACH(node, head) {
168 service = TFM_GET_CONTAINER_PTR(node, struct tfm_spm_service_t, list);
169 if (service->service_db->signal == signal) {
170 return service;
171 }
172 }
173 return NULL;
174}
175
176struct tfm_spm_service_t *tfm_spm_get_service_by_sid(uint32_t sid)
177{
178 uint32_t i;
179 struct tfm_list_node_t *node, *head;
180 struct tfm_spm_service_t *service;
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800181 struct spm_partition_desc_t *partition;
Edison Ai764d41f2018-09-21 15:56:36 +0800182
Mate Toth-Pal3ad2e3e2019-07-11 21:43:37 +0200183 for (i = 0; i < g_spm_partition_db.partition_count; i++) {
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800184 partition = &g_spm_partition_db.partitions[i];
Edison Ai764d41f2018-09-21 15:56:36 +0800185 /* Skip partition without IPC flag */
Mingyang Sunf3d29892019-07-10 17:50:23 +0800186 if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) {
Edison Ai764d41f2018-09-21 15:56:36 +0800187 continue;
188 }
189
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800190 if (tfm_list_is_empty(&partition->runtime_data.service_list)) {
Edison Ai764d41f2018-09-21 15:56:36 +0800191 continue;
192 }
193
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800194 head = &partition->runtime_data.service_list;
Edison Ai764d41f2018-09-21 15:56:36 +0800195 TFM_LIST_FOR_EACH(node, head) {
196 service = TFM_GET_CONTAINER_PTR(node, struct tfm_spm_service_t,
197 list);
198 if (service->service_db->sid == sid) {
199 return service;
200 }
201 }
202 }
203 return NULL;
204}
205
206struct tfm_spm_service_t *
207 tfm_spm_get_service_by_handle(psa_handle_t conn_handle)
208{
209 uint32_t i;
210 struct tfm_conn_handle_t *handle;
211 struct tfm_list_node_t *service_node, *service_head;
212 struct tfm_list_node_t *handle_node, *handle_head;
213 struct tfm_spm_service_t *service;
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800214 struct spm_partition_desc_t *partition;
Edison Ai764d41f2018-09-21 15:56:36 +0800215
Mate Toth-Pal3ad2e3e2019-07-11 21:43:37 +0200216 for (i = 0; i < g_spm_partition_db.partition_count; i++) {
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800217 partition = &g_spm_partition_db.partitions[i];
Edison Ai764d41f2018-09-21 15:56:36 +0800218 /* Skip partition without IPC flag */
Mingyang Sunf3d29892019-07-10 17:50:23 +0800219 if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) {
Edison Ai764d41f2018-09-21 15:56:36 +0800220 continue;
221 }
222
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800223 if (tfm_list_is_empty(&partition->runtime_data.service_list)) {
Edison Ai764d41f2018-09-21 15:56:36 +0800224 continue;
225 }
226
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800227 service_head = &partition->runtime_data.service_list;
Edison Ai764d41f2018-09-21 15:56:36 +0800228 TFM_LIST_FOR_EACH(service_node, service_head) {
229 service = TFM_GET_CONTAINER_PTR(service_node,
230 struct tfm_spm_service_t, list);
231 handle_head = &service->handle_list;
232 TFM_LIST_FOR_EACH(handle_node, handle_head) {
233 handle = TFM_GET_CONTAINER_PTR(handle_node,
234 struct tfm_conn_handle_t, list);
235 if (handle->handle == conn_handle) {
236 return service;
237 }
238 }
239 }
240 }
241 return NULL;
242}
243
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800244struct spm_partition_desc_t *tfm_spm_get_partition_by_id(int32_t partition_id)
Edison Ai764d41f2018-09-21 15:56:36 +0800245{
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800246 uint32_t idx = get_partition_idx(partition_id);
Edison Ai764d41f2018-09-21 15:56:36 +0800247
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800248 if (idx != SPM_INVALID_PARTITION_IDX) {
249 return &(g_spm_partition_db.partitions[idx]);
Edison Ai764d41f2018-09-21 15:56:36 +0800250 }
251 return NULL;
252}
253
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800254struct spm_partition_desc_t *tfm_spm_get_running_partition(void)
Edison Ai764d41f2018-09-21 15:56:36 +0800255{
256 uint32_t spid;
257
Mingyang Sunf3d29892019-07-10 17:50:23 +0800258 spid = tfm_spm_partition_get_running_partition_id();
Edison Ai764d41f2018-09-21 15:56:36 +0800259
260 return tfm_spm_get_partition_by_id(spid);
261}
262
263int32_t tfm_spm_check_client_version(struct tfm_spm_service_t *service,
264 uint32_t minor_version)
265{
266 TFM_ASSERT(service);
267
268 switch (service->service_db->minor_policy) {
269 case TFM_VERSION_POLICY_RELAXED:
Oren Cohen665d8322019-04-28 14:24:40 +0300270 if (minor_version > service->service_db->minor_version) {
Edison Ai764d41f2018-09-21 15:56:36 +0800271 return IPC_ERROR_VERSION;
272 }
273 break;
274 case TFM_VERSION_POLICY_STRICT:
275 if (minor_version != service->service_db->minor_version) {
276 return IPC_ERROR_VERSION;
277 }
278 break;
279 default:
280 return IPC_ERROR_VERSION;
281 }
282 return IPC_SUCCESS;
283}
284
285/* Message functions */
286struct tfm_msg_body_t *tfm_spm_get_msg_from_handle(psa_handle_t msg_handle)
287{
288 /*
289 * There may be one error handle passed by the caller in two conditions:
290 * 1. Not a valid message handle.
291 * 2. Handle between different Partitions. Partition A passes one handle
292 * belong to other Partitions and tries to access other's data.
293 * So, need do necessary checking to prevent those conditions.
294 */
295 struct tfm_msg_body_t *msg;
296 uint32_t partition_id;
297
298 msg = (struct tfm_msg_body_t *)msg_handle;
299 if (!msg) {
300 return NULL;
301 }
302
303 /*
304 * FixMe: For condition 1: using a magic number to define it's a message.
305 * It needs to be an enhancement to check the handle belong to service.
306 */
307 if (msg->magic != TFM_MSG_MAGIC) {
308 return NULL;
309 }
310
311 /* For condition 2: check if the partition ID is same */
Mingyang Sunf3d29892019-07-10 17:50:23 +0800312 partition_id = tfm_spm_partition_get_running_partition_id();
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800313 if (partition_id != msg->service->partition->static_data.partition_id) {
Edison Ai764d41f2018-09-21 15:56:36 +0800314 return NULL;
315 }
316
317 return msg;
318}
319
320struct tfm_msg_body_t *tfm_spm_create_msg(struct tfm_spm_service_t *service,
321 psa_handle_t handle,
Summer Qin632b3e02019-07-29 15:34:38 +0800322 int32_t type, int32_t ns_caller,
Edison Ai764d41f2018-09-21 15:56:36 +0800323 psa_invec *invec, size_t in_len,
324 psa_outvec *outvec, size_t out_len,
325 psa_outvec *caller_outvec)
326{
327 struct tfm_msg_body_t *msg = NULL;
328 uint32_t i;
329
330 TFM_ASSERT(service);
331 TFM_ASSERT(!(invec == NULL && in_len != 0));
332 TFM_ASSERT(!(outvec == NULL && out_len != 0));
333 TFM_ASSERT(in_len <= PSA_MAX_IOVEC);
334 TFM_ASSERT(out_len <= PSA_MAX_IOVEC);
335 TFM_ASSERT(in_len + out_len <= PSA_MAX_IOVEC);
336
337 /* Get message buffer from message pool */
338 msg = (struct tfm_msg_body_t *)tfm_pool_alloc(msg_db_pool);
339 if (!msg) {
340 return NULL;
341 }
342
343 /* Clear message buffer before using it */
344 tfm_memset(msg, 0, sizeof(struct tfm_msg_body_t));
345
Ken Liu35f89392019-03-14 14:51:05 +0800346 tfm_event_init(&msg->ack_evnt);
Edison Ai764d41f2018-09-21 15:56:36 +0800347 msg->magic = TFM_MSG_MAGIC;
348 msg->service = service;
349 msg->handle = handle;
350 msg->caller_outvec = caller_outvec;
351 /* Get current partition id */
352 if (ns_caller) {
353 msg->msg.client_id = tfm_nspm_get_current_client_id();
354 } else {
Mingyang Sunf3d29892019-07-10 17:50:23 +0800355 msg->msg.client_id = tfm_spm_partition_get_running_partition_id();
Edison Ai764d41f2018-09-21 15:56:36 +0800356 }
357
358 /* Copy contents */
359 msg->msg.type = type;
360
361 for (i = 0; i < in_len; i++) {
362 msg->msg.in_size[i] = invec[i].len;
363 msg->invec[i].base = invec[i].base;
364 }
365
366 for (i = 0; i < out_len; i++) {
367 msg->msg.out_size[i] = outvec[i].len;
368 msg->outvec[i].base = outvec[i].base;
369 /* Out len is used to record the writed number, set 0 here again */
370 msg->outvec[i].len = 0;
371 }
372
373 /* Use message address as handle */
374 msg->msg.handle = (psa_handle_t)msg;
375
376 /* For connected handle, set rhandle to every message */
377 if (handle != PSA_NULL_HANDLE) {
378 msg->msg.rhandle = tfm_spm_get_rhandle(service, handle);
379 }
380
381 return msg;
382}
383
384void tfm_spm_free_msg(struct tfm_msg_body_t *msg)
385{
386 tfm_pool_free(msg);
387}
388
389int32_t tfm_spm_send_event(struct tfm_spm_service_t *service,
390 struct tfm_msg_body_t *msg)
391{
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800392 struct spm_partition_runtime_data_t *p_runtime_data =
393 &service->partition->runtime_data;
394
Edison Ai764d41f2018-09-21 15:56:36 +0800395 TFM_ASSERT(service);
396 TFM_ASSERT(msg);
397
398 /* Enqueue message to service message queue */
399 if (tfm_msg_enqueue(&service->msg_queue, msg) != IPC_SUCCESS) {
400 return IPC_ERROR_GENERIC;
401 }
402
403 /* Messages put. Update signals */
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800404 p_runtime_data->signals |= service->service_db->signal;
Edison Ai764d41f2018-09-21 15:56:36 +0800405
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800406 tfm_event_wake(&p_runtime_data->signal_evnt, (p_runtime_data->signals &
407 p_runtime_data->signal_mask));
Edison Ai764d41f2018-09-21 15:56:36 +0800408
Ken Liu35f89392019-03-14 14:51:05 +0800409 tfm_event_wait(&msg->ack_evnt);
Edison Ai764d41f2018-09-21 15:56:36 +0800410
411 return IPC_SUCCESS;
412}
413
Edison Ai7aff9e82019-07-11 14:56:46 +0800414uint32_t tfm_spm_partition_get_stack_bottom(uint32_t partition_idx)
415{
416 return g_spm_partition_db.partitions[partition_idx].
417 memory_data.stack_bottom;
418}
419
420uint32_t tfm_spm_partition_get_stack_top(uint32_t partition_idx)
421{
422 return g_spm_partition_db.partitions[partition_idx].memory_data.stack_top;
423}
424
Mingyang Sunf3d29892019-07-10 17:50:23 +0800425uint32_t tfm_spm_partition_get_running_partition_id(void)
Edison Ai764d41f2018-09-21 15:56:36 +0800426{
427 struct tfm_thrd_ctx *pth = tfm_thrd_curr_thread();
428 struct spm_partition_desc_t *partition;
429
430 partition = TFM_GET_CONTAINER_PTR(pth, struct spm_partition_desc_t,
431 sp_thrd);
432 return partition->static_data.partition_id;
433}
434
435static struct tfm_thrd_ctx *
Mingyang Sunf3d29892019-07-10 17:50:23 +0800436 tfm_spm_partition_get_thread_info(uint32_t partition_idx)
Edison Ai764d41f2018-09-21 15:56:36 +0800437{
438 return &g_spm_partition_db.partitions[partition_idx].sp_thrd;
439}
440
Edison Ai764d41f2018-09-21 15:56:36 +0800441static tfm_thrd_func_t
Mingyang Sunf3d29892019-07-10 17:50:23 +0800442 tfm_spm_partition_get_init_func(uint32_t partition_idx)
Edison Ai764d41f2018-09-21 15:56:36 +0800443{
444 return (tfm_thrd_func_t)(g_spm_partition_db.partitions[partition_idx].
445 static_data.partition_init);
446}
447
Mingyang Sunf3d29892019-07-10 17:50:23 +0800448static uint32_t tfm_spm_partition_get_priority(uint32_t partition_idx)
Edison Ai764d41f2018-09-21 15:56:36 +0800449{
450 return g_spm_partition_db.partitions[partition_idx].static_data.
451 partition_priority;
452}
453
David Hucb05d972019-08-06 18:10:11 +0800454int32_t tfm_memory_check(const void *buffer, size_t len, int32_t ns_caller,
Summer Qineb537e52019-03-29 09:57:10 +0800455 enum tfm_memory_access_e access,
456 uint32_t privileged)
Summer Qin2bfd2a02018-09-26 17:10:41 +0800457{
Hugues de Valon99578562019-06-18 16:08:51 +0100458 enum tfm_status_e err;
Summer Qin2bfd2a02018-09-26 17:10:41 +0800459
460 /* If len is zero, this indicates an empty buffer and base is ignored */
461 if (len == 0) {
462 return IPC_SUCCESS;
463 }
464
465 if (!buffer) {
466 return IPC_ERROR_BAD_PARAMETERS;
467 }
468
469 if ((uintptr_t)buffer > (UINTPTR_MAX - len)) {
470 return IPC_ERROR_MEMORY_CHECK;
471 }
472
Summer Qin424d4db2019-03-25 14:09:51 +0800473 if (access == TFM_MEMORY_ACCESS_RW) {
Summer Qineb537e52019-03-29 09:57:10 +0800474 err = tfm_core_has_write_access_to_region(buffer, len, ns_caller,
475 privileged);
Summer Qin2bfd2a02018-09-26 17:10:41 +0800476 } else {
Summer Qineb537e52019-03-29 09:57:10 +0800477 err = tfm_core_has_read_access_to_region(buffer, len, ns_caller,
478 privileged);
Summer Qin424d4db2019-03-25 14:09:51 +0800479 }
Summer Qin0fc3f592019-04-11 16:00:10 +0800480 if (err == TFM_SUCCESS) {
Summer Qin424d4db2019-03-25 14:09:51 +0800481 return IPC_SUCCESS;
Summer Qin2bfd2a02018-09-26 17:10:41 +0800482 }
483
484 return IPC_ERROR_MEMORY_CHECK;
485}
486
Summer Qineb537e52019-03-29 09:57:10 +0800487uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_idx)
488{
489 if (tfm_spm_partition_get_flags(partition_idx) & SPM_PART_FLAG_PSA_ROT) {
490 return TFM_PARTITION_PRIVILEGED_MODE;
491 } else {
492 return TFM_PARTITION_UNPRIVILEGED_MODE;
493 }
494}
495
Edison Ai764d41f2018-09-21 15:56:36 +0800496/********************** SPM functions for thread mode ************************/
497
498void tfm_spm_init(void)
499{
500 uint32_t i, num;
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800501 struct spm_partition_desc_t *partition;
Edison Ai764d41f2018-09-21 15:56:36 +0800502 struct tfm_spm_service_t *service;
Ken Liu483f5da2019-04-24 10:45:21 +0800503 struct tfm_thrd_ctx *pth, this_thrd;
Edison Ai764d41f2018-09-21 15:56:36 +0800504
505 tfm_pool_init(conn_handle_pool,
506 POOL_BUFFER_SIZE(conn_handle_pool),
507 sizeof(struct tfm_conn_handle_t),
508 TFM_CONN_HANDLE_MAX_NUM);
509 tfm_pool_init(spm_service_pool, POOL_BUFFER_SIZE(spm_service_pool),
510 sizeof(struct tfm_spm_service_t),
511 TFM_SPM_MAX_ROT_SERV_NUM);
512 tfm_pool_init(msg_db_pool, POOL_BUFFER_SIZE(msg_db_pool),
513 sizeof(struct tfm_msg_body_t),
514 TFM_MSG_QUEUE_MAX_MSG_NUM);
515
516 /* Init partition first for it will be used when init service */
Mate Toth-Pal3ad2e3e2019-07-11 21:43:37 +0200517 for (i = 0; i < g_spm_partition_db.partition_count; i++) {
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800518 partition = &g_spm_partition_db.partitions[i];
519 tfm_spm_hal_configure_default_isolation(partition->platform_data);
520 partition->static_data.index = i;
Edison Ai764d41f2018-09-21 15:56:36 +0800521 if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) {
522 continue;
523 }
Ken Liu35f89392019-03-14 14:51:05 +0800524
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800525 tfm_event_init(&partition->runtime_data.signal_evnt);
526 tfm_list_init(&partition->runtime_data.service_list);
Edison Ai764d41f2018-09-21 15:56:36 +0800527
Mingyang Sunf3d29892019-07-10 17:50:23 +0800528 pth = tfm_spm_partition_get_thread_info(i);
Edison Ai764d41f2018-09-21 15:56:36 +0800529 if (!pth) {
530 tfm_panic();
531 }
532
533 tfm_thrd_init(pth,
Mingyang Sunf3d29892019-07-10 17:50:23 +0800534 tfm_spm_partition_get_init_func(i),
Edison Ai764d41f2018-09-21 15:56:36 +0800535 NULL,
Edison Ai788bae22019-02-18 17:38:59 +0800536 (uint8_t *)tfm_spm_partition_get_stack_top(i),
537 (uint8_t *)tfm_spm_partition_get_stack_bottom(i));
Edison Ai788bae22019-02-18 17:38:59 +0800538
Mingyang Sunf3d29892019-07-10 17:50:23 +0800539 pth->prior = tfm_spm_partition_get_priority(i);
Edison Ai764d41f2018-09-21 15:56:36 +0800540
541 /* Kick off */
542 if (tfm_thrd_start(pth) != THRD_SUCCESS) {
543 tfm_panic();
544 }
545 }
546
547 /* Init Service */
548 num = sizeof(g_spm_service_db) / sizeof(struct tfm_spm_service_db_t);
549 for (i = 0; i < num; i++) {
550 partition =
551 tfm_spm_get_partition_by_id(g_spm_service_db[i].partition_id);
552 if (!partition) {
553 tfm_panic();
554 }
555 service = (struct tfm_spm_service_t *)tfm_pool_alloc(spm_service_pool);
556 if (!service) {
557 tfm_panic();
558 }
559 service->service_db = &g_spm_service_db[i];
560 service->partition = partition;
561 tfm_list_init(&service->handle_list);
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800562 tfm_list_add_tail(&partition->runtime_data.service_list,
563 &service->list);
Edison Ai764d41f2018-09-21 15:56:36 +0800564 }
565
Ken Liu483f5da2019-04-24 10:45:21 +0800566 /*
567 * All threads initialized, start the scheduler.
568 *
569 * NOTE:
570 * Here is the booting privileged thread mode, and will never
571 * return to this place after scheduler is started. The start
572 * function has to save current runtime context to act as a
573 * 'current thread' to avoid repeating NULL 'current thread'
574 * checking while context switching. This saved context is worthy
575 * of being saved somewhere if there are potential usage purpose.
576 * Let's save this context in a local variable 'this_thrd' at
577 * current since there is no usage for it.
Mate Toth-Palc430b992019-05-09 21:01:14 +0200578 * Also set tfm_nspm_thread_entry as pfn for this thread to
579 * use in detecting NS/S thread scheduling changes.
Ken Liu483f5da2019-04-24 10:45:21 +0800580 */
Mate Toth-Palc430b992019-05-09 21:01:14 +0200581 this_thrd.pfn = (tfm_thrd_func_t)tfm_nspm_thread_entry;
Ken Liu483f5da2019-04-24 10:45:21 +0800582 tfm_thrd_start_scheduler(&this_thrd);
Edison Ai764d41f2018-09-21 15:56:36 +0800583}
Ken Liu2d175172019-03-21 17:08:41 +0800584
585void tfm_pendsv_do_schedule(struct tfm_state_context_ext *ctxb)
586{
587#if TFM_LVL == 2
588 struct spm_partition_desc_t *p_next_partition;
589 uint32_t is_privileged;
590#endif
591 struct tfm_thrd_ctx *pth_next = tfm_thrd_next_thread();
592 struct tfm_thrd_ctx *pth_curr = tfm_thrd_curr_thread();
593
Mate Toth-Pal32b2ccd2019-04-26 10:00:16 +0200594 if (pth_next != NULL && pth_curr != pth_next) {
Ken Liu2d175172019-03-21 17:08:41 +0800595#if TFM_LVL == 2
596 p_next_partition = TFM_GET_CONTAINER_PTR(pth_next,
597 struct spm_partition_desc_t,
598 sp_thrd);
599
600 if (p_next_partition->static_data.partition_flags &
601 SPM_PART_FLAG_PSA_ROT) {
602 is_privileged = TFM_PARTITION_PRIVILEGED_MODE;
603 } else {
604 is_privileged = TFM_PARTITION_UNPRIVILEGED_MODE;
605 }
606
607 tfm_spm_partition_change_privilege(is_privileged);
608#endif
Mate Toth-Palc430b992019-05-09 21:01:14 +0200609 /* Increase the secure lock, if we enter secure from non-secure */
610 if ((void *)pth_curr->pfn == (void *)tfm_nspm_thread_entry) {
611 ++tfm_secure_lock;
612 }
613 /* Decrease the secure lock, if we return from secure to non-secure */
614 if ((void *)pth_next->pfn == (void *)tfm_nspm_thread_entry) {
615 --tfm_secure_lock;
616 }
617
Ken Liu2d175172019-03-21 17:08:41 +0800618 tfm_thrd_context_switch(ctxb, pth_curr, pth_next);
619 }
620}