blob: 0f5e3ce6632187f6ecdb834061ecdf62c3fcf2f3 [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
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
J-Alves19e20cf2023-08-02 12:48:55 +010081static void check_and_disable_trusted_wdog_timer(ffa_id_t own_id,
82 ffa_id_t receiver_id)
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060083{
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 */
103TEST(secure_interrupts, sp_running)
104{
105 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100106 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000107 struct mailbox_buffers mb = set_up_mailbox();
108 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100109 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -0600110
111 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
112
113 /* Send request to the SP to sleep. */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600114 res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME, 0);
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -0600115
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}
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600128
Kathleen Capella0abd8872024-02-02 18:01:12 -0500129/**
Madhukar Pappireddyed7dee82023-12-06 11:55:15 -0600130 * Test secure interrupt handling while the Secure Partition runs with
131 * interrupts potentially masked. This test helps to validate the functionality
Kathleen Capella0abd8872024-02-02 18:01:12 -0500132 * 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.
Madhukar Pappireddyed7dee82023-12-06 11:55:15 -0600135 */
136TEST(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. */
Madhukar Pappireddyca2f92d2024-02-15 16:39:23 -0600147 res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME,
148 OPTIONS_MASK_INTERRUPTS);
Madhukar Pappireddyed7dee82023-12-06 11:55:15 -0600149
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
Kathleen Capella0abd8872024-02-02 18:01:12 -0500163/**
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 */
170TEST(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
Madhukar Pappireddyed7dee82023-12-06 11:55:15 -0600200/*
Madhukar Pappireddy9ae48e92024-02-15 16:42:37 -0600201 * 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 */
205TEST(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/*
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600235 * Test secure interrupt handling while the Secure Partition is in WAITING
236 * state.
237 */
238TEST(secure_interrupts, sp_waiting)
239{
J-Alves19e20cf2023-08-02 12:48:55 +0100240 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000241 struct mailbox_buffers mb = set_up_mailbox();
242 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100243 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600244 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}
Madhukar Pappireddy8cc6deb2022-12-22 16:46:04 -0600264
265/*
266 * Test secure interrupt handling while the Secure Partition is in BLOCKED
267 * state.
268 */
269TEST(secure_interrupts, sp_blocked)
270{
271 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100272 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000273 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);
J-Alves19e20cf2023-08-02 12:48:55 +0100276 const ffa_id_t receiver_id = service2_info->vm_id;
277 const ffa_id_t companion_id = service1_info->vm_id;
Madhukar Pappireddy8cc6deb2022-12-22 16:46:04 -0600278
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,
Madhukar Pappireddyca2f92d2024-02-15 16:39:23 -0600286 SP_SLEEP_TIME, 0);
Madhukar Pappireddy8cc6deb2022-12-22 16:46:04 -0600287
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}
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600297
298TEST(secure_interrupts, sp_preempted)
299{
300 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100301 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000302 struct mailbox_buffers mb = set_up_mailbox();
303 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100304 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600305
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. */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600320 res = sp_sleep_cmd_send(own_id, receiver_id, 50, 0);
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600321
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}
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600360
361/*
362 * Test Secure Partition runs to completion if it specifies action in response
363 * to Other-S Interrupt as queued.
364 */
365TEST(secure_interrupts, sp_other_s_interrupt_queued)
366{
367 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100368 ffa_id_t own_id = hf_vm_get_id();
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600369 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 */
J-Alves19e20cf2023-08-02 12:48:55 +0100377 const ffa_id_t target_id = service2_info->vm_id;
378 const ffa_id_t receiver_id = service3_info->vm_id;
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600379
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 */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600388 res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME, 0);
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600389
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 */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600398 res = sp_sleep_cmd_send(own_id, target_id, 10, 0);
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600399
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}
Madhukar Pappireddyef062762023-05-23 17:46:57 -0500412
413/*
414 * Test that an SP can attempt to yield CPU cycles while handling secure
415 * interrupt by invoking FFA_YIELD.
416 */
417TEST(secure_interrupts, sp_yield_sec_interrupt_handling)
418{
419 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100420 ffa_id_t own_id = hf_vm_get_id();
Madhukar Pappireddyef062762023-05-23 17:46:57 -0500421 struct mailbox_buffers mb = set_up_mailbox();
422 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100423 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddyef062762023-05-23 17:46:57 -0500424 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}
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500461
462static 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. */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600501 res = sp_sleep_cmd_send(own_id, args->receiver_id, SP_SLEEP_TIME, 0);
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500502 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
539static 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;
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500547
J-Alves0c029c22023-06-21 10:32:57 +0100548 cpu_id = hftest_get_cpu_id(i);
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500549 args.vcpu_id = i;
Karl Meakine8937d92024-03-19 16:04:25 +0000550 HFTEST_LOG("Booting CPU %u - %lx", i, cpu_id);
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500551
J-Alves31e5c952024-07-12 09:45:05 +0100552 EXPECT_EQ(hftest_cpu_start(
553 cpu_id, hftest_get_secondary_ec_stack(i),
554 cpu_entry_sp_sleep_loop, (uintptr_t)&args),
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500555 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 */
Madhukar Pappireddy607c7242024-03-04 15:02:51 -0600568TEST_LONG_RUNNING(secure_interrupts, sp_route_interrupt_to_secondary_vcpu)
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500569{
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}