Using new SPCI beta format for memory region descriptors.

Bug: 141469322, 132429380
Change-Id: Iaa99a90725aba7ca320f3a417d839c6cdfd5debf
diff --git a/inc/hf/spci_internal.h b/inc/hf/spci_internal.h
index c7c0d2e..2bb1457 100644
--- a/inc/hf/spci_internal.h
+++ b/inc/hf/spci_internal.h
@@ -34,32 +34,25 @@
 };
 
 /* TODO: Add device attributes: GRE, cacheability, shareability. */
-static inline uint32_t spci_memory_attrs_to_mode(uint32_t memory_attributes)
+static inline uint32_t spci_memory_attrs_to_mode(uint16_t memory_attributes)
 {
 	uint32_t mode = 0;
-	uint32_t attr_value;
 
-	attr_value = spci_get_lend_access_attr(memory_attributes);
-	switch (attr_value) {
-	case SPCI_LEND_RO_NX:
-		mode |= MM_MODE_R;
+	switch (spci_get_memory_access_attr(memory_attributes)) {
+	case SPCI_MEMORY_RO_NX:
+		mode = MM_MODE_R;
 		break;
-
-	case SPCI_LEND_RO_X:
-		mode |= MM_MODE_R | MM_MODE_X;
+	case SPCI_MEMORY_RO_X:
+		mode = MM_MODE_R | MM_MODE_X;
 		break;
-
-	case SPCI_LEND_RW_NX:
-		mode |= MM_MODE_R | MM_MODE_W;
+	case SPCI_MEMORY_RW_NX:
+		mode = MM_MODE_R | MM_MODE_W;
 		break;
-
-	case SPCI_LEND_RW_X:
-		mode |= MM_MODE_R | MM_MODE_W | MM_MODE_X;
-		break;
-
-	default:
+	case SPCI_MEMORY_RW_X:
+		mode = MM_MODE_R | MM_MODE_W | MM_MODE_X;
 		break;
 	}
+
 	return mode;
 }
 
diff --git a/inc/vmapi/hf/spci.h b/inc/vmapi/hf/spci.h
index 125ea38..6977de8 100644
--- a/inc/vmapi/hf/spci.h
+++ b/inc/vmapi/hf/spci.h
@@ -72,84 +72,83 @@
 /* The maximum length possible for a single message. */
 #define SPCI_MSG_PAYLOAD_MAX HF_MAILBOX_SIZE
 
-enum spci_lend_access {
-	SPCI_LEND_RO_NX,
-	SPCI_LEND_RO_X,
-	SPCI_LEND_RW_NX,
-	SPCI_LEND_RW_X,
+enum spci_memory_access {
+	SPCI_MEMORY_RO_NX,
+	SPCI_MEMORY_RO_X,
+	SPCI_MEMORY_RW_NX,
+	SPCI_MEMORY_RW_X,
 };
 
-enum spci_lend_type {
-	SPCI_LEND_NORMAL_MEM,
-	SPCI_LEND_DEV_NGNRNE,
-	SPCI_LEND_DEV_NGNRE,
-	SPCI_LEND_DEV_NGRE,
-	SPCI_LEND_DEV_GRE,
+enum spci_memory_type {
+	SPCI_MEMORY_DEVICE_MEM,
+	SPCI_MEMORY_NORMAL_MEM,
 };
 
-enum spci_lend_cacheability {
-	SPCI_LEND_CACHE_NON_CACHEABLE,
-	SPCI_LEND_CACHE_WRITE_THROUGH,
-	SPCI_LEND_CACHE_WRITE_BACK,
+enum spci_memory_cacheability {
+	SPCI_MEMORY_CACHE_RESERVED = 0x0,
+	SPCI_MEMORY_CACHE_NON_CACHEABLE = 0x1,
+	SPCI_MEMORY_CACHE_WRITE_THROUGH = 0x2,
+	SPCI_MEMORY_CACHE_WRITE_BACK = 0x4,
+	SPCI_MEMORY_DEV_NGNRNE = 0x0,
+	SPCI_MEMORY_DEV_NGNRE = 0x1,
+	SPCI_MEMORY_DEV_NGRE = 0x2,
+	SPCI_MEMORY_DEV_GRE = 0x3,
 };
 
-enum spci_lend_shareability {
-	SPCI_LEND_SHARE_NON_SHAREABLE,
-	SPCI_LEND_RESERVED,
-	SPCI_LEND_OUTER_SHAREABLE,
-	SPCI_LEND_INNER_SHAREABLE,
+enum spci_memory_shareability {
+	SPCI_MEMORY_SHARE_NON_SHAREABLE,
+	SPCI_MEMORY_RESERVED,
+	SPCI_MEMORY_OUTER_SHAREABLE,
+	SPCI_MEMORY_INNER_SHAREABLE,
 };
 
-#define SPCI_LEND_ACCESS_OFFSET (0x7U)
-#define SPCI_LEND_ACCESS_MASK ((0x3U) << SPCI_LEND_ACCESS_OFFSET)
+#define SPCI_MEMORY_ACCESS_OFFSET (0x5U)
+#define SPCI_MEMORY_ACCESS_MASK ((0x3U) << SPCI_MEMORY_ACCESS_OFFSET)
 
-#define SPCI_LEND_TYPE_OFFSET (0x4U)
-#define SPCI_LEND_TYPE_MASK ((0x7U) << SPCI_LEND_TYPE_OFFSET)
+#define SPCI_MEMORY_TYPE_OFFSET (0x4U)
+#define SPCI_MEMORY_TYPE_MASK ((0x1U) << SPCI_MEMORY_TYPE_OFFSET)
 
-#define SPCI_LEND_CACHEABILITY_OFFSET (0x2U)
-#define SPCI_LEND_CACHEABILITY_MASK ((0x3U) <<\
-	SPCI_LEND_CACHEABILITY_OFFSET)
+#define SPCI_MEMORY_CACHEABILITY_OFFSET (0x2U)
+#define SPCI_MEMORY_CACHEABILITY_MASK ((0x3U) <<\
+	SPCI_MEMORY_CACHEABILITY_OFFSET)
 
-#define SPCI_LEND_SHAREABILITY_OFFSET (0x0U)
-#define SPCI_LEND_SHAREABILITY_MASK ((0x3U) <<\
-	SPCI_LEND_SHAREABILITY_OFFSET)
+#define SPCI_MEMORY_SHAREABILITY_OFFSET (0x0U)
+#define SPCI_MEMORY_SHAREABILITY_MASK ((0x3U) <<\
+	SPCI_MEMORY_SHAREABILITY_OFFSET)
 
 #define LEND_ATTR_FUNCTION_SET(name, offset, mask) \
-static inline void spci_set_lend_##name##_attr(uint16_t *lend_attr,\
-	const enum spci_lend_##name perm)\
+static inline void spci_set_memory_##name##_attr(uint16_t *attr,\
+	const enum spci_memory_##name perm)\
 {\
-	*lend_attr = (*lend_attr & ~(mask)) | ((perm  << offset) & mask);\
+	*attr = (*attr & ~(mask)) | ((perm  << offset) & mask);\
 }
 
 #define LEND_ATTR_FUNCTION_GET(name, offset, mask) \
-static inline enum spci_lend_##name spci_get_lend_##name##_attr(\
-	uint16_t lend_attr)\
+static inline enum spci_memory_##name spci_get_memory_##name##_attr(\
+	uint16_t attr)\
 {\
-	return (enum spci_lend_##name)((lend_attr & mask) >> offset);\
+	return (enum spci_memory_##name)((attr & mask) >> offset);\
 }
 
-LEND_ATTR_FUNCTION_SET(access, SPCI_LEND_ACCESS_OFFSET, SPCI_LEND_ACCESS_MASK)
-LEND_ATTR_FUNCTION_GET(access, SPCI_LEND_ACCESS_OFFSET, SPCI_LEND_ACCESS_MASK)
+LEND_ATTR_FUNCTION_SET(access, SPCI_MEMORY_ACCESS_OFFSET,
+	SPCI_MEMORY_ACCESS_MASK)
+LEND_ATTR_FUNCTION_GET(access, SPCI_MEMORY_ACCESS_OFFSET,
+	SPCI_MEMORY_ACCESS_MASK)
 
-LEND_ATTR_FUNCTION_SET(type, SPCI_LEND_TYPE_OFFSET, SPCI_LEND_TYPE_MASK)
-LEND_ATTR_FUNCTION_GET(type, SPCI_LEND_TYPE_OFFSET, SPCI_LEND_TYPE_MASK)
+LEND_ATTR_FUNCTION_SET(type, SPCI_MEMORY_TYPE_OFFSET, SPCI_MEMORY_TYPE_MASK)
+LEND_ATTR_FUNCTION_GET(type, SPCI_MEMORY_TYPE_OFFSET, SPCI_MEMORY_TYPE_MASK)
 
-LEND_ATTR_FUNCTION_SET(cacheability, SPCI_LEND_CACHEABILITY_OFFSET,
-	SPCI_LEND_CACHEABILITY_MASK)
+LEND_ATTR_FUNCTION_SET(cacheability, SPCI_MEMORY_CACHEABILITY_OFFSET,
+	SPCI_MEMORY_CACHEABILITY_MASK)
 
-LEND_ATTR_FUNCTION_GET(cacheability, SPCI_LEND_CACHEABILITY_OFFSET,
-	SPCI_LEND_CACHEABILITY_MASK)
+LEND_ATTR_FUNCTION_GET(cacheability, SPCI_MEMORY_CACHEABILITY_OFFSET,
+	SPCI_MEMORY_CACHEABILITY_MASK)
 
-LEND_ATTR_FUNCTION_SET(shareability, SPCI_LEND_SHAREABILITY_OFFSET,
-	SPCI_LEND_SHAREABILITY_MASK)
+LEND_ATTR_FUNCTION_SET(shareability, SPCI_MEMORY_SHAREABILITY_OFFSET,
+	SPCI_MEMORY_SHAREABILITY_MASK)
 
-LEND_ATTR_FUNCTION_GET(shareability, SPCI_LEND_SHAREABILITY_OFFSET,
-	SPCI_LEND_SHAREABILITY_MASK)
-
-enum spci_lend_flags {
-	SPCI_LEND_KEEP_MAPPED = 0x0,
-	SPCI_LEND_UNMAP = 0x1
-};
+LEND_ATTR_FUNCTION_GET(shareability, SPCI_MEMORY_SHAREABILITY_OFFSET,
+	SPCI_MEMORY_SHAREABILITY_MASK)
 
 /* clang-format on */
 
@@ -217,35 +216,76 @@
 };
 
 struct spci_memory_region_constituent {
+	/**
+	 * The base IPA of the constituent memory region, aligned to 4 kiB page
+	 * size granularity.
+	 */
 	uint64_t address;
+	/** The number of 4 kiB pages in the constituent memory region. */
 	uint32_t page_count;
 
 	uint32_t reserved;
 };
 
-struct spci_memory_region {
-	spci_memory_handle_t handle;
-	uint32_t count;
-
-	struct spci_memory_region_constituent constituents[];
+struct spci_memory_region_attributes {
+	/** The ID of the VM to which the memory is being given or shared. */
+	spci_vm_id_t receiver;
+	/**
+	 * The attributes with which the memory region should be mapped in the
+	 * receiver's page table.
+	 */
+	uint16_t memory_attributes;
 };
 
-struct spci_memory_lend {
-	uint16_t flags;
-	uint16_t borrower_attributes;
-
-	uint32_t reserved;
-
-	uint8_t payload[];
+struct spci_memory_region {
+	/**
+	 * An implementation defined value associated with the receiver and the
+	 * memory region.
+	 */
+	uint32_t tag;
+	/** Flags to control behaviour of the transaction. */
+	uint32_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
+	 * `spci_memory_region_constituent`.
+	 */
+	uint32_t page_count;
+	/**
+	 * The number of constituents (`spci_memory_region_constituent`)
+	 * included in this memory region.
+	 */
+	uint32_t constituent_count;
+	/**
+	 * The offset in bytes from the base address of this
+	 * `spci_memory_region` to the start of the first
+	 * `spci_memory_region_constituent`.
+	 */
+	uint32_t constituent_offset;
+	/**
+	 * The number of `spci_memory_region_attributes` entries included in
+	 * this memory region.
+	 */
+	uint32_t attribute_count;
+	/**
+	 * An array of `attribute_count` memory region attribute descriptors.
+	 * Each one specifies an endpoint and the attributes with which this
+	 * memory region should be mapped in that endpoint's page table.
+	 */
+	struct spci_memory_region_attributes attributes[];
 };
 
 /* TODO: Move all the functions below this line to a support library. */
 
-static inline struct spci_memory_lend *spci_get_lend_descriptor(void *message)
+/**
+ * Gets the constituent array for an `spci_memory_region`.
+ */
+static inline struct spci_memory_region_constituent *
+spci_memory_region_get_constituents(struct spci_memory_region *memory_region)
 {
-	return (struct spci_memory_lend
-			*)((struct spci_architected_message_header *)message)
-		->payload;
+	return (struct spci_memory_region_constituent
+			*)((uint8_t *)memory_region +
+			   memory_region->constituent_offset);
 }
 
 /**
@@ -263,9 +303,8 @@
 	architected_header->reserved[2] = 0;
 }
 
-/** Obtain a pointer to the start of the memory region in the donate message. */
-static inline struct spci_memory_region *spci_get_donated_memory_region(
-	void *message)
+/** Gets the spci_memory_region within an architected message. */
+static inline struct spci_memory_region *spci_get_memory_region(void *message)
 {
 	struct spci_architected_message_header *architected_header =
 		(struct spci_architected_message_header *)message;
@@ -273,27 +312,50 @@
 }
 
 /**
- * Helper function that copies the memory constituents and the handle
- * information onto the address pointed to by memory_region.
- * The function returns the length in bytes occupied by the data copied to
- * memory_region (constituents and memory region header size).
+ * Initialises the given `spci_memory_region` and copies the constituent
+ * information to it. Returns the length in bytes occupied by the data copied to
+ * `memory_region` (attributes, constituents and memory region header size).
  */
-static inline uint32_t spci_memory_region_add(
-	struct spci_memory_region *memory_region, spci_memory_handle_t handle,
+static inline 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 num_constituents)
+	uint32_t constituent_count, uint32_t tag,
+	enum spci_memory_access access, enum spci_memory_type type,
+	enum spci_memory_cacheability cacheability,
+	enum spci_memory_shareability shareability)
 {
 	uint32_t constituents_length =
-		num_constituents *
+		constituent_count *
 		sizeof(struct spci_memory_region_constituent);
 	uint32_t index;
+	struct spci_memory_region_constituent *region_constituents;
+	uint16_t attributes = 0;
 
-	memory_region->handle = handle;
-	memory_region->count = num_constituents;
+	/* Set memory region's page attributes. */
+	spci_set_memory_access_attr(&attributes, access);
+	spci_set_memory_type_attr(&attributes, type);
+	spci_set_memory_cacheability_attr(&attributes, cacheability);
+	spci_set_memory_shareability_attr(&attributes, shareability);
 
-	for (index = 0; index < num_constituents; index++) {
-		memory_region->constituents[index] = constituents[index];
-		memory_region->constituents[index].reserved = 0;
+	memory_region->tag = tag;
+	memory_region->flags = 0;
+	memory_region->page_count = 0;
+	memory_region->constituent_count = constituent_count;
+	memory_region->attribute_count = 1;
+	memory_region->attributes[0].receiver = receiver;
+	memory_region->attributes[0].memory_attributes = attributes;
+
+	memory_region->constituent_offset =
+		sizeof(struct spci_memory_region) +
+		memory_region->attribute_count *
+			sizeof(struct spci_memory_region_attributes);
+	region_constituents =
+		spci_memory_region_get_constituents(memory_region);
+
+	for (index = 0; index < constituent_count; index++) {
+		region_constituents[index] = constituents[index];
+		region_constituents[index].reserved = 0;
+		memory_region->page_count += constituents[index].page_count;
 	}
 
 	/*
@@ -301,95 +363,80 @@
 	 * length is not greater than SPCI_MSG_PAYLOAD_MAX.
 	 */
 
-	return sizeof(struct spci_memory_region) + constituents_length;
+	return memory_region->constituent_offset + constituents_length;
 }
 
-/** Construct the SPCI donate memory region message. */
+/** Constructs an SPCI donate memory region message. */
 static inline uint32_t spci_memory_donate_init(
-	void *message,
+	void *message, spci_vm_id_t receiver,
 	struct spci_memory_region_constituent *region_constituents,
-	uint32_t num_elements, uint32_t handle)
+	uint32_t constituent_count, uint32_t tag,
+	enum spci_memory_access access, enum spci_memory_type type,
+	enum spci_memory_cacheability cacheability,
+	enum spci_memory_shareability shareability)
 {
-	uint32_t message_length;
+	uint32_t message_length =
+		sizeof(struct spci_architected_message_header);
 	struct spci_memory_region *memory_region =
-		spci_get_donated_memory_region(message);
-
-	message_length = sizeof(struct spci_architected_message_header);
+		spci_get_memory_region(message);
 
 	/* Fill in the details on the common message header. */
 	spci_architected_message_init(message, SPCI_MEMORY_DONATE);
 
-	/* Create single memory region. */
-	message_length += spci_memory_region_add(
-		memory_region, handle, region_constituents, num_elements);
+	/* Fill in memory region. */
+	message_length += spci_memory_region_init(
+		memory_region, receiver, region_constituents, constituent_count,
+		tag, access, type, cacheability, shareability);
 	return message_length;
 }
 
 /**
- * Construct the SPCI memory region relinquish message.
+ * Constructs an SPCI memory region relinquish message.
  * A set of memory regions can be given back to the owner.
  */
 static inline uint32_t spci_memory_relinquish_init(
-	void *message,
+	void *message, spci_vm_id_t receiver,
 	struct spci_memory_region_constituent *region_constituents,
-	uint64_t num_elements, uint32_t handle)
+	uint32_t constituent_count, uint32_t tag)
 {
-	uint32_t message_length;
+	uint32_t message_length =
+		sizeof(struct spci_architected_message_header);
 	struct spci_memory_region *memory_region =
-		spci_get_donated_memory_region(message);
-
-	message_length = sizeof(struct spci_architected_message_header);
+		spci_get_memory_region(message);
 
 	/* Fill in the details on the common message header. */
 	spci_architected_message_init(message, SPCI_MEMORY_RELINQUISH);
 
-	/* Create single memory region. */
-	message_length += spci_memory_region_add(
-		memory_region, handle, region_constituents, num_elements);
+	/* Fill in memory region. */
+	message_length += spci_memory_region_init(
+		memory_region, receiver, region_constituents, constituent_count,
+		tag, SPCI_MEMORY_RW_X, SPCI_MEMORY_DEVICE_MEM,
+		SPCI_MEMORY_DEV_NGNRNE, SPCI_MEMORY_SHARE_NON_SHAREABLE);
 	return message_length;
 }
 
 /**
- * Construct the SPCI memory region lend message.
+ * Constructs an SPCI memory region lend message.
  */
 static inline uint32_t spci_memory_lend_init(
-	void *message,
+	void *message, spci_vm_id_t receiver,
 	struct spci_memory_region_constituent *region_constituents,
-	uint64_t num_elements, uint32_t handle, enum spci_lend_access access,
-	enum spci_lend_type type, enum spci_lend_cacheability cacheability,
-	enum spci_lend_shareability shareability)
+	uint32_t constituent_count, uint32_t tag,
+	enum spci_memory_access access, enum spci_memory_type type,
+	enum spci_memory_cacheability cacheability,
+	enum spci_memory_shareability shareability)
 {
-	uint32_t message_length;
-	struct spci_memory_region *memory_region;
-
-	const struct spci_memory_lend lend_init = {0};
-
-	struct spci_memory_lend *lend_descriptor =
-		spci_get_lend_descriptor(message);
-	memory_region = (struct spci_memory_region *)lend_descriptor->payload;
-
-	/* Initilise all struct elements to zero. */
-	*lend_descriptor = lend_init;
-
-	message_length = sizeof(struct spci_architected_message_header) +
-			 sizeof(struct spci_memory_lend);
+	uint32_t message_length =
+		sizeof(struct spci_architected_message_header);
+	struct spci_memory_region *memory_region =
+		spci_get_memory_region(message);
 
 	/* Fill in the details on the common message header. */
 	spci_architected_message_init(message, SPCI_MEMORY_LEND);
 
-	lend_descriptor->flags = SPCI_LEND_KEEP_MAPPED;
-
-	/* Set memory region's page attributes. */
-	spci_set_lend_access_attr(&lend_descriptor->borrower_attributes,
-				  access);
-	spci_set_lend_type_attr(&lend_descriptor->borrower_attributes, type);
-	spci_set_lend_cacheability_attr(&lend_descriptor->borrower_attributes,
-					cacheability);
-	spci_set_lend_shareability_attr(&lend_descriptor->borrower_attributes,
-					shareability);
-
-	/* Create single memory region. */
-	message_length += spci_memory_region_add(
-		memory_region, handle, region_constituents, num_elements);
+	/* Fill in memory region. */
+	message_length += spci_memory_region_init(
+		memory_region, receiver, region_constituents, constituent_count,
+		tag, access, type, cacheability, shareability);
 	return message_length;
 }
