blob: 661bb56a6eaa0efe7e7438483dcedac07b2043b0 [file] [log] [blame]
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -06001/*
2 * Copyright 2023 The Hafnium Authors.
3 *
4 * Use of this source code is governed by a BSD-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/BSD-3-Clause.
7 */
8
Madhukar Pappireddy66421182022-12-22 16:50:09 -06009#include "hf/arch/irq.h"
Madhukar Pappireddyace2ff72023-05-03 15:45:06 -050010#include "hf/arch/vm/delay.h"
Madhukar Pappireddy66421182022-12-22 16:50:09 -060011#include "hf/arch/vm/interrupts_gicv3.h"
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -050012#include "hf/arch/vm/power_mgmt.h"
Madhukar Pappireddy66421182022-12-22 16:50:09 -060013#include "hf/arch/vm/timer.h"
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -060014
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060015#include "ffa_secure_partitions.h"
Madhukar Pappireddy66421182022-12-22 16:50:09 -060016#include "gicv3.h"
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060017#include "partition_services.h"
18#include "sp_helpers.h"
19
20#define SP_SLEEP_TIME 400U
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -060021#define NS_SLEEP_TIME 200U
22
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -050023#define LAST_SECONDARY_VCPU_ID (MAX_CPUS - 1)
24#define MID_SECONDARY_VCPU_ID (MAX_CPUS / 2)
25
26alignas(4096) static uint8_t secondary_ec_stack[MAX_CPUS - 1][PAGE_SIZE];
27
28struct secondary_cpu_entry_args {
29 ffa_id_t receiver_id;
30 ffa_vcpu_count_t vcpu_count;
31 ffa_vcpu_index_t vcpu_id;
32 struct spinlock lock;
33 ffa_vcpu_index_t target_vcpu_id;
34};
35
J-Alves19e20cf2023-08-02 12:48:55 +010036static void configure_trusted_wdog_interrupt(ffa_id_t source, ffa_id_t dest,
37 bool enable)
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060038{
39 struct ffa_value res;
40
41 res = sp_virtual_interrupt_cmd_send(source, dest, IRQ_TWDOG_INTID,
42 enable, 0);
43
44 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
45 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
46}
47
J-Alves19e20cf2023-08-02 12:48:55 +010048static void enable_trusted_wdog_interrupt(ffa_id_t source, ffa_id_t dest)
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060049{
50 configure_trusted_wdog_interrupt(source, dest, true);
51}
52
J-Alves19e20cf2023-08-02 12:48:55 +010053static void disable_trusted_wdog_interrupt(ffa_id_t source, ffa_id_t dest)
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060054{
55 configure_trusted_wdog_interrupt(source, dest, false);
56}
57
J-Alves19e20cf2023-08-02 12:48:55 +010058static void enable_trigger_trusted_wdog_timer(ffa_id_t own_id,
59 ffa_id_t receiver_id,
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060060 uint32_t timer_ms)
61{
62 struct ffa_value res;
63
64 /* Enable trusted watchdog interrupt as vIRQ in the secure side. */
65 enable_trusted_wdog_interrupt(own_id, receiver_id);
66
67 res = sp_twdog_map_cmd_send(own_id, receiver_id);
68
69 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
70 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
71
72 /*
73 * Send a message to the SP through direct messaging requesting it to
74 * start the trusted watchdog timer.
75 */
76 res = sp_twdog_cmd_send(own_id, receiver_id, timer_ms);
77
78 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
79 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
80}
81
J-Alves19e20cf2023-08-02 12:48:55 +010082static void check_and_disable_trusted_wdog_timer(ffa_id_t own_id,
83 ffa_id_t receiver_id)
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060084{
85 struct ffa_value res;
86
87 /* Check for the last serviced secure virtual interrupt. */
88 res = sp_get_last_interrupt_cmd_send(own_id, receiver_id);
89
90 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
91 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
92
93 /* Make sure Trusted Watchdog timer interrupt was serviced. */
94 EXPECT_EQ(sp_resp_value(res), IRQ_TWDOG_INTID);
95
96 /* Disable Trusted Watchdog interrupt. */
97 disable_trusted_wdog_interrupt(own_id, receiver_id);
98}
99
100/*
101 * Test secure interrupt handling while the Secure Partition is in RUNNING
102 * state.
103 */
104TEST(secure_interrupts, sp_running)
105{
106 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100107 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000108 struct mailbox_buffers mb = set_up_mailbox();
109 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100110 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -0600111
112 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
113
114 /* Send request to the SP to sleep. */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600115 res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME, 0);
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -0600116
117 /*
118 * Secure interrupt should trigger during this time, SP will handle the
119 * trusted watchdog timer interrupt.
120 */
121 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
122 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
123
124 /* Make sure elapsed time not less than sleep time. */
125 EXPECT_GE(sp_resp_value(res), SP_SLEEP_TIME);
126
127 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
128}
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600129
130/*
Madhukar Pappireddyed7dee82023-12-06 11:55:15 -0600131 * Test secure interrupt handling while the Secure Partition runs with
132 * interrupts potentially masked. This test helps to validate the functionality
133 * of the SPMC to intercept a direct response message if there are pending
134 * virtual secure interrupts and reschedule the partition to handle the pending
135 * interrupt.
136 */
137TEST(secure_interrupts, sp_direct_response_intercepted)
138{
139 struct ffa_value res;
140 ffa_id_t own_id = hf_vm_get_id();
141 struct mailbox_buffers mb = set_up_mailbox();
142 struct ffa_partition_info *service2_info = service2(mb.recv);
143 const ffa_id_t receiver_id = service2_info->vm_id;
144
145 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
146
147 /* Send request to the SP to sleep uninterrupted. */
148 res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME, 1);
149
150 /*
151 * Secure interrupt should trigger during this time, SP will handle the
152 * trusted watchdog timer interrupt.
153 */
154 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
155 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
156
157 /* Make sure elapsed time not less than sleep time. */
158 EXPECT_GE(sp_resp_value(res), SP_SLEEP_TIME);
159
160 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
161}
162
163/*
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600164 * Test secure interrupt handling while the Secure Partition is in WAITING
165 * state.
166 */
167TEST(secure_interrupts, sp_waiting)
168{
J-Alves19e20cf2023-08-02 12:48:55 +0100169 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000170 struct mailbox_buffers mb = set_up_mailbox();
171 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100172 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600173 uint64_t time1;
174 volatile uint64_t time_lapsed;
175 uint64_t timer_freq = read_msr(cntfrq_el0);
176
177 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 100);
178 time1 = syscounter_read();
179
180 /*
181 * Sleep for NS_SLEEP_TIME ms. This ensures secure wdog timer triggers
182 * during this time.
183 */
184 waitms(NS_SLEEP_TIME);
185
186 /* Lapsed time should be at least equal to sleep time. */
187 time_lapsed = ((syscounter_read() - time1) * 1000) / timer_freq;
188
189 EXPECT_GE(time_lapsed, NS_SLEEP_TIME);
190
191 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
192}
Madhukar Pappireddy8cc6deb2022-12-22 16:46:04 -0600193
194/*
195 * Test secure interrupt handling while the Secure Partition is in BLOCKED
196 * state.
197 */
198TEST(secure_interrupts, sp_blocked)
199{
200 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100201 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000202 struct mailbox_buffers mb = set_up_mailbox();
203 struct ffa_partition_info *service1_info = service1(mb.recv);
204 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100205 const ffa_id_t receiver_id = service2_info->vm_id;
206 const ffa_id_t companion_id = service1_info->vm_id;
Madhukar Pappireddy8cc6deb2022-12-22 16:46:04 -0600207
208 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
209
210 /*
211 * Send command to receiver SP to send command to companion SP to sleep
212 * there by putting receiver SP in BLOCKED state.
213 */
214 res = sp_fwd_sleep_cmd_send(own_id, receiver_id, companion_id,
215 SP_SLEEP_TIME, false);
216
217 /*
218 * Secure interrupt should trigger during this time, receiver SP will
219 * handle the trusted watchdog timer and sends direct response message.
220 */
221 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
222 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
223
224 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
225}
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600226
227TEST(secure_interrupts, sp_preempted)
228{
229 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100230 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000231 struct mailbox_buffers mb = set_up_mailbox();
232 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100233 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600234
235 gicv3_system_setup();
236 interrupt_enable(PHYSICAL_TIMER_IRQ, true);
237 interrupt_set_priority(PHYSICAL_TIMER_IRQ, 0x80);
238 interrupt_set_edge_triggered(PHYSICAL_TIMER_IRQ, true);
239 interrupt_set_priority_mask(0xff);
240 arch_irq_enable();
241
242 /* Set physical timer for 20 ms and enable. */
243 write_msr(CNTP_TVAL_EL0, ns_to_ticks(20000000));
244 write_msr(CNTP_CTL_EL0, CNTx_CTL_ENABLE_MASK);
245
246 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 200);
247
248 /* Send request to receiver SP to sleep. */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600249 res = sp_sleep_cmd_send(own_id, receiver_id, 50, 0);
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600250
251 /* SP is pre-empted by the non-secure timer interrupt. */
252 EXPECT_EQ(res.func, FFA_INTERRUPT_32);
253
254 /* VM id/vCPU index are passed through arg1. */
255 EXPECT_EQ(res.arg1, ffa_vm_vcpu(receiver_id, 0));
256
257 /* Waiting for interrupt to be serviced in normal world. */
258 while (last_interrupt_id == 0) {
259 EXPECT_EQ(io_read32_array(GICD_ISPENDR, 0), 0);
260 EXPECT_EQ(io_read32(GICR_ISPENDR0), 0);
261 EXPECT_EQ(io_read32_array(GICD_ISACTIVER, 0), 0);
262 EXPECT_EQ(io_read32(GICR_ISACTIVER0), 0);
263 }
264
265 /* Check that we got the interrupt. */
266 EXPECT_EQ(last_interrupt_id, PHYSICAL_TIMER_IRQ);
267
268 /* Check timer status. */
269 EXPECT_EQ(read_msr(CNTP_CTL_EL0),
270 CNTx_CTL_ISTS_MASK | CNTx_CTL_ENABLE_MASK);
271
272 /*
273 * NS Interrupt has been serviced and receiver SP is now in PREEMPTED
274 * state. Wait for trusted watchdog timer to be fired. SPMC queues
275 * the secure virtual interrupt.
276 */
277 waitms(NS_SLEEP_TIME);
278
279 /*
280 * Resume the SP to complete the busy loop, handle the secure virtual
281 * interrupt and return with success.
282 */
283 res = ffa_run(ffa_vm_id(res), ffa_vcpu_index(res));
284 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
285 EXPECT_EQ(res.arg3, SP_SUCCESS);
286
287 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
288}
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600289
290/*
291 * Test Secure Partition runs to completion if it specifies action in response
292 * to Other-S Interrupt as queued.
293 */
294TEST(secure_interrupts, sp_other_s_interrupt_queued)
295{
296 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100297 ffa_id_t own_id = hf_vm_get_id();
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600298 struct mailbox_buffers mb = set_up_mailbox();
299 struct ffa_partition_info *service2_info = service2(mb.recv);
300 struct ffa_partition_info *service3_info = service3(mb.recv);
301
302 /*
303 * Service2 SP is the target of trusted watchdog timer interrupt.
304 * Service3 SP specified action to Other-S Interrupt as queued.
305 */
J-Alves19e20cf2023-08-02 12:48:55 +0100306 const ffa_id_t target_id = service2_info->vm_id;
307 const ffa_id_t receiver_id = service3_info->vm_id;
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600308
309 enable_trigger_trusted_wdog_timer(own_id, target_id, 400);
310
311 /*
312 * Send command to receiver SP(Service3) to sleep for SP_SLEEP_TIME
313 * ms. Secure interrupt should trigger while SP is busy in running the
314 * sleep command. SPMC queues the virtual interrupt and resumes the
315 * SP.
316 */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600317 res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME, 0);
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600318
319 /* Service3 SP finishes and sends direct response back. */
320 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
321 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
322
323 /*
324 * Allocate cycles to target SP for it to handle the virtual secure
325 * interrupt.
326 */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600327 res = sp_sleep_cmd_send(own_id, target_id, 10, 0);
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600328
329 /*
330 * Secure interrupt should trigger during this time, SP will handle the
331 * trusted watchdog timer interrupt.
332 */
333 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
334 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
335
336 /*
337 * Check if the trusted watchdog timer interrupt has been handled.
338 */
339 check_and_disable_trusted_wdog_timer(own_id, target_id);
340}
Madhukar Pappireddyef062762023-05-23 17:46:57 -0500341
342/*
343 * Test that an SP can attempt to yield CPU cycles while handling secure
344 * interrupt by invoking FFA_YIELD.
345 */
346TEST(secure_interrupts, sp_yield_sec_interrupt_handling)
347{
348 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100349 ffa_id_t own_id = hf_vm_get_id();
Madhukar Pappireddyef062762023-05-23 17:46:57 -0500350 struct mailbox_buffers mb = set_up_mailbox();
351 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100352 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddyef062762023-05-23 17:46:57 -0500353 uint64_t time1;
354 volatile uint64_t time_lapsed;
355 uint64_t timer_freq = read_msr(cntfrq_el0);
356
357 /*
358 * Send command to SP asking it attempt to yield cycles while handling
359 * secure interrupt.
360 */
361 res = sp_yield_secure_interrupt_handling_cmd_send(own_id, receiver_id,
362 true);
363
364 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
365 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
366
367 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 75);
368 time1 = syscounter_read();
369
370 /*
371 * Sleep for 100ms. This ensures secure wdog timer triggers
372 * during this time. SP starts handling secure interrupt but attempts
373 * to yields cycles. However, SPMC just resumes the SP to complete
374 * interrupt handling.
375 */
376 waitms(100);
377
378 /* Lapsed time should be at least equal to sleep time. */
379 time_lapsed = ((syscounter_read() - time1) * 1000) / timer_freq;
380
381 EXPECT_GE(time_lapsed, 100);
382
383 res = sp_yield_secure_interrupt_handling_cmd_send(own_id, receiver_id,
384 false);
385
386 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
387 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
388 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
389}
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500390
391static void cpu_entry_sp_sleep_loop(uintptr_t arg)
392{
393 ffa_id_t own_id = hf_vm_get_id();
394 struct ffa_value res;
395 struct secondary_cpu_entry_args *args =
396 // NOLINTNEXTLINE(performance-no-int-to-ptr)
397 (struct secondary_cpu_entry_args *)arg;
398 bool is_receiver_up_sp = args->vcpu_count == 1;
399
400 /*
401 * Execution context(s) of secondary Secure Partitions need CPU cycles
402 * to be allocated through FFA_RUN interface to reach message loop.
403 */
404 if (is_receiver_up_sp) {
405 res = ffa_run(args->receiver_id, (ffa_vcpu_index_t)0);
406 } else {
407 res = ffa_run(args->receiver_id, args->vcpu_id);
408 }
409
410 EXPECT_EQ(ffa_func_id(res), FFA_MSG_WAIT_32);
411
412 /* Prepare for the trusted watchdog interrupt routed to target vCPU. */
413 if (args->vcpu_id == args->target_vcpu_id) {
414 res = sp_route_interrupt_to_target_vcpu_cmd_send(
415 own_id, args->receiver_id, args->target_vcpu_id,
416 IRQ_TWDOG_INTID);
417
418 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
419 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
420
421 /*
422 * Make sure that twdog timer triggers shortly before the
423 * sleep duration ends.
424 */
425 enable_trigger_trusted_wdog_timer(own_id, args->receiver_id,
426 SP_SLEEP_TIME - 50);
427 }
428
429 /* Send request to the SP to sleep. */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600430 res = sp_sleep_cmd_send(own_id, args->receiver_id, SP_SLEEP_TIME, 0);
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500431 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
432 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
433
434 /* Make sure elapsed time not less than sleep time. */
435 EXPECT_GE(sp_resp_value(res), SP_SLEEP_TIME);
436
437 /* Check for the last serviced secure virtual interrupt. */
438 res = sp_get_last_interrupt_cmd_send(own_id, args->receiver_id);
439
440 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
441 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
442
443 /*
444 * Expect the target execution context of Service2 SP to handle the
445 * trusted watchdog interrupt succesfully.
446 */
447 if (args->vcpu_id == args->target_vcpu_id) {
448 EXPECT_EQ(sp_resp_value(res), IRQ_TWDOG_INTID);
449 } else {
450 /*
451 * Make sure Trusted Watchdog timer interrupt was not serviced
452 * by this execution context.
453 */
454 EXPECT_NE(sp_resp_value(res), IRQ_TWDOG_INTID);
455 }
456
457 /* Clear last serviced secure virtual interrupt. */
458 res = sp_clear_last_interrupt_cmd_send(own_id, args->receiver_id);
459
460 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
461 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
462
463 /* Releases the lock passed in. */
464 sl_unlock(&args->lock);
465 arch_cpu_stop();
466}
467
468static void sp_route_interrupt_to_secondary_vcpu_base(
469 struct secondary_cpu_entry_args args)
470{
471 /* Start secondary EC while holding lock. */
472 sl_lock(&args.lock);
473
474 for (ffa_vcpu_index_t i = 1; i < MAX_CPUS; i++) {
475 uintptr_t cpu_id;
476 ffa_vcpu_index_t hftest_cpu_index = MAX_CPUS - i;
477
478 cpu_id = hftest_get_cpu_id(hftest_cpu_index);
479 args.vcpu_id = i;
480 HFTEST_LOG("Booting CPU %u - %x", i, cpu_id);
481
482 EXPECT_EQ(hftest_cpu_start(cpu_id, secondary_ec_stack[i - 1],
483 sizeof(secondary_ec_stack[0]),
484 cpu_entry_sp_sleep_loop,
485 (uintptr_t)&args),
486 true);
487
488 /* Wait for CPU to release the lock. */
489 sl_lock(&args.lock);
490
491 HFTEST_LOG("Done with CPU %u", i);
492 }
493}
494
495/*
496 * Test a Secure Partition can request the SPMC to reconfigure an interrupt to
497 * be routed to a secondary vCPU.
498 */
499TEST(secure_interrupts, sp_route_interrupt_to_secondary_vcpu)
500{
501 struct secondary_cpu_entry_args args = {.lock = SPINLOCK_INIT};
502 struct mailbox_buffers mb = set_up_mailbox();
503 struct ffa_partition_info *service2_info = service2(mb.recv);
504 const ffa_id_t receiver_id = service2_info->vm_id;
505
506 args.receiver_id = receiver_id;
507 args.vcpu_count = service2_info->vcpu_count;
508
509 /*
510 * Reconfigure the twdog interrupt to be routed to last secondary
511 * execution context of SP.
512 */
513 args.target_vcpu_id = LAST_SECONDARY_VCPU_ID;
514 sp_route_interrupt_to_secondary_vcpu_base(args);
515
516 /*
517 * Reconfigure the twdog interrupt to be routed to mid secondary
518 * execution context of SP.
519 */
520 args.target_vcpu_id = MID_SECONDARY_VCPU_ID;
521 sp_route_interrupt_to_secondary_vcpu_base(args);
522}