blob: 6443b524257e9121eeaac89acb89e92ecb28d54f [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"
Edison Ai764d41f2018-09-21 15:56:36 +080020#include "tfm_internal_defines.h"
21#include "tfm_wait.h"
22#include "tfm_message_queue.h"
23#include "tfm_list.h"
24#include "tfm_pools.h"
Edison Ai764d41f2018-09-21 15:56:36 +080025#include "tfm_thread.h"
Summer Qin2bfd2a02018-09-26 17:10:41 +080026#include "region_defs.h"
Edison Ai764d41f2018-09-21 15:56:36 +080027#include "tfm_nspm.h"
Edison Ai807fedb2019-03-07 11:22:03 +080028#include "tfm_memory_utils.h"
Edison Ai764d41f2018-09-21 15:56:36 +080029
Edison Ai764d41f2018-09-21 15:56:36 +080030/* Extern SPM variable */
31extern struct spm_partition_db_t g_spm_partition_db;
32
Mate Toth-Palc430b992019-05-09 21:01:14 +020033/* Extern secure lock variable */
34extern int32_t tfm_secure_lock;
Mingyang Sunf3d29892019-07-10 17:50:23 +080035
Edison Ai764d41f2018-09-21 15:56:36 +080036/* Pools */
37TFM_POOL_DECLARE(conn_handle_pool, sizeof(struct tfm_conn_handle_t),
38 TFM_CONN_HANDLE_MAX_NUM);
39TFM_POOL_DECLARE(spm_service_pool, sizeof(struct tfm_spm_service_t),
40 TFM_SPM_MAX_ROT_SERV_NUM);
41TFM_POOL_DECLARE(msg_db_pool, sizeof(struct tfm_msg_body_t),
42 TFM_MSG_QUEUE_MAX_MSG_NUM);
43
44static struct tfm_spm_service_db_t g_spm_service_db[] = {
45 #include "secure_fw/services/tfm_service_list.inc"
46};
47
48/********************** SPM functions for handler mode ***********************/
49
50/* Service handle management functions */
51psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service)
52{
53 struct tfm_conn_handle_t *node;
54
55 TFM_ASSERT(service);
56
57 /* Get buffer for handle list structure from handle pool */
58 node = (struct tfm_conn_handle_t *)tfm_pool_alloc(conn_handle_pool);
59 if (!node) {
60 return PSA_NULL_HANDLE;
61 }
62
63 /* Global unique handle, use handle buffer address directly */
64 node->handle = (psa_handle_t)node;
65
66 /* Add handle node to list for next psa functions */
67 tfm_list_add_tail(&service->handle_list, &node->list);
68
69 return node->handle;
70}
71
72static struct tfm_conn_handle_t *
Mingyang Sun5e13aa72019-07-10 10:30:16 +080073 tfm_spm_find_conn_handle_node(struct tfm_spm_service_t *service,
74 psa_handle_t conn_handle)
Edison Ai764d41f2018-09-21 15:56:36 +080075{
76 struct tfm_conn_handle_t *handle_node;
77 struct tfm_list_node_t *node, *head;
78
79 TFM_ASSERT(service);
80
81 head = &service->handle_list;
82 TFM_LIST_FOR_EACH(node, head) {
83 handle_node = TFM_GET_CONTAINER_PTR(node, struct tfm_conn_handle_t,
84 list);
85 if (handle_node->handle == conn_handle) {
86 return handle_node;
87 }
88 }
89 return NULL;
90}
91
92int32_t tfm_spm_free_conn_handle(struct tfm_spm_service_t *service,
93 psa_handle_t conn_handle)
94{
95 struct tfm_conn_handle_t *node;
96
97 TFM_ASSERT(service);
98
99 /* There are many handles for each RoT Service */
100 node = tfm_spm_find_conn_handle_node(service, conn_handle);
101 if (!node) {
102 tfm_panic();
103 }
104
105 /* Remove node from handle list */
106 tfm_list_del_node(&node->list);
107
108 /* Back handle buffer to pool */
109 tfm_pool_free(node);
110 return IPC_SUCCESS;
111}
112
113int32_t tfm_spm_set_rhandle(struct tfm_spm_service_t *service,
114 psa_handle_t conn_handle,
115 void *rhandle)
116{
117 struct tfm_conn_handle_t *node;
118
119 TFM_ASSERT(service);
120 /* Set reverse handle value only be allowed for a connected handle */
121 TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
122
123 /* There are many handles for each RoT Service */
124 node = tfm_spm_find_conn_handle_node(service, conn_handle);
125 if (!node) {
126 tfm_panic();
127 }
128
129 node->rhandle = rhandle;
130 return IPC_SUCCESS;
131}
132
133void *tfm_spm_get_rhandle(struct tfm_spm_service_t *service,
134 psa_handle_t conn_handle)
135{
136 struct tfm_conn_handle_t *node;
137
138 TFM_ASSERT(service);
139 /* Get reverse handle value only be allowed for a connected handle */
140 TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
141
142 /* There are many handles for each RoT Service */
143 node = tfm_spm_find_conn_handle_node(service, conn_handle);
144 if (!node) {
145 tfm_panic();
146 }
147
148 return node->rhandle;
149}
150
151/* Partition management functions */
152struct tfm_spm_service_t *
Mingyang Sunf3d29892019-07-10 17:50:23 +0800153 tfm_spm_get_service_by_signal(struct spm_partition_desc_t *partition,
154 psa_signal_t signal)
Edison Ai764d41f2018-09-21 15:56:36 +0800155{
156 struct tfm_list_node_t *node, *head;
157 struct tfm_spm_service_t *service;
158
159 TFM_ASSERT(partition);
160
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800161 if (tfm_list_is_empty(&partition->runtime_data.service_list)) {
Edison Ai764d41f2018-09-21 15:56:36 +0800162 tfm_panic();
163 }
164
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800165 head = &partition->runtime_data.service_list;
Edison Ai764d41f2018-09-21 15:56:36 +0800166 TFM_LIST_FOR_EACH(node, head) {
167 service = TFM_GET_CONTAINER_PTR(node, struct tfm_spm_service_t, list);
168 if (service->service_db->signal == signal) {
169 return service;
170 }
171 }
172 return NULL;
173}
174
175struct tfm_spm_service_t *tfm_spm_get_service_by_sid(uint32_t sid)
176{
177 uint32_t i;
178 struct tfm_list_node_t *node, *head;
179 struct tfm_spm_service_t *service;
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800180 struct spm_partition_desc_t *partition;
Edison Ai764d41f2018-09-21 15:56:36 +0800181
Mate Toth-Pal3ad2e3e2019-07-11 21:43:37 +0200182 for (i = 0; i < g_spm_partition_db.partition_count; i++) {
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800183 partition = &g_spm_partition_db.partitions[i];
Edison Ai764d41f2018-09-21 15:56:36 +0800184 /* Skip partition without IPC flag */
Mingyang Sunf3d29892019-07-10 17:50:23 +0800185 if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) {
Edison Ai764d41f2018-09-21 15:56:36 +0800186 continue;
187 }
188
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800189 if (tfm_list_is_empty(&partition->runtime_data.service_list)) {
Edison Ai764d41f2018-09-21 15:56:36 +0800190 continue;
191 }
192
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800193 head = &partition->runtime_data.service_list;
Edison Ai764d41f2018-09-21 15:56:36 +0800194 TFM_LIST_FOR_EACH(node, head) {
195 service = TFM_GET_CONTAINER_PTR(node, struct tfm_spm_service_t,
196 list);
197 if (service->service_db->sid == sid) {
198 return service;
199 }
200 }
201 }
202 return NULL;
203}
204
205struct tfm_spm_service_t *
206 tfm_spm_get_service_by_handle(psa_handle_t conn_handle)
207{
208 uint32_t i;
209 struct tfm_conn_handle_t *handle;
210 struct tfm_list_node_t *service_node, *service_head;
211 struct tfm_list_node_t *handle_node, *handle_head;
212 struct tfm_spm_service_t *service;
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800213 struct spm_partition_desc_t *partition;
Edison Ai764d41f2018-09-21 15:56:36 +0800214
Mate Toth-Pal3ad2e3e2019-07-11 21:43:37 +0200215 for (i = 0; i < g_spm_partition_db.partition_count; i++) {
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800216 partition = &g_spm_partition_db.partitions[i];
Edison Ai764d41f2018-09-21 15:56:36 +0800217 /* Skip partition without IPC flag */
Mingyang Sunf3d29892019-07-10 17:50:23 +0800218 if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) {
Edison Ai764d41f2018-09-21 15:56:36 +0800219 continue;
220 }
221
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800222 if (tfm_list_is_empty(&partition->runtime_data.service_list)) {
Edison Ai764d41f2018-09-21 15:56:36 +0800223 continue;
224 }
225
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800226 service_head = &partition->runtime_data.service_list;
Edison Ai764d41f2018-09-21 15:56:36 +0800227 TFM_LIST_FOR_EACH(service_node, service_head) {
228 service = TFM_GET_CONTAINER_PTR(service_node,
229 struct tfm_spm_service_t, list);
230 handle_head = &service->handle_list;
231 TFM_LIST_FOR_EACH(handle_node, handle_head) {
232 handle = TFM_GET_CONTAINER_PTR(handle_node,
233 struct tfm_conn_handle_t, list);
234 if (handle->handle == conn_handle) {
235 return service;
236 }
237 }
238 }
239 }
240 return NULL;
241}
242
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800243struct spm_partition_desc_t *tfm_spm_get_partition_by_id(int32_t partition_id)
Edison Ai764d41f2018-09-21 15:56:36 +0800244{
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800245 uint32_t idx = get_partition_idx(partition_id);
Edison Ai764d41f2018-09-21 15:56:36 +0800246
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800247 if (idx != SPM_INVALID_PARTITION_IDX) {
248 return &(g_spm_partition_db.partitions[idx]);
Edison Ai764d41f2018-09-21 15:56:36 +0800249 }
250 return NULL;
251}
252
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800253struct spm_partition_desc_t *tfm_spm_get_running_partition(void)
Edison Ai764d41f2018-09-21 15:56:36 +0800254{
255 uint32_t spid;
256
Mingyang Sunf3d29892019-07-10 17:50:23 +0800257 spid = tfm_spm_partition_get_running_partition_id();
Edison Ai764d41f2018-09-21 15:56:36 +0800258
259 return tfm_spm_get_partition_by_id(spid);
260}
261
262int32_t tfm_spm_check_client_version(struct tfm_spm_service_t *service,
263 uint32_t minor_version)
264{
265 TFM_ASSERT(service);
266
267 switch (service->service_db->minor_policy) {
268 case TFM_VERSION_POLICY_RELAXED:
Oren Cohen665d8322019-04-28 14:24:40 +0300269 if (minor_version > service->service_db->minor_version) {
Edison Ai764d41f2018-09-21 15:56:36 +0800270 return IPC_ERROR_VERSION;
271 }
272 break;
273 case TFM_VERSION_POLICY_STRICT:
274 if (minor_version != service->service_db->minor_version) {
275 return IPC_ERROR_VERSION;
276 }
277 break;
278 default:
279 return IPC_ERROR_VERSION;
280 }
281 return IPC_SUCCESS;
282}
283
284/* Message functions */
285struct tfm_msg_body_t *tfm_spm_get_msg_from_handle(psa_handle_t msg_handle)
286{
287 /*
288 * There may be one error handle passed by the caller in two conditions:
289 * 1. Not a valid message handle.
290 * 2. Handle between different Partitions. Partition A passes one handle
291 * belong to other Partitions and tries to access other's data.
292 * So, need do necessary checking to prevent those conditions.
293 */
294 struct tfm_msg_body_t *msg;
295 uint32_t partition_id;
296
297 msg = (struct tfm_msg_body_t *)msg_handle;
298 if (!msg) {
299 return NULL;
300 }
301
302 /*
303 * FixMe: For condition 1: using a magic number to define it's a message.
304 * It needs to be an enhancement to check the handle belong to service.
305 */
306 if (msg->magic != TFM_MSG_MAGIC) {
307 return NULL;
308 }
309
310 /* For condition 2: check if the partition ID is same */
Mingyang Sunf3d29892019-07-10 17:50:23 +0800311 partition_id = tfm_spm_partition_get_running_partition_id();
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800312 if (partition_id != msg->service->partition->static_data.partition_id) {
Edison Ai764d41f2018-09-21 15:56:36 +0800313 return NULL;
314 }
315
316 return msg;
317}
318
319struct tfm_msg_body_t *tfm_spm_create_msg(struct tfm_spm_service_t *service,
320 psa_handle_t handle,
Summer Qin632b3e02019-07-29 15:34:38 +0800321 int32_t type, int32_t ns_caller,
Edison Ai764d41f2018-09-21 15:56:36 +0800322 psa_invec *invec, size_t in_len,
323 psa_outvec *outvec, size_t out_len,
324 psa_outvec *caller_outvec)
325{
326 struct tfm_msg_body_t *msg = NULL;
327 uint32_t i;
328
329 TFM_ASSERT(service);
330 TFM_ASSERT(!(invec == NULL && in_len != 0));
331 TFM_ASSERT(!(outvec == NULL && out_len != 0));
332 TFM_ASSERT(in_len <= PSA_MAX_IOVEC);
333 TFM_ASSERT(out_len <= PSA_MAX_IOVEC);
334 TFM_ASSERT(in_len + out_len <= PSA_MAX_IOVEC);
335
336 /* Get message buffer from message pool */
337 msg = (struct tfm_msg_body_t *)tfm_pool_alloc(msg_db_pool);
338 if (!msg) {
339 return NULL;
340 }
341
342 /* Clear message buffer before using it */
343 tfm_memset(msg, 0, sizeof(struct tfm_msg_body_t));
344
Ken Liu35f89392019-03-14 14:51:05 +0800345 tfm_event_init(&msg->ack_evnt);
Edison Ai764d41f2018-09-21 15:56:36 +0800346 msg->magic = TFM_MSG_MAGIC;
347 msg->service = service;
348 msg->handle = handle;
349 msg->caller_outvec = caller_outvec;
350 /* Get current partition id */
351 if (ns_caller) {
352 msg->msg.client_id = tfm_nspm_get_current_client_id();
353 } else {
Mingyang Sunf3d29892019-07-10 17:50:23 +0800354 msg->msg.client_id = tfm_spm_partition_get_running_partition_id();
Edison Ai764d41f2018-09-21 15:56:36 +0800355 }
356
357 /* Copy contents */
358 msg->msg.type = type;
359
360 for (i = 0; i < in_len; i++) {
361 msg->msg.in_size[i] = invec[i].len;
362 msg->invec[i].base = invec[i].base;
363 }
364
365 for (i = 0; i < out_len; i++) {
366 msg->msg.out_size[i] = outvec[i].len;
367 msg->outvec[i].base = outvec[i].base;
368 /* Out len is used to record the writed number, set 0 here again */
369 msg->outvec[i].len = 0;
370 }
371
372 /* Use message address as handle */
373 msg->msg.handle = (psa_handle_t)msg;
374
375 /* For connected handle, set rhandle to every message */
376 if (handle != PSA_NULL_HANDLE) {
377 msg->msg.rhandle = tfm_spm_get_rhandle(service, handle);
378 }
379
380 return msg;
381}
382
383void tfm_spm_free_msg(struct tfm_msg_body_t *msg)
384{
385 tfm_pool_free(msg);
386}
387
388int32_t tfm_spm_send_event(struct tfm_spm_service_t *service,
389 struct tfm_msg_body_t *msg)
390{
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800391 struct spm_partition_runtime_data_t *p_runtime_data =
392 &service->partition->runtime_data;
393
Edison Ai764d41f2018-09-21 15:56:36 +0800394 TFM_ASSERT(service);
395 TFM_ASSERT(msg);
396
397 /* Enqueue message to service message queue */
398 if (tfm_msg_enqueue(&service->msg_queue, msg) != IPC_SUCCESS) {
399 return IPC_ERROR_GENERIC;
400 }
401
402 /* Messages put. Update signals */
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800403 p_runtime_data->signals |= service->service_db->signal;
Edison Ai764d41f2018-09-21 15:56:36 +0800404
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800405 tfm_event_wake(&p_runtime_data->signal_evnt, (p_runtime_data->signals &
406 p_runtime_data->signal_mask));
Edison Ai764d41f2018-09-21 15:56:36 +0800407
Ken Liu35f89392019-03-14 14:51:05 +0800408 tfm_event_wait(&msg->ack_evnt);
Edison Ai764d41f2018-09-21 15:56:36 +0800409
410 return IPC_SUCCESS;
411}
412
413/* SPM extend functions */
Mingyang Sunf3d29892019-07-10 17:50:23 +0800414uint32_t tfm_spm_partition_get_running_partition_id(void)
Edison Ai764d41f2018-09-21 15:56:36 +0800415{
416 struct tfm_thrd_ctx *pth = tfm_thrd_curr_thread();
417 struct spm_partition_desc_t *partition;
418
419 partition = TFM_GET_CONTAINER_PTR(pth, struct spm_partition_desc_t,
420 sp_thrd);
421 return partition->static_data.partition_id;
422}
423
424static struct tfm_thrd_ctx *
Mingyang Sunf3d29892019-07-10 17:50:23 +0800425 tfm_spm_partition_get_thread_info(uint32_t partition_idx)
Edison Ai764d41f2018-09-21 15:56:36 +0800426{
427 return &g_spm_partition_db.partitions[partition_idx].sp_thrd;
428}
429
Edison Ai764d41f2018-09-21 15:56:36 +0800430static tfm_thrd_func_t
Mingyang Sunf3d29892019-07-10 17:50:23 +0800431 tfm_spm_partition_get_init_func(uint32_t partition_idx)
Edison Ai764d41f2018-09-21 15:56:36 +0800432{
433 return (tfm_thrd_func_t)(g_spm_partition_db.partitions[partition_idx].
434 static_data.partition_init);
435}
436
Mingyang Sunf3d29892019-07-10 17:50:23 +0800437static uint32_t tfm_spm_partition_get_priority(uint32_t partition_idx)
Edison Ai764d41f2018-09-21 15:56:36 +0800438{
439 return g_spm_partition_db.partitions[partition_idx].static_data.
440 partition_priority;
441}
442
Summer Qin424d4db2019-03-25 14:09:51 +0800443int32_t tfm_memory_check(void *buffer, size_t len, int32_t ns_caller,
Summer Qineb537e52019-03-29 09:57:10 +0800444 enum tfm_memory_access_e access,
445 uint32_t privileged)
Summer Qin2bfd2a02018-09-26 17:10:41 +0800446{
Hugues de Valon99578562019-06-18 16:08:51 +0100447 enum tfm_status_e err;
Summer Qin2bfd2a02018-09-26 17:10:41 +0800448
449 /* If len is zero, this indicates an empty buffer and base is ignored */
450 if (len == 0) {
451 return IPC_SUCCESS;
452 }
453
454 if (!buffer) {
455 return IPC_ERROR_BAD_PARAMETERS;
456 }
457
458 if ((uintptr_t)buffer > (UINTPTR_MAX - len)) {
459 return IPC_ERROR_MEMORY_CHECK;
460 }
461
Summer Qin424d4db2019-03-25 14:09:51 +0800462 if (access == TFM_MEMORY_ACCESS_RW) {
Summer Qineb537e52019-03-29 09:57:10 +0800463 err = tfm_core_has_write_access_to_region(buffer, len, ns_caller,
464 privileged);
Summer Qin2bfd2a02018-09-26 17:10:41 +0800465 } else {
Summer Qineb537e52019-03-29 09:57:10 +0800466 err = tfm_core_has_read_access_to_region(buffer, len, ns_caller,
467 privileged);
Summer Qin424d4db2019-03-25 14:09:51 +0800468 }
Summer Qin0fc3f592019-04-11 16:00:10 +0800469 if (err == TFM_SUCCESS) {
Summer Qin424d4db2019-03-25 14:09:51 +0800470 return IPC_SUCCESS;
Summer Qin2bfd2a02018-09-26 17:10:41 +0800471 }
472
473 return IPC_ERROR_MEMORY_CHECK;
474}
475
Summer Qineb537e52019-03-29 09:57:10 +0800476uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_idx)
477{
478 if (tfm_spm_partition_get_flags(partition_idx) & SPM_PART_FLAG_PSA_ROT) {
479 return TFM_PARTITION_PRIVILEGED_MODE;
480 } else {
481 return TFM_PARTITION_UNPRIVILEGED_MODE;
482 }
483}
484
Edison Ai764d41f2018-09-21 15:56:36 +0800485/********************** SPM functions for thread mode ************************/
486
487void tfm_spm_init(void)
488{
489 uint32_t i, num;
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800490 struct spm_partition_desc_t *partition;
Edison Ai764d41f2018-09-21 15:56:36 +0800491 struct tfm_spm_service_t *service;
Ken Liu483f5da2019-04-24 10:45:21 +0800492 struct tfm_thrd_ctx *pth, this_thrd;
Edison Ai764d41f2018-09-21 15:56:36 +0800493
494 tfm_pool_init(conn_handle_pool,
495 POOL_BUFFER_SIZE(conn_handle_pool),
496 sizeof(struct tfm_conn_handle_t),
497 TFM_CONN_HANDLE_MAX_NUM);
498 tfm_pool_init(spm_service_pool, POOL_BUFFER_SIZE(spm_service_pool),
499 sizeof(struct tfm_spm_service_t),
500 TFM_SPM_MAX_ROT_SERV_NUM);
501 tfm_pool_init(msg_db_pool, POOL_BUFFER_SIZE(msg_db_pool),
502 sizeof(struct tfm_msg_body_t),
503 TFM_MSG_QUEUE_MAX_MSG_NUM);
504
505 /* Init partition first for it will be used when init service */
Mate Toth-Pal3ad2e3e2019-07-11 21:43:37 +0200506 for (i = 0; i < g_spm_partition_db.partition_count; i++) {
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800507 partition = &g_spm_partition_db.partitions[i];
508 tfm_spm_hal_configure_default_isolation(partition->platform_data);
509 partition->static_data.index = i;
Edison Ai764d41f2018-09-21 15:56:36 +0800510 if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) {
511 continue;
512 }
Ken Liu35f89392019-03-14 14:51:05 +0800513
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800514 tfm_event_init(&partition->runtime_data.signal_evnt);
515 tfm_list_init(&partition->runtime_data.service_list);
Edison Ai764d41f2018-09-21 15:56:36 +0800516
Mingyang Sunf3d29892019-07-10 17:50:23 +0800517 pth = tfm_spm_partition_get_thread_info(i);
Edison Ai764d41f2018-09-21 15:56:36 +0800518 if (!pth) {
519 tfm_panic();
520 }
521
522 tfm_thrd_init(pth,
Mingyang Sunf3d29892019-07-10 17:50:23 +0800523 tfm_spm_partition_get_init_func(i),
Edison Ai764d41f2018-09-21 15:56:36 +0800524 NULL,
Edison Ai788bae22019-02-18 17:38:59 +0800525 (uint8_t *)tfm_spm_partition_get_stack_top(i),
526 (uint8_t *)tfm_spm_partition_get_stack_bottom(i));
Edison Ai788bae22019-02-18 17:38:59 +0800527
Mingyang Sunf3d29892019-07-10 17:50:23 +0800528 pth->prior = tfm_spm_partition_get_priority(i);
Edison Ai764d41f2018-09-21 15:56:36 +0800529
530 /* Kick off */
531 if (tfm_thrd_start(pth) != THRD_SUCCESS) {
532 tfm_panic();
533 }
534 }
535
536 /* Init Service */
537 num = sizeof(g_spm_service_db) / sizeof(struct tfm_spm_service_db_t);
538 for (i = 0; i < num; i++) {
539 partition =
540 tfm_spm_get_partition_by_id(g_spm_service_db[i].partition_id);
541 if (!partition) {
542 tfm_panic();
543 }
544 service = (struct tfm_spm_service_t *)tfm_pool_alloc(spm_service_pool);
545 if (!service) {
546 tfm_panic();
547 }
548 service->service_db = &g_spm_service_db[i];
549 service->partition = partition;
550 tfm_list_init(&service->handle_list);
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800551 tfm_list_add_tail(&partition->runtime_data.service_list,
552 &service->list);
Edison Ai764d41f2018-09-21 15:56:36 +0800553 }
554
Ken Liu483f5da2019-04-24 10:45:21 +0800555 /*
556 * All threads initialized, start the scheduler.
557 *
558 * NOTE:
559 * Here is the booting privileged thread mode, and will never
560 * return to this place after scheduler is started. The start
561 * function has to save current runtime context to act as a
562 * 'current thread' to avoid repeating NULL 'current thread'
563 * checking while context switching. This saved context is worthy
564 * of being saved somewhere if there are potential usage purpose.
565 * Let's save this context in a local variable 'this_thrd' at
566 * current since there is no usage for it.
Mate Toth-Palc430b992019-05-09 21:01:14 +0200567 * Also set tfm_nspm_thread_entry as pfn for this thread to
568 * use in detecting NS/S thread scheduling changes.
Ken Liu483f5da2019-04-24 10:45:21 +0800569 */
Mate Toth-Palc430b992019-05-09 21:01:14 +0200570 this_thrd.pfn = (tfm_thrd_func_t)tfm_nspm_thread_entry;
Ken Liu483f5da2019-04-24 10:45:21 +0800571 tfm_thrd_start_scheduler(&this_thrd);
Edison Ai764d41f2018-09-21 15:56:36 +0800572}
Ken Liu2d175172019-03-21 17:08:41 +0800573
574void tfm_pendsv_do_schedule(struct tfm_state_context_ext *ctxb)
575{
576#if TFM_LVL == 2
577 struct spm_partition_desc_t *p_next_partition;
578 uint32_t is_privileged;
579#endif
580 struct tfm_thrd_ctx *pth_next = tfm_thrd_next_thread();
581 struct tfm_thrd_ctx *pth_curr = tfm_thrd_curr_thread();
582
Mate Toth-Pal32b2ccd2019-04-26 10:00:16 +0200583 if (pth_next != NULL && pth_curr != pth_next) {
Ken Liu2d175172019-03-21 17:08:41 +0800584#if TFM_LVL == 2
585 p_next_partition = TFM_GET_CONTAINER_PTR(pth_next,
586 struct spm_partition_desc_t,
587 sp_thrd);
588
589 if (p_next_partition->static_data.partition_flags &
590 SPM_PART_FLAG_PSA_ROT) {
591 is_privileged = TFM_PARTITION_PRIVILEGED_MODE;
592 } else {
593 is_privileged = TFM_PARTITION_UNPRIVILEGED_MODE;
594 }
595
596 tfm_spm_partition_change_privilege(is_privileged);
597#endif
Mate Toth-Palc430b992019-05-09 21:01:14 +0200598 /* Increase the secure lock, if we enter secure from non-secure */
599 if ((void *)pth_curr->pfn == (void *)tfm_nspm_thread_entry) {
600 ++tfm_secure_lock;
601 }
602 /* Decrease the secure lock, if we return from secure to non-secure */
603 if ((void *)pth_next->pfn == (void *)tfm_nspm_thread_entry) {
604 --tfm_secure_lock;
605 }
606
Ken Liu2d175172019-03-21 17:08:41 +0800607 tfm_thrd_context_switch(ctxb, pth_curr, pth_next);
608 }
609}