diff --git a/src/api.c b/src/api.c
index e583a31..c16a808 100644
--- a/src/api.c
+++ b/src/api.c
@@ -1460,6 +1460,8 @@
 	paddr_t pa_end;
 	ipaddr_t begin;
 	ipaddr_t end;
+	struct spci_memory_region_constituent *constituents =
+		spci_memory_region_get_constituents(memory_region);
 
 	size_t size;
 
@@ -1477,8 +1479,8 @@
 
 	/* Obtain the single contiguous set of pages from the memory_region. */
 	/* TODO: Add support for multiple constituent regions. */
-	size = memory_region->constituents[0].page_count * PAGE_SIZE;
-	begin = ipa_init(memory_region->constituents[0].address);
+	size = constituents[0].page_count * PAGE_SIZE;
+	begin = ipa_init(constituents[0].address);
 	end = ipa_add(begin, size);
 
 	/*
diff --git a/src/spci_architected_message.c b/src/spci_architected_message.c
index ec2041e..605a7a9 100644
--- a/src/spci_architected_message.c
+++ b/src/spci_architected_message.c
@@ -26,18 +26,43 @@
 static struct spci_value spci_validate_call_share_memory(
 	struct vm_locked to_locked, struct vm_locked from_locked,
 	struct spci_memory_region *memory_region, uint32_t memory_share_size,
-	uint32_t memory_to_attributes, enum spci_memory_share share)
+	enum spci_memory_share share)
 {
-	uint32_t max_count = memory_region->count;
+	uint32_t memory_to_attributes;
+	uint32_t attributes_size;
+	uint32_t constituents_size;
 
 	/*
 	 * Ensure the number of constituents are within the memory
 	 * bounds.
 	 */
