Pass mapped memory size to secondary VMs on boot in x0.
Bug: 117082339
Change-Id: I851669d79cbae67d0a99dabc026b0919ae4e9ed3
diff --git a/src/load.c b/src/load.c
index ef033a6..0f71770 100644
--- a/src/load.c
+++ b/src/load.c
@@ -348,7 +348,9 @@
dlog("Loaded with %u vcpus, entry at 0x%x\n", cpu,
pa_addr(secondary_mem_begin));
- vm_secondary_start_vcpu(vm, 0, secondary_entry, 0);
+ vm_secondary_start_vcpu(
+ vm, 0, secondary_entry,
+ pa_difference(secondary_mem_begin, secondary_mem_end));
}
/*
diff --git a/test/hftest/hftest_service.c b/test/hftest/hftest_service.c
index c728e27..455b86a 100644
--- a/test/hftest/hftest_service.c
+++ b/test/hftest/hftest_service.c
@@ -76,7 +76,7 @@
}
}
-noreturn void kmain(void)
+noreturn void kmain(size_t memory_size)
{
struct memiter args;
hftest_test_fn service;
@@ -111,6 +111,7 @@
ctx->abort = abort;
ctx->send = (struct spci_message *)send;
ctx->recv = (struct spci_message *)recv;
+ ctx->memory_size = memory_size;
/* Pause so the next time cycles are given the service will be run. */
hf_vcpu_yield();
diff --git a/test/hftest/inc/hftest.h b/test/hftest/inc/hftest.h
index 145c2ed..d22cadf 100644
--- a/test/hftest/inc/hftest.h
+++ b/test/hftest/inc/hftest.h
@@ -72,6 +72,7 @@
#define SERVICE_SEND_BUFFER() HFTEST_SERVICE_SEND_BUFFER()
#define SERVICE_RECV_BUFFER() HFTEST_SERVICE_RECV_BUFFER()
+#define SERVICE_MEMORY_SIZE() HFTEST_SERVICE_MEMORY_SIZE()
/*
* This must be used exactly once in a test image to signal to the linker that
diff --git a/test/hftest/inc/hftest_impl.h b/test/hftest/inc/hftest_impl.h
index 346e496..13b49f1 100644
--- a/test/hftest/inc/hftest_impl.h
+++ b/test/hftest/inc/hftest_impl.h
@@ -136,6 +136,7 @@
/* These are used in services. */
struct spci_message *send;
struct spci_message *recv;
+ size_t memory_size;
};
struct hftest_context *hftest_get_context(void);
@@ -296,5 +297,6 @@
#define HFTEST_SERVICE_SEND_BUFFER() hftest_get_context()->send
#define HFTEST_SERVICE_RECV_BUFFER() hftest_get_context()->recv
+#define HFTEST_SERVICE_MEMORY_SIZE() hftest_get_context()->memory_size
void hftest_register(struct hftest_test test);
diff --git a/test/vmapi/primary_with_secondaries/BUILD.gn b/test/vmapi/primary_with_secondaries/BUILD.gn
index 34f8857..868487e 100644
--- a/test/vmapi/primary_with_secondaries/BUILD.gn
+++ b/test/vmapi/primary_with_secondaries/BUILD.gn
@@ -25,6 +25,7 @@
sources = [
"abort.c",
+ "boot.c",
"interrupts.c",
"mailbox.c",
"memory_sharing.c",
diff --git a/test/vmapi/primary_with_secondaries/boot.c b/test/vmapi/primary_with_secondaries/boot.c
new file mode 100644
index 0000000..d6aa553
--- /dev/null
+++ b/test/vmapi/primary_with_secondaries/boot.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/dlog.h"
+
+#include "vmapi/hf/call.h"
+
+#include "hftest.h"
+#include "primary_with_secondary.h"
+#include "util.h"
+
+/**
+ * The VM gets its memory size on boot, and can access it all.
+ */
+TEST(boot, memory_size)
+{
+ struct hf_vcpu_run_return run_res;
+ struct mailbox_buffers mb = set_up_mailbox();
+
+ SERVICE_SELECT(SERVICE_VM0, "boot_memory", mb.send);
+
+ run_res = hf_vcpu_run(SERVICE_VM0, 0);
+ EXPECT_EQ(run_res.code, HF_VCPU_RUN_YIELD);
+}
+
+/**
+ * Accessing memory outside the given range aborts the VM.
+ */
+TEST(boot, beyond_memory_size)
+{
+ struct hf_vcpu_run_return run_res;
+ struct mailbox_buffers mb = set_up_mailbox();
+
+ SERVICE_SELECT(SERVICE_VM0, "boot_memory_overrun", mb.send);
+
+ run_res = hf_vcpu_run(SERVICE_VM0, 0);
+ EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
+}
+
+/**
+ * Accessing memory before the start of the image aborts the VM.
+ */
+TEST(boot, memory_before_image)
+{
+ struct hf_vcpu_run_return run_res;
+ struct mailbox_buffers mb = set_up_mailbox();
+
+ SERVICE_SELECT(SERVICE_VM0, "boot_memory_underrun", mb.send);
+
+ run_res = hf_vcpu_run(SERVICE_VM0, 0);
+ EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
+}
diff --git a/test/vmapi/primary_with_secondaries/services/BUILD.gn b/test/vmapi/primary_with_secondaries/services/BUILD.gn
index 6b15dc7..377ac03 100644
--- a/test/vmapi/primary_with_secondaries/services/BUILD.gn
+++ b/test/vmapi/primary_with_secondaries/services/BUILD.gn
@@ -72,6 +72,16 @@
]
}
+# Services related to the boot process for VMs.
+source_set("boot") {
+ testonly = true
+ public_configs = [ "//test/hftest:hftest_config" ]
+
+ sources = [
+ "boot.c",
+ ]
+}
+
# Service that can be interrupted.
source_set("interruptible") {
testonly = true
@@ -145,6 +155,7 @@
deps = [
":abort",
+ ":boot",
":check_state",
":echo",
":echo_with_notification",
diff --git a/test/vmapi/primary_with_secondaries/services/boot.c b/test/vmapi/primary_with_secondaries/services/boot.c
new file mode 100644
index 0000000..965c5bb
--- /dev/null
+++ b/test/vmapi/primary_with_secondaries/services/boot.c
@@ -0,0 +1,72 @@
+/*
+ * 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/mm.h"
+#include "hf/std.h"
+
+#include "vmapi/hf/call.h"
+
+#include "hftest.h"
+
+/*
+ * This must match the size specified for services0 in
+ * //test/vmapi/primary_with_secondaries:primary_with_secondaries_test.
+ */
+#define SECONDARY_MEMORY_SIZE 1048576
+
+extern uint8_t volatile text_begin[];
+
+TEST_SERVICE(boot_memory)
+{
+ uint8_t checksum = 0;
+
+ /* Check that the size passed in by Hafnium is what is expected. */
+ ASSERT_EQ(SERVICE_MEMORY_SIZE(), SECONDARY_MEMORY_SIZE);
+
+ /*
+ * Check that we can read all memory up to the given size. Calculate a
+ * basic checksum and check that it is non-zero, as a double-check that
+ * we are actually reading something.
+ */
+ for (size_t i = 0; i < SERVICE_MEMORY_SIZE(); ++i) {
+ checksum += text_begin[i];
+ }
+ ASSERT_NE(checksum, 0);
+ dlog("Checksum of all memory is %d\n", checksum);
+
+ hf_vcpu_yield();
+}
+
+TEST_SERVICE(boot_memory_underrun)
+{
+ /*
+ * Try to read memory below the start of the image. This should result
+ * in the VM being aborted.
+ */
+ dlog("Read memory below limit: %d\n", text_begin[-1]);
+ FAIL("Managed to read memory below limit");
+}
+
+TEST_SERVICE(boot_memory_overrun)
+{
+ /*
+ * Try to read memory above the limit defined by memory_size. This
+ * should result in the VM being aborted.
+ */
+ dlog("Read memory above limit: %d\n",
+ text_begin[SERVICE_MEMORY_SIZE()]);
+ FAIL("Managed to read memory above limit");
+}