mbed-os5 only for TYBLE16
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_thread.c@0:5b88d5760320, 2019-12-17 (annotated)
- Committer:
- kenjiArai
- Date:
- Tue Dec 17 23:23:45 2019 +0000
- Revision:
- 0:5b88d5760320
mbed-os5 only for TYBLE16
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kenjiArai | 0:5b88d5760320 | 1 | /* |
kenjiArai | 0:5b88d5760320 | 2 | * Copyright (c) 2018-2019, Arm Limited. All rights reserved. |
kenjiArai | 0:5b88d5760320 | 3 | * |
kenjiArai | 0:5b88d5760320 | 4 | * SPDX-License-Identifier: BSD-3-Clause |
kenjiArai | 0:5b88d5760320 | 5 | * |
kenjiArai | 0:5b88d5760320 | 6 | */ |
kenjiArai | 0:5b88d5760320 | 7 | #include <inttypes.h> |
kenjiArai | 0:5b88d5760320 | 8 | #include <stdio.h> |
kenjiArai | 0:5b88d5760320 | 9 | #include "tfm_arch_v8m.h" |
kenjiArai | 0:5b88d5760320 | 10 | #include "tfm_thread.h" |
kenjiArai | 0:5b88d5760320 | 11 | #include "tfm_utils.h" |
kenjiArai | 0:5b88d5760320 | 12 | #include "tfm_memory_utils.h" |
kenjiArai | 0:5b88d5760320 | 13 | #include "tfm_svc.h" |
kenjiArai | 0:5b88d5760320 | 14 | #include "spm_api.h" |
kenjiArai | 0:5b88d5760320 | 15 | |
kenjiArai | 0:5b88d5760320 | 16 | /* Force ZERO in case ZI(bss) clear is missing */ |
kenjiArai | 0:5b88d5760320 | 17 | static struct tfm_thrd_ctx *p_thrd_head = NULL; |
kenjiArai | 0:5b88d5760320 | 18 | static struct tfm_thrd_ctx *p_runn_head = NULL; |
kenjiArai | 0:5b88d5760320 | 19 | static struct tfm_thrd_ctx *p_curr_thrd = NULL; |
kenjiArai | 0:5b88d5760320 | 20 | |
kenjiArai | 0:5b88d5760320 | 21 | /* Define Macro to fetch global to support future expansion (PERCPU e.g.) */ |
kenjiArai | 0:5b88d5760320 | 22 | #define LIST_HEAD p_thrd_head |
kenjiArai | 0:5b88d5760320 | 23 | #define RUNN_HEAD p_runn_head |
kenjiArai | 0:5b88d5760320 | 24 | #define CURR_THRD p_curr_thrd |
kenjiArai | 0:5b88d5760320 | 25 | |
kenjiArai | 0:5b88d5760320 | 26 | static struct tfm_thrd_ctx *find_next_running_thread(struct tfm_thrd_ctx *pth) |
kenjiArai | 0:5b88d5760320 | 27 | { |
kenjiArai | 0:5b88d5760320 | 28 | while (pth && pth->status != THRD_STAT_RUNNING) { |
kenjiArai | 0:5b88d5760320 | 29 | pth = pth->next; |
kenjiArai | 0:5b88d5760320 | 30 | } |
kenjiArai | 0:5b88d5760320 | 31 | |
kenjiArai | 0:5b88d5760320 | 32 | return pth; |
kenjiArai | 0:5b88d5760320 | 33 | } |
kenjiArai | 0:5b88d5760320 | 34 | |
kenjiArai | 0:5b88d5760320 | 35 | /* To get next running thread for scheduler */ |
kenjiArai | 0:5b88d5760320 | 36 | struct tfm_thrd_ctx *tfm_thrd_next_thread(void) |
kenjiArai | 0:5b88d5760320 | 37 | { |
kenjiArai | 0:5b88d5760320 | 38 | /* |
kenjiArai | 0:5b88d5760320 | 39 | * First RUNNING thread has highest priority since threads are sorted with |
kenjiArai | 0:5b88d5760320 | 40 | * priority. |
kenjiArai | 0:5b88d5760320 | 41 | */ |
kenjiArai | 0:5b88d5760320 | 42 | return find_next_running_thread(RUNN_HEAD); |
kenjiArai | 0:5b88d5760320 | 43 | } |
kenjiArai | 0:5b88d5760320 | 44 | |
kenjiArai | 0:5b88d5760320 | 45 | /* To get current thread for caller */ |
kenjiArai | 0:5b88d5760320 | 46 | struct tfm_thrd_ctx *tfm_thrd_curr_thread() |
kenjiArai | 0:5b88d5760320 | 47 | { |
kenjiArai | 0:5b88d5760320 | 48 | return CURR_THRD; |
kenjiArai | 0:5b88d5760320 | 49 | } |
kenjiArai | 0:5b88d5760320 | 50 | |
kenjiArai | 0:5b88d5760320 | 51 | /* Insert a new thread into list by descending priority (Highest at head) */ |
kenjiArai | 0:5b88d5760320 | 52 | static void insert_by_prior(struct tfm_thrd_ctx **head, |
kenjiArai | 0:5b88d5760320 | 53 | struct tfm_thrd_ctx *node) |
kenjiArai | 0:5b88d5760320 | 54 | { |
kenjiArai | 0:5b88d5760320 | 55 | if (*head == NULL || (node->prior <= (*head)->prior)) { |
kenjiArai | 0:5b88d5760320 | 56 | node->next = *head; |
kenjiArai | 0:5b88d5760320 | 57 | *head = node; |
kenjiArai | 0:5b88d5760320 | 58 | } else { |
kenjiArai | 0:5b88d5760320 | 59 | struct tfm_thrd_ctx *iter = *head; |
kenjiArai | 0:5b88d5760320 | 60 | |
kenjiArai | 0:5b88d5760320 | 61 | while (iter->next && (node->prior > iter->next->prior)) { |
kenjiArai | 0:5b88d5760320 | 62 | iter = iter->next; |
kenjiArai | 0:5b88d5760320 | 63 | } |
kenjiArai | 0:5b88d5760320 | 64 | node->next = iter->next; |
kenjiArai | 0:5b88d5760320 | 65 | iter->next = node; |
kenjiArai | 0:5b88d5760320 | 66 | } |
kenjiArai | 0:5b88d5760320 | 67 | } |
kenjiArai | 0:5b88d5760320 | 68 | |
kenjiArai | 0:5b88d5760320 | 69 | /* |
kenjiArai | 0:5b88d5760320 | 70 | * Set first running thread as head to reduce enumerate |
kenjiArai | 0:5b88d5760320 | 71 | * depth while searching for a first running thread. |
kenjiArai | 0:5b88d5760320 | 72 | */ |
kenjiArai | 0:5b88d5760320 | 73 | static void update_running_head(struct tfm_thrd_ctx **runn, |
kenjiArai | 0:5b88d5760320 | 74 | struct tfm_thrd_ctx *node) |
kenjiArai | 0:5b88d5760320 | 75 | { |
kenjiArai | 0:5b88d5760320 | 76 | if ((node->status == THRD_STAT_RUNNING) && |
kenjiArai | 0:5b88d5760320 | 77 | (*runn == NULL || (node->prior < (*runn)->prior))) { |
kenjiArai | 0:5b88d5760320 | 78 | *runn = node; |
kenjiArai | 0:5b88d5760320 | 79 | } else { |
kenjiArai | 0:5b88d5760320 | 80 | *runn = find_next_running_thread(LIST_HEAD); |
kenjiArai | 0:5b88d5760320 | 81 | } |
kenjiArai | 0:5b88d5760320 | 82 | } |
kenjiArai | 0:5b88d5760320 | 83 | |
kenjiArai | 0:5b88d5760320 | 84 | /* Set context members only. No validation here */ |
kenjiArai | 0:5b88d5760320 | 85 | void tfm_thrd_init(struct tfm_thrd_ctx *pth, |
kenjiArai | 0:5b88d5760320 | 86 | tfm_thrd_func_t pfn, void *param, |
kenjiArai | 0:5b88d5760320 | 87 | uint8_t *sp_base, uint8_t *sp_top) |
kenjiArai | 0:5b88d5760320 | 88 | { |
kenjiArai | 0:5b88d5760320 | 89 | pth->prior = THRD_PRIOR_MEDIUM; |
kenjiArai | 0:5b88d5760320 | 90 | pth->status = THRD_STAT_CREATING; |
kenjiArai | 0:5b88d5760320 | 91 | pth->pfn = pfn; |
kenjiArai | 0:5b88d5760320 | 92 | pth->param = param; |
kenjiArai | 0:5b88d5760320 | 93 | pth->sp_base = sp_base; |
kenjiArai | 0:5b88d5760320 | 94 | pth->sp_top = sp_top; |
kenjiArai | 0:5b88d5760320 | 95 | } |
kenjiArai | 0:5b88d5760320 | 96 | |
kenjiArai | 0:5b88d5760320 | 97 | uint32_t tfm_thrd_start(struct tfm_thrd_ctx *pth) |
kenjiArai | 0:5b88d5760320 | 98 | { |
kenjiArai | 0:5b88d5760320 | 99 | /* Validate parameters before really start */ |
kenjiArai | 0:5b88d5760320 | 100 | if ((pth->status != THRD_STAT_CREATING) || |
kenjiArai | 0:5b88d5760320 | 101 | (pth->pfn == NULL) || |
kenjiArai | 0:5b88d5760320 | 102 | (pth->sp_base == NULL) || |
kenjiArai | 0:5b88d5760320 | 103 | (pth->sp_top == NULL)) { |
kenjiArai | 0:5b88d5760320 | 104 | return THRD_ERR_INVALID_PARAM; |
kenjiArai | 0:5b88d5760320 | 105 | } |
kenjiArai | 0:5b88d5760320 | 106 | |
kenjiArai | 0:5b88d5760320 | 107 | /* Thread management runs in handler mode; set context for thread mode. */ |
kenjiArai | 0:5b88d5760320 | 108 | tfm_initialize_context(&pth->state_ctx, |
kenjiArai | 0:5b88d5760320 | 109 | (uint32_t)pth->param, (uint32_t)pth->pfn, |
kenjiArai | 0:5b88d5760320 | 110 | (uint32_t)pth->sp_base, (uint32_t)pth->sp_top); |
kenjiArai | 0:5b88d5760320 | 111 | |
kenjiArai | 0:5b88d5760320 | 112 | /* Insert a new thread with priority */ |
kenjiArai | 0:5b88d5760320 | 113 | insert_by_prior(&LIST_HEAD, pth); |
kenjiArai | 0:5b88d5760320 | 114 | |
kenjiArai | 0:5b88d5760320 | 115 | /* Mark it as RUNNING after insertion */ |
kenjiArai | 0:5b88d5760320 | 116 | tfm_thrd_set_status(pth, THRD_STAT_RUNNING); |
kenjiArai | 0:5b88d5760320 | 117 | |
kenjiArai | 0:5b88d5760320 | 118 | return THRD_SUCCESS; |
kenjiArai | 0:5b88d5760320 | 119 | } |
kenjiArai | 0:5b88d5760320 | 120 | |
kenjiArai | 0:5b88d5760320 | 121 | void tfm_thrd_set_status(struct tfm_thrd_ctx *pth, uint32_t new_status) |
kenjiArai | 0:5b88d5760320 | 122 | { |
kenjiArai | 0:5b88d5760320 | 123 | TFM_ASSERT(pth != NULL && new_status < THRD_STAT_INVALID); |
kenjiArai | 0:5b88d5760320 | 124 | |
kenjiArai | 0:5b88d5760320 | 125 | pth->status = new_status; |
kenjiArai | 0:5b88d5760320 | 126 | update_running_head(&RUNN_HEAD, pth); |
kenjiArai | 0:5b88d5760320 | 127 | } |
kenjiArai | 0:5b88d5760320 | 128 | |
kenjiArai | 0:5b88d5760320 | 129 | /* Scheduling won't happen immediately but after the exception returns */ |
kenjiArai | 0:5b88d5760320 | 130 | void tfm_thrd_activate_schedule(void) |
kenjiArai | 0:5b88d5760320 | 131 | { |
kenjiArai | 0:5b88d5760320 | 132 | tfm_trigger_pendsv(); |
kenjiArai | 0:5b88d5760320 | 133 | } |
kenjiArai | 0:5b88d5760320 | 134 | |
kenjiArai | 0:5b88d5760320 | 135 | void tfm_thrd_start_scheduler(struct tfm_thrd_ctx *pth) |
kenjiArai | 0:5b88d5760320 | 136 | { |
kenjiArai | 0:5b88d5760320 | 137 | /* |
kenjiArai | 0:5b88d5760320 | 138 | * There is no selected thread before scheduler start, assign |
kenjiArai | 0:5b88d5760320 | 139 | * a caller provided thread as current thread. This function |
kenjiArai | 0:5b88d5760320 | 140 | * should get called only ONCE; further calling triggers assert. |
kenjiArai | 0:5b88d5760320 | 141 | */ |
kenjiArai | 0:5b88d5760320 | 142 | TFM_ASSERT(CURR_THRD == NULL); |
kenjiArai | 0:5b88d5760320 | 143 | TFM_ASSERT(pth != NULL); |
kenjiArai | 0:5b88d5760320 | 144 | |
kenjiArai | 0:5b88d5760320 | 145 | CURR_THRD = pth; |
kenjiArai | 0:5b88d5760320 | 146 | tfm_thrd_activate_schedule(); |
kenjiArai | 0:5b88d5760320 | 147 | } |
kenjiArai | 0:5b88d5760320 | 148 | |
kenjiArai | 0:5b88d5760320 | 149 | /* Remove current thread out of the schedulable list */ |
kenjiArai | 0:5b88d5760320 | 150 | void tfm_svcall_thrd_exit(void) |
kenjiArai | 0:5b88d5760320 | 151 | { |
kenjiArai | 0:5b88d5760320 | 152 | CURR_THRD->status = THRD_STAT_DETACH; |
kenjiArai | 0:5b88d5760320 | 153 | tfm_trigger_pendsv(); |
kenjiArai | 0:5b88d5760320 | 154 | } |
kenjiArai | 0:5b88d5760320 | 155 | |
kenjiArai | 0:5b88d5760320 | 156 | __attribute__((section("SFN"))) |
kenjiArai | 0:5b88d5760320 | 157 | void tfm_thrd_exit(void) |
kenjiArai | 0:5b88d5760320 | 158 | { |
kenjiArai | 0:5b88d5760320 | 159 | SVC(TFM_SVC_EXIT_THRD); |
kenjiArai | 0:5b88d5760320 | 160 | while (1) { |
kenjiArai | 0:5b88d5760320 | 161 | ; |
kenjiArai | 0:5b88d5760320 | 162 | } |
kenjiArai | 0:5b88d5760320 | 163 | } |
kenjiArai | 0:5b88d5760320 | 164 | |
kenjiArai | 0:5b88d5760320 | 165 | void tfm_thrd_context_switch(struct tfm_state_context_ext *ctxb, |
kenjiArai | 0:5b88d5760320 | 166 | struct tfm_thrd_ctx *prev, |
kenjiArai | 0:5b88d5760320 | 167 | struct tfm_thrd_ctx *next) |
kenjiArai | 0:5b88d5760320 | 168 | { |
kenjiArai | 0:5b88d5760320 | 169 | TFM_ASSERT(prev != NULL); |
kenjiArai | 0:5b88d5760320 | 170 | TFM_ASSERT(next != NULL); |
kenjiArai | 0:5b88d5760320 | 171 | |
kenjiArai | 0:5b88d5760320 | 172 | /* |
kenjiArai | 0:5b88d5760320 | 173 | * First, update latest context into the current thread context. |
kenjiArai | 0:5b88d5760320 | 174 | * Then, update background context with next thread's context. |
kenjiArai | 0:5b88d5760320 | 175 | */ |
kenjiArai | 0:5b88d5760320 | 176 | tfm_memcpy(&prev->state_ctx.ctxb, ctxb, sizeof(*ctxb)); |
kenjiArai | 0:5b88d5760320 | 177 | tfm_memcpy(ctxb, &next->state_ctx.ctxb, sizeof(next->state_ctx.ctxb)); |
kenjiArai | 0:5b88d5760320 | 178 | |
kenjiArai | 0:5b88d5760320 | 179 | /* Update current thread indicator */ |
kenjiArai | 0:5b88d5760320 | 180 | CURR_THRD = next; |
kenjiArai | 0:5b88d5760320 | 181 | } |