-	if (memory_share_size !=
-	    sizeof(struct spci_memory_region) +
-		    (sizeof(struct spci_memory_region_constituent) *
-		     max_count)) {
+	attributes_size = sizeof(struct spci_memory_region_attributes) *
+			  memory_region->attribute_count;
+	constituents_size = sizeof(struct spci_memory_region_constituent) *
+			    memory_region->constituent_count;
+	if (memory_region->constituent_offset <
+		    sizeof(struct spci_memory_region) + attributes_size ||
+	    memory_share_size !=
+		    memory_region->constituent_offset + constituents_size) {
+		return spci_error(SPCI_INVALID_PARAMETERS);
+	}
+
+	/* We only support a single recipient. */
+	if (memory_region->attribute_count != 1) {
+		return spci_error(SPCI_INVALID_PARAMETERS);
+	}
+
+	switch (share) {
+	case SPCI_MEMORY_DONATE:
+	case SPCI_MEMORY_LEND:
+		memory_to_attributes = spci_memory_attrs_to_mode(
+			memory_region->attributes[0].memory_attributes);
+		break;
+	case SPCI_MEMORY_RELINQUISH:
+		memory_to_attributes = MM_MODE_R | MM_MODE_W | MM_MODE_X;
+		break;
+	default:
+		dlog("Invalid memory sharing message.\n");
 		return spci_error(SPCI_INVALID_PARAMETERS);
 	}
 
@@ -57,74 +82,16 @@
 	uint32_t size)
 {
 	struct spci_value ret;
-	struct spci_memory_region *memory_region;
-	uint32_t to_mode;
-	uint32_t message_type;
-	uint32_t memory_share_size;
+	struct spci_memory_region *memory_region =
+		(struct spci_memory_region *)
+			architected_message_replica->payload;
+	uint32_t message_type = architected_message_replica->type;
+	uint32_t memory_share_size =
+		size - sizeof(struct spci_architected_message_header);
 
-	message_type = architected_message_replica->type;
-
-	switch (message_type) {
-	case SPCI_MEMORY_DONATE:
-		memory_region = (struct spci_memory_region *)
-					architected_message_replica->payload;
-
-		memory_share_size =
-			size - sizeof(struct spci_architected_message_header);
-
-		/* TODO: Add memory attributes. */
-		to_mode = MM_MODE_R | MM_MODE_W | MM_MODE_X;
-
-		ret = spci_validate_call_share_memory(
-			to_locked, from_locked, memory_region,
-			memory_share_size, to_mode, message_type);
-		break;
-
-	case SPCI_MEMORY_RELINQUISH:
-
-		memory_region = (struct spci_memory_region *)
-					architected_message_replica->payload;
-
-		memory_share_size =
-			size - sizeof(struct spci_architected_message_header);
-
-		to_mode = MM_MODE_R | MM_MODE_W | MM_MODE_X;
-
-		ret = spci_validate_call_share_memory(
-			to_locked, from_locked, memory_region,
-			memory_share_size, to_mode, message_type);
-
-		break;
-
-	case SPCI_MEMORY_LEND: {
-		/* TODO: Add support for lend exclusive. */
-		struct spci_memory_lend *lend_descriptor;
-		uint32_t borrower_attributes;
-
-		lend_descriptor = (struct spci_memory_lend *)
-					  architected_message_replica->payload;
-
-		borrower_attributes = lend_descriptor->borrower_attributes;
-
-		memory_region =
-			(struct spci_memory_region *)lend_descriptor->payload;
-		memory_share_size =
-			size - sizeof(struct spci_architected_message_header) -
-			sizeof(struct spci_memory_lend);
-
-		to_mode = spci_memory_attrs_to_mode(borrower_attributes);
-
-		ret = spci_validate_call_share_memory(
-			to_locked, from_locked, memory_region,
-			memory_share_size, to_mode, message_type);
-
-		break;
-	}
-
-	default:
-		dlog("Invalid memory sharing message.\n");
-		return spci_error(SPCI_INVALID_PARAMETERS);
-	}
+	ret = spci_validate_call_share_memory(to_locked, from_locked,
+					      memory_region, memory_share_size,
+					      message_type);
 
 	/* Copy data to the destination Rx. */
 	/*
diff --git a/test/vmapi/primary_with_secondaries/memory_sharing.c b/test/vmapi/primary_with_secondaries/memory_sharing.c
index b97dfab..dccc631 100644
--- a/test/vmapi/primary_with_secondaries/memory_sharing.c
+++ b/test/vmapi/primary_with_secondaries/memory_sharing.c
@@ -57,52 +57,60 @@
 	struct spci_memory_region_constituent constituents[])
 
 {
-	enum spci_lend_access lend_access[] = {SPCI_LEND_RO_NX, SPCI_LEND_RO_X,
-					       SPCI_LEND_RW_NX, SPCI_LEND_RW_X};
-	enum spci_lend_type lend_type[] = {
-		SPCI_LEND_NORMAL_MEM, SPCI_LEND_DEV_NGNRNE, SPCI_LEND_DEV_NGNRE,
-		SPCI_LEND_DEV_NGRE, SPCI_LEND_DEV_GRE};
-	enum spci_lend_cacheability lend_cacheability[] = {
-		SPCI_LEND_CACHE_NON_CACHEABLE, SPCI_LEND_CACHE_WRITE_THROUGH,
-		SPCI_LEND_CACHE_WRITE_BACK};
-	enum spci_lend_shareability lend_shareability[] = {
-		SPCI_LEND_SHARE_NON_SHAREABLE, SPCI_LEND_RESERVED,
-		SPCI_LEND_OUTER_SHAREABLE, SPCI_LEND_INNER_SHAREABLE};
+	enum spci_memory_access lend_access[] = {
+		SPCI_MEMORY_RO_NX, SPCI_MEMORY_RO_X, SPCI_MEMORY_RW_NX,
+		SPCI_MEMORY_RW_X};
+	enum spci_memory_cacheability lend_cacheability[] = {
+		SPCI_MEMORY_CACHE_NON_CACHEABLE,
+		SPCI_MEMORY_CACHE_WRITE_THROUGH, SPCI_MEMORY_CACHE_WRITE_BACK};
+	enum spci_memory_cacheability lend_device[] = {
+		SPCI_MEMORY_DEV_NGNRNE, SPCI_MEMORY_DEV_NGNRE,
+		SPCI_MEMORY_DEV_NGRE, SPCI_MEMORY_DEV_GRE};
+	enum spci_memory_shareability lend_shareability[] = {
+		SPCI_MEMORY_SHARE_NON_SHAREABLE, SPCI_MEMORY_RESERVED,
+		SPCI_MEMORY_OUTER_SHAREABLE, SPCI_MEMORY_INNER_SHAREABLE};
 	uint32_t vms[] = {HF_PRIMARY_VM_ID, SERVICE_VM0, SERVICE_VM1};
 
 	int i = 0;
 	int j = 0;
 	int k = 0;
 	int l = 0;
-	int m = 0;
 
 	for (i = 0; i < ARRAY_SIZE(vms); ++i) {
 		for (j = 0; j < ARRAY_SIZE(lend_access); ++j) {
-			for (k = 0; k < ARRAY_SIZE(lend_type); ++k) {
+			for (k = 0; k < ARRAY_SIZE(lend_shareability); ++k) {
 				for (l = 0; l < ARRAY_SIZE(lend_cacheability);
 				     ++l) {
-					for (m = 0;
-					     m < ARRAY_SIZE(lend_shareability);
-					     ++m) {
-						uint32_t msg_size =
-							spci_memory_lend_init(
-								mb.send,
-								constituents, 1,
-								0,
-								lend_access[j],
-								lend_type[k],
-								lend_cacheability
-									[l],
-								lend_shareability
-									[m]);
-						EXPECT_SPCI_ERROR(
-							spci_msg_send(
-								HF_PRIMARY_VM_ID,
-								vms[i],
-								msg_size,
-								SPCI_MSG_SEND_LEGACY_MEMORY),
-							SPCI_INVALID_PARAMETERS);
-					}
+					uint32_t msg_size =
+						spci_memory_lend_init(
+							mb.send, vms[i],
+							constituents, 1, 0,
+							lend_access[j],
+							SPCI_MEMORY_NORMAL_MEM,
+							lend_cacheability[l],
+							lend_shareability[k]);
+					EXPECT_SPCI_ERROR(
+						spci_msg_send(
+							HF_PRIMARY_VM_ID,
+							vms[i], msg_size,
+							SPCI_MSG_SEND_LEGACY_MEMORY),
+						SPCI_INVALID_PARAMETERS);
+				}
+				for (l = 0; l < ARRAY_SIZE(lend_device); ++l) {
+					uint32_t msg_size =
+						spci_memory_lend_init(
+							mb.send, vms[i],
+							constituents, 1, 0,
+							lend_access[j],
+							SPCI_MEMORY_DEVICE_MEM,
+							lend_device[l],
+							lend_shareability[k]);
+					EXPECT_SPCI_ERROR(
+						spci_msg_send(
+							HF_PRIMARY_VM_ID,
+							vms[i], msg_size,
+							SPCI_MSG_SEND_LEGACY_MEMORY),
+						SPCI_INVALID_PARAMETERS);
 				}
 			}
 		}
@@ -128,8 +136,11 @@
 		if (vms[i] == avoid_vm) {
 			continue;
 		}
-		msg_size = spci_memory_donate_init(mb.send, constituents,
-						   num_elements, 0);
+		msg_size = spci_memory_donate_init(
+			mb.send, vms[i], constituents, num_elements, 0,
+			SPCI_MEMORY_RW_X, SPCI_MEMORY_NORMAL_MEM,
+			SPCI_MEMORY_CACHE_WRITE_BACK,
+			SPCI_MEMORY_OUTER_SHAREABLE);
 		EXPECT_SPCI_ERROR(
 			spci_msg_send(HF_PRIMARY_VM_ID, vms[i], msg_size,
 				      SPCI_MSG_SEND_LEGACY_MEMORY),
@@ -152,7 +163,7 @@
 	for (i = 0; i < ARRAY_SIZE(vms); ++i) {
 		for (j = 0; j < ARRAY_SIZE(vms); ++j) {
 			uint32_t msg_size = spci_memory_relinquish_init(
-				mb.send, constituents, num_elements, 0);
+				mb.send, vms[i], constituents, num_elements, 0);
 			EXPECT_SPCI_ERROR(
 				spci_msg_send(vms[j], vms[i], msg_size,
 					      SPCI_MSG_SEND_LEGACY_MEMORY),
@@ -323,7 +334,10 @@
 		{.address = (uint64_t)page, .page_count = 1},
 	};
 
-	msg_size = spci_memory_donate_init(mb.send, constituents, 1, 0);
+	msg_size = spci_memory_donate_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
@@ -363,10 +377,10 @@
 		{.address = (uint64_t)page, .page_count = 1},
 	};
 
-	msg_size = spci_memory_lend_init(mb.send, constituents, 1, 0,
-					 SPCI_LEND_RW_X, SPCI_LEND_NORMAL_MEM,
-					 SPCI_LEND_CACHE_WRITE_BACK,
-					 SPCI_LEND_OUTER_SHAREABLE);
+	msg_size = spci_memory_lend_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
@@ -617,7 +631,10 @@
 		{.address = (uint64_t)page, .page_count = 1},
 	};
 
-	msg_size = spci_memory_donate_init(mb.send, constituents, 1, 0);
+	msg_size = spci_memory_donate_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
@@ -647,7 +664,10 @@
 		{.address = (uint64_t)page, .page_count = 1},
 	};
 
-	msg_size = spci_memory_donate_init(mb.send, constituents, 1, 0);
+	msg_size = spci_memory_donate_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
@@ -679,7 +699,10 @@
 		{.address = (uint64_t)page, .page_count = 1},
 	};
 
-	msg_size = spci_memory_donate_init(mb.send, constituents, 1, 0);
+	msg_size = spci_memory_donate_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
@@ -691,7 +714,10 @@
 	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
 	/* Share the memory with another VM. */
-	msg_size = spci_memory_donate_init(mb.send, constituents, 1, 0);
+	msg_size = spci_memory_donate_init(
+		mb.send, SERVICE_VM1, constituents, 1, 0, SPCI_MEMORY_RW_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,
@@ -728,7 +754,10 @@
 	EXPECT_EQ(run_res.code, HF_VCPU_RUN_WAIT_FOR_MESSAGE);
 
 	/* Donate memory. */
-	msg_size = spci_memory_donate_init(mb.send, constituents, 1, 0);
+	msg_size = spci_memory_donate_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
@@ -772,7 +801,10 @@
 	};
 
 	/* Donate memory to VM0. */
-	msg_size = spci_memory_donate_init(mb.send, constituents, 1, 0);
+	msg_size = spci_memory_donate_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
@@ -814,7 +846,10 @@
 		{.address = (uint64_t)page, .page_count = 1},
 	};
 
