1 /*
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 
9 #include "hf/arch/irq.h"
10 #include "hf/arch/vm/delay.h"
11 #include "hf/arch/vm/interrupts_gicv3.h"
12 #include "hf/arch/vm/power_mgmt.h"
13 #include "hf/arch/vm/timer.h"
14 
15 #include "ffa_secure_partitions.h"
16 #include "gicv3.h"
17 #include "partition_services.h"
18 #include "sp805.h"
19 #include "sp_helpers.h"
20 
21 #define SP_SLEEP_TIME 400U
22 #define NS_SLEEP_TIME 200U
23 
24 #define LAST_SECONDARY_VCPU_ID (MAX_CPUS - 1)
25 #define MID_SECONDARY_VCPU_ID (MAX_CPUS / 2)
26 
27 struct secondary_cpu_entry_args {
28 	ffa_id_t receiver_id;
29 	ffa_vcpu_count_t vcpu_count;
30 	ffa_vcpu_index_t vcpu_id;
31 	struct spinlock lock;
32 	ffa_vcpu_index_t target_vcpu_id;
33 };
34 
configure_trusted_wdog_interrupt(ffa_id_t source,ffa_id_t dest,bool enable)35 static void configure_trusted_wdog_interrupt(ffa_id_t source, ffa_id_t dest,
36 					     bool enable)
37 {
38 	struct ffa_value res;
39 
40 	res = sp_virtual_interrupt_cmd_send(source, dest, IRQ_TWDOG_INTID,
41 					    enable, 0);
42 
43 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
44 	EXPECT_EQ(sp_resp(res), SP_SUCCESS);
45 }
46 
enable_trusted_wdog_interrupt(ffa_id_t source,ffa_id_t dest)47 static void enable_trusted_wdog_interrupt(ffa_id_t source, ffa_id_t dest)
48 {
49 	configure_trusted_wdog_interrupt(source, dest, true);
50 }
51 
disable_trusted_wdog_interrupt(ffa_id_t source,ffa_id_t dest)52 static void disable_trusted_wdog_interrupt(ffa_id_t source, ffa_id_t dest)
53 {
54 	configure_trusted_wdog_interrupt(source, dest, false);
55 }
56 
enable_trigger_trusted_wdog_timer(ffa_id_t own_id,ffa_id_t receiver_id,uint32_t timer_ms)57 static void enable_trigger_trusted_wdog_timer(ffa_id_t own_id,
58 					      ffa_id_t receiver_id,
59 					      uint32_t timer_ms)
60 {
61 	struct ffa_value res;
62 
63 	/* Enable trusted watchdog interrupt as vIRQ in the secure side. */
64 	enable_trusted_wdog_interrupt(own_id, receiver_id);
65 
66 	res = sp_twdog_map_cmd_send(own_id, receiver_id);
67 
68 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
69 	EXPECT_EQ(sp_resp(res), SP_SUCCESS);
70 
71 	/*
72 	 * Send a message to the SP through direct messaging requesting it to
73 	 * start the trusted watchdog timer.
74 	 */
75 	res = sp_twdog_cmd_send(own_id, receiver_id, timer_ms);
76 
77 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
78 	EXPECT_EQ(sp_resp(res), SP_SUCCESS);
79 }
80 
check_and_disable_trusted_wdog_timer(ffa_id_t own_id,ffa_id_t receiver_id)81 static void check_and_disable_trusted_wdog_timer(ffa_id_t own_id,
82 						 ffa_id_t receiver_id)
83 {
84 	struct ffa_value res;
85 
86 	/* Check for the last serviced secure virtual interrupt. */
87 	res = sp_get_last_interrupt_cmd_send(own_id, receiver_id);
88 
89 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
90 	EXPECT_EQ(sp_resp(res), SP_SUCCESS);
91 
92 	/* Make sure Trusted Watchdog timer interrupt was serviced. */
93 	EXPECT_EQ(sp_resp_value(res), IRQ_TWDOG_INTID);
94 
95 	/* Disable Trusted Watchdog interrupt. */
96 	disable_trusted_wdog_interrupt(own_id, receiver_id);
97 }
98 
99 /*
100  * Test secure interrupt handling while the Secure Partition is in RUNNING
101  * state.
102  */
TEST(secure_interrupts,sp_running)103 TEST(secure_interrupts, sp_running)
104 {
105 	struct ffa_value res;
106 	ffa_id_t own_id = hf_vm_get_id();
107 	struct mailbox_buffers mb = set_up_mailbox();
108 	struct ffa_partition_info *service2_info = service2(mb.recv);
109 	const ffa_id_t receiver_id = service2_info->vm_id;
110 
111 	enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
112 
113 	/* Send request to the SP to sleep. */
114 	res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME, 0);
115 
116 	/*
117 	 * Secure interrupt should trigger during this time, SP will handle the
118 	 * trusted watchdog timer interrupt.
119 	 */
120 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
121 	EXPECT_EQ(sp_resp(res), SP_SUCCESS);
122 
123 	/* Make sure elapsed time not less than sleep time. */
124 	EXPECT_GE(sp_resp_value(res), SP_SLEEP_TIME);
125 
126 	check_and_disable_trusted_wdog_timer(own_id, receiver_id);
127 }
128 
129 /**
130  * Test secure interrupt handling while the Secure Partition runs with
131  * interrupts potentially masked. This test helps to validate the functionality
132  * of the SPMC to intercept a direct response message sent via
133  * FFA_MSG_SEND_DIRECT_RESP_32 if there are pending virtual secure interrupts
134  * and reschedule the partition to handle the pending interrupt.
135  */
TEST(secure_interrupts,sp_direct_response_intercepted)136 TEST(secure_interrupts, sp_direct_response_intercepted)
137 {
138 	struct ffa_value res;
139 	ffa_id_t own_id = hf_vm_get_id();
140 	struct mailbox_buffers mb = set_up_mailbox();
141 	struct ffa_partition_info *service2_info = service2(mb.recv);
142 	const ffa_id_t receiver_id = service2_info->vm_id;
143 
144 	enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
145 
146 	/* Send request to the SP to sleep uninterrupted. */
147 	res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME,
148 				OPTIONS_MASK_INTERRUPTS);
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 /**
164  * Test secure interrupt handling while the Secure Partition runs with
165  * interrupts potentially masked. This test helps to validate the functionality
166  * of the SPMC to intercept a direct response message sent via
167  * FFA_MSG_SEND_DIRECT_RESP2_64 if there are pending virtual secure interrupts
168  * and reschedule the partition to handle the pending interrupt.
169  */
TEST(secure_interrupts,sp_direct_response2_intercepted)170 TEST(secure_interrupts, sp_direct_response2_intercepted)
171 {
172 	struct ffa_value res;
173 	ffa_id_t own_id = hf_vm_get_id();
174 	struct mailbox_buffers mb = set_up_mailbox();
175 	struct ffa_partition_info *service2_info = service2(mb.recv);
176 	const ffa_id_t receiver_id = service2_info->vm_id;
177 	const uint64_t msg[] = {SP_SLEEP_CMD, SP_SLEEP_TIME, 1};
178 	struct ffa_uuid uuid;
179 
180 	enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
181 
182 	/* Send request to the SP to sleep uninterrupted. */
183 	ffa_uuid_init(0, 0, 0, 0, &uuid);
184 	res = ffa_msg_send_direct_req2(own_id, receiver_id, &uuid,
185 				       (const uint64_t *)&msg, ARRAY_SIZE(msg));
186 
187 	/*
188 	 * Secure interrupt should trigger during this time, SP will handle the
189 	 * trusted watchdog timer interrupt.
190 	 */
191 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP2_64);
192 	EXPECT_EQ(sp_resp(res), SP_SUCCESS);
193 
194 	/* Make sure elapsed time not less than sleep time. */
195 	EXPECT_GE(res.arg5, SP_SLEEP_TIME);
196 
197 	check_and_disable_trusted_wdog_timer(own_id, receiver_id);
198 }
199 
200 /*
201  * This test is an extension of the 'sp_direct_response_intercepted' test. It
202  * creates a scenario where a direct response message between two Secure
203  * partitions in intercepted to signal a pending virtual secure interrupt.
204  */
TEST(secure_interrupts,sp_forward_direct_response_intercepted)205 TEST(secure_interrupts, sp_forward_direct_response_intercepted)
206 {
207 	struct ffa_value res;
208 	ffa_id_t own_id = hf_vm_get_id();
209 	struct mailbox_buffers mb = set_up_mailbox();
210 	struct ffa_partition_info *service1_info = service1(mb.recv);
211 	struct ffa_partition_info *service2_info = service2(mb.recv);
212 	const ffa_id_t receiver_id = service2_info->vm_id;
213 	const ffa_id_t companion_id = service1_info->vm_id;
214 
215 	enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
216 
217 	/*
218 	 * Send request to the companion SP to send command to receiver SP to
219 	 * sleep uninterrupted.
220 	 */
221 	res = sp_fwd_sleep_cmd_send(own_id, companion_id, receiver_id,
222 				    SP_SLEEP_TIME, OPTIONS_MASK_INTERRUPTS);
223 
224 	/*
225 	 * Secure interrupt should trigger during this time, SP will handle the
226 	 * trusted watchdog timer interrupt.
227 	 */
228 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
229 	EXPECT_EQ(sp_resp(res), SP_SUCCESS);
230 
231 	check_and_disable_trusted_wdog_timer(own_id, receiver_id);
232 }
233 
234 /*
235  * Test secure interrupt handling while the Secure Partition is in WAITING
236  * state.
237  */
TEST(secure_interrupts,sp_waiting)238 TEST(secure_interrupts, sp_waiting)
239 {
240 	ffa_id_t own_id = hf_vm_get_id();
241 	struct mailbox_buffers mb = set_up_mailbox();
242 	struct ffa_partition_info *service2_info = service2(mb.recv);
243 	const ffa_id_t receiver_id = service2_info->vm_id;
244 	uint64_t time1;
245 	volatile uint64_t time_lapsed;
246 	uint64_t timer_freq = read_msr(cntfrq_el0);
247 
248 	enable_trigger_trusted_wdog_timer(own_id, receiver_id, 100);
249 	time1 = syscounter_read();
250 
251 	/*
252 	 * Sleep for NS_SLEEP_TIME ms. This ensures secure wdog timer triggers
253 	 * during this time.
254 	 */
255 	waitms(NS_SLEEP_TIME);
256 
257 	/* Lapsed time should be at least equal to sleep time. */
258 	time_lapsed = ((syscounter_read() - time1) * 1000) / timer_freq;
259 
260 	EXPECT_GE(time_lapsed, NS_SLEEP_TIME);
261 
262 	check_and_disable_trusted_wdog_timer(own_id, receiver_id);
263 }
264 
265 /*
266  * Test secure interrupt handling while the Secure Partition is in BLOCKED
267  * state.
268  */
TEST(secure_interrupts,sp_blocked)269 TEST(secure_interrupts, sp_blocked)
270 {
271 	struct ffa_value res;
272 	ffa_id_t own_id = hf_vm_get_id();
273 	struct mailbox_buffers mb = set_up_mailbox();
274 	struct ffa_partition_info *service1_info = service1(mb.recv);
275 	struct ffa_partition_info *service2_info = service2(mb.recv);
276 	const ffa_id_t receiver_id = service2_info->vm_id;
277 	const ffa_id_t companion_id = service1_info->vm_id;
278 
279 	enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
280 
281 	/*
282 	 * Send command to receiver SP to send command to companion SP to sleep
283 	 * there by putting receiver SP in BLOCKED state.
284 	 */
285 	res = sp_fwd_sleep_cmd_send(own_id, receiver_id, companion_id,
286 				    SP_SLEEP_TIME, 0);
287 
288 	/*
289 	 * Secure interrupt should trigger during this time, receiver SP will
290 	 * handle the trusted watchdog timer and sends direct response message.
291 	 */
292 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
293 	EXPECT_EQ(sp_resp(res), SP_SUCCESS);
294 
295 	check_and_disable_trusted_wdog_timer(own_id, receiver_id);
296 }
297 
TEST(secure_interrupts,sp_preempted)298 TEST(secure_interrupts, sp_preempted)
299 {
300 	struct ffa_value res;
301 	ffa_id_t own_id = hf_vm_get_id();
302 	struct mailbox_buffers mb = set_up_mailbox();
303 	struct ffa_partition_info *service2_info = service2(mb.recv);
304 	const ffa_id_t receiver_id = service2_info->vm_id;
305 
306 	gicv3_system_setup();
307 	interrupt_enable(PHYSICAL_TIMER_IRQ, true);
308 	interrupt_set_priority(PHYSICAL_TIMER_IRQ, 0x80);
309 	interrupt_set_edge_triggered(PHYSICAL_TIMER_IRQ, true);
310 	interrupt_set_priority_mask(0xff);
311 	arch_irq_enable();
312 
313 	/* Set physical timer for 20 ms and enable. */
314 	write_msr(CNTP_TVAL_EL0, ns_to_ticks(20000000));
315 	write_msr(CNTP_CTL_EL0, CNTx_CTL_ENABLE_MASK);
316 
317 	enable_trigger_trusted_wdog_timer(own_id, receiver_id, 200);
318 
319 	/* Send request to receiver SP to sleep. */
320 	res = sp_sleep_cmd_send(own_id, receiver_id, 50, 0);
321 
322 	/* SP is pre-empted by the non-secure timer interrupt. */
323 	EXPECT_EQ(res.func, FFA_INTERRUPT_32);
324 
325 	/* VM id/vCPU index are passed through arg1. */
326 	EXPECT_EQ(res.arg1, ffa_vm_vcpu(receiver_id, 0));
327 
328 	/* Waiting for interrupt to be serviced in normal world. */
329 	while (last_interrupt_id == 0) {
330 		EXPECT_EQ(io_read32_array(GICD_ISPENDR, 0), 0);
331 		EXPECT_EQ(io_read32(GICR_ISPENDR0), 0);
332 		EXPECT_EQ(io_read32_array(GICD_ISACTIVER, 0), 0);
333 		EXPECT_EQ(io_read32(GICR_ISACTIVER0), 0);
334 	}
335 
336 	/* Check that we got the interrupt. */
337 	EXPECT_EQ(last_interrupt_id, PHYSICAL_TIMER_IRQ);
338 
339 	/* Check timer status. */
340 	EXPECT_EQ(read_msr(CNTP_CTL_EL0),
341 		  CNTx_CTL_ISTS_MASK | CNTx_CTL_ENABLE_MASK);
342 
343 	/*
344 	 * NS Interrupt has been serviced and receiver SP is now in PREEMPTED
345 	 * state. Wait for trusted watchdog timer to be fired. SPMC queues
346 	 * the secure virtual interrupt.
347 	 */
348 	waitms(NS_SLEEP_TIME);
349 
350 	/*
351 	 * Resume the SP to complete the busy loop, handle the secure virtual
352 	 * interrupt and return with success.
353 	 */
354 	res = ffa_run(ffa_vm_id(res), ffa_vcpu_index(res));
355 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
356 	EXPECT_EQ(res.arg3, SP_SUCCESS);
357 
358 	check_and_disable_trusted_wdog_timer(own_id, receiver_id);
359 }
360 
361 /*
362  * Test Secure Partition runs to completion if it specifies action in response
363  * to Other-S Interrupt as queued.
364  */
TEST(secure_interrupts,sp_other_s_interrupt_queued)365 TEST(secure_interrupts, sp_other_s_interrupt_queued)
366 {
367 	struct ffa_value res;
368 	ffa_id_t own_id = hf_vm_get_id();
369 	struct mailbox_buffers mb = set_up_mailbox();
370 	struct ffa_partition_info *service2_info = service2(mb.recv);
371 	struct ffa_partition_info *service3_info = service3(mb.recv);
372 
373 	/*
374 	 * Service2 SP is the target of trusted watchdog timer interrupt.
375 	 * Service3 SP specified action to Other-S Interrupt as queued.
376 	 */
377 	const ffa_id_t target_id = service2_info->vm_id;
378 	const ffa_id_t receiver_id = service3_info->vm_id;
379 
380 	enable_trigger_trusted_wdog_timer(own_id, target_id, 400);
381 
382 	/*
383 	 * Send command to receiver SP(Service3) to sleep for SP_SLEEP_TIME
384 	 * ms. Secure interrupt should trigger while SP is busy in running the
385 	 * sleep command. SPMC queues the virtual interrupt and resumes the
386 	 * SP.
387 	 */
388 	res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME, 0);
389 
390 	/* Service3 SP finishes and sends direct response back. */
391 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
392 	EXPECT_EQ(sp_resp(res), SP_SUCCESS);
393 
394 	/*
395 	 * Allocate cycles to target SP for it to handle the virtual secure
396 	 * interrupt.
397 	 */
398 	res = sp_sleep_cmd_send(own_id, target_id, 10, 0);
399 
400 	/*
401 	 * Secure interrupt should trigger during this time, SP will handle the
402 	 * trusted watchdog timer interrupt.
403 	 */
404 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
405 	EXPECT_EQ(sp_resp(res), SP_SUCCESS);
406 
407 	/*
408 	 * Check if the trusted watchdog timer interrupt has been handled.
409 	 */
410 	check_and_disable_trusted_wdog_timer(own_id, target_id);
411 }
412 
413 /*
414  * Test that an SP can attempt to yield CPU cycles while handling secure
415  * interrupt by invoking FFA_YIELD.
416  */
TEST(secure_interrupts,sp_yield_sec_interrupt_handling)417 TEST(secure_interrupts, sp_yield_sec_interrupt_handling)
418 {
419 	struct ffa_value res;
420 	ffa_id_t own_id = hf_vm_get_id();
421 	struct mailbox_buffers mb = set_up_mailbox();
422 	struct ffa_partition_info *service2_info = service2(mb.recv);
423 	const ffa_id_t receiver_id = service2_info->vm_id;
424 	uint64_t time1;
425 	volatile uint64_t time_lapsed;
426 	uint64_t timer_freq = read_msr(cntfrq_el0);
427 
428 	/*
429 	 * Send command to SP asking it attempt to yield cycles while handling
430 	 * secure interrupt.
431 	 */
432 	res = sp_yield_secure_interrupt_handling_cmd_send(own_id, receiver_id,
433 							  true);
434 
435 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
436 	EXPECT_EQ(sp_resp(res), SP_SUCCESS);
437 
438 	enable_trigger_trusted_wdog_timer(own_id, receiver_id, 75);
439 	time1 = syscounter_read();
440 
441 	/*
442 	 * Sleep for 100ms. This ensures secure wdog timer triggers
443 	 * during this time. SP starts handling secure interrupt but attempts
444 	 * to yields cycles. However, SPMC just resumes the SP to complete
445 	 * interrupt handling.
446 	 */
447 	waitms(100);
448 
449 	/* Lapsed time should be at least equal to sleep time. */
450 	time_lapsed = ((syscounter_read() - time1) * 1000) / timer_freq;
451 
452 	EXPECT_GE(time_lapsed, 100);
453 
454 	res = sp_yield_secure_interrupt_handling_cmd_send(own_id, receiver_id,
455 							  false);
456 
457 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
458 	EXPECT_EQ(sp_resp(res), SP_SUCCESS);
459 	check_and_disable_trusted_wdog_timer(own_id, receiver_id);
460 }
461 
cpu_entry_sp_sleep_loop(uintptr_t arg)462 static void cpu_entry_sp_sleep_loop(uintptr_t arg)
463 {
464 	ffa_id_t own_id = hf_vm_get_id();
465 	struct ffa_value res;
466 	struct secondary_cpu_entry_args *args =
467 		// NOLINTNEXTLINE(performance-no-int-to-ptr)
468 		(struct secondary_cpu_entry_args *)arg;
469 	bool is_receiver_up_sp = args->vcpu_count == 1;
470 
471 	/*
472 	 * Execution context(s) of secondary Secure Partitions need CPU cycles
473 	 * to be allocated through FFA_RUN interface to reach message loop.
474 	 */
475 	if (is_receiver_up_sp) {
476 		res = ffa_run(args->receiver_id, (ffa_vcpu_index_t)0);
477 	} else {
478 		res = ffa_run(args->receiver_id, args->vcpu_id);
479 	}
480 
481 	EXPECT_EQ(ffa_func_id(res), FFA_MSG_WAIT_32);
482 
483 	/* Prepare for the trusted watchdog interrupt routed to target vCPU. */
484 	if (args->vcpu_id == args->target_vcpu_id) {
485 		res = sp_route_interrupt_to_target_vcpu_cmd_send(
486 			own_id, args->receiver_id, args->target_vcpu_id,
487 			IRQ_TWDOG_INTID);
488 
489 		EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
490 		EXPECT_EQ(sp_resp(res), SP_SUCCESS);
491 
492 		/*
493 		 * Make sure that twdog timer triggers shortly before the
494 		 * sleep duration ends.
495 		 */
496 		enable_trigger_trusted_wdog_timer(own_id, args->receiver_id,
497 						  SP_SLEEP_TIME - 50);
498 	}
499 
500 	/* Send request to the SP to sleep. */
501 	res = sp_sleep_cmd_send(own_id, args->receiver_id, SP_SLEEP_TIME, 0);
502 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
503 	EXPECT_EQ(sp_resp(res), SP_SUCCESS);
504 
505 	/* Make sure elapsed time not less than sleep time. */
506 	EXPECT_GE(sp_resp_value(res), SP_SLEEP_TIME);
507 
508 	/* Check for the last serviced secure virtual interrupt. */
509 	res = sp_get_last_interrupt_cmd_send(own_id, args->receiver_id);
510 
511 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
512 	EXPECT_EQ(sp_resp(res), SP_SUCCESS);
513 
514 	/*
515 	 * Expect the target execution context of Service2 SP to handle the
516 	 * trusted watchdog interrupt succesfully.
517 	 */
518 	if (args->vcpu_id == args->target_vcpu_id) {
519 		EXPECT_EQ(sp_resp_value(res), IRQ_TWDOG_INTID);
520 	} else {
521 		/*
522 		 * Make sure Trusted Watchdog timer interrupt was not serviced
523 		 * by this execution context.
524 		 */
525 		EXPECT_NE(sp_resp_value(res), IRQ_TWDOG_INTID);
526 	}
527 
528 	/* Clear last serviced secure virtual interrupt. */
529 	res = sp_clear_last_interrupt_cmd_send(own_id, args->receiver_id);
530 
531 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
532 	EXPECT_EQ(sp_resp(res), SP_SUCCESS);
533 
534 	/* Releases the lock passed in. */
535 	sl_unlock(&args->lock);
536 	arch_cpu_stop();
537 }
538 
sp_route_interrupt_to_secondary_vcpu_base(struct secondary_cpu_entry_args args)539 static void sp_route_interrupt_to_secondary_vcpu_base(
540 	struct secondary_cpu_entry_args args)
541 {
542 	/* Start secondary EC while holding lock. */
543 	sl_lock(&args.lock);
544 
545 	for (ffa_vcpu_index_t i = 1; i < MAX_CPUS; i++) {
546 		uintptr_t cpu_id;
547 
548 		cpu_id = hftest_get_cpu_id(i);
549 		args.vcpu_id = i;
550 		HFTEST_LOG("Booting CPU %u - %lx", i, cpu_id);
551 
552 		EXPECT_EQ(hftest_cpu_start(
553 				  cpu_id, hftest_get_secondary_ec_stack(i),
554 				  cpu_entry_sp_sleep_loop, (uintptr_t)&args),
555 			  true);
556 
557 		/* Wait for CPU to release the lock. */
558 		sl_lock(&args.lock);
559 
560 		HFTEST_LOG("Done with CPU %u", i);
561 	}
562 }
563 
564 /*
565  * Test a Secure Partition can request the SPMC to reconfigure an interrupt to
566  * be routed to a secondary vCPU.
567  */
TEST_LONG_RUNNING(secure_interrupts,sp_route_interrupt_to_secondary_vcpu)568 TEST_LONG_RUNNING(secure_interrupts, sp_route_interrupt_to_secondary_vcpu)
569 {
570 	struct secondary_cpu_entry_args args = {.lock = SPINLOCK_INIT};
571 	struct mailbox_buffers mb = set_up_mailbox();
572 	struct ffa_partition_info *service2_info = service2(mb.recv);
573 	const ffa_id_t receiver_id = service2_info->vm_id;
574 
575 	args.receiver_id = receiver_id;
576 	args.vcpu_count = service2_info->vcpu_count;
577 
578 	/*
579 	 * Reconfigure the twdog interrupt to be routed to last secondary
580 	 * execution context of SP.
581 	 */
582 	args.target_vcpu_id = LAST_SECONDARY_VCPU_ID;
583 	sp_route_interrupt_to_secondary_vcpu_base(args);
584 
585 	/*
586 	 * Reconfigure the twdog interrupt to be routed to mid secondary
587 	 * execution context of SP.
588 	 */
589 	args.target_vcpu_id = MID_SECONDARY_VCPU_ID;
590 	sp_route_interrupt_to_secondary_vcpu_base(args);
591 }
592