SPCI: Donate memory architected message.
The donate mechnism accepts a single memory region as per the spec but
restrics the number of constituents of this regions to 1.
Multiple constituents will be introduced in a later commit.
Change-Id: I7af9b80068060aedb953d3e204fa3e03c9ccc438
diff --git a/test/hftest/inc/hftest_impl.h b/test/hftest/inc/hftest_impl.h
index 64eeac4..f3eb407 100644
--- a/test/hftest/inc/hftest_impl.h
+++ b/test/hftest/inc/hftest_impl.h
@@ -22,6 +22,8 @@
#include "hf/spci.h"
#include "hf/std.h"
+#include "vmapi/hf/spci.h"
+
#define HFTEST_MAX_TESTS 50
/*
diff --git a/test/vmapi/primary_with_secondaries/memory_sharing.c b/test/vmapi/primary_with_secondaries/memory_sharing.c
index 70dbc08..ed402b8 100644
--- a/test/vmapi/primary_with_secondaries/memory_sharing.c
+++ b/test/vmapi/primary_with_secondaries/memory_sharing.c
@@ -163,6 +163,45 @@
}
/**
+ * SPCI Memory given away can be given back.
+ * Employing SPCI donate architected messages.
+ */
+TEST(memory_sharing, spci_give_and_get_back)
+{
+ struct hf_vcpu_run_return run_res;
+ struct mailbox_buffers mb = set_up_mailbox();
+ uint8_t *ptr = page;
+
+ SERVICE_SELECT(SERVICE_VM0, "memory_return_spci", mb.send);
+
+ /* Initialise the memory before giving it. */
+ memset_s(ptr, sizeof(page), 'b', PAGE_SIZE);
+
+ /* Can only donate single constituent memory region. */
+ struct spci_memory_region_constituent constituents[] = {
+ {.address = (uint64_t)page, .page_count = 1},
+ };
+
+ spci_memory_donate(mb.send, SERVICE_VM0, HF_PRIMARY_VM_ID, constituents,
+ 1, 0);
+
+ EXPECT_EQ(spci_msg_send(0), SPCI_SUCCESS);
+ run_res = hf_vcpu_run(SERVICE_VM0, 0);
+
+ /* Let the memory be returned. */
+ EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
+
+ /* Ensure that the secondary VM accessed the region. */
+ for (int i = 0; i < PAGE_SIZE; ++i) {
+ ASSERT_EQ(ptr[i], 'c');
+ }
+
+ /* Observe the service faulting when accessing the memory. */
+ run_res = hf_vcpu_run(SERVICE_VM0, 0);
+ EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
+}
+
+/**
* Memory given away can be given back.
*/
TEST(memory_sharing, give_and_get_back)
diff --git a/test/vmapi/primary_with_secondaries/services/memory.c b/test/vmapi/primary_with_secondaries/services/memory.c
index f17932c..8b65600 100644
--- a/test/vmapi/primary_with_secondaries/services/memory.c
+++ b/test/vmapi/primary_with_secondaries/services/memory.c
@@ -55,6 +55,41 @@
}
}
+TEST_SERVICE(memory_return_spci)
+{
+ /* Loop, giving memory back to the sender. */
+ for (;;) {
+ spci_msg_recv(SPCI_MSG_RECV_BLOCK);
+ uint8_t *ptr;
+
+ struct spci_message *recv_buf = SERVICE_RECV_BUFFER();
+ struct spci_message *send_buf = SERVICE_SEND_BUFFER();
+ struct spci_memory_region *memory_region =
+ spci_get_donated_memory_region(recv_buf);
+
+ ptr = (uint8_t *)memory_region->constituents[0].address;
+ /* Relevant information read, mailbox can be cleared. */
+ hf_mailbox_clear();
+
+ /* Check that one has access to the shared region. */
+ for (int i = 0; i < PAGE_SIZE; ++i) {
+ ptr[i]++;
+ }
+
+ /* Give the memory back and notify the sender. */
+ spci_memory_donate(
+ send_buf, HF_PRIMARY_VM_ID, recv_buf->target_vm_id,
+ memory_region->constituents, memory_region->count, 0);
+ spci_msg_send(0);
+
+ /*
+ * Try and access the memory which will cause a fault unless the
+ * memory has been shared back again.
+ */
+ ptr[0] = 123;
+ }
+}
+
TEST_SERVICE(memory_return)
{
/* Loop, giving memory back to the sender. */