-	msg_size = spci_memory_donate_init(mb.send, constituents, 1, 0);
+	msg_size = spci_memory_donate_init(
+		mb.send, HF_PRIMARY_VM_ID, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 
 	EXPECT_SPCI_ERROR(spci_msg_send(HF_PRIMARY_VM_ID, HF_PRIMARY_VM_ID,
 					msg_size, SPCI_MSG_SEND_LEGACY_MEMORY),
@@ -836,10 +871,10 @@
 		{.address = (uint64_t)page, .page_count = 1},
 	};
 
-	msg_size = spci_memory_lend_init(mb.send, constituents, 1, 0,
-					 SPCI_LEND_RW_X, SPCI_LEND_NORMAL_MEM,
-					 SPCI_LEND_CACHE_WRITE_BACK,
-					 SPCI_LEND_OUTER_SHAREABLE);
+	msg_size = spci_memory_lend_init(
+		mb.send, HF_PRIMARY_VM_ID, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_SPCI_ERROR(spci_msg_send(HF_PRIMARY_VM_ID, HF_PRIMARY_VM_ID,
 					msg_size, SPCI_MSG_SEND_LEGACY_MEMORY),
 			  SPCI_INVALID_PARAMETERS);
@@ -865,23 +900,35 @@
 	};
 
 	/* Try invalid configurations. */
-	msg_size = spci_memory_donate_init(mb.send, constituents, 1, 0);
+	msg_size = spci_memory_donate_init(
+		mb.send, HF_PRIMARY_VM_ID, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_SPCI_ERROR(spci_msg_send(SERVICE_VM0, HF_PRIMARY_VM_ID, msg_size,
 					SPCI_MSG_SEND_LEGACY_MEMORY),
 			  SPCI_INVALID_PARAMETERS);
 
-	msg_size = spci_memory_donate_init(mb.send, constituents, 1, 0);
+	msg_size = spci_memory_donate_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_SPCI_ERROR(spci_msg_send(SERVICE_VM0, SERVICE_VM0, msg_size,
 					SPCI_MSG_SEND_LEGACY_MEMORY),
 			  SPCI_INVALID_PARAMETERS);
 
-	msg_size = spci_memory_donate_init(mb.send, constituents, 1, 0);
+	msg_size = spci_memory_donate_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_SPCI_ERROR(spci_msg_send(SERVICE_VM1, SERVICE_VM0, msg_size,
 					SPCI_MSG_SEND_LEGACY_MEMORY),
 			  SPCI_INVALID_PARAMETERS);
 
 	/* Successfully donate to VM0. */
-	msg_size = spci_memory_donate_init(mb.send, constituents, 1, 0);
+	msg_size = spci_memory_donate_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
@@ -909,16 +956,20 @@
 		struct spci_memory_region_constituent constituents[] = {
 			{.address = (uint64_t)page + i, .page_count = 1},
 		};
-		uint32_t msg_size =
-			spci_memory_donate_init(mb.send, constituents, 1, 0);
+		uint32_t msg_size = spci_memory_donate_init(
+			mb.send, SERVICE_VM0, constituents, 1, 0,
+			SPCI_MEMORY_RW_X, SPCI_MEMORY_NORMAL_MEM,
+			SPCI_MEMORY_CACHE_WRITE_BACK,
+			SPCI_MEMORY_OUTER_SHAREABLE);
 		EXPECT_SPCI_ERROR(
 			spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				      SPCI_MSG_SEND_LEGACY_MEMORY),
 			SPCI_INVALID_PARAMETERS);
 		msg_size = spci_memory_lend_init(
-			mb.send, constituents, 1, 0, SPCI_LEND_RW_X,
-			SPCI_LEND_NORMAL_MEM, SPCI_LEND_CACHE_WRITE_BACK,
-			SPCI_LEND_OUTER_SHAREABLE);
+			mb.send, SERVICE_VM0, constituents, 1, 0,
+			SPCI_MEMORY_RW_X, SPCI_MEMORY_NORMAL_MEM,
+			SPCI_MEMORY_CACHE_WRITE_BACK,
+			SPCI_MEMORY_OUTER_SHAREABLE);
 		EXPECT_SPCI_ERROR(
 			spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				      SPCI_MSG_SEND_LEGACY_MEMORY),
