Support SPCI memory sharing clear flag.
Bug: 132420445
Change-Id: I2705cc8114dcf3ad500e4060be54527cebc3d5a2
diff --git a/inc/vmapi/hf/spci.h b/inc/vmapi/hf/spci.h
index 30feb0e..812865b 100644
--- a/inc/vmapi/hf/spci.h
+++ b/inc/vmapi/hf/spci.h
@@ -264,6 +264,15 @@
uint16_t memory_attributes;
};
+/** Flags to control the behaviour of a memory sharing transaction. */
+typedef uint32_t spci_memory_region_flags_t;
+
+/**
+ * Clear memory region contents after unmapping it from the sender and before
+ * mapping it for any receiver.
+ */
+#define SPCI_MEMORY_REGION_FLAG_CLEAR 0x1
+
struct spci_memory_region {
/**
* An implementation defined value associated with the receiver and the
@@ -271,7 +280,7 @@
*/
uint32_t tag;
/** Flags to control behaviour of the transaction. */
- uint32_t flags;
+ spci_memory_region_flags_t flags;
/**
* The total number of 4 kiB pages included in this memory region. This
* must be equal to the sum of page counts specified in each
@@ -327,16 +336,16 @@
struct spci_memory_region *memory_region, spci_vm_id_t receiver,
const struct spci_memory_region_constituent constituents[],
uint32_t constituent_count, uint32_t tag,
- enum spci_memory_access access, enum spci_memory_type type,
- enum spci_memory_cacheability cacheability,
+ spci_memory_region_flags_t flags, enum spci_memory_access access,
+ enum spci_memory_type type, enum spci_memory_cacheability cacheability,
enum spci_memory_shareability shareability);
uint32_t spci_memory_init(
void *message, enum spci_memory_share share_type, spci_vm_id_t receiver,
struct spci_memory_region_constituent *region_constituents,
uint32_t constituent_count, uint32_t tag,
- enum spci_memory_access access, enum spci_memory_type type,
- enum spci_memory_cacheability cacheability,
+ spci_memory_region_flags_t flags, enum spci_memory_access access,
+ enum spci_memory_type type, enum spci_memory_cacheability cacheability,
enum spci_memory_shareability shareability);
/** Constructs an SPCI donate memory region message. */
@@ -349,7 +358,7 @@
enum spci_memory_shareability shareability)
{
return spci_memory_init(message, SPCI_MEMORY_DONATE, receiver,
- region_constituents, constituent_count, tag,
+ region_constituents, constituent_count, tag, 0,
access, type, cacheability, shareability);
}
@@ -365,7 +374,7 @@
enum spci_memory_shareability shareability)
{
return spci_memory_init(message, SPCI_MEMORY_LEND, receiver,
- region_constituents, constituent_count, tag,
+ region_constituents, constituent_count, tag, 0,
access, type, cacheability, shareability);
}
@@ -381,7 +390,7 @@
enum spci_memory_shareability shareability)
{
return spci_memory_init(message, SPCI_MEMORY_SHARE, receiver,
- region_constituents, constituent_count, tag,
+ region_constituents, constituent_count, tag, 0,
access, type, cacheability, shareability);
}
@@ -395,7 +404,7 @@
uint32_t constituent_count, uint32_t tag)
{
return spci_memory_init(message, SPCI_MEMORY_RELINQUISH, receiver,
- region_constituents, constituent_count, tag,
+ region_constituents, constituent_count, tag, 0,
SPCI_MEMORY_RW_X, SPCI_MEMORY_DEVICE_MEM,
SPCI_MEMORY_DEV_NGNRNE,
SPCI_MEMORY_SHARE_NON_SHAREABLE);
diff --git a/src/api.c b/src/api.c
index caf024c..c748fb5 100644
--- a/src/api.c
+++ b/src/api.c
@@ -1544,6 +1544,19 @@
goto out;
}
+ /* Clear the memory so no VM or device can see the previous contents. */
+ if ((memory_region->flags & SPCI_MEMORY_REGION_FLAG_CLEAR) &&
+ !api_clear_memory(pa_begin, pa_end, &local_page_pool)) {
+ ret = spci_error(SPCI_NO_MEMORY);
+
+ /* Return memory to the sender. */
+ CHECK(mm_vm_identity_map(&from->ptable, pa_begin, pa_end,
+ orig_from_mode, NULL,
+ &local_page_pool));
+
+ goto out;
+ }
+
/* Complete the transfer by mapping the memory into the recipient. */
if (!mm_vm_identity_map(&to->ptable, pa_begin, pa_end, to_mode, NULL,
&local_page_pool)) {
diff --git a/test/vmapi/primary_with_secondaries/memory_sharing.c b/test/vmapi/primary_with_secondaries/memory_sharing.c
index e8dd6c5..1606c6d 100644
--- a/test/vmapi/primary_with_secondaries/memory_sharing.c
+++ b/test/vmapi/primary_with_secondaries/memory_sharing.c
@@ -1655,3 +1655,38 @@
SPCI_INVALID_PARAMETERS);
}
}
+
+/**
+ * SPCI: Memory can be cleared while being shared.
+ */
+TEST(memory_sharing, spci_share_clear)
+{
+ struct mailbox_buffers mb = set_up_mailbox();
+ uint8_t *ptr = page;
+ uint32_t msg_size;
+ size_t i;
+
+ SERVICE_SELECT(SERVICE_VM1, "spci_memory_return", mb.send);
+
+ /* Initialise the memory before giving it. */
+ memset_s(ptr, sizeof(page) * 2, 'b', PAGE_SIZE * 2);
+
+ struct spci_memory_region_constituent constituents[] = {
+ {.address = (uint64_t)page, .page_count = 2},
+ };
+
+ msg_size = spci_memory_init(
+ mb.send, SPCI_MEMORY_SHARE, SERVICE_VM1, constituents,
+ ARRAY_SIZE(constituents), 0, SPCI_MEMORY_REGION_FLAG_CLEAR,
+ SPCI_MEMORY_RO_X, SPCI_MEMORY_NORMAL_MEM,
+ SPCI_MEMORY_CACHE_WRITE_BACK, SPCI_MEMORY_OUTER_SHAREABLE);
+ EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, msg_size,
+ SPCI_MSG_SEND_LEGACY_MEMORY)
+ .func,
+ SPCI_SUCCESS_32);
+
+ /* Check that it has been cleared. */
+ for (i = 0; i < PAGE_SIZE * 2; ++i) {
+ ASSERT_EQ(ptr[i], 0);
+ };
+}
diff --git a/vmlib/spci.c b/vmlib/spci.c
index 93fe88d..19da8d7 100644
--- a/vmlib/spci.c
+++ b/vmlib/spci.c
@@ -48,7 +48,7 @@
uint32_t spci_memory_region_init(
struct spci_memory_region *memory_region, spci_vm_id_t receiver,
const struct spci_memory_region_constituent constituents[],
- uint32_t constituent_count, uint32_t tag,
+ uint32_t constituent_count, uint32_t tag, spci_memory_region_flags_t flags,
enum spci_memory_access access, enum spci_memory_type type,
enum spci_memory_cacheability cacheability,
enum spci_memory_shareability shareability)
@@ -67,7 +67,7 @@
spci_set_memory_shareability_attr(&attributes, shareability);
memory_region->tag = tag;
- memory_region->flags = 0;
+ memory_region->flags = flags;
memory_region->page_count = 0;
memory_region->constituent_count = constituent_count;
memory_region->attribute_count = 1;
@@ -107,7 +107,7 @@
uint32_t spci_memory_init(
void *message, enum spci_memory_share share_type, spci_vm_id_t receiver,
struct spci_memory_region_constituent *region_constituents,
- uint32_t constituent_count, uint32_t tag,
+ uint32_t constituent_count, uint32_t tag, spci_memory_region_flags_t flags,
enum spci_memory_access access, enum spci_memory_type type,
enum spci_memory_cacheability cacheability,
enum spci_memory_shareability shareability)
@@ -123,6 +123,6 @@
/* Fill in memory region. */
message_length += spci_memory_region_init(
memory_region, receiver, region_constituents, constituent_count,
- tag, access, type, cacheability, shareability);
+ tag, flags, access, type, cacheability, shareability);
return message_length;
}