blob: 920554c54185baca895039eb9df25f9facaff923 [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 Pengca59ec02021-12-09 14:35:50 +080011#include "current.h"
Kevin Peng3f67b2e2021-10-18 17:47:27 +080012#include "tfm_arch.h"
13#include "tfm_hal_interrupt.h"
14#include "tfm_hal_isolation.h"
15#include "thread.h"
16#include "utilities.h"
17
18#include "load/spm_load_api.h"
19
20__attribute__((naked))
21static psa_flih_result_t tfm_flih_deprivileged_handling(void *p_pt,
22 uintptr_t fn_flih,
Kevin Pengca59ec02021-12-09 14:35:50 +080023 void *curr_component)
Kevin Peng3f67b2e2021-10-18 17:47:27 +080024{
25 __ASM volatile("SVC %0 \n"
26 "BX LR \n"
27 : : "I" (TFM_SVC_PREPARE_DEPRIV_FLIH));
28}
29
30struct irq_load_info_t *get_irq_info_for_signal(
31 const struct partition_load_info_t *p_ldinf,
32 psa_signal_t signal)
33{
34 size_t i;
35 struct irq_load_info_t *irq_info;
36
37 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
38 return NULL;
39 }
40
41 irq_info = (struct irq_load_info_t *)LOAD_INFO_IRQ(p_ldinf);
42 for (i = 0; i < p_ldinf->nirqs; i++) {
43 if (irq_info[i].signal == signal) {
44 return &irq_info[i];
45 }
46 }
47
48 return NULL;
49}
50
51extern void tfm_flih_func_return(psa_flih_result_t result);
52
Kevin Pengf7a20d82021-12-13 14:38:37 +080053uint32_t tfm_flih_prepare_depriv_flih(struct partition_t *p_owner_sp,
54 uintptr_t flih_func)
Kevin Peng3f67b2e2021-10-18 17:47:27 +080055{
56 struct partition_t *p_curr_sp;
Kevin Pengca59ec02021-12-09 14:35:50 +080057 uintptr_t sp_base, sp_limit, curr_stack, ctx_stack;
Kevin Peng3f67b2e2021-10-18 17:47:27 +080058 struct context_ctrl_t flih_ctx_ctrl;
59
60 /* Come too early before runtime setup, should not happen. */
61 if (!CURRENT_THREAD) {
62 tfm_core_panic();
63 }
64
Kevin Pengca59ec02021-12-09 14:35:50 +080065 p_curr_sp = GET_CURRENT_COMPONENT();
66 sp_base = LOAD_ALLOCED_STACK_ADDR(p_owner_sp->p_ldinf)
67 + p_owner_sp->p_ldinf->stack_size;
68 sp_limit = LOAD_ALLOCED_STACK_ADDR(p_owner_sp->p_ldinf);
Kevin Peng3f67b2e2021-10-18 17:47:27 +080069
Kevin Pengca59ec02021-12-09 14:35:50 +080070 curr_stack = (uintptr_t)__get_PSP();
71 if (curr_stack < sp_base && curr_stack > sp_limit) {
72 /* The IRQ Partition's stack is being used */
73 ctx_stack = curr_stack;
Kevin Peng3f67b2e2021-10-18 17:47:27 +080074 } else {
Kevin Pengca59ec02021-12-09 14:35:50 +080075 ctx_stack =
76 ((struct context_ctrl_t *)p_owner_sp->thrd.p_context_ctrl)->sp;
Kevin Peng3f67b2e2021-10-18 17:47:27 +080077 }
78
Kevin Pengca59ec02021-12-09 14:35:50 +080079 if (p_owner_sp->p_boundaries != p_curr_sp->p_boundaries) {
80 tfm_hal_update_boundaries(p_owner_sp->p_ldinf,
81 p_owner_sp->p_boundaries);
82 }
83
84 /*
85 * The CURRENT_COMPONENT has been stored on MSP by the SVC call, safe to
86 * update it.
87 */
88 SET_CURRENT_COMPONENT(p_owner_sp);
89
Kevin Peng3f67b2e2021-10-18 17:47:27 +080090 tfm_arch_init_context(&flih_ctx_ctrl,
Kevin Pengf7a20d82021-12-13 14:38:37 +080091 flih_func, NULL,
Kevin Peng3f67b2e2021-10-18 17:47:27 +080092 (uintptr_t)tfm_flih_func_return,
Kevin Pengca59ec02021-12-09 14:35:50 +080093 sp_limit, ctx_stack);
Kevin Peng3f67b2e2021-10-18 17:47:27 +080094
95 (void)tfm_arch_refresh_hardware_context(&flih_ctx_ctrl);
96
97 return flih_ctx_ctrl.exc_ret;
98}
99
100/* Go back to ISR from FLIH functions */
Kevin Pengf7a20d82021-12-13 14:38:37 +0800101uint32_t tfm_flih_return_to_isr(psa_flih_result_t result,
102 struct context_flih_ret_t *p_ctx_flih_ret)
Kevin Peng3f67b2e2021-10-18 17:47:27 +0800103{
104 struct partition_t *p_prev_sp, *p_owner_sp;
Kevin Peng3f67b2e2021-10-18 17:47:27 +0800105
Kevin Pengca59ec02021-12-09 14:35:50 +0800106 p_prev_sp = (struct partition_t *)(p_ctx_flih_ret->state_ctx.r2);
107 p_owner_sp = GET_CURRENT_COMPONENT();
Kevin Peng3f67b2e2021-10-18 17:47:27 +0800108
109 if (p_owner_sp->p_boundaries != p_prev_sp->p_boundaries) {
110 tfm_hal_update_boundaries(p_prev_sp->p_ldinf,
111 p_prev_sp->p_boundaries);
112 }
113
Kevin Pengca59ec02021-12-09 14:35:50 +0800114 /* Restore current component */
115 SET_CURRENT_COMPONENT(p_prev_sp);
Kevin Peng3f67b2e2021-10-18 17:47:27 +0800116
Kevin Pengca59ec02021-12-09 14:35:50 +0800117 tfm_arch_set_psplim(p_ctx_flih_ret->psplim);
Kevin Peng3f67b2e2021-10-18 17:47:27 +0800118 __set_PSP(p_ctx_flih_ret->psp);
119
120 /* Set FLIH result to the ISR */
121 p_ctx_flih_ret->state_ctx.r0 = (uint32_t)result;
122
Kevin Pengca59ec02021-12-09 14:35:50 +0800123 return EXC_RETURN_HANDLER_S_MSP;
Kevin Peng3f67b2e2021-10-18 17:47:27 +0800124}
125
126void spm_handle_interrupt(void *p_pt, struct irq_load_info_t *p_ildi)
127{
128 psa_flih_result_t flih_result;
129 struct partition_t *p_part;
130
131 if (!p_pt || !p_ildi) {
132 tfm_core_panic();
133 }
134
135 p_part = (struct partition_t *)p_pt;
136
137 if (p_ildi->pid != p_part->p_ldinf->pid) {
138 tfm_core_panic();
139 }
140
141 if (p_ildi->flih_func == NULL) {
142 /* SLIH Model Handling */
143 tfm_hal_irq_disable(p_ildi->source);
144 flih_result = PSA_FLIH_SIGNAL;
145 } else {
146 /* FLIH Model Handling */
147 if (tfm_spm_partition_get_privileged_mode(p_part->p_ldinf->flags) ==
148 TFM_PARTITION_PRIVILEGED_MODE) {
149 flih_result = p_ildi->flih_func();
150 } else {
151 flih_result = tfm_flih_deprivileged_handling(
152 p_part,
153 (uintptr_t)p_ildi->flih_func,
Kevin Pengca59ec02021-12-09 14:35:50 +0800154 GET_CURRENT_COMPONENT());
Kevin Peng3f67b2e2021-10-18 17:47:27 +0800155 }
156 }
157
158 if (flih_result == PSA_FLIH_SIGNAL) {
159 spm_assert_signal(p_pt, p_ildi->signal);
Kevin Peng8a579692021-12-15 13:44:42 +0800160
161 if (THRD_EXPECTING_SCHEDULE()) {
162 tfm_arch_trigger_pendsv();
163 }
Kevin Peng3f67b2e2021-10-18 17:47:27 +0800164 }
165}