@@ -945,19 +996,19 @@
 	};
 
 	/* Check cannot swap VM IDs. */
-	msg_size = spci_memory_lend_init(mb.send, constituents, 1, 0,
-					 SPCI_LEND_RW_X, SPCI_LEND_NORMAL_MEM,
-					 SPCI_LEND_CACHE_WRITE_BACK,
-					 SPCI_LEND_OUTER_SHAREABLE);
+	msg_size = spci_memory_lend_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_SPCI_ERROR(spci_msg_send(SERVICE_VM0, HF_PRIMARY_VM_ID, msg_size,
 					SPCI_MSG_SEND_LEGACY_MEMORY),
 			  SPCI_INVALID_PARAMETERS);
 
 	/* Lend memory to VM0. */
-	msg_size = spci_memory_lend_init(mb.send, constituents, 1, 0,
-					 SPCI_LEND_RW_X, SPCI_LEND_NORMAL_MEM,
-					 SPCI_LEND_CACHE_WRITE_BACK,
-					 SPCI_LEND_OUTER_SHAREABLE);
+	msg_size = spci_memory_lend_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
@@ -992,10 +1043,10 @@
 		{.address = (uint64_t)page, .page_count = 1},
 	};
 
-	msg_size = spci_memory_lend_init(mb.send, constituents, 1, 0,
-					 SPCI_LEND_RW_X, SPCI_LEND_NORMAL_MEM,
-					 SPCI_LEND_CACHE_WRITE_BACK,
-					 SPCI_LEND_OUTER_SHAREABLE);
+	msg_size = spci_memory_lend_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
@@ -1019,10 +1070,10 @@
 	/* Re-initialise the memory before giving it. */
 	memset_s(ptr, sizeof(page), 'b', PAGE_SIZE);
 
-	msg_size = spci_memory_lend_init(mb.send, constituents, 1, 0,
-					 SPCI_LEND_RO_X, SPCI_LEND_NORMAL_MEM,
-					 SPCI_LEND_CACHE_WRITE_BACK,
-					 SPCI_LEND_OUTER_SHAREABLE);
+	msg_size = spci_memory_lend_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, 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_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
@@ -1064,10 +1115,10 @@
 		{.address = (uint64_t)page, .page_count = 1},
 	};
 
-	msg_size = spci_memory_lend_init(mb.send, constituents, 1, 0,
-					 SPCI_LEND_RW_NX, SPCI_LEND_NORMAL_MEM,
-					 SPCI_LEND_CACHE_WRITE_BACK,
-					 SPCI_LEND_OUTER_SHAREABLE);
+	msg_size = spci_memory_lend_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_NX,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
@@ -1090,10 +1141,10 @@
 	/* Re-initialise the memory before giving it. */
 	memset_s(ptr, sizeof(page), 'b', PAGE_SIZE);
 
-	msg_size = spci_memory_lend_init(mb.send, constituents, 1, 0,
-					 SPCI_LEND_RO_NX, SPCI_LEND_NORMAL_MEM,
-					 SPCI_LEND_CACHE_WRITE_BACK,
-					 SPCI_LEND_OUTER_SHAREABLE);
+	msg_size = spci_memory_lend_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RO_NX,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
@@ -1138,10 +1189,10 @@
 		{.address = (uint64_t)page, .page_count = 1},
 	};
 
-	msg_size = spci_memory_lend_init(mb.send, constituents, 1, 0,
-					 SPCI_LEND_RW_X, SPCI_LEND_NORMAL_MEM,
-					 SPCI_LEND_CACHE_WRITE_BACK,
-					 SPCI_LEND_OUTER_SHAREABLE);
+	msg_size = spci_memory_lend_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
@@ -1151,10 +1202,10 @@
 	run_res = hf_vcpu_run(SERVICE_VM0, 0);
 	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
-	msg_size = spci_memory_lend_init(mb.send, constituents, 1, 0,
-					 SPCI_LEND_RW_NX, SPCI_LEND_NORMAL_MEM,
-					 SPCI_LEND_CACHE_WRITE_BACK,
-					 SPCI_LEND_OUTER_SHAREABLE);
+	msg_size = spci_memory_lend_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_NX,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
@@ -1188,10 +1239,10 @@
 		{.address = (uint64_t)page, .page_count = 1},
 	};
 
