Test a message being echoed.

Send a message to a secondary VM and check it gets echoed back.

Bug: 116705004
Change-Id: Ia67873cc15cc68f38418f52531146f976d1f4e3f
diff --git a/BUILD.gn b/BUILD.gn
index 622f91e..83622bc 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -22,8 +22,8 @@
 
   deps = [
     ":hypervisor",
-    "//test/vm/primary_only:primary_only_test($arch_toolchain)",
-    "//test/vm/primary_with_secondary:primary_with_secondary_test($arch_toolchain)",
+    "//test/vm/:primary_only_test($arch_toolchain)",
+    "//test/vm/:primary_with_secondaries_test($arch_toolchain)",
   ]
 }
 
diff --git a/kokoro/ubuntu/test.sh b/kokoro/ubuntu/test.sh
index 8580712..db3ad10 100755
--- a/kokoro/ubuntu/test.sh
+++ b/kokoro/ubuntu/test.sh
@@ -24,4 +24,4 @@
 
 # Run the tests with a timeout so they can't loop forever.
 $HFTEST primary_only_test
-$HFTEST primary_with_secondary_test
+$HFTEST primary_with_secondaries_test
diff --git a/test/vm/BUILD.gn b/test/vm/BUILD.gn
index 21c9ad0..4d7155f 100644
--- a/test/vm/BUILD.gn
+++ b/test/vm/BUILD.gn
@@ -1,5 +1,6 @@
 import("//build/image/image.gni")
 
+# Primary VMs host the test framework.
 source_set("hftest_vm") {
   sources = [
     "hftest.c",
@@ -18,8 +19,8 @@
   ]
 }
 
