blob: 50d06dad9ccdef2ac572815a853d0e1bca7c8675 [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
Kathleen Capella0abd8872024-02-02 18:01:12 -0500131/**
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
Kathleen Capella0abd8872024-02-02 18:01:12 -0500134 * of the SPMC to intercept a direct response message sent via
135 * FFA_MSG_SEND_DIRECT_RESP_32 if there are pending virtual secure interrupts
136 * and reschedule the partition to handle the pending interrupt.
Madhukar Pappireddyed7dee82023-12-06 11:55:15 -0600137 */
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
Kathleen Capella0abd8872024-02-02 18:01:12 -0500165/**
166 * Test secure interrupt handling while the Secure Partition runs with
167 * interrupts potentially masked. This test helps to validate the functionality
168 * of the SPMC to intercept a direct response message sent via
169 * FFA_MSG_SEND_DIRECT_RESP2_64 if there are pending virtual secure interrupts
170 * and reschedule the partition to handle the pending interrupt.
171 */
172TEST(secure_interrupts, sp_direct_response2_intercepted)
173{
174 struct ffa_value res;
175 ffa_id_t own_id = hf_vm_get_id();
176 struct mailbox_buffers mb = set_up_mailbox();
177 struct ffa_partition_info *service2_info = service2(mb.recv);
178 const ffa_id_t receiver_id = service2_info->vm_id;
179 const uint64_t msg[] = {SP_SLEEP_CMD, SP_SLEEP_TIME, 1};
180 struct ffa_uuid uuid;
181
182 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
183
184 /* Send request to the SP to sleep uninterrupted. */
185 ffa_uuid_init(0, 0, 0, 0, &uuid);
186 res = ffa_msg_send_direct_req2(own_id, receiver_id, &uuid,
187 (const uint64_t *)&msg, ARRAY_SIZE(msg));
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_RESP2_64);
194 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
195
196 /* Make sure elapsed time not less than sleep time. */
197 EXPECT_GE(res.arg5, SP_SLEEP_TIME);
198
199 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
200}
201
Madhukar Pappireddyed7dee82023-12-06 11:55:15 -0600202/*
Madhukar Pappireddy9ae48e92024-02-15 16:42:37 -0600203 * This test is an extension of the 'sp_direct_response_intercepted' test. It
204 * creates a scenario where a direct response message between two Secure
205 * partitions in intercepted to signal a pending virtual secure interrupt.
206 */
207TEST(secure_interrupts, sp_forward_direct_response_intercepted)
208{
209 struct ffa_value res;
210 ffa_id_t own_id = hf_vm_get_id();
211 struct mailbox_buffers mb = set_up_mailbox();
212 struct ffa_partition_info *service1_info = service1(mb.recv);
213 struct ffa_partition_info *service2_info = service2(mb.recv);
214 const ffa_id_t receiver_id = service2_info->vm_id;
215 const ffa_id_t companion_id = service1_info->vm_id;
216
217 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
218
219 /*
220 * Send request to the companion SP to send command to receiver SP to
221 * sleep uninterrupted.
222 */
223 res = sp_fwd_sleep_cmd_send(own_id, companion_id, receiver_id,
224 SP_SLEEP_TIME, OPTIONS_MASK_INTERRUPTS);
225
226 /*
227 * Secure interrupt should trigger during this time, SP will handle the
228 * trusted watchdog timer interrupt.
229 */
230 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
231 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
232
233 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
234}
235
236/*
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600237 * Test secure interrupt handling while the Secure Partition is in WAITING
238 * state.
239 */
240TEST(secure_interrupts, sp_waiting)
241{
J-Alves19e20cf2023-08-02 12:48:55 +0100242 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000243 struct mailbox_buffers mb = set_up_mailbox();
244 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100245 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600246 uint64_t time1;
247 volatile uint64_t time_lapsed;
248 uint64_t timer_freq = read_msr(cntfrq_el0);
249
250 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 100);
251 time1 = syscounter_read();
252
253 /*
254 * Sleep for NS_SLEEP_TIME ms. This ensures secure wdog timer triggers
255 * during this time.
256 */
257 waitms(NS_SLEEP_TIME);
258
259 /* Lapsed time should be at least equal to sleep time. */
260 time_lapsed = ((syscounter_read() - time1) * 1000) / timer_freq;
261
262 EXPECT_GE(time_lapsed, NS_SLEEP_TIME);
263
264 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
265}
Madhukar Pappireddy8cc6deb2022-12-22 16:46:04 -0600266
267/*
268 * Test secure interrupt handling while the Secure Partition is in BLOCKED
269 * state.
270 */
271TEST(secure_interrupts, sp_blocked)
272{
273 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100274 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000275 struct mailbox_buffers mb = set_up_mailbox();
276 struct ffa_partition_info *service1_info = service1(mb.recv);
277 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100278 const ffa_id_t receiver_id = service2_info->vm_id;
279 const ffa_id_t companion_id = service1_info->vm_id;
Madhukar Pappireddy8cc6deb2022-12-22 16:46:04 -0600280
281 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
282
283 /*
284 * Send command to receiver SP to send command to companion SP to sleep
285 * there by putting receiver SP in BLOCKED state.
286 */
287 res = sp_fwd_sleep_cmd_send(own_id, receiver_id, companion_id,
Madhukar Pappireddyca2f92d2024-02-15 16:39:23 -0600288 SP_SLEEP_TIME, 0);
Madhukar Pappireddy8cc6deb2022-12-22 16:46:04 -0600289
290 /*
291 * Secure interrupt should trigger during this time, receiver SP will
292 * handle the trusted watchdog timer and sends direct response message.
293 */
294 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
295 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
296
297 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
298}
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600299
300TEST(secure_interrupts, sp_preempted)
301{
302 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100303 ffa_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000304 struct mailbox_buffers mb = set_up_mailbox();
305 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100306 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600307
308 gicv3_system_setup();
309 interrupt_enable(PHYSICAL_TIMER_IRQ, true);
310 interrupt_set_priority(PHYSICAL_TIMER_IRQ, 0x80);
311 interrupt_set_edge_triggered(PHYSICAL_TIMER_IRQ, true);
312 interrupt_set_priority_mask(0xff);
313 arch_irq_enable();
314
315 /* Set physical timer for 20 ms and enable. */
316 write_msr(CNTP_TVAL_EL0, ns_to_ticks(20000000));
317 write_msr(CNTP_CTL_EL0, CNTx_CTL_ENABLE_MASK);
318
319 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 200);
320
321 /* Send request to receiver SP to sleep. */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600322 res = sp_sleep_cmd_send(own_id, receiver_id, 50, 0);
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600323
324 /* SP is pre-empted by the non-secure timer interrupt. */
325 EXPECT_EQ(res.func, FFA_INTERRUPT_32);
326
327 /* VM id/vCPU index are passed through arg1. */
328 EXPECT_EQ(res.arg1, ffa_vm_vcpu(receiver_id, 0));
329
330 /* Waiting for interrupt to be serviced in normal world. */
331 while (last_interrupt_id == 0) {
332 EXPECT_EQ(io_read32_array(GICD_ISPENDR, 0), 0);
333 EXPECT_EQ(io_read32(GICR_ISPENDR0), 0);
334 EXPECT_EQ(io_read32_array(GICD_ISACTIVER, 0), 0);
335 EXPECT_EQ(io_read32(GICR_ISACTIVER0), 0);
336 }
337
338 /* Check that we got the interrupt. */
339 EXPECT_EQ(last_interrupt_id, PHYSICAL_TIMER_IRQ);
340
341 /* Check timer status. */
342 EXPECT_EQ(read_msr(CNTP_CTL_EL0),
343 CNTx_CTL_ISTS_MASK | CNTx_CTL_ENABLE_MASK);
344
345 /*
346 * NS Interrupt has been serviced and receiver SP is now in PREEMPTED
347 * state. Wait for trusted watchdog timer to be fired. SPMC queues
348 * the secure virtual interrupt.
349 */
350 waitms(NS_SLEEP_TIME);
351
352 /*
353 * Resume the SP to complete the busy loop, handle the secure virtual
354 * interrupt and return with success.
355 */
356 res = ffa_run(ffa_vm_id(res), ffa_vcpu_index(res));
357 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
358 EXPECT_EQ(res.arg3, SP_SUCCESS);
359
360 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
361}
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600362
363/*
364 * Test Secure Partition runs to completion if it specifies action in response
365 * to Other-S Interrupt as queued.
366 */
367TEST(secure_interrupts, sp_other_s_interrupt_queued)
368{
369 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100370 ffa_id_t own_id = hf_vm_get_id();
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600371 struct mailbox_buffers mb = set_up_mailbox();
372 struct ffa_partition_info *service2_info = service2(mb.recv);
373 struct ffa_partition_info *service3_info = service3(mb.recv);
374
375 /*
376 * Service2 SP is the target of trusted watchdog timer interrupt.
377 * Service3 SP specified action to Other-S Interrupt as queued.
378 */
J-Alves19e20cf2023-08-02 12:48:55 +0100379 const ffa_id_t target_id = service2_info->vm_id;
380 const ffa_id_t receiver_id = service3_info->vm_id;
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600381
382 enable_trigger_trusted_wdog_timer(own_id, target_id, 400);
383
384 /*
385 * Send command to receiver SP(Service3) to sleep for SP_SLEEP_TIME
386 * ms. Secure interrupt should trigger while SP is busy in running the
387 * sleep command. SPMC queues the virtual interrupt and resumes the
388 * SP.
389 */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600390 res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME, 0);
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600391
392 /* Service3 SP finishes and sends direct response back. */
393 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
394 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
395
396 /*
397 * Allocate cycles to target SP for it to handle the virtual secure
398 * interrupt.
399 */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600400 res = sp_sleep_cmd_send(own_id, target_id, 10, 0);
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600401
402 /*
403 * Secure interrupt should trigger during this time, SP will handle the
404 * trusted watchdog timer interrupt.
405 */
406 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
407 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
408
409 /*
410 * Check if the trusted watchdog timer interrupt has been handled.
411 */
412 check_and_disable_trusted_wdog_timer(own_id, target_id);
413}
Madhukar Pappireddyef062762023-05-23 17:46:57 -0500414
415/*
416 * Test that an SP can attempt to yield CPU cycles while handling secure
417 * interrupt by invoking FFA_YIELD.
418 */
419TEST(secure_interrupts, sp_yield_sec_interrupt_handling)
420{
421 struct ffa_value res;
J-Alves19e20cf2023-08-02 12:48:55 +0100422 ffa_id_t own_id = hf_vm_get_id();
Madhukar Pappireddyef062762023-05-23 17:46:57 -0500423 struct mailbox_buffers mb = set_up_mailbox();
424 struct ffa_partition_info *service2_info = service2(mb.recv);
J-Alves19e20cf2023-08-02 12:48:55 +0100425 const ffa_id_t receiver_id = service2_info->vm_id;
Madhukar Pappireddyef062762023-05-23 17:46:57 -0500426 uint64_t time1;
427 volatile uint64_t time_lapsed;
428 uint64_t timer_freq = read_msr(cntfrq_el0);
429
430 /*
431 * Send command to SP asking it attempt to yield cycles while handling
432 * secure interrupt.
433 */
434 res = sp_yield_secure_interrupt_handling_cmd_send(own_id, receiver_id,
435 true);
436
437 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
438 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
439
440 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 75);
441 time1 = syscounter_read();
442
443 /*
444 * Sleep for 100ms. This ensures secure wdog timer triggers
445 * during this time. SP starts handling secure interrupt but attempts
446 * to yields cycles. However, SPMC just resumes the SP to complete
447 * interrupt handling.
448 */
449 waitms(100);
450
451 /* Lapsed time should be at least equal to sleep time. */
452 time_lapsed = ((syscounter_read() - time1) * 1000) / timer_freq;
453
454 EXPECT_GE(time_lapsed, 100);
455
456 res = sp_yield_secure_interrupt_handling_cmd_send(own_id, receiver_id,
457 false);
458
459 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
460 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
461 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
462}
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500463
464static void cpu_entry_sp_sleep_loop(uintptr_t arg)
465{
466 ffa_id_t own_id = hf_vm_get_id();
467 struct ffa_value res;
468 struct secondary_cpu_entry_args *args =
469 // NOLINTNEXTLINE(performance-no-int-to-ptr)
470 (struct secondary_cpu_entry_args *)arg;
471 bool is_receiver_up_sp = args->vcpu_count == 1;
472
473 /*
474 * Execution context(s) of secondary Secure Partitions need CPU cycles
475 * to be allocated through FFA_RUN interface to reach message loop.
476 */
477 if (is_receiver_up_sp) {
478 res = ffa_run(args->receiver_id, (ffa_vcpu_index_t)0);
479 } else {
480 res = ffa_run(args->receiver_id, args->vcpu_id);
481 }
482
483 EXPECT_EQ(ffa_func_id(res), FFA_MSG_WAIT_32);
484
485 /* Prepare for the trusted watchdog interrupt routed to target vCPU. */
486 if (args->vcpu_id == args->target_vcpu_id) {
487 res = sp_route_interrupt_to_target_vcpu_cmd_send(
488 own_id, args->receiver_id, args->target_vcpu_id,
489 IRQ_TWDOG_INTID);
490
491 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
492 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
493
494 /*
495 * Make sure that twdog timer triggers shortly before the
496 * sleep duration ends.
497 */
498 enable_trigger_trusted_wdog_timer(own_id, args->receiver_id,
499 SP_SLEEP_TIME - 50);
500 }
501
502 /* Send request to the SP to sleep. */
Madhukar Pappireddy3aafcb62023-12-06 11:49:04 -0600503 res = sp_sleep_cmd_send(own_id, args->receiver_id, SP_SLEEP_TIME, 0);
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500504 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
505 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
506
507 /* Make sure elapsed time not less than sleep time. */
508 EXPECT_GE(sp_resp_value(res), SP_SLEEP_TIME);
509
510 /* Check for the last serviced secure virtual interrupt. */
511 res = sp_get_last_interrupt_cmd_send(own_id, args->receiver_id);
512
513 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
514 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
515
516 /*
517 * Expect the target execution context of Service2 SP to handle the
518 * trusted watchdog interrupt succesfully.
519 */
520 if (args->vcpu_id == args->target_vcpu_id) {
521 EXPECT_EQ(sp_resp_value(res), IRQ_TWDOG_INTID);
522 } else {
523 /*
524 * Make sure Trusted Watchdog timer interrupt was not serviced
525 * by this execution context.
526 */
527 EXPECT_NE(sp_resp_value(res), IRQ_TWDOG_INTID);
528 }
529
530 /* Clear last serviced secure virtual interrupt. */
531 res = sp_clear_last_interrupt_cmd_send(own_id, args->receiver_id);
532
533 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
534 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
535
536 /* Releases the lock passed in. */
537 sl_unlock(&args->lock);
538 arch_cpu_stop();
539}
540
541static void sp_route_interrupt_to_secondary_vcpu_base(
542 struct secondary_cpu_entry_args args)
543{
544 /* Start secondary EC while holding lock. */
545 sl_lock(&args.lock);
546
547 for (ffa_vcpu_index_t i = 1; i < MAX_CPUS; i++) {
548 uintptr_t cpu_id;
549 ffa_vcpu_index_t hftest_cpu_index = MAX_CPUS - i;
550
551 cpu_id = hftest_get_cpu_id(hftest_cpu_index);
552 args.vcpu_id = i;
553 HFTEST_LOG("Booting CPU %u - %x", i, cpu_id);
554
555 EXPECT_EQ(hftest_cpu_start(cpu_id, secondary_ec_stack[i - 1],
556 sizeof(secondary_ec_stack[0]),
557 cpu_entry_sp_sleep_loop,
558 (uintptr_t)&args),
559 true);
560
561 /* Wait for CPU to release the lock. */
562 sl_lock(&args.lock);
563
564 HFTEST_LOG("Done with CPU %u", i);
565 }
566}
567
568/*
569 * Test a Secure Partition can request the SPMC to reconfigure an interrupt to
570 * be routed to a secondary vCPU.
571 */
Madhukar Pappireddy607c7242024-03-04 15:02:51 -0600572TEST_LONG_RUNNING(secure_interrupts, sp_route_interrupt_to_secondary_vcpu)
Madhukar Pappireddy6c23d432023-07-24 16:39:41 -0500573{
574 struct secondary_cpu_entry_args args = {.lock = SPINLOCK_INIT};
575 struct mailbox_buffers mb = set_up_mailbox();
576 struct ffa_partition_info *service2_info = service2(mb.recv);
577 const ffa_id_t receiver_id = service2_info->vm_id;
578
579 args.receiver_id = receiver_id;
580 args.vcpu_count = service2_info->vcpu_count;
581
582 /*
583 * Reconfigure the twdog interrupt to be routed to last secondary
584 * execution context of SP.
585 */
586 args.target_vcpu_id = LAST_SECONDARY_VCPU_ID;
587 sp_route_interrupt_to_secondary_vcpu_base(args);
588
589 /*
590 * Reconfigure the twdog interrupt to be routed to mid secondary
591 * execution context of SP.
592 */
593 args.target_vcpu_id = MID_SECONDARY_VCPU_ID;
594 sp_route_interrupt_to_secondary_vcpu_base(args);
595}