blob: 1d66e256f5ca69ae76014ca88962655575097b07 [file] [log] [blame]
Ken Liu91d44da2018-09-20 22:42:31 +08001/*
Summer Qin66f1e032020-01-06 15:40:03 +08002 * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
Ken Liu91d44da2018-09-20 22:42:31 +08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7#include <inttypes.h>
David Hu50711e32019-06-12 18:32:30 +08008#include "tfm_arch.h"
Ken Liu91d44da2018-09-20 22:42:31 +08009#include "tfm_thread.h"
10#include "tfm_utils.h"
Edison Ai807fedb2019-03-07 11:22:03 +080011#include "tfm_memory_utils.h"
Ken Liu1f345b02020-05-30 21:11:05 +080012#include "tfm/tfm_core_svc.h"
13#include "tfm/spm_api.h"
Mingyang Sun94b1b412019-09-20 15:11:14 +080014#include "tfm_core_utils.h"
Ken Liu91d44da2018-09-20 22:42:31 +080015
16/* Force ZERO in case ZI(bss) clear is missing */
Summer Qin66f1e032020-01-06 15:40:03 +080017static struct tfm_core_thread_t *p_thrd_head = NULL;
18static struct tfm_core_thread_t *p_runn_head = NULL;
19static struct tfm_core_thread_t *p_curr_thrd = NULL;
Ken Liu91d44da2018-09-20 22:42:31 +080020
21/* Define Macro to fetch global to support future expansion (PERCPU e.g.) */
22#define LIST_HEAD p_thrd_head
23#define RUNN_HEAD p_runn_head
24#define CURR_THRD p_curr_thrd
25
Summer Qin66f1e032020-01-06 15:40:03 +080026static struct tfm_core_thread_t *find_next_running_thread(
27 struct tfm_core_thread_t *pth)
Ken Liu91d44da2018-09-20 22:42:31 +080028{
Summer Qin66f1e032020-01-06 15:40:03 +080029 while (pth && pth->state != THRD_STATE_RUNNING) {
Ken Liu91d44da2018-09-20 22:42:31 +080030 pth = pth->next;
31 }
32
33 return pth;
34}
35
Mate Toth-Pal82cc07c2019-01-30 14:04:13 +010036/* To get next running thread for scheduler */
Summer Qin66f1e032020-01-06 15:40:03 +080037struct tfm_core_thread_t *tfm_core_thrd_get_next_thread(void)
Mate Toth-Pal82cc07c2019-01-30 14:04:13 +010038{
39 /*
40 * First RUNNING thread has highest priority since threads are sorted with
41 * priority.
42 */
43 return find_next_running_thread(RUNN_HEAD);
44}
45
Ken Liu91d44da2018-09-20 22:42:31 +080046/* To get current thread for caller */
Summer Qin66f1e032020-01-06 15:40:03 +080047struct tfm_core_thread_t *tfm_core_thrd_get_curr_thread(void)
Ken Liu91d44da2018-09-20 22:42:31 +080048{
49 return CURR_THRD;
50}
51
52/* Insert a new thread into list by descending priority (Highest at head) */
Summer Qin66f1e032020-01-06 15:40:03 +080053static void insert_by_prior(struct tfm_core_thread_t **head,
54 struct tfm_core_thread_t *node)
Ken Liu91d44da2018-09-20 22:42:31 +080055{
56 if (*head == NULL || (node->prior <= (*head)->prior)) {
57 node->next = *head;
58 *head = node;
59 } else {
Summer Qin66f1e032020-01-06 15:40:03 +080060 struct tfm_core_thread_t *iter = *head;
Ken Liu91d44da2018-09-20 22:42:31 +080061
62 while (iter->next && (node->prior > iter->next->prior)) {
63 iter = iter->next;
64 }
65 node->next = iter->next;
66 iter->next = node;
67 }
68}
69
70/*
71 * Set first running thread as head to reduce enumerate
72 * depth while searching for a first running thread.
73 */
Summer Qin66f1e032020-01-06 15:40:03 +080074static void update_running_head(struct tfm_core_thread_t **runn,
75 struct tfm_core_thread_t *node)
Ken Liu91d44da2018-09-20 22:42:31 +080076{
Summer Qin66f1e032020-01-06 15:40:03 +080077 if ((node->state == THRD_STATE_RUNNING) &&
Mate Toth-Pal82cc07c2019-01-30 14:04:13 +010078 (*runn == NULL || (node->prior < (*runn)->prior))) {
Ken Liu91d44da2018-09-20 22:42:31 +080079 *runn = node;
80 } else {
Summer Qinff8db152019-07-22 14:47:26 +080081 *runn = LIST_HEAD;
Ken Liu91d44da2018-09-20 22:42:31 +080082 }
83}
84
85/* Set context members only. No validation here */
Summer Qin66f1e032020-01-06 15:40:03 +080086void tfm_core_thrd_init(struct tfm_core_thread_t *pth,
87 tfm_core_thrd_entry_t pfn, void *param,
Summer Qincb190872020-01-06 16:08:26 +080088 uintptr_t stk_top, uintptr_t stk_btm)
Ken Liu91d44da2018-09-20 22:42:31 +080089{
90 pth->prior = THRD_PRIOR_MEDIUM;
Summer Qin66f1e032020-01-06 15:40:03 +080091 pth->state = THRD_STATE_CREATING;
Ken Liu91d44da2018-09-20 22:42:31 +080092 pth->pfn = pfn;
93 pth->param = param;
Summer Qincb190872020-01-06 16:08:26 +080094 pth->stk_btm = stk_btm;
95 pth->stk_top = stk_top;
Ken Liu91d44da2018-09-20 22:42:31 +080096}
97
Summer Qin66f1e032020-01-06 15:40:03 +080098uint32_t tfm_core_thrd_start(struct tfm_core_thread_t *pth)
Ken Liu91d44da2018-09-20 22:42:31 +080099{
100 /* Validate parameters before really start */
Summer Qin66f1e032020-01-06 15:40:03 +0800101 if ((pth->state != THRD_STATE_CREATING) ||
Ken Liu91d44da2018-09-20 22:42:31 +0800102 (pth->pfn == NULL) ||
Summer Qincb190872020-01-06 16:08:26 +0800103 (pth->stk_btm == 0) ||
104 (pth->stk_top == 0)) {
Ken Liu91d44da2018-09-20 22:42:31 +0800105 return THRD_ERR_INVALID_PARAM;
106 }
107
108 /* Thread management runs in handler mode; set context for thread mode. */
Summer Qinaf3b9e12020-01-13 15:56:36 +0800109 tfm_arch_init_context(&pth->arch_ctx, pth->param, (uintptr_t)pth->pfn,
110 pth->stk_btm, pth->stk_top);
Ken Liu91d44da2018-09-20 22:42:31 +0800111
112 /* Insert a new thread with priority */
113 insert_by_prior(&LIST_HEAD, pth);
114
115 /* Mark it as RUNNING after insertion */
Summer Qin66f1e032020-01-06 15:40:03 +0800116 tfm_core_thrd_set_state(pth, THRD_STATE_RUNNING);
Ken Liu91d44da2018-09-20 22:42:31 +0800117
118 return THRD_SUCCESS;
119}
120
Summer Qin66f1e032020-01-06 15:40:03 +0800121void tfm_core_thrd_set_state(struct tfm_core_thread_t *pth, uint32_t new_state)
Ken Liu91d44da2018-09-20 22:42:31 +0800122{
Summer Qin66f1e032020-01-06 15:40:03 +0800123 TFM_CORE_ASSERT(pth != NULL && new_state < THRD_STATE_INVALID);
Ken Liu91d44da2018-09-20 22:42:31 +0800124
Summer Qin66f1e032020-01-06 15:40:03 +0800125 pth->state = new_state;
Ken Liu91d44da2018-09-20 22:42:31 +0800126 update_running_head(&RUNN_HEAD, pth);
127}
128
Ken Liu91d44da2018-09-20 22:42:31 +0800129/* Scheduling won't happen immediately but after the exception returns */
Summer Qin66f1e032020-01-06 15:40:03 +0800130void tfm_core_thrd_activate_schedule(void)
Ken Liu91d44da2018-09-20 22:42:31 +0800131{
David Hu50711e32019-06-12 18:32:30 +0800132 tfm_arch_trigger_pendsv();
Ken Liu91d44da2018-09-20 22:42:31 +0800133}
134
Summer Qin66f1e032020-01-06 15:40:03 +0800135void tfm_core_thrd_start_scheduler(struct tfm_core_thread_t *pth)
Ken Liu483f5da2019-04-24 10:45:21 +0800136{
137 /*
Ken Liu490281d2019-12-30 15:55:26 +0800138 * There is no selected thread before scheduler start, assign the caller
139 * provided thread as the current thread. Update the hardware PSP/PSPLIM
140 * with the value in thread context to ensure they are identical.
141 * This function can be called only ONCE; further calling triggers assert.
Ken Liu483f5da2019-04-24 10:45:21 +0800142 */
Ken Liuf250b8b2019-12-27 16:31:24 +0800143 TFM_CORE_ASSERT(CURR_THRD == NULL);
144 TFM_CORE_ASSERT(pth != NULL);
Summer Qind2ad7e72020-01-06 18:16:35 +0800145 TFM_CORE_ASSERT(pth->arch_ctx.sp != 0);
Ken Liu490281d2019-12-30 15:55:26 +0800146
Summer Qind2ad7e72020-01-06 18:16:35 +0800147 tfm_arch_update_ctx(&pth->arch_ctx);
Ken Liu483f5da2019-04-24 10:45:21 +0800148
149 CURR_THRD = pth;
Ken Liu490281d2019-12-30 15:55:26 +0800150
Summer Qin66f1e032020-01-06 15:40:03 +0800151 tfm_core_thrd_activate_schedule();
Ken Liu483f5da2019-04-24 10:45:21 +0800152}
153
Summer Qind2ad7e72020-01-06 18:16:35 +0800154void tfm_core_thrd_switch_context(struct tfm_arch_ctx_t *p_actx,
Summer Qin66f1e032020-01-06 15:40:03 +0800155 struct tfm_core_thread_t *prev,
156 struct tfm_core_thread_t *next)
Ken Liu91d44da2018-09-20 22:42:31 +0800157{
Ken Liuf250b8b2019-12-27 16:31:24 +0800158 TFM_CORE_ASSERT(prev != NULL);
159 TFM_CORE_ASSERT(next != NULL);
Ken Liu483f5da2019-04-24 10:45:21 +0800160
161 /*
162 * First, update latest context into the current thread context.
163 * Then, update background context with next thread's context.
164 */
Summer Qind2ad7e72020-01-06 18:16:35 +0800165 tfm_core_util_memcpy(&prev->arch_ctx, p_actx, sizeof(*p_actx));
166 tfm_core_util_memcpy(p_actx, &next->arch_ctx, sizeof(next->arch_ctx));
Ken Liu483f5da2019-04-24 10:45:21 +0800167
168 /* Update current thread indicator */
Ken Liu91d44da2018-09-20 22:42:31 +0800169 CURR_THRD = next;
170}