SPCI: Introduce SPCI_MSG_SEND.
Morph the vmapi service HF_MAILBOX_SEND onto SPCI_MSG_SEND.
The current SPCI_MSG_SEND only allows for implementation defined
messages to be exchanged between VMs.
The new SPCI service returns SPCI_SUCCESS if message is delivered or one
of the following error codes:
SPCI_INVALID_PARAMETER: one of the parameters in the header does
not conform;
SPCI_BUSY: the mailbox was full or the target VM does not exist.
Adapted the tests to this new service.
Added tests specific to spci_message_init and spci_msg_send.
Change-Id: I55adfe68502ddc7bf864432f3e567b6cfe785f92
diff --git a/test/hftest/hftest_service.c b/test/hftest/hftest_service.c
index 9850a07..2a1b2a0 100644
--- a/test/hftest/hftest_service.c
+++ b/test/hftest/hftest_service.c
@@ -20,6 +20,7 @@
#include "hf/arch/std.h"
#include "hf/memiter.h"
+#include "hf/spci.h"
#include "vmapi/hf/call.h"
@@ -80,17 +81,18 @@
{
struct memiter args;
hftest_test_fn service;
- struct hf_mailbox_receive_return res;
struct hftest_context *ctx;
+ struct spci_message *recv_msg = (struct spci_message *)recv;
+
/* Prepare the context. */
/* Set up the mailbox. */
hf_vm_configure(send_addr, recv_addr);
/* Receive the name of the service to run. */
- res = hf_mailbox_receive(true);
- memiter_init(&args, recv, res.size);
+ hf_mailbox_receive(true);
+ memiter_init(&args, recv_msg->payload, recv_msg->length);
service = find_service(&args);
hf_mailbox_clear();
@@ -108,8 +110,8 @@
ctx = hftest_get_context();
memset(ctx, 0, sizeof(*ctx));
ctx->abort = abort;
- ctx->send = send;
- ctx->recv = recv;
+ ctx->send = (struct spci_message *)send;
+ ctx->recv = (struct spci_message *)recv;
/* Pause so the next time cycles are given the service will be run. */
hf_vcpu_yield();
diff --git a/test/hftest/inc/hftest_impl.h b/test/hftest/inc/hftest_impl.h
index 5778b20..328f664 100644
--- a/test/hftest/inc/hftest_impl.h
+++ b/test/hftest/inc/hftest_impl.h
@@ -20,6 +20,8 @@
#include "hf/arch/std.h"
+#include "hf/spci.h"
+
#define HFTEST_MAX_TESTS 50
/*
@@ -133,8 +135,8 @@
noreturn void (*abort)(void);
/* These are used in services. */
- void *send;
- void *recv;
+ struct spci_message *send;
+ struct spci_message *recv;
};
struct hftest_context *hftest_get_context(void);
@@ -271,6 +273,7 @@
#define HFTEST_SERVICE_SELECT(vm_id, service, send_buffer) \
do { \
struct hf_vcpu_run_return run_res; \
+ uint32_t msg_length = strlen(service); \
\
/* \
* Let the service configure its mailbox and wait for a \
@@ -281,8 +284,11 @@
ASSERT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE); \
\
/* Send the selected service to run and let it be handled. */ \
- memcpy(send_buffer, service, strlen(service)); \
- ASSERT_EQ(hf_mailbox_send(vm_id, strlen(service), false), 0); \
+ memcpy(send_buffer->payload, service, msg_length); \
+ spci_message_init(send_buffer, msg_length, vm_id, \
+ hf_vm_get_id()); \
+ \
+ ASSERT_EQ(spci_msg_send(0), 0); \
run_res = hf_vcpu_run(vm_id, 0); \
ASSERT_EQ(run_res.code, HF_VCPU_RUN_YIELD); \
} while (0)
diff --git a/test/vmapi/gicv3/busy_secondary.c b/test/vmapi/gicv3/busy_secondary.c
index 9ea691f..f694031 100644
--- a/test/vmapi/gicv3/busy_secondary.c
+++ b/test/vmapi/gicv3/busy_secondary.c
@@ -19,6 +19,7 @@
#include "hf/arch/vm/interrupts_gicv3.h"
#include "hf/dlog.h"
+#include "hf/spci.h"
#include "vmapi/hf/call.h"
@@ -38,7 +39,7 @@
{
system_setup();
EXPECT_EQ(hf_vm_configure(send_page_addr, recv_page_addr), 0);
- SERVICE_SELECT(SERVICE_VM0, "busy", send_page);
+ SERVICE_SELECT(SERVICE_VM0, "busy", send_buffer);
}
TEST(busy_secondary, virtual_timer)
@@ -78,8 +79,10 @@
/* Let secondary start looping. */
dlog("Telling secondary to loop.\n");
- memcpy(send_page, message, sizeof(message));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(message), false), 0);
+ memcpy(send_buffer->payload, message, sizeof(message));
+ spci_message_init(send_buffer, 0, SERVICE_VM0,
+ recv_buffer->target_vm_id);
+ EXPECT_EQ(spci_msg_send(0), 0);
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_PREEMPTED);
@@ -133,8 +136,10 @@
/* Let secondary start looping. */
dlog("Telling secondary to loop.\n");
- memcpy(send_page, message, sizeof(message));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(message), false), 0);
+ memcpy(send_buffer->payload, message, sizeof(message));
+ spci_message_init(send_buffer, 0, SERVICE_VM0,
+ recv_buffer->target_vm_id);
+ EXPECT_EQ(spci_msg_send(0), 0);
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_PREEMPTED);
diff --git a/test/vmapi/gicv3/gicv3.c b/test/vmapi/gicv3/gicv3.c
index bc1e24d..dc0a081 100644
--- a/test/vmapi/gicv3/gicv3.c
+++ b/test/vmapi/gicv3/gicv3.c
@@ -34,6 +34,9 @@
hf_ipaddr_t send_page_addr = (hf_ipaddr_t)send_page;
hf_ipaddr_t recv_page_addr = (hf_ipaddr_t)recv_page;
+struct spci_message *send_buffer = (struct spci_message *)send_page;
+struct spci_message *recv_buffer = (struct spci_message *)recv_page;
+
volatile uint32_t last_interrupt_id = 0;
static void irq(void)
diff --git a/test/vmapi/gicv3/inc/gicv3.h b/test/vmapi/gicv3/inc/gicv3.h
index e4748cb..264dc0c 100644
--- a/test/vmapi/gicv3/inc/gicv3.h
+++ b/test/vmapi/gicv3/inc/gicv3.h
@@ -33,6 +33,9 @@
extern hf_ipaddr_t send_page_addr;
extern hf_ipaddr_t recv_page_addr;
+extern struct spci_message *send_buffer;
+extern struct spci_message *recv_buffer;
+
extern volatile uint32_t last_interrupt_id;
void system_setup();
diff --git a/test/vmapi/gicv3/services/busy.c b/test/vmapi/gicv3/services/busy.c
index f311124..4a18d35 100644
--- a/test/vmapi/gicv3/services/busy.c
+++ b/test/vmapi/gicv3/services/busy.c
@@ -31,7 +31,7 @@
TEST_SERVICE(busy)
{
dlog("Secondary waiting for message...\n");
- (void)mailbox_receive_retry();
+ mailbox_receive_retry();
hf_mailbox_clear();
dlog("Secondary received message, looping forever.\n");
for (;;) {
diff --git a/test/vmapi/gicv3/services/timer.c b/test/vmapi/gicv3/services/timer.c
index 029c729..79a2b8a 100644
--- a/test/vmapi/gicv3/services/timer.c
+++ b/test/vmapi/gicv3/services/timer.c
@@ -46,8 +46,10 @@
}
buffer[8] = '0' + interrupt_id / 10;
buffer[9] = '0' + interrupt_id % 10;
- memcpy(SERVICE_SEND_BUFFER(), buffer, size);
- hf_mailbox_send(HF_PRIMARY_VM_ID, size, false);
+ memcpy(SERVICE_SEND_BUFFER()->payload, buffer, size);
+ spci_message_init(SERVICE_SEND_BUFFER(), size, HF_PRIMARY_VM_ID,
+ SERVICE_RECV_BUFFER()->target_vm_id);
+ spci_msg_send(0);
dlog("secondary IRQ %d ended\n", interrupt_id);
event_send_local();
}
@@ -60,19 +62,22 @@
for (;;) {
const char timer_wfi_message[] = "**** xxxxxxx";
- char *message = SERVICE_RECV_BUFFER();
+ struct spci_message *message_header = SERVICE_RECV_BUFFER();
+ uint8_t *message;
bool wfi, wfe, receive;
bool disable_interrupts;
uint32_t ticks;
- struct hf_mailbox_receive_return received_message =
- mailbox_receive_retry();
+ mailbox_receive_retry();
- if (received_message.vm_id != HF_PRIMARY_VM_ID ||
- received_message.size != sizeof(timer_wfi_message)) {
+ if (message_header->source_vm_id != HF_PRIMARY_VM_ID ||
+ message_header->length != sizeof(timer_wfi_message)) {
FAIL("Got unexpected message from VM %d, size %d.\n",
- received_message.vm_id, received_message.size);
+ message_header->source_vm_id,
+ message_header->length);
}
+ message = message_header->payload;
+
/*
* Start a timer to send the message back: enable it and
* set it for the requested number of ticks.
diff --git a/test/vmapi/gicv3/timer_secondary.c b/test/vmapi/gicv3/timer_secondary.c
index dcb2e87..e554551 100644
--- a/test/vmapi/gicv3/timer_secondary.c
+++ b/test/vmapi/gicv3/timer_secondary.c
@@ -19,6 +19,7 @@
#include "hf/abi.h"
#include "hf/call.h"
+#include "hf/spci.h"
#include "gicv3.h"
#include "hftest.h"
@@ -28,7 +29,7 @@
system_setup();
EXPECT_EQ(hf_vm_configure(send_page_addr, recv_page_addr), 0);
- SERVICE_SELECT(SERVICE_VM0, "timer", send_page);
+ SERVICE_SELECT(SERVICE_VM0, "timer", send_buffer);
interrupt_enable(VIRTUAL_TIMER_IRQ, true);
interrupt_set_edge_triggered(VIRTUAL_TIMER_IRQ, true);
@@ -48,8 +49,10 @@
EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
/* Send the message for the secondary to set a timer. */
- memcpy(send_page, message, sizeof(message));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(message), false), 0);
+ memcpy(send_buffer->payload, message, sizeof(message));
+ spci_message_init(send_buffer, sizeof(message), SERVICE_VM0,
+ HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), 0);
/*
* Let the secondary handle the message and set the timer. It will loop
@@ -71,9 +74,9 @@
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(expected_response));
- EXPECT_EQ(
- memcmp(recv_page, expected_response, sizeof(expected_response)),
- 0);
+ EXPECT_EQ(memcmp(recv_buffer->payload, expected_response,
+ sizeof(expected_response)),
+ 0);
EXPECT_EQ(hf_mailbox_clear(), 0);
}
@@ -104,8 +107,10 @@
EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
/* Send the message for the secondary to set a timer. */
- memcpy(send_page, message, message_length);
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, message_length, false), 0);
+ memcpy(send_buffer->payload, message, message_length);
+ spci_message_init(send_buffer, message_length, SERVICE_VM0,
+ HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), 0);
/*
* Let the secondary handle the message and set the timer. Then there's
@@ -152,9 +157,9 @@
/* Once we wake it up it should get the timer interrupt and respond. */
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(expected_response));
- EXPECT_EQ(
- memcmp(recv_page, expected_response, sizeof(expected_response)),
- 0);
+ EXPECT_EQ(memcmp(recv_buffer->payload, expected_response,
+ sizeof(expected_response)),
+ 0);
EXPECT_EQ(hf_mailbox_clear(), 0);
}
@@ -240,8 +245,10 @@
EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
/* Send the message for the secondary to set a timer. */
- memcpy(send_page, message, message_length);
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, message_length, false), 0);
+ memcpy(send_buffer->payload, message, message_length);
+ spci_message_init(send_buffer, message_length, SERVICE_VM0,
+ HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), 0);
/*
* Let the secondary handle the message and set the timer.
diff --git a/test/vmapi/primary_with_secondaries/BUILD.gn b/test/vmapi/primary_with_secondaries/BUILD.gn
index b82fa30..34f8857 100644
--- a/test/vmapi/primary_with_secondaries/BUILD.gn
+++ b/test/vmapi/primary_with_secondaries/BUILD.gn
@@ -30,6 +30,7 @@
"memory_sharing.c",
"no_services.c",
"run_race.c",
+ "spci.c",
]
sources += [ "util.c" ]
diff --git a/test/vmapi/primary_with_secondaries/inc/util.h b/test/vmapi/primary_with_secondaries/inc/util.h
index b127fae..eca641f 100644
--- a/test/vmapi/primary_with_secondaries/inc/util.h
+++ b/test/vmapi/primary_with_secondaries/inc/util.h
@@ -16,9 +16,11 @@
#pragma once
+#include "vmapi/hf/spci.h"
+
struct mailbox_buffers {
- void *send;
- void *recv;
+ struct spci_message *send;
+ struct spci_message *recv;
};
struct mailbox_buffers set_up_mailbox(void);
diff --git a/test/vmapi/primary_with_secondaries/interrupts.c b/test/vmapi/primary_with_secondaries/interrupts.c
index 655ca54..9429acc 100644
--- a/test/vmapi/primary_with_secondaries/interrupts.c
+++ b/test/vmapi/primary_with_secondaries/interrupts.c
@@ -42,12 +42,15 @@
EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
/* Set the message, echo it and wait for a response. */
- memcpy(mb.send, message, sizeof(message));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(message), false), 0);
+ memcpy(mb.send->payload, message, sizeof(message));
+ spci_message_init(mb.send, sizeof(message), SERVICE_VM0,
+ HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), 0);
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(expected_response));
- EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
+ EXPECT_EQ(memcmp(mb.recv->payload, expected_response,
+ sizeof(expected_response)),
0);
EXPECT_EQ(hf_mailbox_clear(), 0);
}
@@ -74,7 +77,8 @@
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(expected_response));
- EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
+ EXPECT_EQ(memcmp(mb.recv->payload, expected_response,
+ sizeof(expected_response)),
0);
EXPECT_EQ(hf_mailbox_clear(), 0);
@@ -83,7 +87,8 @@
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(expected_response));
- EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
+ EXPECT_EQ(memcmp(mb.recv->payload, expected_response,
+ sizeof(expected_response)),
0);
EXPECT_EQ(hf_mailbox_clear(), 0);
}
@@ -110,7 +115,8 @@
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(expected_response));
- EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
+ EXPECT_EQ(memcmp(mb.recv->payload, expected_response,
+ sizeof(expected_response)),
0);
EXPECT_EQ(hf_mailbox_clear(), 0);
@@ -119,7 +125,7 @@
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(expected_response_2));
- EXPECT_EQ(memcmp(mb.recv, expected_response_2,
+ EXPECT_EQ(memcmp(mb.recv->payload, expected_response_2,
sizeof(expected_response_2)),
0);
EXPECT_EQ(hf_mailbox_clear(), 0);
@@ -149,7 +155,8 @@
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(expected_response));
- EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
+ EXPECT_EQ(memcmp(mb.recv->payload, expected_response,
+ sizeof(expected_response)),
0);
EXPECT_EQ(hf_mailbox_clear(), 0);
@@ -158,12 +165,14 @@
EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
/* Now send a message to the secondary. */
- memcpy(mb.send, message, sizeof(message));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(message), false), 0);
+ memcpy(mb.send->payload, message, sizeof(message));
+ spci_message_init(mb.send, sizeof(message), SERVICE_VM0,
+ HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), 0);
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(expected_response_2));
- EXPECT_EQ(memcmp(mb.recv, expected_response_2,
+ EXPECT_EQ(memcmp(mb.recv->payload, expected_response_2,
sizeof(expected_response_2)),
0);
EXPECT_EQ(hf_mailbox_clear(), 0);
@@ -193,12 +202,15 @@
* Now send a message to the secondary to enable the interrupt ID, and
* expect the response from the interrupt we sent before.
*/
- memcpy(mb.send, message, sizeof(message));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(message), false), 0);
+ memcpy(mb.send->payload, message, sizeof(message));
+ spci_message_init(mb.send, sizeof(message), SERVICE_VM0,
+ HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), 0);
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(expected_response));
- EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
+ EXPECT_EQ(memcmp(mb.recv->payload, expected_response,
+ sizeof(expected_response)),
0);
EXPECT_EQ(hf_mailbox_clear(), 0);
}
@@ -225,7 +237,8 @@
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(expected_response));
- EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
+ EXPECT_EQ(memcmp(mb.recv->payload, expected_response,
+ sizeof(expected_response)),
0);
EXPECT_EQ(hf_mailbox_clear(), 0);
}
@@ -252,7 +265,8 @@
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(expected_response));
- EXPECT_EQ(memcmp(mb.recv, expected_response, sizeof(expected_response)),
+ EXPECT_EQ(memcmp(mb.recv->payload, expected_response,
+ sizeof(expected_response)),
0);
EXPECT_EQ(hf_mailbox_clear(), 0);
}
@@ -273,12 +287,14 @@
EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
- memcpy(mb.send, message, sizeof(message));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(message), false), 0);
+ memcpy(mb.send->payload, message, sizeof(message));
+ spci_message_init(mb.send, sizeof(message), SERVICE_VM0,
+ HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), SPCI_SUCCESS);
hf_interrupt_inject(SERVICE_VM0, 0, EXTERNAL_INTERRUPT_ID_A);
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(message));
- EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
+ EXPECT_EQ(memcmp(mb.recv->payload, message, sizeof(message)), 0);
EXPECT_EQ(hf_mailbox_clear(), 0);
}
diff --git a/test/vmapi/primary_with_secondaries/mailbox.c b/test/vmapi/primary_with_secondaries/mailbox.c
index 1e1a4d3..8615957 100644
--- a/test/vmapi/primary_with_secondaries/mailbox.c
+++ b/test/vmapi/primary_with_secondaries/mailbox.c
@@ -18,6 +18,8 @@
#include "hf/arch/std.h"
+#include "hf/spci.h"
+
#include "vmapi/hf/call.h"
#include "hftest.h"
@@ -87,12 +89,14 @@
EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
/* Set the message, echo it and check it didn't change. */
- memcpy(mb.send, message, sizeof(message));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(message), false), 0);
+ memcpy(mb.send->payload, message, sizeof(message));
+ spci_message_init(mb.send, sizeof(message), SERVICE_VM0,
+ HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), 0);
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(message));
- EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
+ EXPECT_EQ(memcmp(mb.send->payload, message, sizeof(message)), 0);
EXPECT_EQ(hf_mailbox_clear(), 0);
}
@@ -116,13 +120,15 @@
/* Set the message, echo it and check it didn't change. */
next_permutation(message, sizeof(message) - 1);
- memcpy(mb.send, message, sizeof(message));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(message), false),
- 0);
+ memcpy(mb.send->payload, message, sizeof(message));
+ spci_message_init(mb.send, sizeof(message), SERVICE_VM0,
+ HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), 0);
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(message));
- EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
+ EXPECT_EQ(memcmp(mb.recv->payload, message, sizeof(message)),
+ 0);
EXPECT_EQ(hf_mailbox_clear(), 0);
}
}
@@ -152,15 +158,15 @@
* SERVICE_VM0, then to SERVICE_VM1 and finally back to here.
*/
{
- uint32_t *chain = mb.send;
+ uint32_t *chain = (uint32_t *)mb.send->payload;
*chain++ = htole32(SERVICE_VM1);
*chain++ = htole32(HF_PRIMARY_VM_ID);
memcpy(chain, message, sizeof(message));
- EXPECT_EQ(hf_mailbox_send(
- SERVICE_VM0,
+
+ spci_message_init(mb.send,
sizeof(message) + (2 * sizeof(uint32_t)),
- false),
- 0);
+ SERVICE_VM0, HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), 0);
}
/* Let SERVICE_VM0 forward the message. */
@@ -176,7 +182,7 @@
/* Ensure the message is in tact. */
EXPECT_EQ(run_res.message.vm_id, HF_PRIMARY_VM_ID);
EXPECT_EQ(run_res.message.size, sizeof(message));
- EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
+ EXPECT_EQ(memcmp(mb.recv->payload, message, sizeof(message)), 0);
EXPECT_EQ(hf_mailbox_clear(), 0);
}
@@ -188,15 +194,16 @@
{
struct hf_vcpu_run_return run_res;
- set_up_mailbox();
-
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, 0, false), -1);
+ struct mailbox_buffers mb = set_up_mailbox();
+ spci_message_init(mb.send, 0, SERVICE_VM0, HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), SPCI_BUSY);
run_res = hf_vcpu_run(SERVICE_VM0, 0);
+ spci_message_init(mb.send, 0, SERVICE_VM0, HF_PRIMARY_VM_ID);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, 0, false), 0);
+ EXPECT_EQ(spci_msg_send(0), SPCI_SUCCESS);
}
/**
@@ -207,9 +214,10 @@
{
struct hf_vcpu_run_return run_res;
- set_up_mailbox();
+ struct mailbox_buffers mb = set_up_mailbox();
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, 0, true), -1);
+ spci_message_init(mb.send, 0, SERVICE_VM0, HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(SPCI_MSG_SEND_NOTIFY), SPCI_BUSY);
/*
* Run first VM for it to configure itself. It should result in
@@ -223,7 +231,7 @@
EXPECT_EQ(hf_mailbox_waiter_get(SERVICE_VM0), -1);
/* Send should now succeed. */
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, 0, false), 0);
+ EXPECT_EQ(spci_msg_send(0), SPCI_SUCCESS);
}
/**
@@ -244,12 +252,14 @@
EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
/* Send a message to echo service, and get response back. */
- memcpy(mb.send, message, sizeof(message));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(message), false), 0);
+ memcpy(mb.send->payload, message, sizeof(message));
+ spci_message_init(mb.send, sizeof(message), SERVICE_VM0,
+ HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), 0);
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(message));
- EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
+ EXPECT_EQ(memcmp(mb.recv->payload, message, sizeof(message)), 0);
/* Let secondary VM continue running so that it will wait again. */
run_res = hf_vcpu_run(SERVICE_VM0, 0);
@@ -258,8 +268,12 @@
/* Without clearing our mailbox, send message again. */
reverse(message, strlen(message));
- memcpy(mb.send, message, sizeof(message));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(message), false), 0);
+ memcpy(mb.send->payload, message, sizeof(message));
+ spci_message_init(mb.send, sizeof(message), SERVICE_VM0,
+ HF_PRIMARY_VM_ID);
+
+ /* Message should be dropped since the mailbox was not cleared. */
+ EXPECT_EQ(spci_msg_send(0), 0);
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_INTERRUPT);
EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
@@ -281,7 +295,7 @@
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(message));
- EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
+ EXPECT_EQ(memcmp(mb.recv->payload, message, sizeof(message)), 0);
}
/**
@@ -302,15 +316,17 @@
EXPECT_EQ(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
/* Send a message to echo service twice. The second should fail. */
- memcpy(mb.send, message, sizeof(message));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(message), false), 0);
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(message), true), -1);
+ memcpy(mb.send->payload, message, sizeof(message));
+ spci_message_init(mb.send, sizeof(message), SERVICE_VM0,
+ HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), SPCI_SUCCESS);
+ EXPECT_EQ(spci_msg_send(SPCI_MSG_SEND_NOTIFY), SPCI_BUSY);
/* Receive a reply for the first message. */
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
EXPECT_EQ(run_res.message.size, sizeof(message));
- EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
+ EXPECT_EQ(memcmp(mb.recv->payload, message, sizeof(message)), 0);
/* Run VM again so that it clears its mailbox. */
run_res = hf_vcpu_run(SERVICE_VM0, 0);
@@ -321,5 +337,5 @@
EXPECT_EQ(hf_mailbox_waiter_get(SERVICE_VM0), -1);
/* Send should now succeed. */
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, 0, false), 0);
+ EXPECT_EQ(spci_msg_send(0), SPCI_SUCCESS);
}
diff --git a/test/vmapi/primary_with_secondaries/memory_sharing.c b/test/vmapi/primary_with_secondaries/memory_sharing.c
index e44dd93..8d8bb47 100644
--- a/test/vmapi/primary_with_secondaries/memory_sharing.c
+++ b/test/vmapi/primary_with_secondaries/memory_sharing.c
@@ -104,8 +104,9 @@
* API is still to be agreed on so the address is passed
* explicitly to test the mechanism.
*/
- memcpy(mb.send, &ptr, sizeof(ptr));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(ptr), false), 0);
+ memcpy(mb.send->payload, &ptr, sizeof(ptr));
+ spci_message_init(mb.send, sizeof(ptr), SERVICE_VM0, HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), SPCI_SUCCESS);
run_res = hf_vcpu_run(SERVICE_VM0, 0);
EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
@@ -146,8 +147,9 @@
* API is still to be agreed on so the address is passed
* explicitly to test the mechanism.
*/
- memcpy(mb.send, &ptr, sizeof(ptr));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(ptr), false), 0);
+ memcpy(mb.send->payload, &ptr, sizeof(ptr));
+ spci_message_init(mb.send, sizeof(ptr), SERVICE_VM0, HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), SPCI_SUCCESS);
/* Let the memory be returned. */
run_res = hf_vcpu_run(SERVICE_VM0, 0);
@@ -183,8 +185,9 @@
* API is still to be agreed on so the address is passed
* explicitly to test the mechanism.
*/
- memcpy(mb.send, &ptr, sizeof(ptr));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(ptr), false), 0);
+ memcpy(mb.send->payload, &ptr, sizeof(ptr));
+ spci_message_init(mb.send, sizeof(ptr), SERVICE_VM0, HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), SPCI_SUCCESS);
/* Let the memory be returned. */
run_res = hf_vcpu_run(SERVICE_VM0, 0);
@@ -220,8 +223,9 @@
* API is still to be agreed on so the address is passed
* explicitly to test the mechanism.
*/
- memcpy(mb.send, &ptr, sizeof(ptr));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(ptr), false), 0);
+ memcpy(mb.send->payload, &ptr, sizeof(ptr));
+ spci_message_init(mb.send, sizeof(ptr), SERVICE_VM0, HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), SPCI_SUCCESS);
/* Let the memory be returned. */
run_res = hf_vcpu_run(SERVICE_VM0, 0);
@@ -256,8 +260,9 @@
* API is still to be agreed on so the address is passed
* explicitly to test the mechanism.
*/
- memcpy(mb.send, &ptr, sizeof(ptr));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(ptr), false), 0);
+ memcpy(mb.send->payload, &ptr, sizeof(ptr));
+ spci_message_init(mb.send, sizeof(ptr), SERVICE_VM0, HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), SPCI_SUCCESS);
/* Let the memory be returned. */
run_res = hf_vcpu_run(SERVICE_VM0, 0);
@@ -295,8 +300,9 @@
* API is still to be agreed on so the address is passed
* explicitly to test the mechanism.
*/
- memcpy(mb.send, &ptr, sizeof(ptr));
- EXPECT_EQ(hf_mailbox_send(SERVICE_VM0, sizeof(ptr), false), 0);
+ memcpy(mb.send->payload, &ptr, sizeof(ptr));
+ spci_message_init(mb.send, sizeof(ptr), SERVICE_VM0, HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), SPCI_SUCCESS);
/* Let the memory be returned. */
run_res = hf_vcpu_run(SERVICE_VM0, 0);
@@ -328,7 +334,7 @@
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
/* Check the memory was cleared. */
- memcpy(&ptr, mb.recv, sizeof(ptr));
+ memcpy(&ptr, mb.recv->payload, sizeof(ptr));
for (int i = 0; i < PAGE_SIZE; ++i) {
ASSERT_EQ(ptr[i], 0);
}
@@ -354,7 +360,7 @@
EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
/* Check the memory was cleared. */
- memcpy(&ptr, mb.recv, sizeof(ptr));
+ memcpy(&ptr, mb.recv->payload, sizeof(ptr));
for (int i = 0; i < PAGE_SIZE; ++i) {
ASSERT_EQ(ptr[i], 0);
}
diff --git a/test/vmapi/primary_with_secondaries/run_race.c b/test/vmapi/primary_with_secondaries/run_race.c
index f77a7b1..2a25c65 100644
--- a/test/vmapi/primary_with_secondaries/run_race.c
+++ b/test/vmapi/primary_with_secondaries/run_race.c
@@ -57,7 +57,7 @@
/* Copies the contents of the received boolean to the return value. */
if (run_res.message.size == sizeof(ok)) {
- memcpy(&ok, mb->recv, sizeof(ok));
+ memcpy(&ok, mb->recv->payload, sizeof(ok));
}
hf_mailbox_clear();
diff --git a/test/vmapi/primary_with_secondaries/services/BUILD.gn b/test/vmapi/primary_with_secondaries/services/BUILD.gn
index b0ef794..6b15dc7 100644
--- a/test/vmapi/primary_with_secondaries/services/BUILD.gn
+++ b/test/vmapi/primary_with_secondaries/services/BUILD.gn
@@ -125,6 +125,19 @@
]
}
+# Service to receive messages in a secondary VM and ensure that the header fields are correctly set.
+source_set("spci_check") {
+ testonly = true
+ public_configs = [
+ "..:config",
+ "//test/hftest:hftest_config",
+ ]
+
+ sources = [
+ "spci_check.c",
+ ]
+}
+
# Group services together into VMs.
vm_kernel("service_vm0") {
@@ -139,6 +152,7 @@
":memory",
":receive_block",
":relay",
+ ":spci_check",
":wfi",
"//test/hftest:hftest_secondary_vm",
]
diff --git a/test/vmapi/primary_with_secondaries/services/check_state.c b/test/vmapi/primary_with_secondaries/services/check_state.c
index 735b8a5..e467f52 100644
--- a/test/vmapi/primary_with_secondaries/services/check_state.c
+++ b/test/vmapi/primary_with_secondaries/services/check_state.c
@@ -21,13 +21,13 @@
#include "hftest.h"
-void send_with_retry(uint32_t vm_id, size_t size)
+void send_with_retry()
{
int64_t res;
do {
- res = hf_mailbox_send(vm_id, size, false);
- } while (res == -1);
+ res = spci_msg_send(0);
+ } while (res != SPCI_SUCCESS);
}
/**
@@ -48,6 +48,9 @@
static volatile uintptr_t expected;
static volatile uintptr_t actual;
+ spci_message_init(SERVICE_SEND_BUFFER(), 0, HF_PRIMARY_VM_ID,
+ hf_vm_get_id());
+
for (i = 0; i < 100000; i++) {
/*
* We store the expected/actual values in volatile static
@@ -56,13 +59,15 @@
*/
expected = i;
per_cpu_ptr_set(expected);
- send_with_retry(HF_PRIMARY_VM_ID, 0);
+ send_with_retry();
actual = per_cpu_ptr_get();
ok &= expected == actual;
}
/* Send two replies, one for each physical CPU. */
- memcpy(SERVICE_SEND_BUFFER(), &ok, sizeof(ok));
- send_with_retry(HF_PRIMARY_VM_ID, sizeof(ok));
- send_with_retry(HF_PRIMARY_VM_ID, sizeof(ok));
+ memcpy(SERVICE_SEND_BUFFER()->payload, &ok, sizeof(ok));
+ spci_message_init(SERVICE_SEND_BUFFER(), sizeof(ok), HF_PRIMARY_VM_ID,
+ hf_vm_get_id());
+ send_with_retry();
+ send_with_retry();
}
diff --git a/test/vmapi/primary_with_secondaries/services/echo.c b/test/vmapi/primary_with_secondaries/services/echo.c
index ffb89df..c58ccfb 100644
--- a/test/vmapi/primary_with_secondaries/services/echo.c
+++ b/test/vmapi/primary_with_secondaries/services/echo.c
@@ -16,6 +16,8 @@
#include "hf/arch/std.h"
+#include "hf/spci.h"
+
#include "vmapi/hf/call.h"
#include "hftest.h"
@@ -24,9 +26,16 @@
{
/* Loop, echo messages back to the sender. */
for (;;) {
- struct hf_mailbox_receive_return res = hf_mailbox_receive(true);
- memcpy(SERVICE_SEND_BUFFER(), SERVICE_RECV_BUFFER(), res.size);
+ hf_mailbox_receive(true);
+ struct spci_message *send_buf = SERVICE_SEND_BUFFER();
+ struct spci_message *recv_buf = SERVICE_RECV_BUFFER();
+
+ memcpy(send_buf->payload, recv_buf->payload, recv_buf->length);
+ spci_message_init(SERVICE_SEND_BUFFER(), recv_buf->length,
+ recv_buf->source_vm_id,
+ recv_buf->target_vm_id);
+
hf_mailbox_clear();
- hf_mailbox_send(res.vm_id, res.size, false);
+ spci_msg_send(0);
}
}
diff --git a/test/vmapi/primary_with_secondaries/services/echo_with_notification.c b/test/vmapi/primary_with_secondaries/services/echo_with_notification.c
index 2e733ae..e6c66c0 100644
--- a/test/vmapi/primary_with_secondaries/services/echo_with_notification.c
+++ b/test/vmapi/primary_with_secondaries/services/echo_with_notification.c
@@ -18,6 +18,8 @@
#include "hf/arch/std.h"
#include "hf/arch/vm/interrupts_gicv3.h"
+#include "hf/spci.h"
+
#include "vmapi/hf/call.h"
#include "../msr.h"
@@ -51,11 +53,18 @@
/* Loop, echo messages back to the sender. */
for (;;) {
- struct hf_mailbox_receive_return res = hf_mailbox_receive(true);
+ hf_mailbox_receive(true);
- memcpy(SERVICE_SEND_BUFFER(), SERVICE_RECV_BUFFER(), res.size);
- while (hf_mailbox_send(res.vm_id, res.size, true) < 0) {
- wait_for_vm(res.vm_id);
+ struct spci_message *send_buf = SERVICE_SEND_BUFFER();
+ struct spci_message *recv_buf = SERVICE_RECV_BUFFER();
+
+ memcpy(send_buf->payload, recv_buf->payload, recv_buf->length);
+ spci_message_init(send_buf, recv_buf->length,
+ recv_buf->source_vm_id,
+ recv_buf->target_vm_id);
+
+ while (spci_msg_send(SPCI_MSG_SEND_NOTIFY) != SPCI_SUCCESS) {
+ wait_for_vm(recv_buf->source_vm_id);
}
hf_mailbox_clear();
diff --git a/test/vmapi/primary_with_secondaries/services/interruptible.c b/test/vmapi/primary_with_secondaries/services/interruptible.c
index 9b36e8c..c5c67a5 100644
--- a/test/vmapi/primary_with_secondaries/services/interruptible.c
+++ b/test/vmapi/primary_with_secondaries/services/interruptible.c
@@ -38,8 +38,10 @@
dlog("secondary IRQ %d from current\n", interrupt_id);
buffer[8] = '0' + interrupt_id / 10;
buffer[9] = '0' + interrupt_id % 10;
- memcpy(SERVICE_SEND_BUFFER(), buffer, size);
- hf_mailbox_send(HF_PRIMARY_VM_ID, size, false);
+ memcpy(SERVICE_SEND_BUFFER()->payload, buffer, size);
+ spci_message_init(SERVICE_SEND_BUFFER(), size, HF_PRIMARY_VM_ID,
+ hf_vm_get_id());
+ spci_msg_send(0);
dlog("secondary IRQ %d ended\n", interrupt_id);
}
@@ -62,6 +64,7 @@
TEST_SERVICE(interruptible)
{
uint32_t this_vm_id = hf_vm_get_id();
+ struct spci_message *recv_buf = SERVICE_RECV_BUFFER();
exception_setup(irq);
hf_interrupt_enable(SELF_INTERRUPT_ID, true);
@@ -72,23 +75,23 @@
for (;;) {
const char ping_message[] = "Ping";
const char enable_message[] = "Enable interrupt C";
- struct hf_mailbox_receive_return received_message =
- mailbox_receive_retry();
- if (received_message.vm_id == HF_PRIMARY_VM_ID &&
- received_message.size == sizeof(ping_message) &&
- memcmp(SERVICE_RECV_BUFFER(), ping_message,
+
+ mailbox_receive_retry();
+ if (recv_buf->source_vm_id == HF_PRIMARY_VM_ID &&
+ recv_buf->length == sizeof(ping_message) &&
+ memcmp(recv_buf->payload, ping_message,
sizeof(ping_message)) == 0) {
/* Interrupt ourselves */
hf_interrupt_inject(this_vm_id, 0, SELF_INTERRUPT_ID);
- } else if (received_message.vm_id == HF_PRIMARY_VM_ID &&
- received_message.size == sizeof(enable_message) &&
- memcmp(SERVICE_RECV_BUFFER(), enable_message,
+ } else if (recv_buf->source_vm_id == HF_PRIMARY_VM_ID &&
+ recv_buf->length == sizeof(enable_message) &&
+ memcmp(recv_buf->payload, enable_message,
sizeof(enable_message)) == 0) {
/* Enable interrupt ID C. */
hf_interrupt_enable(EXTERNAL_INTERRUPT_ID_C, true);
} else {
dlog("Got unexpected message from VM %d, size %d.\n",
- received_message.vm_id, received_message.size);
+ recv_buf->source_vm_id, recv_buf->length);
FAIL("Unexpected message");
}
hf_mailbox_clear();
diff --git a/test/vmapi/primary_with_secondaries/services/interruptible_echo.c b/test/vmapi/primary_with_secondaries/services/interruptible_echo.c
index e1eb643..dff3b6d 100644
--- a/test/vmapi/primary_with_secondaries/services/interruptible_echo.c
+++ b/test/vmapi/primary_with_secondaries/services/interruptible_echo.c
@@ -39,6 +39,7 @@
for (;;) {
struct hf_mailbox_receive_return res = hf_mailbox_receive(true);
+ struct spci_message *message = SERVICE_SEND_BUFFER();
/* Retry if interrupted but made visible with the yield. */
while (res.vm_id == HF_INVALID_VM_ID && res.size == 0) {
@@ -46,8 +47,12 @@
res = hf_mailbox_receive(true);
}
- memcpy(SERVICE_SEND_BUFFER(), SERVICE_RECV_BUFFER(), res.size);
+ memcpy(message->payload, SERVICE_RECV_BUFFER()->payload,
+ res.size);
+ spci_message_init(message, res.size, HF_PRIMARY_VM_ID,
+ SERVICE_VM0);
+
hf_mailbox_clear();
- hf_mailbox_send(res.vm_id, res.size, false);
+ spci_msg_send(0);
}
}
diff --git a/test/vmapi/primary_with_secondaries/services/memory.c b/test/vmapi/primary_with_secondaries/services/memory.c
index b85b003..a826184 100644
--- a/test/vmapi/primary_with_secondaries/services/memory.c
+++ b/test/vmapi/primary_with_secondaries/services/memory.c
@@ -28,12 +28,16 @@
{
/* Loop, writing message to the shared memory. */
for (;;) {
- struct hf_mailbox_receive_return res = hf_mailbox_receive(true);
+ hf_mailbox_receive(true);
uint8_t *ptr;
size_t i;
/* Check the memory was cleared. */
- memcpy(&ptr, SERVICE_RECV_BUFFER(), sizeof(ptr));
+ struct spci_message *recv_buf = SERVICE_RECV_BUFFER();
+ memcpy(&ptr, recv_buf->payload, sizeof(ptr));
+ spci_message_init(SERVICE_SEND_BUFFER(), sizeof(ptr),
+ recv_buf->source_vm_id, hf_vm_get_id());
+
for (int i = 0; i < PAGE_SIZE; ++i) {
ASSERT_EQ(ptr[i], 0);
}
@@ -48,7 +52,7 @@
/* Signal completion and reset. */
hf_mailbox_clear();
- hf_mailbox_send(res.vm_id, 0, false);
+ spci_msg_send(0);
}
}
@@ -56,21 +60,26 @@
{
/* Loop, giving memory back to the sender. */
for (;;) {
- struct hf_mailbox_receive_return res = hf_mailbox_receive(true);
+ hf_mailbox_receive(true);
uint8_t *ptr;
/* Check the memory was cleared. */
- memcpy(&ptr, SERVICE_RECV_BUFFER(), sizeof(ptr));
+ struct spci_message *recv_buf = SERVICE_RECV_BUFFER();
+ memcpy(&ptr, recv_buf->payload, sizeof(ptr));
+ spci_message_init(SERVICE_SEND_BUFFER(), sizeof(ptr),
+ recv_buf->source_vm_id, hf_vm_get_id());
+
for (int i = 0; i < PAGE_SIZE; ++i) {
ASSERT_EQ(ptr[i], 0);
}
/* Give the memory back and notify the sender. */
- ASSERT_EQ(hf_share_memory(res.vm_id, (hf_ipaddr_t)ptr,
- PAGE_SIZE, HF_MEMORY_GIVE),
+ ASSERT_EQ(hf_share_memory(recv_buf->source_vm_id,
+ (hf_ipaddr_t)ptr, PAGE_SIZE,
+ HF_MEMORY_GIVE),
0);
hf_mailbox_clear();
- hf_mailbox_send(res.vm_id, 0, false);
+ spci_msg_send(0);
/*
* Try and access the memory which will cause a fault unless the
@@ -94,8 +103,10 @@
* API is still to be agreed on so the address is passed
* explicitly to test the mechanism.
*/
- memcpy(SERVICE_SEND_BUFFER(), &ptr, sizeof(ptr));
- EXPECT_EQ(hf_mailbox_send(HF_PRIMARY_VM_ID, sizeof(ptr), false), 0);
+ memcpy(SERVICE_SEND_BUFFER()->payload, &ptr, sizeof(ptr));
+ spci_message_init(SERVICE_SEND_BUFFER(), sizeof(ptr), HF_PRIMARY_VM_ID,
+ hf_vm_get_id());
+ EXPECT_EQ(spci_msg_send(0), 0);
/* Try using the memory that isn't valid unless it's been returned. */
page[16] = 123;
@@ -115,8 +126,10 @@
* API is still to be agreed on so the address is passed
* explicitly to test the mechanism.
*/
- memcpy(SERVICE_SEND_BUFFER(), &ptr, sizeof(ptr));
- EXPECT_EQ(hf_mailbox_send(HF_PRIMARY_VM_ID, sizeof(ptr), false), 0);
+ memcpy(SERVICE_SEND_BUFFER()->payload, &ptr, sizeof(ptr));
+ spci_message_init(SERVICE_SEND_BUFFER(), sizeof(ptr), HF_PRIMARY_VM_ID,
+ hf_vm_get_id());
+ EXPECT_EQ(spci_msg_send(0), 0);
/* Try using the memory that isn't valid unless it's been returned. */
page[633] = 180;
diff --git a/test/vmapi/primary_with_secondaries/services/receive_block.c b/test/vmapi/primary_with_secondaries/services/receive_block.c
index bdfbed6..59a10a5 100644
--- a/test/vmapi/primary_with_secondaries/services/receive_block.c
+++ b/test/vmapi/primary_with_secondaries/services/receive_block.c
@@ -18,6 +18,7 @@
#include "hf/arch/vm/interrupts_gicv3.h"
#include "hf/dlog.h"
+#include "hf/spci.h"
#include "vmapi/hf/call.h"
@@ -50,6 +51,9 @@
EXPECT_EQ(res.size, 0);
}
- memcpy(SERVICE_SEND_BUFFER(), message, sizeof(message));
- hf_mailbox_send(HF_PRIMARY_VM_ID, sizeof(message), false);
+ memcpy(SERVICE_SEND_BUFFER()->payload, message, sizeof(message));
+ spci_message_init(SERVICE_SEND_BUFFER(), sizeof(message),
+ HF_PRIMARY_VM_ID, hf_vm_get_id());
+
+ spci_msg_send(0);
}
diff --git a/test/vmapi/primary_with_secondaries/services/relay.c b/test/vmapi/primary_with_secondaries/services/relay.c
index f509835..627a461 100644
--- a/test/vmapi/primary_with_secondaries/services/relay.c
+++ b/test/vmapi/primary_with_secondaries/services/relay.c
@@ -36,18 +36,24 @@
uint32_t next_message_size;
/* Receive the message to relay. */
- struct hf_mailbox_receive_return res = hf_mailbox_receive(true);
- ASSERT_GE(res.size, sizeof(uint32_t));
+ hf_mailbox_receive(true);
/* Prepare to relay the message. */
- chain = SERVICE_RECV_BUFFER();
+ struct spci_message *recv_buf = SERVICE_RECV_BUFFER();
+ struct spci_message *send_buf = SERVICE_SEND_BUFFER();
+ ASSERT_GE(recv_buf->length, sizeof(uint32_t));
+
+ chain = (uint32_t *)recv_buf->payload;
next_vm_id = le32toh(*chain);
next_message = chain + 1;
- next_message_size = res.size - sizeof(uint32_t);
+ next_message_size = recv_buf->length - sizeof(uint32_t);
/* Send the message to the next stage. */
- memcpy(SERVICE_SEND_BUFFER(), next_message, next_message_size);
+ memcpy(send_buf->payload, next_message, next_message_size);
+ spci_message_init(send_buf, next_message_size, next_vm_id,
+ hf_vm_get_id());
+
hf_mailbox_clear();
- hf_mailbox_send(next_vm_id, next_message_size, false);
+ spci_msg_send(0);
}
}
diff --git a/test/vmapi/primary_with_secondaries/services/spci_check.c b/test/vmapi/primary_with_secondaries/services/spci_check.c
new file mode 100644
index 0000000..a81fc01
--- /dev/null
+++ b/test/vmapi/primary_with_secondaries/services/spci_check.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2019 The Hafnium Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hf/arch/std.h"
+
+#include "hf/spci.h"
+
+#include "vmapi/hf/call.h"
+
+#include "hftest.h"
+#include "primary_with_secondary.h"
+
+TEST_SERVICE(spci_check)
+{
+ struct spci_message *recv_buf = SERVICE_RECV_BUFFER();
+ const char message[] = "spci_msg_send";
+ struct spci_message expected_message = {
+ .flags = SPCI_MESSAGE_IMPDEF_MASK,
+ .length = sizeof(message),
+ .target_vm_id = SERVICE_VM0,
+ .source_vm_id = HF_PRIMARY_VM_ID,
+
+ /*
+ * TODO: Padding fields may be set to MBZ in the next SPCI spec
+ * versions.
+ */
+ .reserved_1 = 0,
+ .reserved_2 = 0,
+ };
+
+ /* Wait for single message to be sent by the primary VM. */
+ hf_mailbox_receive(true);
+
+ /* Ensure message header has all fields correctly set. */
+ EXPECT_EQ(recv_buf->flags, expected_message.flags);
+ EXPECT_EQ(recv_buf->length, expected_message.length);
+ EXPECT_EQ(recv_buf->target_vm_id, expected_message.target_vm_id);
+ EXPECT_EQ(recv_buf->source_vm_id, expected_message.source_vm_id);
+
+ /* TODO: Padding fields may be set to MBZ in the next SPCI spec
+ * versions. */
+ EXPECT_EQ(recv_buf->reserved_1, expected_message.reserved_1);
+ EXPECT_EQ(recv_buf->reserved_2, expected_message.reserved_2);
+
+ /* Ensure message header has all fields correctly set. */
+ EXPECT_EQ(memcmp(recv_buf, &expected_message, sizeof(expected_message)),
+ 0);
+
+ /* Ensure that the payload was correctly transmitted. */
+ EXPECT_EQ(memcmp(recv_buf->payload, message, sizeof(message)), 0);
+
+ hf_vcpu_yield();
+}
diff --git a/test/vmapi/primary_with_secondaries/services/wfi.c b/test/vmapi/primary_with_secondaries/services/wfi.c
index 9c4f66e..6d3a05c 100644
--- a/test/vmapi/primary_with_secondaries/services/wfi.c
+++ b/test/vmapi/primary_with_secondaries/services/wfi.c
@@ -48,6 +48,9 @@
interrupt_wait();
}
- memcpy(SERVICE_SEND_BUFFER(), message, sizeof(message));
- hf_mailbox_send(HF_PRIMARY_VM_ID, sizeof(message), false);
+ memcpy(SERVICE_SEND_BUFFER()->payload, message, sizeof(message));
+ spci_message_init(SERVICE_SEND_BUFFER(), sizeof(message),
+ HF_PRIMARY_VM_ID, hf_vm_get_id());
+
+ spci_msg_send(0);
}
diff --git a/test/vmapi/primary_with_secondaries/spci.c b/test/vmapi/primary_with_secondaries/spci.c
new file mode 100644
index 0000000..e6d1049
--- /dev/null
+++ b/test/vmapi/primary_with_secondaries/spci.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2019 The Hafnium Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hf/spci.h"
+
+#include <stdint.h>
+
+#include "hf/arch/std.h"
+
+#include "vmapi/hf/call.h"
+
+#include "hftest.h"
+#include "primary_with_secondary.h"
+#include "util.h"
+
+/**
+ * Send a message to a secondary VM which checks the validity of the received
+ * header.
+ */
+TEST(spci, msg_send)
+{
+ const char message[] = "spci_msg_send";
+ struct hf_vcpu_run_return run_res;
+ struct mailbox_buffers mb = set_up_mailbox();
+
+ SERVICE_SELECT(SERVICE_VM0, "spci_check", mb.send);
+
+ /* Set the payload, init the message header and send the message. */
+ memcpy(mb.send->payload, message, sizeof(message));
+ spci_message_init(mb.send, sizeof(message), SERVICE_VM0,
+ HF_PRIMARY_VM_ID);
+ EXPECT_EQ(spci_msg_send(0), 0);
+
+ run_res = hf_vcpu_run(SERVICE_VM0, 0);
+ EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
+}
+
+/**
+ * Send a message to a secondary VM spoofing the source vm id.
+ */
+TEST(spci, msg_send_spoof)
+{
+ const char message[] = "spci_msg_send";
+ struct mailbox_buffers mb = set_up_mailbox();
+
+ SERVICE_SELECT(SERVICE_VM0, "spci_check", mb.send);
+
+ /* Set the payload, init the message header and send the message. */
+ memcpy(mb.send->payload, message, sizeof(message));
+ spci_message_init(mb.send, sizeof(message), SERVICE_VM0, SERVICE_VM1);
+ EXPECT_EQ(spci_msg_send(0), SPCI_INVALID_PARAMETERS);
+}
diff --git a/test/vmapi/primary_with_secondaries/util.c b/test/vmapi/primary_with_secondaries/util.c
index 86830c4..24b2b9e 100644
--- a/test/vmapi/primary_with_secondaries/util.c
+++ b/test/vmapi/primary_with_secondaries/util.c
@@ -17,6 +17,7 @@
#include "util.h"
#include "hf/mm.h"
+#include "hf/spci.h"
#include "vmapi/hf/call.h"
@@ -34,7 +35,7 @@
{
ASSERT_EQ(hf_vm_configure(send_page_addr, recv_page_addr), 0);
return (struct mailbox_buffers){
- .send = send_page,
- .recv = recv_page,
+ .send = ((struct spci_message *)send_page),
+ .recv = ((struct spci_message *)recv_page),
};
}