-	msg_size = spci_memory_lend_init(mb.send, constituents, 1, 0,
-					 SPCI_LEND_RO_X, SPCI_LEND_NORMAL_MEM,
-					 SPCI_LEND_CACHE_WRITE_BACK,
-					 SPCI_LEND_OUTER_SHAREABLE);
+	msg_size = spci_memory_lend_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, 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_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
@@ -1201,10 +1252,10 @@
 	run_res = hf_vcpu_run(SERVICE_VM0, 0);
 	EXPECT_EQ(run_res.code, HF_VCPU_RUN_MESSAGE);
 
-	msg_size = spci_memory_lend_init(mb.send, constituents, 1, 0,
-					 SPCI_LEND_RO_NX, SPCI_LEND_NORMAL_MEM,
-					 SPCI_LEND_CACHE_WRITE_BACK,
-					 SPCI_LEND_OUTER_SHAREABLE);
+	msg_size = spci_memory_lend_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RO_NX,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
@@ -1235,10 +1286,10 @@
 		{.address = (uint64_t)page, .page_count = 2},
 	};
 
-	msg_size = spci_memory_lend_init(mb.send, constituents, 1, 0,
-					 SPCI_LEND_RO_X, SPCI_LEND_NORMAL_MEM,
-					 SPCI_LEND_CACHE_WRITE_BACK,
-					 SPCI_LEND_OUTER_SHAREABLE);
+	msg_size = spci_memory_lend_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, 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_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
@@ -1253,7 +1304,11 @@
 	constituents[0].page_count = 1;
 	for (int i = 1; i < PAGE_SIZE * 2; i++) {
 		constituents[0].address = (uint64_t)page + PAGE_SIZE;
-		msg_size = spci_memory_donate_init(mb.send, constituents, 1, 0);
+		msg_size = spci_memory_donate_init(
+			mb.send, SERVICE_VM1, constituents, 1, 0,
+			SPCI_MEMORY_RW_X, SPCI_MEMORY_NORMAL_MEM,
+			SPCI_MEMORY_CACHE_WRITE_BACK,
+			SPCI_MEMORY_OUTER_SHAREABLE);
 		EXPECT_SPCI_ERROR(
 			spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, msg_size,
 				      SPCI_MSG_SEND_LEGACY_MEMORY),
@@ -1261,7 +1316,10 @@
 	}
 
 	/* Ensure we can donate to the only borrower. */
-	msg_size = spci_memory_donate_init(mb.send, constituents, 1, 0);
+	msg_size = spci_memory_donate_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_EQ(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
@@ -1288,10 +1346,10 @@
 		{.address = (uint64_t)page, .page_count = 2},
 	};
 
-	msg_size = spci_memory_lend_init(mb.send, constituents, 1, 0,
-					 SPCI_LEND_RO_X, SPCI_LEND_NORMAL_MEM,
-					 SPCI_LEND_CACHE_WRITE_BACK,
-					 SPCI_LEND_OUTER_SHAREABLE);
+	msg_size = spci_memory_lend_init(
+		mb.send, SERVICE_VM0, constituents, 1, 0, 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_VM0, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
@@ -1314,9 +1372,10 @@
 	for (int i = 1; i < PAGE_SIZE * 2; i++) {
 		constituents[0].address = (uint64_t)page + PAGE_SIZE;
 		msg_size = spci_memory_lend_init(
-			mb.send, constituents, 1, 0, SPCI_LEND_RO_X,
-			SPCI_LEND_NORMAL_MEM, SPCI_LEND_CACHE_WRITE_BACK,
-			SPCI_LEND_OUTER_SHAREABLE);
+			mb.send, SERVICE_VM0, constituents, 1, 0,
+			SPCI_MEMORY_RO_X, SPCI_MEMORY_NORMAL_MEM,
+			SPCI_MEMORY_CACHE_WRITE_BACK,
+			SPCI_MEMORY_OUTER_SHAREABLE);
 		EXPECT_SPCI_ERROR(
 			spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, msg_size,
 				      SPCI_MSG_SEND_LEGACY_MEMORY),
diff --git a/test/vmapi/primary_with_secondaries/services/memory.c b/test/vmapi/primary_with_secondaries/services/memory.c
index cf15554..ca72bf2 100644
--- a/test/vmapi/primary_with_secondaries/services/memory.c
+++ b/test/vmapi/primary_with_secondaries/services/memory.c
@@ -73,11 +73,11 @@
 		void *recv_buf = SERVICE_RECV_BUFFER();
 		void *send_buf = SERVICE_SEND_BUFFER();
 		struct spci_memory_region *memory_region =
-			(struct spci_memory_region *)(spci_get_lend_descriptor(
-							      recv_buf)
-							      ->payload);
+			spci_get_memory_region(recv_buf);
+		struct spci_memory_region_constituent *constituents =
+			spci_memory_region_get_constituents(memory_region);
 
-		ptr = (uint8_t *)memory_region->constituents[0].address;
+		ptr = (uint8_t *)constituents[0].address;
 		/* Relevant information read, mailbox can be cleared. */
 		hf_mailbox_clear();
 
@@ -89,8 +89,8 @@
 		hf_mailbox_clear();
 		/* Give the memory back and notify the sender. */
 		msg_size = spci_memory_relinquish_init(
-			send_buf, memory_region->constituents,
-			memory_region->count, 0);
+			send_buf, HF_PRIMARY_VM_ID, constituents,
+			memory_region->constituent_count, 0);
 		spci_msg_send(spci_msg_send_receiver(ret), HF_PRIMARY_VM_ID,
 			      msg_size, SPCI_MSG_SEND_LEGACY_MEMORY);
 
@@ -196,14 +196,16 @@
 		void *recv_buf = SERVICE_RECV_BUFFER();
 		void *send_buf = SERVICE_SEND_BUFFER();
 		struct spci_memory_region *memory_region =
-			spci_get_donated_memory_region(recv_buf);
+			spci_get_memory_region(recv_buf);
+		struct spci_memory_region_constituent *constituents =
+			spci_memory_region_get_constituents(memory_region);
 
 		EXPECT_EQ(ret.func, SPCI_MSG_SEND_32);
 		EXPECT_EQ(spci_msg_send_attributes(ret),
 			  SPCI_MSG_SEND_LEGACY_MEMORY);
 		hf_mailbox_clear();
 
-		ptr = (uint8_t *)memory_region->constituents[0].address;
+		ptr = (uint8_t *)constituents[0].address;
 
 		/* Check that one has access to the shared region. */
 		for (int i = 0; i < PAGE_SIZE; ++i) {
@@ -211,9 +213,11 @@
 		}
 
 		/* Give the memory back and notify the sender. */
-		msg_size = spci_memory_donate_init(send_buf,
-						   memory_region->constituents,
-						   memory_region->count, 0);
+		msg_size = spci_memory_donate_init(
+			send_buf, HF_PRIMARY_VM_ID, constituents,
+			memory_region->constituent_count, 0, SPCI_MEMORY_RW_X,
+			SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+			SPCI_MEMORY_OUTER_SHAREABLE);
 		spci_msg_send(spci_msg_send_receiver(ret), HF_PRIMARY_VM_ID,
 			      msg_size, SPCI_MSG_SEND_LEGACY_MEMORY);
 
@@ -231,13 +235,15 @@
 	uint8_t *ptr;
 	void *recv_buf = SERVICE_RECV_BUFFER();
 	struct spci_memory_region *memory_region =
-		spci_get_donated_memory_region(recv_buf);
+		spci_get_memory_region(recv_buf);
+	struct spci_memory_region_constituent *constituents =
+		spci_memory_region_get_constituents(memory_region);
 
 	EXPECT_EQ(ret.func, SPCI_MSG_SEND_32);
 	EXPECT_EQ(spci_msg_send_attributes(ret), SPCI_MSG_SEND_LEGACY_MEMORY);
 	hf_mailbox_clear();
 
-	ptr = (uint8_t *)memory_region->constituents[0].address;
+	ptr = (uint8_t *)constituents[0].address;
 
 	/* Check that one cannot access out of bounds after donated region. */
 	ptr[PAGE_SIZE]++;
@@ -249,13 +255,15 @@
 	uint8_t *ptr;
 	void *recv_buf = SERVICE_RECV_BUFFER();
 	struct spci_memory_region *memory_region =
-		spci_get_donated_memory_region(recv_buf);
+		spci_get_memory_region(recv_buf);
+	struct spci_memory_region_constituent *constituents =
+		spci_memory_region_get_constituents(memory_region);
 
 	EXPECT_EQ(ret.func, SPCI_MSG_SEND_32);
 	EXPECT_EQ(spci_msg_send_attributes(ret), SPCI_MSG_SEND_LEGACY_MEMORY);
 	hf_mailbox_clear();
 
-	ptr = (uint8_t *)memory_region->constituents[0].address;
+	ptr = (uint8_t *)constituents[0].address;
 
 	/* Check that one cannot access out of bounds before donated region. */
 	ptr[-1]++;
@@ -272,17 +280,22 @@
 	void *recv_buf = SERVICE_RECV_BUFFER();
 	void *send_buf = SERVICE_SEND_BUFFER();
 	struct spci_memory_region *memory_region =