-# TODO: work out what to run in the secondary VMs
-source_set("other_vm") {
+# Secondary VMs can be used as part of a test in the primary.
+source_set("secondary_vm") {
   deps = [
     "//src:common",
     "//src:dlog",
@@ -29,3 +30,45 @@
     "//src/arch/${arch}/vm:vm_entry",
   ]
 }
+
+# Tests with no secondary VMs.
+vm_kernel("primary_only_test_vm") {
+  testonly = true
+
+  sources = [
+    "primary_only.c",
+  ]
+
+  deps = [
+    ":hftest_vm",
+  ]
+}
+
+initrd("primary_only_test") {
+  testonly = true
+  primary_vm = ":primary_only_test_vm"
+}
+
+# Tests with secondary VMs.
+vm_kernel("primary_with_secondaries_test_vm") {
+  testonly = true
+
+  sources = [
+    "primary_with_secondaries.c",
+  ]
+
+  deps = [
+    ":hftest_vm",
+  ]
+}
+
+initrd("primary_with_secondaries_test") {
+  testonly = true
+  primary_vm = ":primary_with_secondaries_test_vm"
+  secondary_vms = [ [
+        "1048576",
+        "1",
+        "echo",
+        "//test/vm/secondaries:echo",
+      ] ]
+}
diff --git a/test/vm/primary_only/primary.c b/test/vm/primary_only.c
similarity index 93%
rename from test/vm/primary_only/primary.c
rename to test/vm/primary_only.c
index b2ee0d5..4667783 100644
--- a/test/vm/primary_only/primary.c
+++ b/test/vm/primary_only.c
@@ -1,6 +1,6 @@
 #include "vmapi/hf/call.h"
 
-#include "../hftest.h"
+#include "hftest.h"
 
 TEST(hf_vm_get_count, no_secondary_vms)
 {
diff --git a/test/vm/primary_only/BUILD.gn b/test/vm/primary_only/BUILD.gn
deleted file mode 100644
index 821ef0e..0000000
--- a/test/vm/primary_only/BUILD.gn
+++ /dev/null
@@ -1,18 +0,0 @@
-import("//build/image/image.gni")
-
-vm_kernel("primary_only_test_vm") {
-  testonly = true
-
-  sources = [
-    "primary.c",
-  ]
-
-  deps = [
-    "//test/vm:hftest_vm",
-  ]
-}
-
-initrd("primary_only_test") {
-  testonly = true
-  primary_vm = ":primary_only_test_vm"
-}
diff --git a/test/vm/primary_with_secondary/primary.c b/test/vm/primary_with_secondaries.c
similarity index 73%
rename from test/vm/primary_with_secondary/primary.c
rename to test/vm/primary_with_secondaries.c
index af488c2..52417f8 100644
--- a/test/vm/primary_with_secondary/primary.c
+++ b/test/vm/primary_with_secondaries.c
@@ -3,10 +3,11 @@
 #include <stdint.h>
 
 #include "hf/mm.h"
+#include "hf/std.h"
 
 #include "vmapi/hf/call.h"
 
-#include "../hftest.h"
+#include "hftest.h"
 
 static alignas(PAGE_SIZE) uint8_t send_page[PAGE_SIZE];
 static alignas(PAGE_SIZE) uint8_t recv_page[PAGE_SIZE];
@@ -16,6 +17,8 @@
 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
+
 /**
  * Confirm there is 1 secondary VM.
  */
@@ -84,3 +87,25 @@
 {
 	EXPECT_EQ(hf_vm_configure(send_page_addr, recv_page_addr), 0);
 }
+
+/**
+ * Send and receive the same message from the echo VM.
+ */
+TEST(mailbox, echo)
+{
+	const char message[] = "Echo this back to me!";
+
+	/* Configure mailbox pages. */
+	EXPECT_EQ(hf_vm_configure(send_page_addr, recv_page_addr), 0);
+	EXPECT_EQ(hf_vcpu_run(ECHO_VM_ID, 0),
+		  HF_VCPU_RUN_RESPONSE(HF_VCPU_RUN_WAIT_FOR_INTERRUPT, 0, 0));
+
+	/* Set the message, echo it and check it didn't change. */
+	memcpy(send_page, message, sizeof(message));
+	EXPECT_EQ(hf_mailbox_send(ECHO_VM_ID, sizeof(message)), 0);
+	EXPECT_EQ(
+		hf_vcpu_run(ECHO_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/primary_with_secondary/BUILD.gn b/test/vm/primary_with_secondary/BUILD.gn
deleted file mode 100644
index 8b4c489..0000000
--- a/test/vm/primary_with_secondary/BUILD.gn
+++ /dev/null
@@ -1,36 +0,0 @@
-import("//build/image/image.gni")
-
-vm_kernel("primary_with_secondary_test_primary_vm") {
-  testonly = true
-
-  sources = [
-    "primary.c",
-  ]
-
-  deps = [
-    "//test/vm:hftest_vm",
-  ]
-}
-
-vm_kernel("primary_with_secondary_test_secondary_vm") {
-  testonly = true
-
-  sources = [
-    "secondary.c",
-  ]
-
-  deps = [
-    "//test/vm:other_vm",
-  ]
-}
-
-initrd("primary_with_secondary_test") {
-  testonly = true
-  primary_vm = ":primary_with_secondary_test_primary_vm"
-  secondary_vms = [ [
-        "1048576",
-        "1",
-        "secondary",
-        ":primary_with_secondary_test_secondary_vm",
-      ] ]
-}
diff --git a/test/vm/primary_with_secondary/secondary.c b/test/vm/primary_with_secondary/secondary.c
deleted file mode 100644
index 788e310..0000000
--- a/test/vm/primary_with_secondary/secondary.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <stdalign.h>
-#include <stdint.h>
-
-#include "vmapi/hf/call.h"
-
-#include "../hftest.h"
-
-alignas(4096) uint8_t kstack[4096];
-
-void kmain(void)
-{
-	for (;;) {
-		/* Do nothing. */
-	}
-}
diff --git a/test/vm/secondaries/BUILD.gn b/test/vm/secondaries/BUILD.gn
new file mode 100644
index 0000000..3f17fc6
--- /dev/null
+++ b/test/vm/secondaries/BUILD.gn
@@ -0,0 +1,13 @@
+import("//build/image/image.gni")
+
+vm_kernel("echo") {
+  testonly = true
+
+  sources = [
+    "echo.c",
+  ]
+
+  deps = [
+    "//test/vm:secondary_vm",
+  ]
+}
diff --git a/test/vm/secondaries/echo.c b/test/vm/secondaries/echo.c
new file mode 100644
index 0000000..4bc3f83
--- /dev/null
+++ b/test/vm/secondaries/echo.c
@@ -0,0 +1,31 @@
+#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, echo messages back to the sender. */
+	for (;;) {
+		uint64_t ret = hf_mailbox_receive(true);
+		uint32_t vm_id = HF_MAILBOX_RECEIVE_VM_ID(ret);
+		uint32_t size = HF_MAILBOX_RECEIVE_SIZE(ret);
+		memcpy(send_page, recv_page, size);
+		hf_mailbox_clear();
+		hf_mailbox_send(vm_id, size);
+	}
+}