blob: 5bb984ea6623d3c68b157660fc1ef8981496cdc2 [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
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -050027struct 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
J-Alves19e20cf2023-08-02 12:48:55 +010035static void configure_trusted_wdog_interrupt(ffa_id_t source, ffa_id_t dest,
36 bool enable)
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060037{
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
J-Alves19e20cf2023-08-02 12:48:55 +010047static void enable_trusted_wdog_interrupt(ffa_id_t source, ffa_id_t dest)
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060048{
49 configure_trusted_wdog_interrupt(source, dest, true);
50}
51
J-Alves19e20cf2023-08-02 12:48:55 +010052static void disable_trusted_wdog_interrupt(ffa_id_t source, ffa_id_t dest)
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060053{
54 configure_trusted_wdog_interrupt(source, dest, false);
55}
56
J-Alves19e20cf2023-08-02 12:48:55 +010057static void enable_trigger_trusted_wdog_timer(ffa_id_t own_id,
58 ffa_id_t receiver_id,
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060059 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
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060066 /*
67 * Send a message to the SP through direct messaging requesting it to
68 * start the trusted watchdog timer.
69 */
70 res = sp_twdog_cmd_send(own_id, receiver_id, timer_ms);
71
72 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
73 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
74}
75
J-Alves19e20cf2023-08-02 12:48:55 +010076static void check_and_disable_trusted_wdog_timer(ffa_id_t own_id,
77 ffa_id_t receiver_id)
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060078{
79 struct ffa_value res;
80
81 /* Check for the last serviced secure virtual interrupt. */
82 res = sp_get_last_interrupt_cmd_send(own_id, receiver_id);
83
84 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
85 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
86
87 /* Make sure Trusted Watchdog timer interrupt was serviced. */
88 EXPECT_EQ(sp_resp_value(res), IRQ_TWDOG_INTID);
89
90 /* Disable Trusted Watchdog interrupt. */
91 disable_trusted_wdog_interrupt(own_id, receiver_id);
92}
93
94/*
95 * Test secure interrupt handling while the Secure Partition is in RUNNING
96 * state.
97 */
98TEST(secure_interrupts, sp_running)
99{
100 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100101 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000102 struct mailbox_buffers mb = set_up_mailbox();
103 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100104 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -0600105
106 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
107
108 /* Send request to the SP to sleep. */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600109 res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME, 0);
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -0600110
111 /*
112 * Secure interrupt should trigger during this time, SP will handle the
113 * trusted watchdog timer interrupt.
114 */
115 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
116 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
117
118 /* Make sure elapsed time not less than sleep time. */
119 EXPECT_GE(sp_resp_value(res), SP_SLEEP_TIME);
120
121 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
122}
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600123
Kathleen Capella0abd8872024-02-02 18:01:12 -0500124/**
Madhukar Pappireddyed7dee82023-12-06 11:55:15 -0600125 * Test secure interrupt handling while the Secure Partition runs with
126 * interrupts potentially masked. This test helps to validate the functionality
Kathleen Capella0abd8872024-02-02 18:01:12 -0500127 * of the SPMC to intercept a direct response message sent via
128 * FFA_MSG_SEND_DIRECT_RESP_32 if there are pending virtual secure interrupts
129 * and reschedule the partition to handle the pending interrupt.
Madhukar Pappireddyed7dee82023-12-06 11:55:15 -0600130 */
131TEST(secure_interrupts, sp_direct_response_intercepted)
132{
133 struct ffa_value res;
134 ffa_id_t own_id = hf_vm_get_id();
135 struct mailbox_buffers mb = set_up_mailbox();
136 struct ffa_partition_info *service2_info = service2(mb.recv);
137 const ffa_id_t receiver_id = service2_info->vm_id;
138
139 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
140
141 /* Send request to the SP to sleep uninterrupted. */
Madhukar Pappireddyca2f92d2024-02-15 16:39:23 -0600142 res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME,
143 OPTIONS_MASK_INTERRUPTS);
Madhukar Pappireddyed7dee82023-12-06 11:55:15 -0600144
145 /*
146 * Secure interrupt should trigger during this time, SP will handle the
147 * trusted watchdog timer interrupt.
148 */
149 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
150 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
151
152 /* Make sure elapsed time not less than sleep time. */
153 EXPECT_GE(sp_resp_value(res), SP_SLEEP_TIME);
154
155 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
156}
157
Kathleen Capella0abd8872024-02-02 18:01:12 -0500158/**
159 * Test secure interrupt handling while the Secure Partition runs with
160 * interrupts potentially masked. This test helps to validate the functionality
161 * of the SPMC to intercept a direct response message sent via
162 * FFA_MSG_SEND_DIRECT_RESP2_64 if there are pending virtual secure interrupts
163 * and reschedule the partition to handle the pending interrupt.
164 */
165TEST(secure_interrupts, sp_direct_response2_intercepted)
166{
167 struct ffa_value res;
168 ffa_id_t own_id = hf_vm_get_id();
169 struct mailbox_buffers mb = set_up_mailbox();
170 struct ffa_partition_info *service2_info = service2(mb.recv);
171 const ffa_id_t receiver_id = service2_info->vm_id;
172 const uint64_t msg[] = {SP_SLEEP_CMD, SP_SLEEP_TIME, 1};
173 struct ffa_uuid uuid;
174
175 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
176
177 /* Send request to the SP to sleep uninterrupted. */
178 ffa_uuid_init(0, 0, 0, 0, &uuid);
179 res = ffa_msg_send_direct_req2(own_id, receiver_id, &uuid,
180 (const uint64_t *)&msg, ARRAY_SIZE(msg));
181
182 /*
183 * Secure interrupt should trigger during this time, SP will handle the
184 * trusted watchdog timer interrupt.
185 */
186 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP2_64);
187 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
188
189 /* Make sure elapsed time not less than sleep time. */
190 EXPECT_GE(res.arg5, SP_SLEEP_TIME);
191
192 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
193}
194
Madhukar Pappireddyed7dee82023-12-06 11:55:15 -0600195/*
Madhukar Pappireddy9ae48e92024-02-15 16:42:37 -0600196 * This test is an extension of the 'sp_direct_response_intercepted' test. It
197 * creates a scenario where a direct response message between two Secure
198 * partitions in intercepted to signal a pending virtual secure interrupt.
199 */
200TEST(secure_interrupts, sp_forward_direct_response_intercepted)
201{
202 struct ffa_value res;
203 ffa_id_t own_id = hf_vm_get_id();
204 struct mailbox_buffers mb = set_up_mailbox();
205 struct ffa_partition_info *service1_info = service1(mb.recv);
206 struct ffa_partition_info *service2_info = service2(mb.recv);
207 const ffa_id_t receiver_id = service2_info->vm_id;
208 const ffa_id_t companion_id = service1_info->vm_id;
209
210 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
211
212 /*
213 * Send request to the companion SP to send command to receiver SP to
214 * sleep uninterrupted.
215 */
216 res = sp_fwd_sleep_cmd_send(own_id, companion_id, receiver_id,
217 SP_SLEEP_TIME, OPTIONS_MASK_INTERRUPTS);
218
219 /*
220 * Secure interrupt should trigger during this time, SP will handle the
221 * trusted watchdog timer interrupt.
222 */
223 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
224 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
225
226 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
227}
228
229/*
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600230 * Test secure interrupt handling while the Secure Partition is in WAITING
231 * state.
232 */
233TEST(secure_interrupts, sp_waiting)
234{
J-Alves19e20cf2023-08-02 12:48:55 +0100235 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000236 struct mailbox_buffers mb = set_up_mailbox();
237 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100238 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600239 uint64_t time1;
240 volatile uint64_t time_lapsed;
241 uint64_t timer_freq = read_msr(cntfrq_el0);
242
243 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 100);
244 time1 = syscounter_read();
245
246 /*
247 * Sleep for NS_SLEEP_TIME ms. This ensures secure wdog timer triggers
248 * during this time.
249 */
250 waitms(NS_SLEEP_TIME);
251
252 /* Lapsed time should be at least equal to sleep time. */
253 time_lapsed = ((syscounter_read() - time1) * 1000) / timer_freq;
254
255 EXPECT_GE(time_lapsed, NS_SLEEP_TIME);
256
257 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
258}
Madhukar Pappireddy8cc6deb2022-12-22 16:46:04 -0600259
260/*
261 * Test secure interrupt handling while the Secure Partition is in BLOCKED
262 * state.
263 */
264TEST(secure_interrupts, sp_blocked)
265{
266 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100267 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000268 struct mailbox_buffers mb = set_up_mailbox();
269 struct ffa_partition_info *service1_info = service1(mb.recv);
270 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100271 const ffa_id_t receiver_id = service2_info->vm_id;
272 const ffa_id_t companion_id = service1_info->vm_id;
Madhukar Pappireddy8cc6deb2022-12-22 16:46:04 -0600273
274 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
275
276 /*
277 * Send command to receiver SP to send command to companion SP to sleep
278 * there by putting receiver SP in BLOCKED state.
279 */
280 res = sp_fwd_sleep_cmd_send(own_id, receiver_id, companion_id,
Madhukar Pappireddyca2f92d2024-02-15 16:39:23 -0600281 SP_SLEEP_TIME, 0);
Madhukar Pappireddy8cc6deb2022-12-22 16:46:04 -0600282
283 /*
284 * Secure interrupt should trigger during this time, receiver SP will
285 * handle the trusted watchdog timer and sends direct response message.
286 */
287 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
288 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
289
290 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
291}
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600292
293TEST(secure_interrupts, sp_preempted)
294{
295 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100296 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000297 struct mailbox_buffers mb = set_up_mailbox();
298 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100299 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600300
301 gicv3_system_setup();
302 interrupt_enable(PHYSICAL_TIMER_IRQ, true);
303 interrupt_set_priority(PHYSICAL_TIMER_IRQ, 0x80);
304 interrupt_set_edge_triggered(PHYSICAL_TIMER_IRQ, true);
305 interrupt_set_priority_mask(0xff);
306 arch_irq_enable();
307
308 /* Set physical timer for 20 ms and enable. */
309 write_msr(CNTP_TVAL_EL0, ns_to_ticks(20000000));
310 write_msr(CNTP_CTL_EL0, CNTx_CTL_ENABLE_MASK);
311
312 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 200);
313
314 /* Send request to receiver SP to sleep. */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600315 res = sp_sleep_cmd_send(own_id, receiver_id, 50, 0);
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600316
317 /* SP is pre-empted by the non-secure timer interrupt. */
318 EXPECT_EQ(res.func, FFA_INTERRUPT_32);
319
320 /* VM id/vCPU index are passed through arg1. */
321 EXPECT_EQ(res.arg1, ffa_vm_vcpu(receiver_id, 0));
322
323 /* Waiting for interrupt to be serviced in normal world. */
324 while (last_interrupt_id == 0) {
325 EXPECT_EQ(io_read32_array(GICD_ISPENDR, 0), 0);
326 EXPECT_EQ(io_read32(GICR_ISPENDR0), 0);
327 EXPECT_EQ(io_read32_array(GICD_ISACTIVER, 0), 0);
328 EXPECT_EQ(io_read32(GICR_ISACTIVER0), 0);
329 }
330
331 /* Check that we got the interrupt. */
332 EXPECT_EQ(last_interrupt_id, PHYSICAL_TIMER_IRQ);
333
334 /* Check timer status. */
335 EXPECT_EQ(read_msr(CNTP_CTL_EL0),
336 CNTx_CTL_ISTS_MASK | CNTx_CTL_ENABLE_MASK);
337
338 /*
339 * NS Interrupt has been serviced and receiver SP is now in PREEMPTED
340 * state. Wait for trusted watchdog timer to be fired. SPMC queues
341 * the secure virtual interrupt.
342 */
343 waitms(NS_SLEEP_TIME);
344
345 /*
346 * Resume the SP to complete the busy loop, handle the secure virtual
347 * interrupt and return with success.
348 */
349 res = ffa_run(ffa_vm_id(res), ffa_vcpu_index(res));
350 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
351 EXPECT_EQ(res.arg3, SP_SUCCESS);
352
353 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
354}
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600355
356/*
357 * Test Secure Partition runs to completion if it specifies action in response
358 * to Other-S Interrupt as queued.
359 */
360TEST(secure_interrupts, sp_other_s_interrupt_queued)
361{
362 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100363 ffa_id_t own_id = hf_vm_get_id();
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600364 struct mailbox_buffers mb = set_up_mailbox();
365 struct ffa_partition_info *service2_info = service2(mb.recv);
366 struct ffa_partition_info *service3_info = service3(mb.recv);
367
368 /*
369 * Service2 SP is the target of trusted watchdog timer interrupt.
370 * Service3 SP specified action to Other-S Interrupt as queued.
371 */
J-Alves19e20cf2023-08-02 12:48:55 +0100372 const ffa_id_t target_id = service2_info->vm_id;
373 const ffa_id_t receiver_id = service3_info->vm_id;
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600374
375 enable_trigger_trusted_wdog_timer(own_id, target_id, 400);
376
377 /*
378 * Send command to receiver SP(Service3) to sleep for SP_SLEEP_TIME
379 * ms. Secure interrupt should trigger while SP is busy in running the
380 * sleep command. SPMC queues the virtual interrupt and resumes the
381 * SP.
382 */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600383 res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME, 0);
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600384
385 /* Service3 SP finishes and sends direct response back. */
386 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
387 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
388
389 /*
390 * Allocate cycles to target SP for it to handle the virtual secure
391 * interrupt.
392 */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600393 res = sp_sleep_cmd_send(own_id, target_id, 10, 0);
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600394
395 /*
396 * Secure interrupt should trigger during this time, SP will handle the
397 * trusted watchdog timer interrupt.
398 */
399 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
400 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
401
402 /*
403 * Check if the trusted watchdog timer interrupt has been handled.
404 */
405 check_and_disable_trusted_wdog_timer(own_id, target_id);
406}
Madhukar Pappireddyef062762023-05-23 17:46:57 -0500407
408/*
409 * Test that an SP can attempt to yield CPU cycles while handling secure
410 * interrupt by invoking FFA_YIELD.
411 */
412TEST(secure_interrupts, sp_yield_sec_interrupt_handling)
413{
414 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100415 ffa_id_t own_id = hf_vm_get_id();
Madhukar Pappireddyef062762023-05-23 17:46:57 -0500416 struct mailbox_buffers mb = set_up_mailbox();
417 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100418 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddyef062762023-05-23 17:46:57 -0500419 uint64_t time1;
420 volatile uint64_t time_lapsed;
421 uint64_t timer_freq = read_msr(cntfrq_el0);
422
423 /*
424 * Send command to SP asking it attempt to yield cycles while handling
425 * secure interrupt.
426 */
427 res = sp_yield_secure_interrupt_handling_cmd_send(own_id, receiver_id,
428 true);
429
430 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
431 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
432
433 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 75);
434 time1 = syscounter_read();
435
436 /*
437 * Sleep for 100ms. This ensures secure wdog timer triggers
438 * during this time. SP starts handling secure interrupt but attempts
439 * to yields cycles. However, SPMC just resumes the SP to complete
440 * interrupt handling.
441 */
442 waitms(100);
443
444 /* Lapsed time should be at least equal to sleep time. */
445 time_lapsed = ((syscounter_read() - time1) * 1000) / timer_freq;
446
447 EXPECT_GE(time_lapsed, 100);
448
449 res = sp_yield_secure_interrupt_handling_cmd_send(own_id, receiver_id,
450 false);
451
452 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
453 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
454 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
455}
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500456
457static void cpu_entry_sp_sleep_loop(uintptr_t arg)
458{
459 ffa_id_t own_id = hf_vm_get_id();
460 struct ffa_value res;
461 struct secondary_cpu_entry_args *args =
462 // NOLINTNEXTLINE(performance-no-int-to-ptr)
463 (struct secondary_cpu_entry_args *)arg;
464 bool is_receiver_up_sp = args->vcpu_count == 1;
465
466 /*
467 * Execution context(s) of secondary Secure Partitions need CPU cycles
468 * to be allocated through FFA_RUN interface to reach message loop.
469 */
470 if (is_receiver_up_sp) {
471 res = ffa_run(args->receiver_id, (ffa_vcpu_index_t)0);
472 } else {
473 res = ffa_run(args->receiver_id, args->vcpu_id);
474 }
475
476 EXPECT_EQ(ffa_func_id(res), FFA_MSG_WAIT_32);
477
478 /* Prepare for the trusted watchdog interrupt routed to target vCPU. */
479 if (args->vcpu_id == args->target_vcpu_id) {
480 res = sp_route_interrupt_to_target_vcpu_cmd_send(
481 own_id, args->receiver_id, args->target_vcpu_id,
482 IRQ_TWDOG_INTID);
483
484 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
485 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
486
487 /*
488 * Make sure that twdog timer triggers shortly before the
489 * sleep duration ends.
490 */
491 enable_trigger_trusted_wdog_timer(own_id, args->receiver_id,
492 SP_SLEEP_TIME - 50);
493 }
494
495 /* Send request to the SP to sleep. */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600496 res = sp_sleep_cmd_send(own_id, args->receiver_id, SP_SLEEP_TIME, 0);
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500497 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
498 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
499
500 /* Make sure elapsed time not less than sleep time. */
501 EXPECT_GE(sp_resp_value(res), SP_SLEEP_TIME);
502
503 /* Check for the last serviced secure virtual interrupt. */
504 res = sp_get_last_interrupt_cmd_send(own_id, args->receiver_id);
505
506 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
507 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
508
509 /*
510 * Expect the target execution context of Service2 SP to handle the
511 * trusted watchdog interrupt succesfully.
512 */
513 if (args->vcpu_id == args->target_vcpu_id) {
514 EXPECT_EQ(sp_resp_value(res), IRQ_TWDOG_INTID);
515 } else {
516 /*
517 * Make sure Trusted Watchdog timer interrupt was not serviced
518 * by this execution context.
519 */
520 EXPECT_NE(sp_resp_value(res), IRQ_TWDOG_INTID);
521 }
522
523 /* Clear last serviced secure virtual interrupt. */
524 res = sp_clear_last_interrupt_cmd_send(own_id, args->receiver_id);
525
526 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
527 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
528
529 /* Releases the lock passed in. */
530 sl_unlock(&args->lock);
531 arch_cpu_stop();
532}
533
534static void sp_route_interrupt_to_secondary_vcpu_base(
535 struct secondary_cpu_entry_args args)
536{
537 /* Start secondary EC while holding lock. */
538 sl_lock(&args.lock);
539
540 for (ffa_vcpu_index_t i = 1; i < MAX_CPUS; i++) {
541 uintptr_t cpu_id;
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500542
J-Alves0c029c22023-06-21 10:32:57 +0100543 cpu_id = hftest_get_cpu_id(i);
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500544 args.vcpu_id = i;
Karl Meakine8937d92024-03-19 16:04:25 +0000545 HFTEST_LOG("Booting CPU %u - %lx", i, cpu_id);
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500546
J-Alves31e5c952024-07-12 09:45:05 +0100547 EXPECT_EQ(hftest_cpu_start(
548 cpu_id, hftest_get_secondary_ec_stack(i),
549 cpu_entry_sp_sleep_loop, (uintptr_t)&args),
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500550 true);
551
552 /* Wait for CPU to release the lock. */
553 sl_lock(&args.lock);
554
555 HFTEST_LOG("Done with CPU %u", i);
556 }
557}
558
559/*
560 * Test a Secure Partition can request the SPMC to reconfigure an interrupt to
561 * be routed to a secondary vCPU.
562 */
Madhukar Pappireddy607c7242024-03-04 15:02:51 -0600563TEST_LONG_RUNNING(secure_interrupts, sp_route_interrupt_to_secondary_vcpu)
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500564{
565 struct secondary_cpu_entry_args args = {.lock = SPINLOCK_INIT};
566 struct mailbox_buffers mb = set_up_mailbox();
567 struct ffa_partition_info *service2_info = service2(mb.recv);
568 const ffa_id_t receiver_id = service2_info->vm_id;
569
570 args.receiver_id = receiver_id;
571 args.vcpu_count = service2_info->vcpu_count;
572
573 /*
574 * Reconfigure the twdog interrupt to be routed to last secondary
575 * execution context of SP.
576 */
577 args.target_vcpu_id = LAST_SECONDARY_VCPU_ID;
578 sp_route_interrupt_to_secondary_vcpu_base(args);
579
580 /*
581 * Reconfigure the twdog interrupt to be routed to mid secondary
582 * execution context of SP.
583 */
584 args.target_vcpu_id = MID_SECONDARY_VCPU_ID;
585 sp_route_interrupt_to_secondary_vcpu_base(args);
586}