blob: ae7cae4440a4c642b95f8df412ba3d06f5320354 [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"
Madhukar Pappireddy9a1b9c02024-01-04 17:14:16 -060018#include "sp805.h"
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060019#include "sp_helpers.h"
20
21#define SP_SLEEP_TIME 400U
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -060022#define NS_SLEEP_TIME 200U
23
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -050024#define LAST_SECONDARY_VCPU_ID (MAX_CPUS - 1)
25#define MID_SECONDARY_VCPU_ID (MAX_CPUS / 2)
26
27alignas(4096) static uint8_t secondary_ec_stack[MAX_CPUS - 1][PAGE_SIZE];
28
29struct secondary_cpu_entry_args {
30 ffa_id_t receiver_id;
31 ffa_vcpu_count_t vcpu_count;
32 ffa_vcpu_index_t vcpu_id;
33 struct spinlock lock;
34 ffa_vcpu_index_t target_vcpu_id;
35};
36
J-Alves19e20cf2023-08-02 12:48:55 +010037static void configure_trusted_wdog_interrupt(ffa_id_t source, ffa_id_t dest,
38 bool enable)
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060039{
40 struct ffa_value res;
41
42 res = sp_virtual_interrupt_cmd_send(source, dest, IRQ_TWDOG_INTID,
43 enable, 0);
44
45 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
46 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
47}
48
J-Alves19e20cf2023-08-02 12:48:55 +010049static void enable_trusted_wdog_interrupt(ffa_id_t source, ffa_id_t dest)
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060050{
51 configure_trusted_wdog_interrupt(source, dest, true);
52}
53
J-Alves19e20cf2023-08-02 12:48:55 +010054static void disable_trusted_wdog_interrupt(ffa_id_t source, ffa_id_t dest)
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060055{
56 configure_trusted_wdog_interrupt(source, dest, false);
57}
58
J-Alves19e20cf2023-08-02 12:48:55 +010059static void enable_trigger_trusted_wdog_timer(ffa_id_t own_id,
60 ffa_id_t receiver_id,
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060061 uint32_t timer_ms)
62{
63 struct ffa_value res;
64
65 /* Enable trusted watchdog interrupt as vIRQ in the secure side. */
66 enable_trusted_wdog_interrupt(own_id, receiver_id);
67
68 res = sp_twdog_map_cmd_send(own_id, receiver_id);
69
70 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
71 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
72
73 /*
74 * Send a message to the SP through direct messaging requesting it to
75 * start the trusted watchdog timer.
76 */
77 res = sp_twdog_cmd_send(own_id, receiver_id, timer_ms);
78
79 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
80 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
81}
82
J-Alves19e20cf2023-08-02 12:48:55 +010083static void check_and_disable_trusted_wdog_timer(ffa_id_t own_id,
84 ffa_id_t receiver_id)
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060085{
86 struct ffa_value res;
87
88 /* Check for the last serviced secure virtual interrupt. */
89 res = sp_get_last_interrupt_cmd_send(own_id, receiver_id);
90
91 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
92 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
93
94 /* Make sure Trusted Watchdog timer interrupt was serviced. */
95 EXPECT_EQ(sp_resp_value(res), IRQ_TWDOG_INTID);
96
97 /* Disable Trusted Watchdog interrupt. */
98 disable_trusted_wdog_interrupt(own_id, receiver_id);
99}
100
101/*
102 * Test secure interrupt handling while the Secure Partition is in RUNNING
103 * state.
104 */
105TEST(secure_interrupts, sp_running)
106{
107 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100108 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000109 struct mailbox_buffers mb = set_up_mailbox();
110 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100111 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -0600112
113 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
114
115 /* Send request to the SP to sleep. */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600116 res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME, 0);
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -0600117
118 /*
119 * Secure interrupt should trigger during this time, SP will handle the
120 * trusted watchdog timer interrupt.
121 */
122 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
123 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
124
125 /* Make sure elapsed time not less than sleep time. */
126 EXPECT_GE(sp_resp_value(res), SP_SLEEP_TIME);
127
128 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
129}
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600130
131/*
Madhukar Pappireddyed7dee82023-12-06 11:55:15 -0600132 * Test secure interrupt handling while the Secure Partition runs with
133 * interrupts potentially masked. This test helps to validate the functionality
134 * of the SPMC to intercept a direct response message if there are pending
135 * virtual secure interrupts and reschedule the partition to handle the pending
136 * interrupt.
137 */
138TEST(secure_interrupts, sp_direct_response_intercepted)
139{
140 struct ffa_value res;
141 ffa_id_t own_id = hf_vm_get_id();
142 struct mailbox_buffers mb = set_up_mailbox();
143 struct ffa_partition_info *service2_info = service2(mb.recv);
144 const ffa_id_t receiver_id = service2_info->vm_id;
145
146 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
147
148 /* Send request to the SP to sleep uninterrupted. */
Madhukar Pappireddyca2f92d2024-02-15 16:39:23 -0600149 res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME,
150 OPTIONS_MASK_INTERRUPTS);
Madhukar Pappireddyed7dee82023-12-06 11:55:15 -0600151
152 /*
153 * Secure interrupt should trigger during this time, SP will handle the
154 * trusted watchdog timer interrupt.
155 */
156 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
157 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
158
159 /* Make sure elapsed time not less than sleep time. */
160 EXPECT_GE(sp_resp_value(res), SP_SLEEP_TIME);
161
162 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
163}
164
165/*
Madhukar Pappireddy9ae48e92024-02-15 16:42:37 -0600166 * This test is an extension of the 'sp_direct_response_intercepted' test. It
167 * creates a scenario where a direct response message between two Secure
168 * partitions in intercepted to signal a pending virtual secure interrupt.
169 */
170TEST(secure_interrupts, sp_forward_direct_response_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 *service1_info = service1(mb.recv);
176 struct ffa_partition_info *service2_info = service2(mb.recv);
177 const ffa_id_t receiver_id = service2_info->vm_id;
178 const ffa_id_t companion_id = service1_info->vm_id;
179
180 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
181
182 /*
183 * Send request to the companion SP to send command to receiver SP to
184 * sleep uninterrupted.
185 */
186 res = sp_fwd_sleep_cmd_send(own_id, companion_id, receiver_id,
187 SP_SLEEP_TIME, OPTIONS_MASK_INTERRUPTS);
188
189 /*
190 * Secure interrupt should trigger during this time, SP will handle the
191 * trusted watchdog timer interrupt.
192 */
193 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
194 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
195
196 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
197}
198
199/*
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600200 * Test secure interrupt handling while the Secure Partition is in WAITING
201 * state.
202 */
203TEST(secure_interrupts, sp_waiting)
204{
J-Alves19e20cf2023-08-02 12:48:55 +0100205 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000206 struct mailbox_buffers mb = set_up_mailbox();
207 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100208 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600209 uint64_t time1;
210 volatile uint64_t time_lapsed;
211 uint64_t timer_freq = read_msr(cntfrq_el0);
212
213 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 100);
214 time1 = syscounter_read();
215
216 /*
217 * Sleep for NS_SLEEP_TIME ms. This ensures secure wdog timer triggers
218 * during this time.
219 */
220 waitms(NS_SLEEP_TIME);
221
222 /* Lapsed time should be at least equal to sleep time. */
223 time_lapsed = ((syscounter_read() - time1) * 1000) / timer_freq;
224
225 EXPECT_GE(time_lapsed, NS_SLEEP_TIME);
226
227 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
228}
Madhukar Pappireddy8cc6deb2022-12-22 16:46:04 -0600229
230/*
231 * Test secure interrupt handling while the Secure Partition is in BLOCKED
232 * state.
233 */
234TEST(secure_interrupts, sp_blocked)
235{
236 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100237 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000238 struct mailbox_buffers mb = set_up_mailbox();
239 struct ffa_partition_info *service1_info = service1(mb.recv);
240 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100241 const ffa_id_t receiver_id = service2_info->vm_id;
242 const ffa_id_t companion_id = service1_info->vm_id;
Madhukar Pappireddy8cc6deb2022-12-22 16:46:04 -0600243
244 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
245
246 /*
247 * Send command to receiver SP to send command to companion SP to sleep
248 * there by putting receiver SP in BLOCKED state.
249 */
250 res = sp_fwd_sleep_cmd_send(own_id, receiver_id, companion_id,
Madhukar Pappireddyca2f92d2024-02-15 16:39:23 -0600251 SP_SLEEP_TIME, 0);
Madhukar Pappireddy8cc6deb2022-12-22 16:46:04 -0600252
253 /*
254 * Secure interrupt should trigger during this time, receiver SP will
255 * handle the trusted watchdog timer and sends direct response message.
256 */
257 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
258 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
259
260 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
261}
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600262
263TEST(secure_interrupts, sp_preempted)
264{
265 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100266 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000267 struct mailbox_buffers mb = set_up_mailbox();
268 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100269 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600270
271 gicv3_system_setup();
272 interrupt_enable(PHYSICAL_TIMER_IRQ, true);
273 interrupt_set_priority(PHYSICAL_TIMER_IRQ, 0x80);
274 interrupt_set_edge_triggered(PHYSICAL_TIMER_IRQ, true);
275 interrupt_set_priority_mask(0xff);
276 arch_irq_enable();
277
278 /* Set physical timer for 20 ms and enable. */
279 write_msr(CNTP_TVAL_EL0, ns_to_ticks(20000000));
280 write_msr(CNTP_CTL_EL0, CNTx_CTL_ENABLE_MASK);
281
282 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 200);
283
284 /* Send request to receiver SP to sleep. */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600285 res = sp_sleep_cmd_send(own_id, receiver_id, 50, 0);
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600286
287 /* SP is pre-empted by the non-secure timer interrupt. */
288 EXPECT_EQ(res.func, FFA_INTERRUPT_32);
289
290 /* VM id/vCPU index are passed through arg1. */
291 EXPECT_EQ(res.arg1, ffa_vm_vcpu(receiver_id, 0));
292
293 /* Waiting for interrupt to be serviced in normal world. */
294 while (last_interrupt_id == 0) {
295 EXPECT_EQ(io_read32_array(GICD_ISPENDR, 0), 0);
296 EXPECT_EQ(io_read32(GICR_ISPENDR0), 0);
297 EXPECT_EQ(io_read32_array(GICD_ISACTIVER, 0), 0);
298 EXPECT_EQ(io_read32(GICR_ISACTIVER0), 0);
299 }
300
301 /* Check that we got the interrupt. */
302 EXPECT_EQ(last_interrupt_id, PHYSICAL_TIMER_IRQ);
303
304 /* Check timer status. */
305 EXPECT_EQ(read_msr(CNTP_CTL_EL0),
306 CNTx_CTL_ISTS_MASK | CNTx_CTL_ENABLE_MASK);
307
308 /*
309 * NS Interrupt has been serviced and receiver SP is now in PREEMPTED
310 * state. Wait for trusted watchdog timer to be fired. SPMC queues
311 * the secure virtual interrupt.
312 */
313 waitms(NS_SLEEP_TIME);
314
315 /*
316 * Resume the SP to complete the busy loop, handle the secure virtual
317 * interrupt and return with success.
318 */
319 res = ffa_run(ffa_vm_id(res), ffa_vcpu_index(res));
320 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
321 EXPECT_EQ(res.arg3, SP_SUCCESS);
322
323 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
324}
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600325
326/*
327 * Test Secure Partition runs to completion if it specifies action in response
328 * to Other-S Interrupt as queued.
329 */
330TEST(secure_interrupts, sp_other_s_interrupt_queued)
331{
332 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100333 ffa_id_t own_id = hf_vm_get_id();
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600334 struct mailbox_buffers mb = set_up_mailbox();
335 struct ffa_partition_info *service2_info = service2(mb.recv);
336 struct ffa_partition_info *service3_info = service3(mb.recv);
337
338 /*
339 * Service2 SP is the target of trusted watchdog timer interrupt.
340 * Service3 SP specified action to Other-S Interrupt as queued.
341 */
J-Alves19e20cf2023-08-02 12:48:55 +0100342 const ffa_id_t target_id = service2_info->vm_id;
343 const ffa_id_t receiver_id = service3_info->vm_id;
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600344
345 enable_trigger_trusted_wdog_timer(own_id, target_id, 400);
346
347 /*
348 * Send command to receiver SP(Service3) to sleep for SP_SLEEP_TIME
349 * ms. Secure interrupt should trigger while SP is busy in running the
350 * sleep command. SPMC queues the virtual interrupt and resumes the
351 * SP.
352 */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600353 res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME, 0);
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600354
355 /* Service3 SP finishes and sends direct response back. */
356 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
357 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
358
359 /*
360 * Allocate cycles to target SP for it to handle the virtual secure
361 * interrupt.
362 */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600363 res = sp_sleep_cmd_send(own_id, target_id, 10, 0);
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600364
365 /*
366 * Secure interrupt should trigger during this time, SP will handle the
367 * trusted watchdog timer interrupt.
368 */
369 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
370 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
371
372 /*
373 * Check if the trusted watchdog timer interrupt has been handled.
374 */
375 check_and_disable_trusted_wdog_timer(own_id, target_id);
376}
Madhukar Pappireddyef062762023-05-23 17:46:57 -0500377
378/*
379 * Test that an SP can attempt to yield CPU cycles while handling secure
380 * interrupt by invoking FFA_YIELD.
381 */
382TEST(secure_interrupts, sp_yield_sec_interrupt_handling)
383{
384 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100385 ffa_id_t own_id = hf_vm_get_id();
Madhukar Pappireddyef062762023-05-23 17:46:57 -0500386 struct mailbox_buffers mb = set_up_mailbox();
387 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100388 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddyef062762023-05-23 17:46:57 -0500389 uint64_t time1;
390 volatile uint64_t time_lapsed;
391 uint64_t timer_freq = read_msr(cntfrq_el0);
392
393 /*
394 * Send command to SP asking it attempt to yield cycles while handling
395 * secure interrupt.
396 */
397 res = sp_yield_secure_interrupt_handling_cmd_send(own_id, receiver_id,
398 true);
399
400 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
401 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
402
403 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 75);
404 time1 = syscounter_read();
405
406 /*
407 * Sleep for 100ms. This ensures secure wdog timer triggers
408 * during this time. SP starts handling secure interrupt but attempts
409 * to yields cycles. However, SPMC just resumes the SP to complete
410 * interrupt handling.
411 */
412 waitms(100);
413
414 /* Lapsed time should be at least equal to sleep time. */
415 time_lapsed = ((syscounter_read() - time1) * 1000) / timer_freq;
416
417 EXPECT_GE(time_lapsed, 100);
418
419 res = sp_yield_secure_interrupt_handling_cmd_send(own_id, receiver_id,
420 false);
421
422 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
423 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
424 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
425}
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500426
427static void cpu_entry_sp_sleep_loop(uintptr_t arg)
428{
429 ffa_id_t own_id = hf_vm_get_id();
430 struct ffa_value res;
431 struct secondary_cpu_entry_args *args =
432 // NOLINTNEXTLINE(performance-no-int-to-ptr)
433 (struct secondary_cpu_entry_args *)arg;
434 bool is_receiver_up_sp = args->vcpu_count == 1;
435
436 /*
437 * Execution context(s) of secondary Secure Partitions need CPU cycles
438 * to be allocated through FFA_RUN interface to reach message loop.
439 */
440 if (is_receiver_up_sp) {
441 res = ffa_run(args->receiver_id, (ffa_vcpu_index_t)0);
442 } else {
443 res = ffa_run(args->receiver_id, args->vcpu_id);
444 }
445
446 EXPECT_EQ(ffa_func_id(res), FFA_MSG_WAIT_32);
447
448 /* Prepare for the trusted watchdog interrupt routed to target vCPU. */
449 if (args->vcpu_id == args->target_vcpu_id) {
450 res = sp_route_interrupt_to_target_vcpu_cmd_send(
451 own_id, args->receiver_id, args->target_vcpu_id,
452 IRQ_TWDOG_INTID);
453
454 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
455 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
456
457 /*
458 * Make sure that twdog timer triggers shortly before the
459 * sleep duration ends.
460 */
461 enable_trigger_trusted_wdog_timer(own_id, args->receiver_id,
462 SP_SLEEP_TIME - 50);
463 }
464
465 /* Send request to the SP to sleep. */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600466 res = sp_sleep_cmd_send(own_id, args->receiver_id, SP_SLEEP_TIME, 0);
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500467 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
468 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
469
470 /* Make sure elapsed time not less than sleep time. */
471 EXPECT_GE(sp_resp_value(res), SP_SLEEP_TIME);
472
473 /* Check for the last serviced secure virtual interrupt. */
474 res = sp_get_last_interrupt_cmd_send(own_id, args->receiver_id);
475
476 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
477 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
478
479 /*
480 * Expect the target execution context of Service2 SP to handle the
481 * trusted watchdog interrupt succesfully.
482 */
483 if (args->vcpu_id == args->target_vcpu_id) {
484 EXPECT_EQ(sp_resp_value(res), IRQ_TWDOG_INTID);
485 } else {
486 /*
487 * Make sure Trusted Watchdog timer interrupt was not serviced
488 * by this execution context.
489 */
490 EXPECT_NE(sp_resp_value(res), IRQ_TWDOG_INTID);
491 }
492
493 /* Clear last serviced secure virtual interrupt. */
494 res = sp_clear_last_interrupt_cmd_send(own_id, args->receiver_id);
495
496 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
497 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
498
499 /* Releases the lock passed in. */
500 sl_unlock(&args->lock);
501 arch_cpu_stop();
502}
503
504static void sp_route_interrupt_to_secondary_vcpu_base(
505 struct secondary_cpu_entry_args args)
506{
507 /* Start secondary EC while holding lock. */
508 sl_lock(&args.lock);
509
510 for (ffa_vcpu_index_t i = 1; i < MAX_CPUS; i++) {
511 uintptr_t cpu_id;
512 ffa_vcpu_index_t hftest_cpu_index = MAX_CPUS - i;
513
514 cpu_id = hftest_get_cpu_id(hftest_cpu_index);
515 args.vcpu_id = i;
516 HFTEST_LOG("Booting CPU %u - %x", i, cpu_id);
517
518 EXPECT_EQ(hftest_cpu_start(cpu_id, secondary_ec_stack[i - 1],
519 sizeof(secondary_ec_stack[0]),
520 cpu_entry_sp_sleep_loop,
521 (uintptr_t)&args),
522 true);
523
524 /* Wait for CPU to release the lock. */
525 sl_lock(&args.lock);
526
527 HFTEST_LOG("Done with CPU %u", i);
528 }
529}
530
531/*
532 * Test a Secure Partition can request the SPMC to reconfigure an interrupt to
533 * be routed to a secondary vCPU.
534 */
535TEST(secure_interrupts, sp_route_interrupt_to_secondary_vcpu)
536{
537 struct secondary_cpu_entry_args args = {.lock = SPINLOCK_INIT};
538 struct mailbox_buffers mb = set_up_mailbox();
539 struct ffa_partition_info *service2_info = service2(mb.recv);
540 const ffa_id_t receiver_id = service2_info->vm_id;
541
542 args.receiver_id = receiver_id;
543 args.vcpu_count = service2_info->vcpu_count;
544
545 /*
546 * Reconfigure the twdog interrupt to be routed to last secondary
547 * execution context of SP.
548 */
549 args.target_vcpu_id = LAST_SECONDARY_VCPU_ID;
550 sp_route_interrupt_to_secondary_vcpu_base(args);
551
552 /*
553 * Reconfigure the twdog interrupt to be routed to mid secondary
554 * execution context of SP.
555 */
556 args.target_vcpu_id = MID_SECONDARY_VCPU_ID;
557 sp_route_interrupt_to_secondary_vcpu_base(args);
558}