Add message relay test.
This test sends messages between two secondary VMs. The message is send
from the primary, to relay_a, to relay_b and finally back to the
primary.
Bug: 116705004
Change-Id: Iff5b1726b870e9f502dedd9a4075da2529f50a09
diff --git a/test/vm/BUILD.gn b/test/vm/BUILD.gn
index 4d7155f..743326d 100644
--- a/test/vm/BUILD.gn
+++ b/test/vm/BUILD.gn
@@ -65,10 +65,24 @@
initrd("primary_with_secondaries_test") {
testonly = true
primary_vm = ":primary_with_secondaries_test_vm"
- secondary_vms = [ [
- "1048576",
- "1",
- "echo",
- "//test/vm/secondaries:echo",
- ] ]
+ secondary_vms = [
+ [
+ "1048576",
+ "1",
+ "relay_a",
+ "//test/vm/secondaries:relay_a",
+ ],
+ [
+ "1048576",
+ "1",
+ "relay_b",
+ "//test/vm/secondaries:relay_b",
+ ],
+ [
+ "1048576",
+ "1",
+ "echo",
+ "//test/vm/secondaries:echo",
+ ],
+ ]
}
diff --git a/test/vm/primary_with_secondaries.c b/test/vm/primary_with_secondaries.c
index 52417f8..9e9fce0 100644
--- a/test/vm/primary_with_secondaries.c
+++ b/test/vm/primary_with_secondaries.c
@@ -17,14 +17,21 @@
static hf_ipaddr_t send_page_addr = (hf_ipaddr_t)send_page;
static hf_ipaddr_t recv_page_addr = (hf_ipaddr_t)recv_page;
-#define ECHO_VM_ID 1
+/* Keep macro alignment */
+/* clang-format off */
+
+#define RELAY_A_VM_ID 1
+#define RELAY_B_VM_ID 2
+#define ECHO_VM_ID 3
+
+/* clang-format on */
/**
- * Confirm there is 1 secondary VM.
+ * Confirm there are 3 secondary VMs.
*/
-TEST(hf_vm_get_count, one_secondary_vm)
+TEST(hf_vm_get_count, three_secondary_vms)
{
- EXPECT_EQ(hf_vm_get_count(), 2);
+ EXPECT_EQ(hf_vm_get_count(), 4);
}
/**
@@ -109,3 +116,33 @@
EXPECT_EQ(memcmp(recv_page, message, sizeof(message)), 0);
EXPECT_EQ(hf_mailbox_clear(), 0);
}
+
+/**
+ * Send a message to relay_a which will forward it to relay_b where it will be
+ * sent back here.
+ */
+TEST(mailbox, relay)
+{
+ const char message[] = "Send this round the relay!";
+
+ /* Configure mailbox pages. */
+ EXPECT_EQ(hf_vm_configure(send_page_addr, recv_page_addr), 0);
+ EXPECT_EQ(hf_vcpu_run(RELAY_A_VM_ID, 0),
+ HF_VCPU_RUN_RESPONSE(HF_VCPU_RUN_WAIT_FOR_INTERRUPT, 0, 0));
+ EXPECT_EQ(hf_vcpu_run(RELAY_B_VM_ID, 0),
+ HF_VCPU_RUN_RESPONSE(HF_VCPU_RUN_WAIT_FOR_INTERRUPT, 0, 0));
+
+ /*
+ * Send the message to relay_a which is then sent to relay_b before
+ * checking that relay_b send the message back here.
+ */
+ memcpy(send_page, message, sizeof(message));
+ EXPECT_EQ(hf_mailbox_send(RELAY_A_VM_ID, sizeof(message)), 0);
+ EXPECT_EQ(hf_vcpu_run(RELAY_A_VM_ID, 0),
+ HF_VCPU_RUN_RESPONSE(HF_VCPU_RUN_WAKE_UP, RELAY_B_VM_ID, 0));
+ EXPECT_EQ(
+ hf_vcpu_run(RELAY_B_VM_ID, 0),
+ HF_VCPU_RUN_RESPONSE(HF_VCPU_RUN_MESSAGE, 0, sizeof(message)));
+ EXPECT_EQ(memcmp(recv_page, message, sizeof(message)), 0);
+ EXPECT_EQ(hf_mailbox_clear(), 0);
+}
diff --git a/test/vm/secondaries/BUILD.gn b/test/vm/secondaries/BUILD.gn
index 3f17fc6..85700da 100644
--- a/test/vm/secondaries/BUILD.gn
+++ b/test/vm/secondaries/BUILD.gn
@@ -11,3 +11,27 @@
"//test/vm:secondary_vm",
]
}
+
+vm_kernel("relay_a") {
+ testonly = true
+
+ sources = [
+ "relay_a.c",
+ ]
+
+ deps = [
+ "//test/vm:secondary_vm",
+ ]
+}
+
+vm_kernel("relay_b") {
+ testonly = true
+
+ sources = [
+ "relay_b.c",
+ ]
+
+ deps = [
+ "//test/vm:secondary_vm",
+ ]
+}
diff --git a/test/vm/secondaries/relay_a.c b/test/vm/secondaries/relay_a.c
new file mode 100644
index 0000000..e44267d
--- /dev/null
+++ b/test/vm/secondaries/relay_a.c
@@ -0,0 +1,32 @@
+#include <stdalign.h>
+#include <stdint.h>
+
+#include "hf/mm.h"
+#include "hf/std.h"
+
+#include "vmapi/hf/call.h"
+
+#define FORWARD_VM_ID 2
+
+alignas(4096) uint8_t kstack[4096];
+
+static alignas(PAGE_SIZE) uint8_t send_page[PAGE_SIZE];
+static alignas(PAGE_SIZE) uint8_t recv_page[PAGE_SIZE];
+
+static hf_ipaddr_t send_page_addr = (hf_ipaddr_t)send_page;
+static hf_ipaddr_t recv_page_addr = (hf_ipaddr_t)recv_page;
+
+void kmain(void)
+{
+ hf_vm_configure(send_page_addr, recv_page_addr);
+ hf_vm_configure(send_page_addr, recv_page_addr);
+
+ /* Loop, forward messages to the next VM. */
+ for (;;) {
+ uint64_t ret = hf_mailbox_receive(true);
+ uint32_t size = HF_MAILBOX_RECEIVE_SIZE(ret);
+ memcpy(send_page, recv_page, size);
+ hf_mailbox_clear();
+ hf_mailbox_send(FORWARD_VM_ID, size);
+ }
+}
diff --git a/test/vm/secondaries/relay_b.c b/test/vm/secondaries/relay_b.c
new file mode 100644
index 0000000..ce83ce2
--- /dev/null
+++ b/test/vm/secondaries/relay_b.c
@@ -0,0 +1,30 @@
+#include <stdalign.h>
+#include <stdint.h>
+
+#include "hf/mm.h"
+#include "hf/std.h"
+
+#include "vmapi/hf/call.h"
+
+alignas(4096) uint8_t kstack[4096];
+
+static alignas(PAGE_SIZE) uint8_t send_page[PAGE_SIZE];
+static alignas(PAGE_SIZE) uint8_t recv_page[PAGE_SIZE];
+
+static hf_ipaddr_t send_page_addr = (hf_ipaddr_t)send_page;
+static hf_ipaddr_t recv_page_addr = (hf_ipaddr_t)recv_page;
+
+void kmain(void)
+{
+ hf_vm_configure(send_page_addr, recv_page_addr);
+ hf_vm_configure(send_page_addr, recv_page_addr);
+
+ /* Loop, forward messages to the primary. */
+ for (;;) {
+ uint64_t ret = hf_mailbox_receive(true);
+ uint32_t size = HF_MAILBOX_RECEIVE_SIZE(ret);
+ memcpy(send_page, recv_page, size);
+ hf_mailbox_clear();
+ hf_mailbox_send(HF_PRIMARY_VM_ID, size);
+ }
+}