blob: 8ae1a1cd2fbe8b27a6583da87f5e2a403a2d92f2 [file] [log] [blame]
Andrew Scull2e7a76d2019-01-24 11:47:26 +00001/*
Andrew Walbran692b3252019-03-07 15:51:31 +00002 * Copyright 2019 The Hafnium Authors.
Andrew Scull2e7a76d2019-01-24 11:47:26 +00003 *
Andrew Walbrane959ec12020-06-17 15:01:09 +01004 * 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.
Andrew Scull2e7a76d2019-01-24 11:47:26 +00007 */
8
9#include <stdint.h>
10
Andrew Scull8d9e1212019-04-05 13:52:55 +010011#include "hf/std.h"
Andrew Scull2e7a76d2019-01-24 11:47:26 +000012
13#include "vmapi/hf/call.h"
14
Andrew Scull2e7a76d2019-01-24 11:47:26 +000015#include "primary_with_secondary.h"
Andrew Walbran1e7c7742019-12-13 17:10:02 +000016#include "test/hftest.h"
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010017#include "test/vmapi/ffa.h"
Andrew Scull2e7a76d2019-01-24 11:47:26 +000018
Andrew Walbrana0168d52019-12-16 11:55:06 +000019TEAR_DOWN(interrupts)
20{
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010021 EXPECT_FFA_ERROR(ffa_rx_release(), FFA_DENIED);
Andrew Walbrana0168d52019-12-16 11:55:06 +000022}
23
Andrew Scull2e7a76d2019-01-24 11:47:26 +000024/**
25 * Send a message to the interruptible VM, which will interrupt itself to send a
26 * response back.
27 */
28TEST(interrupts, interrupt_self)
29{
30 const char message[] = "Ping";
31 const char expected_response[] = "Got IRQ 05.";
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010032 struct ffa_value run_res;
Andrew Scull2e7a76d2019-01-24 11:47:26 +000033 struct mailbox_buffers mb = set_up_mailbox();
34
Fuad Tabba7bd14132019-11-07 14:18:52 +000035 SERVICE_SELECT(SERVICE_VM1, "interruptible", mb.send);
Andrew Scull2e7a76d2019-01-24 11:47:26 +000036
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010037 run_res = ffa_run(SERVICE_VM1, 0);
38 EXPECT_EQ(run_res.func, FFA_MSG_WAIT_32);
39 EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
Andrew Scull2e7a76d2019-01-24 11:47:26 +000040
41 /* Set the message, echo it and wait for a response. */
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010042 memcpy_s(mb.send, FFA_MSG_PAYLOAD_MAX, message, sizeof(message));
Andrew Walbran70bc8622019-10-07 14:15:58 +010043 EXPECT_EQ(
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010044 ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, sizeof(message), 0)
Andrew Walbran70bc8622019-10-07 14:15:58 +010045 .func,
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010046 FFA_SUCCESS_32);
47 run_res = ffa_run(SERVICE_VM1, 0);
48 EXPECT_EQ(run_res.func, FFA_MSG_SEND_32);
49 EXPECT_EQ(ffa_msg_send_size(run_res), sizeof(expected_response));
Andrew Walbran70bc8622019-10-07 14:15:58 +010050 EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
Andrew Scull2e7a76d2019-01-24 11:47:26 +000051 0);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010052 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
Andrew Scull2e7a76d2019-01-24 11:47:26 +000053}
54
55/**
56 * Inject an interrupt to the interrupt VM, which will send a message back.
57 * Repeat this twice to make sure it doesn't get into a bad state after the
58 * first one.
59 */
60TEST(interrupts, inject_interrupt_twice)
61{
62 const char expected_response[] = "Got IRQ 07.";
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010063 struct ffa_value run_res;
Andrew Scull2e7a76d2019-01-24 11:47:26 +000064 struct mailbox_buffers mb = set_up_mailbox();
65
Fuad Tabba7bd14132019-11-07 14:18:52 +000066 SERVICE_SELECT(SERVICE_VM1, "interruptible", mb.send);
Andrew Scull2e7a76d2019-01-24 11:47:26 +000067
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010068 run_res = ffa_run(SERVICE_VM1, 0);
69 EXPECT_EQ(run_res.func, FFA_MSG_WAIT_32);
70 EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
Andrew Scull2e7a76d2019-01-24 11:47:26 +000071
72 /* Inject the interrupt and wait for a message. */
Fuad Tabba7bd14132019-11-07 14:18:52 +000073 hf_interrupt_inject(SERVICE_VM1, 0, EXTERNAL_INTERRUPT_ID_A);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010074 run_res = ffa_run(SERVICE_VM1, 0);
75 EXPECT_EQ(run_res.func, FFA_MSG_SEND_32);
76 EXPECT_EQ(ffa_msg_send_size(run_res), sizeof(expected_response));
Andrew Walbran70bc8622019-10-07 14:15:58 +010077 EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
Andrew Scull2e7a76d2019-01-24 11:47:26 +000078 0);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010079 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
Andrew Scull2e7a76d2019-01-24 11:47:26 +000080
81 /* Inject the interrupt again, and wait for the same message. */
Fuad Tabba7bd14132019-11-07 14:18:52 +000082 hf_interrupt_inject(SERVICE_VM1, 0, EXTERNAL_INTERRUPT_ID_A);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010083 run_res = ffa_run(SERVICE_VM1, 0);
84 EXPECT_EQ(run_res.func, FFA_MSG_SEND_32);
85 EXPECT_EQ(ffa_msg_send_size(run_res), sizeof(expected_response));
Andrew Walbran70bc8622019-10-07 14:15:58 +010086 EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
Andrew Scull2e7a76d2019-01-24 11:47:26 +000087 0);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010088 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
Andrew Scull2e7a76d2019-01-24 11:47:26 +000089}
90
91/**
92 * Inject two different interrupts to the interrupt VM, which will send a
93 * message back each time.
94 */
95TEST(interrupts, inject_two_interrupts)
96{
97 const char expected_response[] = "Got IRQ 07.";
98 const char expected_response_2[] = "Got IRQ 08.";
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010099 struct ffa_value run_res;
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000100 struct mailbox_buffers mb = set_up_mailbox();
101
Fuad Tabba7bd14132019-11-07 14:18:52 +0000102 SERVICE_SELECT(SERVICE_VM1, "interruptible", mb.send);
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000103
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100104 run_res = ffa_run(SERVICE_VM1, 0);
105 EXPECT_EQ(run_res.func, FFA_MSG_WAIT_32);
106 EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000107
108 /* Inject the interrupt and wait for a message. */
Fuad Tabba7bd14132019-11-07 14:18:52 +0000109 hf_interrupt_inject(SERVICE_VM1, 0, EXTERNAL_INTERRUPT_ID_A);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100110 run_res = ffa_run(SERVICE_VM1, 0);
111 EXPECT_EQ(run_res.func, FFA_MSG_SEND_32);
112 EXPECT_EQ(ffa_msg_send_size(run_res), sizeof(expected_response));
Andrew Walbran70bc8622019-10-07 14:15:58 +0100113 EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000114 0);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100115 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000116
117 /* Inject a different interrupt and wait for a different message. */
Fuad Tabba7bd14132019-11-07 14:18:52 +0000118 hf_interrupt_inject(SERVICE_VM1, 0, EXTERNAL_INTERRUPT_ID_B);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100119 run_res = ffa_run(SERVICE_VM1, 0);
120 EXPECT_EQ(run_res.func, FFA_MSG_SEND_32);
121 EXPECT_EQ(ffa_msg_send_size(run_res), sizeof(expected_response_2));
Andrew Walbran70bc8622019-10-07 14:15:58 +0100122 EXPECT_EQ(memcmp(mb.recv, expected_response_2,
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000123 sizeof(expected_response_2)),
124 0);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100125 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000126}
127
128/**
129 * Inject an interrupt then send a message to the interrupt VM, which will send
130 * a message back each time. This is to test that interrupt injection doesn't
131 * interfere with message reception.
132 */
133TEST(interrupts, inject_interrupt_message)
134{
135 const char expected_response[] = "Got IRQ 07.";
136 const char message[] = "Ping";
137 const char expected_response_2[] = "Got IRQ 05.";
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100138 struct ffa_value run_res;
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000139 struct mailbox_buffers mb = set_up_mailbox();
140
Fuad Tabba7bd14132019-11-07 14:18:52 +0000141 SERVICE_SELECT(SERVICE_VM1, "interruptible", mb.send);
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000142
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100143 run_res = ffa_run(SERVICE_VM1, 0);
144 EXPECT_EQ(run_res.func, FFA_MSG_WAIT_32);
145 EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000146
147 /* Inject the interrupt and wait for a message. */
Fuad Tabba7bd14132019-11-07 14:18:52 +0000148 hf_interrupt_inject(SERVICE_VM1, 0, EXTERNAL_INTERRUPT_ID_A);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100149 run_res = ffa_run(SERVICE_VM1, 0);
150 EXPECT_EQ(run_res.func, FFA_MSG_SEND_32);
151 EXPECT_EQ(ffa_msg_send_size(run_res), sizeof(expected_response));
Andrew Walbran70bc8622019-10-07 14:15:58 +0100152 EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000153 0);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100154 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000155
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100156 run_res = ffa_run(SERVICE_VM1, 0);
157 EXPECT_EQ(run_res.func, FFA_MSG_WAIT_32);
158 EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000159
160 /* Now send a message to the secondary. */
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100161 memcpy_s(mb.send, FFA_MSG_PAYLOAD_MAX, message, sizeof(message));
Andrew Walbran70bc8622019-10-07 14:15:58 +0100162 EXPECT_EQ(
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100163 ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, sizeof(message), 0)
Andrew Walbran70bc8622019-10-07 14:15:58 +0100164 .func,
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100165 FFA_SUCCESS_32);
166 run_res = ffa_run(SERVICE_VM1, 0);
167 EXPECT_EQ(run_res.func, FFA_MSG_SEND_32);
168 EXPECT_EQ(ffa_msg_send_size(run_res), sizeof(expected_response_2));
Andrew Walbran70bc8622019-10-07 14:15:58 +0100169 EXPECT_EQ(memcmp(mb.recv, expected_response_2,
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000170 sizeof(expected_response_2)),
171 0);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100172 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000173}
174
175/**
176 * Inject an interrupt which the target VM has not enabled, and then send a
177 * message telling it to enable that interrupt ID. It should then (and only
178 * then) send a message back.
179 */
180TEST(interrupts, inject_interrupt_disabled)
181{
182 const char expected_response[] = "Got IRQ 09.";
183 const char message[] = "Enable interrupt C";
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100184 struct ffa_value run_res;
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000185 struct mailbox_buffers mb = set_up_mailbox();
186
Fuad Tabba7bd14132019-11-07 14:18:52 +0000187 SERVICE_SELECT(SERVICE_VM1, "interruptible", mb.send);
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000188
189 /* Inject the interrupt and expect not to get a message. */
Fuad Tabba7bd14132019-11-07 14:18:52 +0000190 hf_interrupt_inject(SERVICE_VM1, 0, EXTERNAL_INTERRUPT_ID_C);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100191 run_res = ffa_run(SERVICE_VM1, 0);
192 EXPECT_EQ(run_res.func, FFA_MSG_WAIT_32);
193 EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000194
195 /*
196 * Now send a message to the secondary to enable the interrupt ID, and
197 * expect the response from the interrupt we sent before.
198 */
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100199 memcpy_s(mb.send, FFA_MSG_PAYLOAD_MAX, message, sizeof(message));
Andrew Walbran70bc8622019-10-07 14:15:58 +0100200 EXPECT_EQ(
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100201 ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, sizeof(message), 0)
Andrew Walbran70bc8622019-10-07 14:15:58 +0100202 .func,
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100203 FFA_SUCCESS_32);
204 run_res = ffa_run(SERVICE_VM1, 0);
205 EXPECT_EQ(run_res.func, FFA_MSG_SEND_32);
206 EXPECT_EQ(ffa_msg_send_size(run_res), sizeof(expected_response));
Andrew Walbran70bc8622019-10-07 14:15:58 +0100207 EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000208 0);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100209 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
Andrew Scull2e7a76d2019-01-24 11:47:26 +0000210}
Andrew Walbran9311c9a2019-03-12 16:59:04 +0000211
212/**
213 * If a secondary VM has an enabled and pending interrupt, even if interrupts
214 * are disabled globally via PSTATE, then hf_mailbox_receive should not block
215 * even if `block` is true.
216 */
217TEST(interrupts, pending_interrupt_no_blocking_receive)
218{
219 const char expected_response[] = "Done waiting";
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100220 struct ffa_value run_res;
Andrew Walbran9311c9a2019-03-12 16:59:04 +0000221 struct mailbox_buffers mb = set_up_mailbox();
222
Fuad Tabba7bd14132019-11-07 14:18:52 +0000223 SERVICE_SELECT(SERVICE_VM1, "receive_block", mb.send);
Andrew Walbran9311c9a2019-03-12 16:59:04 +0000224
225 /*
226 * Inject the interrupt and run the VM. It should disable interrupts
227 * globally, enable the specific interrupt, and then send us a message
228 * back after failing to receive a message a few times.
229 */
Fuad Tabba7bd14132019-11-07 14:18:52 +0000230 hf_interrupt_inject(SERVICE_VM1, 0, EXTERNAL_INTERRUPT_ID_A);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100231 run_res = ffa_run(SERVICE_VM1, 0);
232 EXPECT_EQ(run_res.func, FFA_MSG_SEND_32);
233 EXPECT_EQ(ffa_msg_send_size(run_res), sizeof(expected_response));
Andrew Walbran70bc8622019-10-07 14:15:58 +0100234 EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
Andrew Walbran9311c9a2019-03-12 16:59:04 +0000235 0);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100236 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
Andrew Walbran9311c9a2019-03-12 16:59:04 +0000237}
Andrew Walbran2d10e882019-03-14 18:17:42 +0000238
239/**
240 * If a secondary VM has an enabled and pending interrupt, even if interrupts
241 * are disabled globally via PSTATE, then WFI should be treated as a no-op and
242 * not return to the primary.
243 */
244TEST(interrupts, pending_interrupt_wfi_not_trapped)
245{
246 const char expected_response[] = "Done waiting";
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100247 struct ffa_value run_res;
Andrew Walbran2d10e882019-03-14 18:17:42 +0000248 struct mailbox_buffers mb = set_up_mailbox();
249
Fuad Tabba7bd14132019-11-07 14:18:52 +0000250 SERVICE_SELECT(SERVICE_VM1, "wfi", mb.send);
Andrew Walbran2d10e882019-03-14 18:17:42 +0000251
252 /*
253 * Inject the interrupt and run the VM. It should disable interrupts
254 * globally, enable the specific interrupt, and then send us a message
255 * back after running WFI a few times.
256 */
Fuad Tabba7bd14132019-11-07 14:18:52 +0000257 hf_interrupt_inject(SERVICE_VM1, 0, EXTERNAL_INTERRUPT_ID_A);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100258 run_res = ffa_run(SERVICE_VM1, 0);
259 EXPECT_EQ(run_res.func, FFA_MSG_SEND_32);
260 EXPECT_EQ(ffa_msg_send_size(run_res), sizeof(expected_response));
Andrew Walbran70bc8622019-10-07 14:15:58 +0100261 EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
Andrew Walbran2d10e882019-03-14 18:17:42 +0000262 0);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100263 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
Andrew Walbran2d10e882019-03-14 18:17:42 +0000264}
Andrew Scullb06d1752019-02-04 10:15:48 +0000265
266/*
267 * Deliver an interrupt and a message to the same vCPU and check that both are
268 * delivered the next time the vCPU is run.
269 */
270TEST(interrupts, deliver_interrupt_and_message)
271{
272 const char message[] = "I\'ll see you again.";
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100273 struct ffa_value run_res;
Andrew Scullb06d1752019-02-04 10:15:48 +0000274 struct mailbox_buffers mb = set_up_mailbox();
275
Fuad Tabba7bd14132019-11-07 14:18:52 +0000276 SERVICE_SELECT(SERVICE_VM1, "interruptible_echo", mb.send);
Andrew Scullb06d1752019-02-04 10:15:48 +0000277
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100278 run_res = ffa_run(SERVICE_VM1, 0);
279 EXPECT_EQ(run_res.func, FFA_MSG_WAIT_32);
280 EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
Andrew Scullb06d1752019-02-04 10:15:48 +0000281
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100282 memcpy_s(mb.send, FFA_MSG_PAYLOAD_MAX, message, sizeof(message));
Andrew Walbran70bc8622019-10-07 14:15:58 +0100283 EXPECT_EQ(
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100284 ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, sizeof(message), 0)
Andrew Walbran70bc8622019-10-07 14:15:58 +0100285 .func,
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100286 FFA_SUCCESS_32);
Fuad Tabba7bd14132019-11-07 14:18:52 +0000287 hf_interrupt_inject(SERVICE_VM1, 0, EXTERNAL_INTERRUPT_ID_A);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100288 run_res = ffa_run(SERVICE_VM1, 0);
289 EXPECT_EQ(run_res.func, FFA_MSG_SEND_32);
290 EXPECT_EQ(ffa_msg_send_size(run_res), sizeof(message));
Andrew Walbran70bc8622019-10-07 14:15:58 +0100291 EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100292 EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
Andrew Scullb06d1752019-02-04 10:15:48 +0000293}
Olivier Deprezfcfa8812020-08-06 16:24:11 +0200294
295/**
296 * The secondary vCPU is waiting for a direct msg request, but the primary
297 * instead injects an interrupt into it and calls FFA_RUN. The secondary
298 * should get FFA_INTERRUPT_32 returned, as well as the interrupt itself.
299 */
300TEST(interrupts_direct_msg, direct_msg_request_interrupted)
301{
302 struct mailbox_buffers mb = set_up_mailbox();
303 struct ffa_value res;
304
305 SERVICE_SELECT(SERVICE_VM1, "interruptible_echo_direct_msg", mb.send);
306
307 /* Let the secondary get started and wait for a message. */
308 res = ffa_run(SERVICE_VM1, 0);
309 EXPECT_EQ(res.func, FFA_MSG_WAIT_32);
310 EXPECT_EQ(res.arg2, FFA_SLEEP_INDEFINITE);
311
312 /* Send an initial direct message request */
313 res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, SERVICE_VM1, 1, 0, 0, 0,
314 0);
315 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
316 EXPECT_EQ(res.arg3, 2);
317
318 /* Inject an interrupt to the secondary VM */
319 hf_interrupt_inject(SERVICE_VM1, 0, EXTERNAL_INTERRUPT_ID_A);
320
321 /* Let the secondary VM run */
322 res = ffa_run(SERVICE_VM1, 0);
323 EXPECT_EQ(res.func, FFA_MSG_WAIT_32);
324
325 res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, SERVICE_VM1, 3, 0, 0, 0,
326 0);
327 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
328 EXPECT_EQ(res.arg3, 4);
329}
330
331/**
332 * The secondary vCPU is waiting for a direct request. The primary injects
333 * an interrupt into it and then calls FFA_MSG_SEND_DIRECT_REQ. The secondary
334 * shall get both the direct request and the interrupt.
335 */
336TEST(interrupts_direct_msg, direct_msg_request_with_interrupt)
337{
338 struct mailbox_buffers mb = set_up_mailbox();
339 struct ffa_value res;
340
341 SERVICE_SELECT(SERVICE_VM1,
342 "interruptible_echo_direct_msg_with_interrupt", mb.send);
343
344 /* Let the secondary get started and wait for a message. */
345 res = ffa_run(SERVICE_VM1, 0);
346 EXPECT_EQ(res.func, FFA_MSG_WAIT_32);
347 EXPECT_EQ(res.arg2, FFA_SLEEP_INDEFINITE);
348
349 /* Inject an interrupt to the secondary VM */
350 hf_interrupt_inject(SERVICE_VM1, 0, EXTERNAL_INTERRUPT_ID_A);
351
352 /*
353 * Send a direct message request. Expect the secondary VM to receive
354 * the message and the interrupt together. The secondary VM then
355 * replies with a direct message response.
356 */
357 res = ffa_msg_send_direct_req(HF_PRIMARY_VM_ID, SERVICE_VM1, 1, 0, 0, 0,
358 0);
359 EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
360 EXPECT_EQ(res.arg3, 2);
361}