blob: d5d03108b0af40534f85b379fdd01b004ec90890 [file] [log] [blame]
Summer Qin90602de2020-08-04 10:23:39 +08001/*
2 * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
Summer Qin9c1fba12020-08-12 15:49:12 +08008#include "arch.h"
Summer Qin90602de2020-08-04 10:23:39 +08009#include "tfm_secure_api.h"
Summer Qin90602de2020-08-04 10:23:39 +080010#include "tfm/tfm_spm_services.h"
11
12nsfptr_t ns_entry;
13
14void jump_to_ns_code(void)
15{
16 /* Calls the non-secure Reset_Handler to jump to the non-secure binary */
17 ns_entry();
18}
19
20__attribute__((naked))
21int32_t tfm_core_get_caller_client_id(int32_t *caller_client_id)
22{
23 __ASM volatile(
24 "SVC %0\n"
25 "BX LR\n"
26 : : "I" (TFM_SVC_GET_CALLER_CLIENT_ID));
27}
28
29__attribute__((naked))
30int32_t tfm_spm_request(void)
31{
32 __ASM volatile(
33 "SVC %0\n"
34 "BX lr\n"
35 : : "I" (TFM_SVC_SPM_REQUEST));
36}
37
38__attribute__((naked))
39int32_t tfm_spm_request_reset_vote(void)
40{
41 __ASM volatile(
42 "MOVS R0, %0\n"
43 "B tfm_spm_request\n"
44 : : "I" (TFM_SPM_REQUEST_RESET_VOTE));
45}
46
47__attribute__((naked))
48void tfm_enable_irq(psa_signal_t irq_signal)
49{
50 __ASM("SVC %0\n"
51 "BX LR\n"
52 : : "I" (TFM_SVC_ENABLE_IRQ));
53}
54
55__attribute__((naked))
56void tfm_disable_irq(psa_signal_t irq_signal)
57{
58 __ASM("SVC %0\n"
59 "BX LR\n"
60 : : "I" (TFM_SVC_DISABLE_IRQ));
61}
62
63__attribute__((naked))
64static psa_signal_t psa_wait_internal(psa_signal_t signal_mask,
65 uint32_t timeout)
66{
67 __ASM("SVC %0\n"
68 "BX LR\n"
69 : : "I" (TFM_SVC_PSA_WAIT));
70}
71
72psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout)
73{
74 /* FIXME: By using the 'WFI' instruction this function blocks until an
75 * interrupt happens. It is necessary to do this here as tfm_core_psa_wait
76 * runs with the priority of the SVC, so it cannot be interrupted, so
77 * waiting in it for the required interrupt to happen is not an option.
78 */
79 psa_signal_t actual_signal_mask;
80
81 while (1) {
82 actual_signal_mask = psa_wait_internal(signal_mask, timeout);
83 if ((actual_signal_mask & signal_mask) != 0) {
84 return actual_signal_mask;
85 }
86 __WFI();
87 }
88}
89
90__attribute__((naked))
91void psa_eoi(psa_signal_t irq_signal)
92{
93 __ASM("SVC %0\n"
94 "BX LR\n"
95 : : "I" (TFM_SVC_PSA_EOI));
96}
97
98#if defined(__ARM_ARCH_8_1M_MAIN__) || defined(__ARM_ARCH_8M_MAIN__)
99__attribute__((section("SFN"), naked))
100int32_t tfm_core_sfn_request(const struct tfm_sfn_req_s *desc_ptr)
101{
102 __ASM volatile(
103 "PUSH {r4-r12, lr} \n"
104 "SVC %[SVC_REQ] \n"
105 "MOV r4, #0 \n"
106 "MOV r5, r4 \n"
107 "MOV r6, r4 \n"
108 "MOV r7, r4 \n"
109 "MOV r8, r4 \n"
110 "MOV r9, r4 \n"
111 "MOV r10, r4 \n"
112 "MOV r11, r4 \n"
113 "BLX lr \n"
114 "SVC %[SVC_RET] \n"
115 "POP {r4-r12, pc} \n"
116 : : [SVC_REQ] "I" (TFM_SVC_SFN_REQUEST),
117 [SVC_RET] "I" (TFM_SVC_SFN_RETURN)
118 );
119}
120
121__attribute__((section("SFN"), naked))
122void priv_irq_handler_main(uint32_t partition_id, uint32_t unpriv_handler,
123 uint32_t irq_signal, uint32_t irq_line)
124{
125 __ASM(
126 /* Save the callee saved registers*/
127 "PUSH {r4-r12, lr} \n"
128 /* Request SVC to configure environment for the unpriv IRQ handler */
129 "SVC %[SVC_REQ] \n"
130 /* clear the callee saved registers to prevent information leak */
131 "MOV r4, #0 \n"
132 "MOV r5, r4 \n"
133 "MOV r6, r4 \n"
134 "MOV r7, r4 \n"
135 "MOV r8, r4 \n"
136 "MOV r9, r4 \n"
137 "MOV r10, r4 \n"
138 "MOV r11, r4 \n"
139 /* Branch to the unprivileged handler */
140 "BLX lr \n"
141 /* Request SVC to reconfigure the environment of the interrupted
142 * partition
143 */
144 "SVC %[SVC_RET] \n"
145 /* restore callee saved registers and return */
146 "POP {r4-r12, pc} \n"
147 : : [SVC_REQ] "I" (TFM_SVC_DEPRIV_REQ)
148 , [SVC_RET] "I" (TFM_SVC_DEPRIV_RET)
149 );
150}
151#elif defined(__ARM_ARCH_8M_BASE__)
152__attribute__((section("SFN"), naked))
153int32_t tfm_core_sfn_request(const struct tfm_sfn_req_s *desc_ptr)
154{
155 __ASM volatile(
156 "PUSH {lr} \n"
157 "PUSH {r4-r7} \n"
158 "MOV r4, r8 \n"
159 "MOV r5, r9 \n"
160 "MOV r6, r10 \n"
161 "MOV r7, r11 \n"
162 "PUSH {r4-r7} \n"
163 "MOV r4, r12 \n"
164 "PUSH {r4} \n"
165 "SVC %[SVC_REQ] \n"
166 "MOVS r4, #0 \n"
167 "MOV r5, r4 \n"
168 "MOV r6, r4 \n"
169 "MOV r7, r4 \n"
170 "MOV r8, r4 \n"
171 "MOV r9, r4 \n"
172 "MOV r10, r4 \n"
173 "MOV r11, r4 \n"
174 "BLX lr \n"
175 "SVC %[SVC_RET] \n"
176 "POP {r4} \n"
177 "MOV r12, r4 \n"
178 "POP {r4-r7} \n"
179 "MOV r8, r4 \n"
180 "MOV r9, r5 \n"
181 "MOV r10, r6 \n"
182 "MOV r11, r7 \n"
183 "POP {r4-r7} \n"
184 "POP {pc} \n"
185 : : [SVC_REQ] "I" (TFM_SVC_SFN_REQUEST),
186 [SVC_RET] "I" (TFM_SVC_SFN_RETURN)
187 );
188}
189
190__attribute__((section("SFN"), naked))
191void priv_irq_handler_main(uint32_t partition_id, uint32_t unpriv_handler,
192 uint32_t irq_signal, uint32_t irq_line)
193{
194 __ASM(
195 /* Save the callee saved registers*/
196 "PUSH {r4-r7, lr} \n"
197 "MOV r4, r8 \n"
198 "MOV r5, r9 \n"
199 "MOV r6, r10 \n"
200 "MOV r7, r11 \n"
201 "PUSH {r4-r7} \n"
202 "MOV r4, r12 \n"
203 "PUSH {r4} \n"
204 /* Request SVC to configure environment for the unpriv IRQ handler */
205 "SVC %[SVC_REQ] \n"
206 /* clear the callee saved registers to prevent information leak */
207 "MOVS r4, #0 \n"
208 "MOV r5, r4 \n"
209 "MOV r6, r4 \n"
210 "MOV r7, r4 \n"
211 "MOV r8, r4 \n"
212 "MOV r9, r4 \n"
213 "MOV r10, r4 \n"
214 "MOV r11, r4 \n"
215 /* Branch to the unprivileged handler */
216 "BLX lr \n"
217 /* Request SVC to reconfigure the environment of the interrupted
218 * partition
219 */
220 "SVC %[SVC_RET] \n"
221 /* restore callee saved registers and return */
222 "POP {r4} \n"
223 "MOV r12, r4 \n"
224 "POP {r4-r7} \n"
225 "MOV r8, r4 \n"
226 "MOV r9, r5 \n"
227 "MOV r10, r6 \n"
228 "MOV r11, r7 \n"
229 "POP {r4-r7, pc} \n"
230 : : [SVC_REQ] "I" (TFM_SVC_DEPRIV_REQ)
231 , [SVC_RET] "I" (TFM_SVC_DEPRIV_RET)
232 );
233}
234#endif
235
236#if defined(__ARM_ARCH_8_1M_MAIN__) || \
237 defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__)
238void tfm_arch_prioritize_secure_exception(void)
239{
240 uint32_t VECTKEY;
241 SCB_Type *scb = SCB;
242 uint32_t AIRCR;
243
244 /* Set PRIS flag in AIRCR */
245 AIRCR = scb->AIRCR;
246 VECTKEY = (~AIRCR & SCB_AIRCR_VECTKEYSTAT_Msk);
247 scb->AIRCR = SCB_AIRCR_PRIS_Msk |
248 VECTKEY |
249 (AIRCR & ~SCB_AIRCR_VECTKEY_Msk);
250}
251#elif defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_7M__) || \
252 defined(__ARM_ARCH_7EM__)
253void tfm_arch_prioritize_secure_exception(void)
254{
255}
256#endif
257
258#if defined(__ARM_ARCH_8_1M_MAIN__) || defined(__ARM_ARCH_8M_MAIN__)
259__attribute__((naked)) void SVC_Handler(void)
260{
261 __ASM volatile(
262 "MRS r2, MSP \n"
263 /* Check store SP in thread mode to r0 */
264 "TST lr, #4 \n"
265 "ITE EQ \n"
266 "MOVEQ r0, r2 \n"
267 "MRSNE r0, PSP \n"
268 "MOV r1, lr \n"
269 "BL tfm_core_svc_handler \n"
270 "BX r0 \n"
271 );
272}
273#elif defined(__ARM_ARCH_8M_BASE__)
274__attribute__((naked)) void SVC_Handler(void)
275{
276 __ASM volatile(
277 "MRS r2, MSP \n"
278 "MOVS r1, #4 \n"
279 "MOV r3, lr \n"
280 "MOV r0, r2 \n"
281 "TST r1, r3 \n"
282 "BEQ handler \n"
283 /* If SVC was made from thread mode, overwrite r0 with PSP */
284 "MRS r0, PSP \n"
285 "handler: \n"
286 "MOV r1, lr \n"
287 "BL tfm_core_svc_handler \n"
288 "BX r0 \n"
289 );
290}
291#elif defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_7M__) || \
292 defined(__ARM_ARCH_7EM__)
293__attribute__((naked)) void SVC_Handler(void)
294{
295 __ASM volatile(
296 "MOVS r0, #4 \n" /* Check store SP in thread mode to r0 */
297 "MOV r1, lr \n"
298 "TST r0, r1 \n"
299 "BEQ handler \n"
300 "MRS r0, PSP \n" /* Coming from thread mode */
301 "B sp_stored \n"
302 "handler: \n"
303 "BX lr \n" /* Coming from handler mode */
304 "sp_stored: \n"
305 "MOV r1, lr \n"
306 "BL tfm_core_svc_handler \n"
307 "BX r0 \n"
308 );
309}
310#endif