blob: 87c075171724b134217644a3f504efdc48b130ba [file] [log] [blame]
Kevin Peng3f67b2e2021-10-18 17:47:27 +08001/*
2 * Copyright (c) 2021, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include "interrupt.h"
9
10#include "bitops.h"
Kevin Peng3f67b2e2021-10-18 17:47:27 +080011#include "tfm_arch.h"
12#include "tfm_hal_interrupt.h"
13#include "tfm_hal_isolation.h"
14#include "thread.h"
15#include "utilities.h"
16
17#include "load/spm_load_api.h"
18
19__attribute__((naked))
20static psa_flih_result_t tfm_flih_deprivileged_handling(void *p_pt,
21 uintptr_t fn_flih,
22 void *p_context_ctrl)
23{
24 __ASM volatile("SVC %0 \n"
25 "BX LR \n"
26 : : "I" (TFM_SVC_PREPARE_DEPRIV_FLIH));
27}
28
29struct irq_load_info_t *get_irq_info_for_signal(
30 const struct partition_load_info_t *p_ldinf,
31 psa_signal_t signal)
32{
33 size_t i;
34 struct irq_load_info_t *irq_info;
35
36 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
37 return NULL;
38 }
39
40 irq_info = (struct irq_load_info_t *)LOAD_INFO_IRQ(p_ldinf);
41 for (i = 0; i < p_ldinf->nirqs; i++) {
42 if (irq_info[i].signal == signal) {
43 return &irq_info[i];
44 }
45 }
46
47 return NULL;
48}
49
50extern void tfm_flih_func_return(psa_flih_result_t result);
51
Kevin Pengf7a20d82021-12-13 14:38:37 +080052uint32_t tfm_flih_prepare_depriv_flih(struct partition_t *p_owner_sp,
53 uintptr_t flih_func)
Kevin Peng3f67b2e2021-10-18 17:47:27 +080054{
55 struct partition_t *p_curr_sp;
Kevin Peng3f67b2e2021-10-18 17:47:27 +080056 uintptr_t sp_limit, stack;
57 struct context_ctrl_t flih_ctx_ctrl;
58
59 /* Come too early before runtime setup, should not happen. */
60 if (!CURRENT_THREAD) {
61 tfm_core_panic();
62 }
63
64 p_curr_sp = GET_CTX_OWNER(CURRENT_THREAD->p_context_ctrl);
65 sp_limit =
66 ((struct context_ctrl_t *)p_owner_sp->thrd.p_context_ctrl)->sp_limit;
67
68 if (p_owner_sp == p_curr_sp) {
69 stack = (uintptr_t)__get_PSP();
70 } else {
71 stack = ((struct context_ctrl_t *)p_owner_sp->thrd.p_context_ctrl)->sp;
72
73 if (p_owner_sp->p_boundaries != p_curr_sp->p_boundaries) {
74 tfm_hal_update_boundaries(p_owner_sp->p_ldinf,
75 p_owner_sp->p_boundaries);
76 }
77
78 /*
79 * CURRENT_THREAD->p_context_ctrl is the svc_args[2] on MSP, safe to
80 * update it. It is only used to track the owner of the thread data,
81 * i.e. the partition that has been interrupted.
82 */
83 THRD_UPDATE_CUR_CTXCTRL(&(p_owner_sp->ctx_ctrl));
84 }
85
86 tfm_arch_init_context(&flih_ctx_ctrl,
Kevin Pengf7a20d82021-12-13 14:38:37 +080087 flih_func, NULL,
Kevin Peng3f67b2e2021-10-18 17:47:27 +080088 (uintptr_t)tfm_flih_func_return,
89 sp_limit, stack);
90
91 (void)tfm_arch_refresh_hardware_context(&flih_ctx_ctrl);
92
93 return flih_ctx_ctrl.exc_ret;
94}
95
96/* Go back to ISR from FLIH functions */
Kevin Pengf7a20d82021-12-13 14:38:37 +080097uint32_t tfm_flih_return_to_isr(psa_flih_result_t result,
98 struct context_flih_ret_t *p_ctx_flih_ret)
Kevin Peng3f67b2e2021-10-18 17:47:27 +080099{
100 struct partition_t *p_prev_sp, *p_owner_sp;
Kevin Peng3f67b2e2021-10-18 17:47:27 +0800101
102 p_prev_sp = GET_CTX_OWNER(p_ctx_flih_ret->state_ctx.r2);
103 p_owner_sp = GET_CTX_OWNER(CURRENT_THREAD->p_context_ctrl);
104
105 if (p_owner_sp->p_boundaries != p_prev_sp->p_boundaries) {
106 tfm_hal_update_boundaries(p_prev_sp->p_ldinf,
107 p_prev_sp->p_boundaries);
108 }
109
110 /* Restore context pointer */
111 THRD_UPDATE_CUR_CTXCTRL(p_ctx_flih_ret->state_ctx.r2);
112
113 tfm_arch_set_psplim(
114 ((struct context_ctrl_t *)CURRENT_THREAD->p_context_ctrl)->sp_limit);
115 __set_PSP(p_ctx_flih_ret->psp);
116
117 /* Set FLIH result to the ISR */
118 p_ctx_flih_ret->state_ctx.r0 = (uint32_t)result;
119
120 return p_ctx_flih_ret->exc_ret;
121}
122
123void spm_handle_interrupt(void *p_pt, struct irq_load_info_t *p_ildi)
124{
125 psa_flih_result_t flih_result;
126 struct partition_t *p_part;
127
128 if (!p_pt || !p_ildi) {
129 tfm_core_panic();
130 }
131
132 p_part = (struct partition_t *)p_pt;
133
134 if (p_ildi->pid != p_part->p_ldinf->pid) {
135 tfm_core_panic();
136 }
137
138 if (p_ildi->flih_func == NULL) {
139 /* SLIH Model Handling */
140 tfm_hal_irq_disable(p_ildi->source);
141 flih_result = PSA_FLIH_SIGNAL;
142 } else {
143 /* FLIH Model Handling */
144 if (tfm_spm_partition_get_privileged_mode(p_part->p_ldinf->flags) ==
145 TFM_PARTITION_PRIVILEGED_MODE) {
146 flih_result = p_ildi->flih_func();
147 } else {
148 flih_result = tfm_flih_deprivileged_handling(
149 p_part,
150 (uintptr_t)p_ildi->flih_func,
151 CURRENT_THREAD->p_context_ctrl);
152 }
153 }
154
155 if (flih_result == PSA_FLIH_SIGNAL) {
156 spm_assert_signal(p_pt, p_ildi->signal);
Kevin Peng8a579692021-12-15 13:44:42 +0800157
158 if (THRD_EXPECTING_SCHEDULE()) {
159 tfm_arch_trigger_pendsv();
160 }
Kevin Peng3f67b2e2021-10-18 17:47:27 +0800161 }
162}