blob: d038f862bb0127a588916c511a60c5a51dd1c5a4 [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
Boyan Karatotev794b0ac2025-06-20 13:13:29 +01002 * Copyright (c) 2018-2025, Arm Limited. All rights reserved.
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_helpers.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02008#include <assert.h>
9#include <debug.h>
Antonio Nino Diaz09a00ef2019-01-11 13:12:58 +000010#include <drivers/arm/arm_gic.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020011#include <irq.h>
12#include <mmio.h>
13#include <platform.h>
14#include <platform_def.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020015#include <smccc.h>
16#include <std_svc.h>
17#include <stdlib.h>
18#include <string.h>
19#include <test_helpers.h>
20#include <tftf.h>
21
22#define STRESS_COUNT 100
23
24/*
25 * The shared data between the handler and the
26 * preempt_tsp_via_SGI routine.
27 */
28typedef struct {
29 smc_ret_values tsp_result;
30 int wait_for_fiq;
31} irq_handler_shared_data;
32
33static irq_handler_shared_data shared_data;
34
35/*
36 * Handler for the SGI #0.
37 */
38static int sgi_handler(void *data)
39{
40 /* Ensure this is the SGI we expect */
41 assert(*(unsigned int *)data == IRQ_NS_SGI_0);
42
43 if (shared_data.wait_for_fiq)
44 wfi(); /* We will get woken by the FIQ firing */
45
46 return 0;
47}
48
49/*
50 * This routine issues a SGI with interrupts disabled to make sure that the
51 * pending SGI will preempt a STD SMC.
52 */
53static test_result_t preempt_tsp_via_SGI(const smc_args *tsp_svc_params,
54 int hold_irq_handler_for_fiq)
55{
56 int rc;
57 unsigned int core_mpid = read_mpidr_el1() & MPID_MASK;
58 unsigned int core_pos = platform_get_core_pos(core_mpid);
59 test_result_t result = TEST_RESULT_SUCCESS;
60
61 memset(&shared_data, 0, sizeof(shared_data));
62
63 if (hold_irq_handler_for_fiq)
64 shared_data.wait_for_fiq = 1;
65
66 /* Register Handler for the interrupt. SGIs #0 - #6 are available. */
Boyan Karatotev6d144db2025-06-23 15:04:53 +010067 rc = tftf_irq_register_handler_sgi(IRQ_NS_SGI_0, sgi_handler);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020068 if (rc != 0) {
69 tftf_testcase_printf("Failed to register SGI handler. "
70 "Error code = %d\n", rc);
71 return TEST_RESULT_SKIPPED;
72 }
73
74 /* Enable SGI #0 */
Boyan Karatotev6d144db2025-06-23 15:04:53 +010075 tftf_irq_enable_sgi(IRQ_NS_SGI_0, GIC_HIGHEST_NS_PRIORITY);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020076
77 /* Set PSTATE.I to 0. */
78 disable_irq();
79
80 /*
81 * Send SGI to the current CPU. It can't be handled because the
82 * interrupts are disabled.
83 */
84 tftf_send_sgi(IRQ_NS_SGI_0, core_pos);
85
86 /*
87 * Invoke an STD SMC. Should be pre-empted because of the SGI that is
88 * waiting.
89 */
90 shared_data.tsp_result = tftf_smc(tsp_svc_params);
91 if (shared_data.tsp_result.ret0 != TSP_SMC_PREEMPTED) {
92 tftf_testcase_printf("SMC returned 0x%llX instead of "
93 "TSP_SMC_PREEMPTED.\n",
94 (unsigned long long)shared_data.tsp_result.ret0);
95 result = TEST_RESULT_FAIL;
96 }
97
98 /* Set PSTATE.I to 1. The SGI will be handled after this. */
99 enable_irq();
100
101 /* Disable SGI #0 */
Boyan Karatotev6d144db2025-06-23 15:04:53 +0100102 tftf_irq_disable_sgi(IRQ_NS_SGI_0);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200103
104 /* Unregister handler */
Boyan Karatotev6d144db2025-06-23 15:04:53 +0100105 rc = tftf_irq_unregister_handler_sgi(IRQ_NS_SGI_0);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200106 if (rc != 0) {
107 tftf_testcase_printf("Failed to unregister IRQ handler. "
108 "Error code = %d\n", rc);
109 result = TEST_RESULT_FAIL;
110 }
111
112 return result;
113}
114
115/*
116 * @Test_Aim@ Test the secure world preemption by non secure interrupt.
117 *
118 * Steps: 1. Issue Standard SMC and preempt it via SGI
119 * 2. Resume the preempted SMC
120 * Returns SUCCESS if above 2 steps are performed correctly else failure.
121 */
122test_result_t tsp_int_and_resume(void)
123{
124 smc_args tsp_svc_params;
125 smc_ret_values tsp_result = {0};
126 test_result_t res;
127
128 SKIP_TEST_IF_TSP_NOT_PRESENT();
129
130 /* Standard SMC */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100131 tsp_svc_params.fid = TSP_STD_FID(TSP_ADD);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200132 tsp_svc_params.arg1 = 4;
133 tsp_svc_params.arg2 = 6;
134 res = preempt_tsp_via_SGI(&tsp_svc_params, 0);
135 if (res == TEST_RESULT_FAIL)
136 return res;
137
138 /* Now that we have ensured preemption, issue RESUME */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100139 tsp_svc_params.fid = TSP_FID_RESUME;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200140 tsp_result = tftf_smc(&tsp_svc_params);
141
142 /* Check the result of the addition */
143 if (tsp_result.ret0 != 0 || tsp_result.ret1 != 8 ||
144 tsp_result.ret2 != 12) {
145 tftf_testcase_printf("SMC resume returned wrong result:"
146 "got %d %d %d expected: 0 8 12\n",
147 (unsigned int)tsp_result.ret0,
148 (unsigned int)tsp_result.ret1,
149 (unsigned int)tsp_result.ret2);
150 tftf_testcase_printf("SMC resume returned wrong result\n");
151 return TEST_RESULT_FAIL;
152 }
153
154 /* Standard SMC */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100155 tsp_svc_params.fid = TSP_STD_FID(TSP_SUB);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200156 tsp_svc_params.arg1 = 4;
157 tsp_svc_params.arg2 = 6;
158 res = preempt_tsp_via_SGI(&tsp_svc_params, 0);
159 if (res == TEST_RESULT_FAIL)
160 return res;
161
162 /* Now that we have ensured preemption, issue RESUME */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100163 tsp_svc_params.fid = TSP_FID_RESUME;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200164 tsp_result = tftf_smc(&tsp_svc_params);
165
166 /* Check the result of the substraction */
167 if (tsp_result.ret0 != 0 || tsp_result.ret1 != 0 ||
168 tsp_result.ret2 != 0) {
169 tftf_testcase_printf("SMC resume returned wrong result:"
170 "got %d %d %d expected: 0 0 0\n",
171 (unsigned int)tsp_result.ret0,
172 (unsigned int)tsp_result.ret1,
173 (unsigned int)tsp_result.ret2);
174 return TEST_RESULT_FAIL;
175 }
176
177 /* Standard SMC */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100178 tsp_svc_params.fid = TSP_STD_FID(TSP_MUL);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200179 tsp_svc_params.arg1 = 4;
180 tsp_svc_params.arg2 = 6;
181 res = preempt_tsp_via_SGI(&tsp_svc_params, 0);
182 if (res == TEST_RESULT_FAIL)
183 return res;
184
185 /* Now that we have ensured preemption, issue RESUME */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100186 tsp_svc_params.fid = TSP_FID_RESUME;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200187 tsp_result = tftf_smc(&tsp_svc_params);
188
189 /* Check the result of the multiplication */
190 if (tsp_result.ret0 != 0 || tsp_result.ret1 != 16 ||
191 tsp_result.ret2 != 36) {
192 tftf_testcase_printf("SMC resume returned wrong result:"
193 "got %d %d %d expected: 0 16 36\n",
194 (unsigned int)tsp_result.ret0,
195 (unsigned int)tsp_result.ret1,
196 (unsigned int)tsp_result.ret2);
197 return TEST_RESULT_FAIL;
198 }
199
200 /* Standard SMC */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100201 tsp_svc_params.fid = TSP_STD_FID(TSP_DIV);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200202 tsp_svc_params.arg1 = 4;
203 tsp_svc_params.arg2 = 6;
204 res = preempt_tsp_via_SGI(&tsp_svc_params, 0);
205 if (res == TEST_RESULT_FAIL)
206 return res;
207
208 /* Now that we have ensured preemption, issue RESUME */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100209 tsp_svc_params.fid = TSP_FID_RESUME;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200210 tsp_result = tftf_smc(&tsp_svc_params);
211
212 /* Check the result of the division */
213 if (tsp_result.ret0 != 0 || tsp_result.ret1 != 1 ||
214 tsp_result.ret2 != 1) {
215 tftf_testcase_printf("SMC resume returned wrong result:"
216 "got %d %d %d expected: 0 1 1\n",
217 (unsigned int)tsp_result.ret0,
218 (unsigned int)tsp_result.ret1,
219 (unsigned int)tsp_result.ret2);
220 return TEST_RESULT_FAIL;
221 }
222
223 return TEST_RESULT_SUCCESS;
224}
225
226/*
227 * @Test_Aim@ Verify Fast SMC request on an interrupted tsp returns error.
228 *
229 * Steps: 1. Issue Standard SMC and preempt it via SGI
230 * 2. Issue Fast SMC, this is not expected and TSP should return error.
231 * 3. Resume the preempted SMC and verify the result.
232 * Returns SUCCESS if above 3 steps are performed correctly else failure.
233 */
234test_result_t test_fast_smc_when_tsp_preempted(void)
235{
236 smc_args tsp_svc_params;
237 smc_ret_values tsp_result = {0};
238 test_result_t res = TEST_RESULT_SUCCESS;
239
240 SKIP_TEST_IF_TSP_NOT_PRESENT();
241
242 /* Standard SMC */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100243 tsp_svc_params.fid = TSP_STD_FID(TSP_ADD);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200244 tsp_svc_params.arg1 = 4;
245 tsp_svc_params.arg2 = 6;
246 res = preempt_tsp_via_SGI(&tsp_svc_params, 0);
247 if (res == TEST_RESULT_FAIL)
248 return res;
249
250 /* Now that we have ensured preemption, issue Fast SMC */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100251 tsp_svc_params.fid = TSP_FAST_FID(TSP_ADD);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200252 tsp_svc_params.arg1 = 4;
253 tsp_svc_params.arg2 = 6;
254
255 tsp_result = tftf_smc(&tsp_svc_params);
256
257 if (tsp_result.ret0 != SMC_UNKNOWN) {
258 tftf_testcase_printf("Fast SMC should not execute"
259 "while SMC is preempted\n");
260 res = TEST_RESULT_FAIL;
261 }
262
263 /* Issue RESUME */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100264 tsp_svc_params.fid = TSP_FID_RESUME;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200265 tsp_result = tftf_smc(&tsp_svc_params);
266
267 /* Check the result of the addition */
268 if (tsp_result.ret0 != 0 || tsp_result.ret1 != 8 ||
269 tsp_result.ret2 != 12) {
270 tftf_testcase_printf("SMC resume returned wrong result:"
271 "got %d %d %d expected: 0 8 12\n",
272 (unsigned int)tsp_result.ret0,
273 (unsigned int)tsp_result.ret1,
274 (unsigned int)tsp_result.ret2);
275
276 res = TEST_RESULT_FAIL;
277 }
278
279 return res;
280}
281
282/*
283 * @Test_Aim@ Test the Standard SMC when tsp is pre-empted by interrupt.
284 *
285 * Steps:
286 * 1. Issue Standard SMC and preempt it via SGI
287 * 2. Issue another Standard SMC. this is not expected and TSP should return
288 * error.
289 * 3. Resume the preempted SMC or abort if the parameter `abort_smc` is set to
290 * 1.
291 * 4. Check the result if the SMC was resumed, or just carry on if it was
292 * aborted.
293 * Returns SUCCESS if above 4 steps are performed correctly else failure.
294 */
295static test_result_t test_std_smc_when_tsp_preempted(int abort_smc)
296{
297 smc_args tsp_svc_params;
298 smc_ret_values tsp_result = {0};
299 test_result_t res = TEST_RESULT_SUCCESS;
300
301 SKIP_TEST_IF_TSP_NOT_PRESENT();
302
303 /* Standard SMC */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100304 tsp_svc_params.fid = TSP_STD_FID(TSP_ADD);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200305 tsp_svc_params.arg1 = 4;
306 tsp_svc_params.arg2 = 6;
307 res = preempt_tsp_via_SGI(&tsp_svc_params, 0);
308 if (res == TEST_RESULT_FAIL)
309 return res;
310
311 /* Now that we have ensured preemption, issue Standard SMC */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100312 tsp_svc_params.fid = TSP_STD_FID(TSP_ADD);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200313 tsp_svc_params.arg1 = 4;
314 tsp_svc_params.arg2 = 6;
315
316 tsp_result = tftf_smc(&tsp_svc_params);
317
318 if (tsp_result.ret0 != SMC_UNKNOWN) {
319 tftf_testcase_printf("Standard SMC should not execute while SMC is preempted\n");
320 res = TEST_RESULT_FAIL;
321 }
322
323 /* Issue ABORT or RESUME */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100324 tsp_svc_params.fid = abort_smc ? TSP_FID_ABORT : TSP_FID_RESUME;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200325 tsp_result = tftf_smc(&tsp_svc_params);
326
327 /*
328 * There is no way to check that the ABORT succeeded or failed because
329 * it will return SMC_UNKNOWN in both cases.
330 */
331 if (!abort_smc) {
332 /*
333 * Check the result of the addition if we issued RESUME.
334 */
335 if (tsp_result.ret0 != 0 || tsp_result.ret1 != 8 ||
336 tsp_result.ret2 != 12) {
337 tftf_testcase_printf("SMC resume returned wrong result: got %d %d %d expected: 0 8 12\n",
338 (unsigned int)tsp_result.ret0,
339 (unsigned int)tsp_result.ret1,
340 (unsigned int)tsp_result.ret2);
341 res = TEST_RESULT_FAIL;
342 }
343 }
344
345 return res;
346}
347
348test_result_t test_std_smc_when_tsp_preempted_resume(void)
349{
350 return test_std_smc_when_tsp_preempted(0);
351}
352
353test_result_t test_std_smc_when_tsp_preempted_abort(void)
354{
355 return test_std_smc_when_tsp_preempted(1);
356}
357
358/*
359 * @Test_Aim@ Test RESUME SMC call when TSP is not preempted. RESUME should fail.
360 *
361 * Issues resume SMC. This is not expected by TSP and returns error.
362 * This is a negative test, Return SUCCESS is RESUME returns SMC_UNKNOWN
363 */
364test_result_t test_resume_smc_without_preemption(void)
365{
366 smc_args tsp_svc_params;
367 smc_ret_values tsp_result = {0};
368
369 SKIP_TEST_IF_TSP_NOT_PRESENT();
370
371 /* Issue RESUME */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100372 tsp_svc_params.fid = TSP_FID_RESUME;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200373 tsp_result = tftf_smc(&tsp_svc_params);
374
375 if (tsp_result.ret0 != SMC_UNKNOWN) {
376 tftf_testcase_printf("SMC Resume should return UNKNOWN, got:%d\n", \
377 (unsigned int)tsp_result.ret0);
378 return TEST_RESULT_FAIL;
379 }
380
381 return TEST_RESULT_SUCCESS;
382}
383
384/*
385 * @Test_Aim@ Stress Test the secure world preemption by non secure interrupt
386 *
387 * Steps: 1. Issue Standard SMC and preempt it via SGI
388 * 2. Resume the preempted SMC and repeat from Step 1 for STRESS_COUNT times.
389 * Returns SUCCESS if above 2 steps are performed correctly else failure.
390 */
391test_result_t tsp_int_and_resume_stress(void)
392{
393 smc_args tsp_svc_params;
394 smc_ret_values tsp_result = {0};
395 test_result_t res = TEST_RESULT_SUCCESS;
396
397 SKIP_TEST_IF_TSP_NOT_PRESENT();
398
399 int count = 0;
400
401 NOTICE("This stress test will repeat %d times\n", STRESS_COUNT);
402 while ((count < STRESS_COUNT) &&
403 (res == TEST_RESULT_SUCCESS)) {
404 /* Standard SMC */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100405 tsp_svc_params.fid = TSP_STD_FID(TSP_ADD);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200406 tsp_svc_params.arg1 = 4;
407 tsp_svc_params.arg2 = 6;
408 /* Try to preempt TSP via IRQ */
409 res = preempt_tsp_via_SGI(&tsp_svc_params, 0);
410 if (res == TEST_RESULT_FAIL)
411 return res;
412
413 /* Issue RESUME */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100414 tsp_svc_params.fid = TSP_FID_RESUME;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200415 tsp_result = tftf_smc(&tsp_svc_params);
416
417 /* Check the result of the addition */
418 if (tsp_result.ret0 != 0 || tsp_result.ret1 != 8 ||
419 tsp_result.ret2 != 12) {
420 tftf_testcase_printf("SMC resume returned wrong result:"
421 "got %d %d %d expected: 0 8 12\n",
422 (unsigned int)tsp_result.ret0,
423 (unsigned int)tsp_result.ret1,
424 (unsigned int)tsp_result.ret2);
425 res = TEST_RESULT_FAIL;
426 }
427
428 count++;
429 }
430 return res;
431}
432
433/*
434 * @Test_Aim@ Test Secure FIQ when pre-empted by non secure interrupt.
435 *
436 * We really cannot verify whether FIQ fired and preempted the SGI handler
437 * or not. The TSP prints the address at which the execution was interrupted
438 * for the FIQ. By looking at the address printed from the TSP logs, we can
439 * verify that the SGI handler was interrupted by FIQ. For now, We are assuming
440 * CPU is woken by Secure Timer Interrupt.
441 *
442 * Steps: 1. Issue Standard SMC and preempt it via SGI
443 * 2. Wait in the SGI handler for FIQ which is firing every 500 ms.
444 * 3. Resume the preempted SMC
445 * Returns SUCCESS if above 3 steps are performed correctly else failure.
446 */
447test_result_t tsp_fiq_while_int(void)
448{
449 smc_args tsp_svc_params;
450 smc_ret_values tsp_result = {0};
451 test_result_t res;
452
453 SKIP_TEST_IF_TSP_NOT_PRESENT();
454
455 /* Standard SMC */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100456 tsp_svc_params.fid = TSP_STD_FID(TSP_ADD);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200457 tsp_svc_params.arg1 = 4;
458 tsp_svc_params.arg2 = 6;
459 res = preempt_tsp_via_SGI(&tsp_svc_params, 1);
460 if (res == TEST_RESULT_FAIL)
461 return res;
462
463 /* Now that we have ensured preemption, issue RESUME */
Sandrine Bailleux17795062018-12-13 16:02:41 +0100464 tsp_svc_params.fid = TSP_FID_RESUME;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200465 tsp_result = tftf_smc(&tsp_svc_params);
466
467 /* Check the result of the addition */
468 if (tsp_result.ret0 != 0 || tsp_result.ret1 != 8 ||
469 tsp_result.ret2 != 12) {
470 tftf_testcase_printf("SMC resume returned wrong result:"
471 "got %d %d %d expected: 0 8 12\n",
472 (unsigned int)tsp_result.ret0,
473 (unsigned int)tsp_result.ret1,
474 (unsigned int)tsp_result.ret2);
475 return TEST_RESULT_FAIL;
476 }
477 return TEST_RESULT_SUCCESS;
478}