blob: 319a9c5358ba7be8a6dfef10fd1d9ef39000cd7b [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"
12#include "hf/arch/vm/timer.h"
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -060013
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060014#include "ffa_secure_partitions.h"
Madhukar Pappireddy66421182022-12-22 16:50:09 -060015#include "gicv3.h"
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060016#include "partition_services.h"
17#include "sp_helpers.h"
18
19#define SP_SLEEP_TIME 400U
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -060020#define NS_SLEEP_TIME 200U
21
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060022static void configure_trusted_wdog_interrupt(ffa_vm_id_t source,
23 ffa_vm_id_t dest, bool enable)
24{
25 struct ffa_value res;
26
27 res = sp_virtual_interrupt_cmd_send(source, dest, IRQ_TWDOG_INTID,
28 enable, 0);
29
30 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
31 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
32}
33
34static void enable_trusted_wdog_interrupt(ffa_vm_id_t source, ffa_vm_id_t dest)
35{
36 configure_trusted_wdog_interrupt(source, dest, true);
37}
38
39static void disable_trusted_wdog_interrupt(ffa_vm_id_t source, ffa_vm_id_t dest)
40{
41 configure_trusted_wdog_interrupt(source, dest, false);
42}
43
44static void enable_trigger_trusted_wdog_timer(ffa_vm_id_t own_id,
45 ffa_vm_id_t receiver_id,
46 uint32_t timer_ms)
47{
48 struct ffa_value res;
49
50 /* Enable trusted watchdog interrupt as vIRQ in the secure side. */
51 enable_trusted_wdog_interrupt(own_id, receiver_id);
52
53 res = sp_twdog_map_cmd_send(own_id, receiver_id);
54
55 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
56 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
57
58 /*
59 * Send a message to the SP through direct messaging requesting it to
60 * start the trusted watchdog timer.
61 */
62 res = sp_twdog_cmd_send(own_id, receiver_id, timer_ms);
63
64 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
65 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
66}
67
68static void check_and_disable_trusted_wdog_timer(ffa_vm_id_t own_id,
69 ffa_vm_id_t receiver_id)
70{
71 struct ffa_value res;
72
73 /* Check for the last serviced secure virtual interrupt. */
74 res = sp_get_last_interrupt_cmd_send(own_id, receiver_id);
75
76 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
77 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
78
79 /* Make sure Trusted Watchdog timer interrupt was serviced. */
80 EXPECT_EQ(sp_resp_value(res), IRQ_TWDOG_INTID);
81
82 /* Disable Trusted Watchdog interrupt. */
83 disable_trusted_wdog_interrupt(own_id, receiver_id);
84}
85
86/*
87 * Test secure interrupt handling while the Secure Partition is in RUNNING
88 * state.
89 */
90TEST(secure_interrupts, sp_running)
91{
92 struct ffa_value res;
93 ffa_vm_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +000094 struct mailbox_buffers mb = set_up_mailbox();
95 struct ffa_partition_info *service2_info = service2(mb.recv);
Madhukar Pappireddy457af4c2022-12-22 16:13:37 -060096 const ffa_vm_id_t receiver_id = service2_info->vm_id;
97
98 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
99
100 /* Send request to the SP to sleep. */
101 res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME);
102
103 /*
104 * Secure interrupt should trigger during this time, SP will handle the
105 * trusted watchdog timer interrupt.
106 */
107 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
108 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
109
110 /* Make sure elapsed time not less than sleep time. */
111 EXPECT_GE(sp_resp_value(res), SP_SLEEP_TIME);
112
113 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
114}
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600115
116/*
117 * Test secure interrupt handling while the Secure Partition is in WAITING
118 * state.
119 */
120TEST(secure_interrupts, sp_waiting)
121{
122 ffa_vm_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000123 struct mailbox_buffers mb = set_up_mailbox();
124 struct ffa_partition_info *service2_info = service2(mb.recv);
Madhukar Pappireddy4d16db62022-12-22 16:38:10 -0600125 const ffa_vm_id_t receiver_id = service2_info->vm_id;
126 uint64_t time1;
127 volatile uint64_t time_lapsed;
128 uint64_t timer_freq = read_msr(cntfrq_el0);
129
130 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 100);
131 time1 = syscounter_read();
132
133 /*
134 * Sleep for NS_SLEEP_TIME ms. This ensures secure wdog timer triggers
135 * during this time.
136 */
137 waitms(NS_SLEEP_TIME);
138
139 /* Lapsed time should be at least equal to sleep time. */
140 time_lapsed = ((syscounter_read() - time1) * 1000) / timer_freq;
141
142 EXPECT_GE(time_lapsed, NS_SLEEP_TIME);
143
144 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
145}
Madhukar Pappireddy8cc6deb2022-12-22 16:46:04 -0600146
147/*
148 * Test secure interrupt handling while the Secure Partition is in BLOCKED
149 * state.
150 */
151TEST(secure_interrupts, sp_blocked)
152{
153 struct ffa_value res;
154 ffa_vm_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000155 struct mailbox_buffers mb = set_up_mailbox();
156 struct ffa_partition_info *service1_info = service1(mb.recv);
157 struct ffa_partition_info *service2_info = service2(mb.recv);
Madhukar Pappireddy8cc6deb2022-12-22 16:46:04 -0600158 const ffa_vm_id_t receiver_id = service2_info->vm_id;
159 const ffa_vm_id_t companion_id = service1_info->vm_id;
160
161 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
162
163 /*
164 * Send command to receiver SP to send command to companion SP to sleep
165 * there by putting receiver SP in BLOCKED state.
166 */
167 res = sp_fwd_sleep_cmd_send(own_id, receiver_id, companion_id,
168 SP_SLEEP_TIME, false);
169
170 /*
171 * Secure interrupt should trigger during this time, receiver SP will
172 * handle the trusted watchdog timer and sends direct response message.
173 */
174 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
175 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
176
177 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
178}
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600179
180TEST(secure_interrupts, sp_preempted)
181{
182 struct ffa_value res;
183 ffa_vm_id_t own_id = hf_vm_get_id();
J-Alves5d6926a2022-12-08 14:44:28 +0000184 struct mailbox_buffers mb = set_up_mailbox();
185 struct ffa_partition_info *service2_info = service2(mb.recv);
Madhukar Pappireddy66421182022-12-22 16:50:09 -0600186 const ffa_vm_id_t receiver_id = service2_info->vm_id;
187
188 gicv3_system_setup();
189 interrupt_enable(PHYSICAL_TIMER_IRQ, true);
190 interrupt_set_priority(PHYSICAL_TIMER_IRQ, 0x80);
191 interrupt_set_edge_triggered(PHYSICAL_TIMER_IRQ, true);
192 interrupt_set_priority_mask(0xff);
193 arch_irq_enable();
194
195 /* Set physical timer for 20 ms and enable. */
196 write_msr(CNTP_TVAL_EL0, ns_to_ticks(20000000));
197 write_msr(CNTP_CTL_EL0, CNTx_CTL_ENABLE_MASK);
198
199 enable_trigger_trusted_wdog_timer(own_id, receiver_id, 200);
200
201 /* Send request to receiver SP to sleep. */
202 res = sp_sleep_cmd_send(own_id, receiver_id, 50);
203
204 /* SP is pre-empted by the non-secure timer interrupt. */
205 EXPECT_EQ(res.func, FFA_INTERRUPT_32);
206
207 /* VM id/vCPU index are passed through arg1. */
208 EXPECT_EQ(res.arg1, ffa_vm_vcpu(receiver_id, 0));
209
210 /* Waiting for interrupt to be serviced in normal world. */
211 while (last_interrupt_id == 0) {
212 EXPECT_EQ(io_read32_array(GICD_ISPENDR, 0), 0);
213 EXPECT_EQ(io_read32(GICR_ISPENDR0), 0);
214 EXPECT_EQ(io_read32_array(GICD_ISACTIVER, 0), 0);
215 EXPECT_EQ(io_read32(GICR_ISACTIVER0), 0);
216 }
217
218 /* Check that we got the interrupt. */
219 EXPECT_EQ(last_interrupt_id, PHYSICAL_TIMER_IRQ);
220
221 /* Check timer status. */
222 EXPECT_EQ(read_msr(CNTP_CTL_EL0),
223 CNTx_CTL_ISTS_MASK | CNTx_CTL_ENABLE_MASK);
224
225 /*
226 * NS Interrupt has been serviced and receiver SP is now in PREEMPTED
227 * state. Wait for trusted watchdog timer to be fired. SPMC queues
228 * the secure virtual interrupt.
229 */
230 waitms(NS_SLEEP_TIME);
231
232 /*
233 * Resume the SP to complete the busy loop, handle the secure virtual
234 * interrupt and return with success.
235 */
236 res = ffa_run(ffa_vm_id(res), ffa_vcpu_index(res));
237 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
238 EXPECT_EQ(res.arg3, SP_SUCCESS);
239
240 check_and_disable_trusted_wdog_timer(own_id, receiver_id);
241}
Madhukar Pappireddy7adccf72023-01-31 15:16:47 -0600242
243/*
244 * Test Secure Partition runs to completion if it specifies action in response
245 * to Other-S Interrupt as queued.
246 */
247TEST(secure_interrupts, sp_other_s_interrupt_queued)
248{
249 struct ffa_value res;
250 ffa_vm_id_t own_id = hf_vm_get_id();
251 struct mailbox_buffers mb = set_up_mailbox();
252 struct ffa_partition_info *service2_info = service2(mb.recv);
253 struct ffa_partition_info *service3_info = service3(mb.recv);
254
255 /*
256 * Service2 SP is the target of trusted watchdog timer interrupt.
257 * Service3 SP specified action to Other-S Interrupt as queued.
258 */
259 const ffa_vm_id_t target_id = service2_info->vm_id;
260 const ffa_vm_id_t receiver_id = service3_info->vm_id;
261
262 enable_trigger_trusted_wdog_timer(own_id, target_id, 400);
263
264 /*
265 * Send command to receiver SP(Service3) to sleep for SP_SLEEP_TIME
266 * ms. Secure interrupt should trigger while SP is busy in running the
267 * sleep command. SPMC queues the virtual interrupt and resumes the
268 * SP.
269 */
270 res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME);
271
272 /* Service3 SP finishes and sends direct response back. */
273 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
274 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
275
276 /*
277 * Allocate cycles to target SP for it to handle the virtual secure
278 * interrupt.
279 */
280 res = sp_sleep_cmd_send(own_id, target_id, 10);
281
282 /*
283 * Secure interrupt should trigger during this time, SP will handle the
284 * trusted watchdog timer interrupt.
285 */
286 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
287 EXPECT_EQ(sp_resp(res), SP_SUCCESS);
288
289 /*
290 * Check if the trusted watchdog timer interrupt has been handled.
291 */
292 check_and_disable_trusted_wdog_timer(own_id, target_id);
293}