-		spci_get_donated_memory_region(recv_buf);
+		spci_get_memory_region(recv_buf);
+	struct spci_memory_region_constituent *constituents =
+		spci_memory_region_get_constituents(memory_region);
 
 	EXPECT_EQ(ret.func, SPCI_MSG_SEND_32);
 	EXPECT_EQ(spci_msg_send_attributes(ret), SPCI_MSG_SEND_LEGACY_MEMORY);
 	hf_mailbox_clear();
 
-	ptr = (uint8_t *)memory_region->constituents[0].address;
+	ptr = (uint8_t *)constituents[0].address;
 
 	/* Donate memory to next VM. */
 	msg_size = spci_memory_donate_init(
-		send_buf, memory_region->constituents, memory_region->count, 0);
+		send_buf, SERVICE_VM1, constituents,
+		memory_region->constituent_count, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_EQ(spci_msg_send(spci_msg_send_receiver(ret), SERVICE_VM1,
 				msg_size, SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
@@ -304,9 +317,9 @@
 	void *recv_buf = SERVICE_RECV_BUFFER();
 	void *send_buf = SERVICE_SEND_BUFFER();
 	struct spci_memory_region *memory_region =
-		spci_get_donated_memory_region(recv_buf);
+		spci_get_memory_region(recv_buf);
 	struct spci_memory_region_constituent constituent =
-		memory_region->constituents[0];
+		spci_memory_region_get_constituents(memory_region)[0];
 
 	EXPECT_EQ(ret.func, SPCI_MSG_SEND_32);
 	EXPECT_EQ(spci_msg_send_attributes(ret), SPCI_MSG_SEND_LEGACY_MEMORY);
@@ -316,16 +329,22 @@
 	spci_yield();
 
 	/* Give the memory back and notify the sender. */
-	msg_size = spci_memory_donate_init(send_buf, &constituent,
-					   memory_region->count, 0);
+	msg_size = spci_memory_donate_init(
+		send_buf, HF_PRIMARY_VM_ID, &constituent,
+		memory_region->constituent_count, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_EQ(spci_msg_send(SERVICE_VM0, HF_PRIMARY_VM_ID, msg_size,
 				SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
 		  SPCI_SUCCESS_32);
 
 	/* Attempt to donate the memory to another VM. */
-	msg_size = spci_memory_donate_init(send_buf, &constituent,
-					   memory_region->count, 0);
+	msg_size = spci_memory_donate_init(
+		send_buf, SERVICE_VM1, &constituent,
+		memory_region->constituent_count, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_SPCI_ERROR(
 		spci_msg_send(spci_msg_send_receiver(ret), SERVICE_VM1,
 			      msg_size, SPCI_MSG_SEND_LEGACY_MEMORY),
@@ -345,14 +364,16 @@
 		uint8_t *ptr;
 		void *recv_buf = SERVICE_RECV_BUFFER();
 		struct spci_memory_region *memory_region =
-			spci_get_donated_memory_region(recv_buf);
+			spci_get_memory_region(recv_buf);
+		struct spci_memory_region_constituent *constituents =
+			spci_memory_region_get_constituents(memory_region);
 
 		EXPECT_EQ(ret.func, SPCI_MSG_SEND_32);
 		EXPECT_EQ(spci_msg_send_attributes(ret),
 			  SPCI_MSG_SEND_LEGACY_MEMORY);
 		hf_mailbox_clear();
 
-		ptr = (uint8_t *)memory_region->constituents[0].address;
+		ptr = (uint8_t *)constituents[0].address;
 		ptr[0] = 'd';
 		spci_yield();
 
@@ -372,7 +393,9 @@
 	void *recv_buf = SERVICE_RECV_BUFFER();
 	void *send_buf = SERVICE_SEND_BUFFER();
 	struct spci_memory_region *memory_region =
-		spci_get_donated_memory_region(recv_buf);
+		spci_get_memory_region(recv_buf);
+	struct spci_memory_region_constituent *constituents =
+		spci_memory_region_get_constituents(memory_region);
 
 	EXPECT_EQ(ret.func, SPCI_MSG_SEND_32);
 	EXPECT_EQ(spci_msg_send_attributes(ret), SPCI_MSG_SEND_LEGACY_MEMORY);
@@ -380,7 +403,10 @@
 
 	/* Give the memory back and notify the sender. */
 	msg_size = spci_memory_donate_init(
-		send_buf, memory_region->constituents, memory_region->count, 0);
+		send_buf, HF_PRIMARY_VM_ID, constituents,
+		memory_region->constituent_count, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_EQ(spci_msg_send(spci_msg_send_receiver(ret), HF_PRIMARY_VM_ID,
 				msg_size, SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
@@ -388,7 +414,10 @@
 
 	/* Fail to donate the memory from the primary to VM1. */
 	msg_size = spci_memory_donate_init(
-		send_buf, memory_region->constituents, memory_region->count, 0);
+		send_buf, SERVICE_VM1, constituents,
+		memory_region->constituent_count, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_SPCI_ERROR(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, msg_size,
 					SPCI_MSG_SEND_LEGACY_MEMORY),
 			  SPCI_INVALID_PARAMETERS);
@@ -406,14 +435,14 @@
 		void *recv_buf = SERVICE_RECV_BUFFER();
 		void *send_buf = SERVICE_SEND_BUFFER();
 		struct spci_memory_region *memory_region =
-			(struct spci_memory_region *)(spci_get_lend_descriptor(
-							      recv_buf)
-							      ->payload);
+			spci_get_memory_region(recv_buf);
+		struct spci_memory_region_constituent *constituents =
+			spci_memory_region_get_constituents(memory_region);
 
 		EXPECT_EQ(ret.func, SPCI_MSG_SEND_32);
 		EXPECT_EQ(spci_msg_send_attributes(ret),
 			  SPCI_MSG_SEND_LEGACY_MEMORY);
-		ptr = (uint8_t *)memory_region->constituents[0].address;
+		ptr = (uint8_t *)constituents[0].address;
 		/* Relevant information read, mailbox can be cleared. */
 		hf_mailbox_clear();
 
@@ -425,8 +454,8 @@
 		hf_mailbox_clear();
 		/* Give the memory back and notify the sender. */
 		msg_size = spci_memory_relinquish_init(
-			send_buf, memory_region->constituents,
-			memory_region->count, 0);
+			send_buf, HF_PRIMARY_VM_ID, constituents,
+			memory_region->constituent_count, 0);
 		spci_msg_send(spci_msg_send_receiver(ret), HF_PRIMARY_VM_ID,
 			      msg_size, SPCI_MSG_SEND_LEGACY_MEMORY);
 
@@ -451,14 +480,16 @@
 		void *recv_buf = SERVICE_RECV_BUFFER();
 		void *send_buf = SERVICE_SEND_BUFFER();
 		struct spci_memory_region *memory_region =
-			spci_get_donated_memory_region(recv_buf);
+			spci_get_memory_region(recv_buf);
+		struct spci_memory_region_constituent *constituents =
+			spci_memory_region_get_constituents(memory_region);
 
 		EXPECT_EQ(ret.func, SPCI_MSG_SEND_32);
 		EXPECT_EQ(spci_msg_send_attributes(ret),
 			  SPCI_MSG_SEND_LEGACY_MEMORY);
 		hf_mailbox_clear();
 
-		ptr = (uint8_t *)memory_region->constituents[0].address;
+		ptr = (uint8_t *)constituents[0].address;
 
 		/* Check that one has access to the shared region. */
 		for (int i = 0; i < PAGE_SIZE; ++i) {
@@ -466,8 +497,8 @@
 		}
 		/* Give the memory back and notify the sender. */
 		msg_size = spci_memory_relinquish_init(
-			send_buf, memory_region->constituents,
-			memory_region->count, 0);
+			send_buf, HF_PRIMARY_VM_ID, constituents,
+			memory_region->constituent_count, 0);
 		EXPECT_SPCI_ERROR(spci_msg_send(spci_msg_send_receiver(ret),
 						HF_PRIMARY_VM_ID, msg_size,
 						SPCI_MSG_SEND_LEGACY_MEMORY),
@@ -491,8 +522,9 @@
 	void *recv_buf = SERVICE_RECV_BUFFER();
 	void *send_buf = SERVICE_SEND_BUFFER();
 	struct spci_memory_region *memory_region =
-		(struct spci_memory_region *)(spci_get_lend_descriptor(recv_buf)
-						      ->payload);
+		spci_get_memory_region(recv_buf);
+	struct spci_memory_region_constituent *constituents =
+		spci_memory_region_get_constituents(memory_region);
 
 	EXPECT_EQ(ret.func, SPCI_MSG_SEND_32);
 	EXPECT_EQ(spci_msg_send_attributes(ret), SPCI_MSG_SEND_LEGACY_MEMORY);
@@ -500,7 +532,8 @@
 
 	/* Attempt to relinquish from primary VM. */
 	msg_size = spci_memory_relinquish_init(
-		send_buf, memory_region->constituents, memory_region->count, 0);
+		send_buf, spci_msg_send_receiver(ret), constituents,
+		memory_region->constituent_count, 0);
 	EXPECT_SPCI_ERROR(
 		spci_msg_send(HF_PRIMARY_VM_ID, spci_msg_send_receiver(ret),
 			      msg_size, SPCI_MSG_SEND_LEGACY_MEMORY),
@@ -508,7 +541,8 @@
 
 	/* Give the memory back and notify the sender. */
 	msg_size = spci_memory_relinquish_init(
-		send_buf, memory_region->constituents, memory_region->count, 0);
+		send_buf, HF_PRIMARY_VM_ID, constituents,
+		memory_region->constituent_count, 0);
 	EXPECT_EQ(spci_msg_send(spci_msg_send_receiver(ret), HF_PRIMARY_VM_ID,
 				msg_size, SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,
@@ -516,9 +550,10 @@
 
 	/* Ensure we cannot lend from the primary to another secondary. */
 	msg_size = spci_memory_lend_init(
-		send_buf, memory_region->constituents, memory_region->count, 0,
-		SPCI_LEND_RW_X, SPCI_LEND_NORMAL_MEM,
-		SPCI_LEND_CACHE_WRITE_BACK, SPCI_LEND_OUTER_SHAREABLE);
+		send_buf, SERVICE_VM1, constituents,
+		memory_region->constituent_count, 0, SPCI_MEMORY_RW_X,
+		SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+		SPCI_MEMORY_OUTER_SHAREABLE);
 	EXPECT_SPCI_ERROR(spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, msg_size,
 					SPCI_MSG_SEND_LEGACY_MEMORY),
 			  SPCI_INVALID_PARAMETERS);
@@ -538,16 +573,16 @@
 		void *recv_buf = SERVICE_RECV_BUFFER();
 		void *send_buf = SERVICE_SEND_BUFFER();
 		struct spci_memory_region *memory_region =
-			(struct spci_memory_region *)(spci_get_lend_descriptor(
-							      recv_buf)
-							      ->payload);
+			spci_get_memory_region(recv_buf);
+		struct spci_memory_region_constituent *constituents =
+			spci_memory_region_get_constituents(memory_region);
 
 		EXPECT_EQ(ret.func, SPCI_MSG_SEND_32);
 		EXPECT_EQ(spci_msg_send_attributes(ret),
 			  SPCI_MSG_SEND_LEGACY_MEMORY);
 		hf_mailbox_clear();
 
-		ptr = (uint64_t *)memory_region->constituents[0].address;
+		ptr = (uint64_t *)constituents[0].address;
 		/*
 		 * Verify that the instruction in memory is the encoded RET
 		 * instruction.
@@ -558,8 +593,8 @@
 
 		/* Release the memory again. */
 		msg_size = spci_memory_relinquish_init(
-			send_buf, memory_region->constituents,
-			memory_region->count, 0);
+			send_buf, HF_PRIMARY_VM_ID, constituents,
+			memory_region->constituent_count, 0);
 		EXPECT_EQ(spci_msg_send(spci_msg_send_receiver(ret),
 					HF_PRIMARY_VM_ID, msg_size,
 					SPCI_MSG_SEND_LEGACY_MEMORY)
@@ -581,16 +616,16 @@
 		void *recv_buf = SERVICE_RECV_BUFFER();
 		void *send_buf = SERVICE_SEND_BUFFER();
 		struct spci_memory_region *memory_region =
-			(struct spci_memory_region *)(spci_get_lend_descriptor(
-							      recv_buf)
-							      ->payload);
+			spci_get_memory_region(recv_buf);
+		struct spci_memory_region_constituent *constituents =
+			spci_memory_region_get_constituents(memory_region);
 
 		EXPECT_EQ(ret.func, SPCI_MSG_SEND_32);
 		EXPECT_EQ(spci_msg_send_attributes(ret),
 			  SPCI_MSG_SEND_LEGACY_MEMORY);
 		hf_mailbox_clear();
 
-		ptr = (uint8_t *)memory_region->constituents[0].address;
+		ptr = (uint8_t *)constituents[0].address;
 
 		/* Check that we have read access. */
 		for (int i = 0; i < PAGE_SIZE; ++i) {
@@ -606,8 +641,8 @@
 		}
 
 		msg_size = spci_memory_relinquish_init(
-			send_buf, memory_region->constituents,
-			memory_region->count, 0);
+			send_buf, HF_PRIMARY_VM_ID, constituents,
+			memory_region->constituent_count, 0);
 		EXPECT_EQ(spci_msg_send(spci_msg_send_receiver(ret),
 					HF_PRIMARY_VM_ID, msg_size,
 					SPCI_MSG_SEND_LEGACY_MEMORY)
@@ -626,14 +661,15 @@
 
 	void *recv_buf = SERVICE_RECV_BUFFER();
 	struct spci_memory_region *memory_region =
-		(struct spci_memory_region *)(spci_get_lend_descriptor(recv_buf)
-						      ->payload);
+		spci_get_memory_region(recv_buf);
+	struct spci_memory_region_constituent *constituents =
+		spci_memory_region_get_constituents(memory_region);
 
 	EXPECT_EQ(ret.func, SPCI_MSG_SEND_32);
 	EXPECT_EQ(spci_msg_send_attributes(ret), SPCI_MSG_SEND_LEGACY_MEMORY);
 	hf_mailbox_clear();
 
-	ptr = (uint8_t *)memory_region->constituents[0].address;
+	ptr = (uint8_t *)constituents[0].address;
 
 	/* Check that one cannot access before donated region. */
 	ptr[-1]++;
@@ -649,14 +685,15 @@
 
 	void *recv_buf = SERVICE_RECV_BUFFER();
 	struct spci_memory_region *memory_region =
-		(struct spci_memory_region *)(spci_get_lend_descriptor(recv_buf)
-						      ->payload);
+		spci_get_memory_region(recv_buf);
+	struct spci_memory_region_constituent *constituents =
+		spci_memory_region_get_constituents(memory_region);
 
 	EXPECT_EQ(ret.func, SPCI_MSG_SEND_32);
 	EXPECT_EQ(spci_msg_send_attributes(ret), SPCI_MSG_SEND_LEGACY_MEMORY);
 	hf_mailbox_clear();
 
-	ptr = (uint8_t *)memory_region->constituents[0].address;
+	ptr = (uint8_t *)constituents[0].address;
 
 	/* Check that one cannot access after donated region. */
 	ptr[PAGE_SIZE]++;
@@ -671,14 +708,15 @@
 	void *recv_buf = SERVICE_RECV_BUFFER();
 	void *send_buf = SERVICE_SEND_BUFFER();
 	struct spci_memory_region *memory_region =
-		(struct spci_memory_region *)(spci_get_lend_descriptor(recv_buf)
-						      ->payload);
+		spci_get_memory_region(recv_buf);
+	struct spci_memory_region_constituent *constituents =
+		spci_memory_region_get_constituents(memory_region);
 
 	EXPECT_EQ(ret.func, SPCI_MSG_SEND_32);
 	EXPECT_EQ(spci_msg_send_attributes(ret), SPCI_MSG_SEND_LEGACY_MEMORY);
 	hf_mailbox_clear();
 
-	ptr = (uint8_t *)memory_region->constituents[0].address;
+	ptr = (uint8_t *)constituents[0].address;
 
 	/* Check that we have read access. */
 	for (int i = 0; i < PAGE_SIZE; ++i) {
@@ -694,14 +732,14 @@
 	}
 
 	for (int i = 1; i < PAGE_SIZE * 2; i++) {
-		memory_region->constituents[0].address = (uint64_t)ptr + i;
+		constituents[0].address = (uint64_t)ptr + i;
 
 		/* Fail to lend the memory back to the primary. */
 		msg_size = spci_memory_lend_init(
-			send_buf, memory_region->constituents,
-			memory_region->count, 0, SPCI_LEND_RW_X,
-			SPCI_LEND_NORMAL_MEM, SPCI_LEND_CACHE_WRITE_BACK,
-			SPCI_LEND_OUTER_SHAREABLE);
+			send_buf, SERVICE_VM1, constituents,
+			memory_region->constituent_count, 0, SPCI_MEMORY_RW_X,
+			SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
+			SPCI_MEMORY_OUTER_SHAREABLE);
 		EXPECT_SPCI_ERROR(
 			spci_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, msg_size,
 				      SPCI_MSG_SEND_LEGACY_MEMORY),
@@ -709,7 +747,8 @@
 	}
 
 	msg_size = spci_memory_relinquish_init(
-		send_buf, memory_region->constituents, memory_region->count, 0);
+		send_buf, HF_PRIMARY_VM_ID, constituents,
+		memory_region->constituent_count, 0);
 	EXPECT_EQ(spci_msg_send(spci_msg_send_receiver(ret), HF_PRIMARY_VM_ID,
 				msg_size, SPCI_MSG_SEND_LEGACY_MEMORY)
 			  .func,