Update SPCI memory sharing to match latest FF-A spec 1.0 EAC.
SPCI is now called PSA FF-A. Symbols will be renamed in a later change.
Disabled checkpatch SPACING because it disagrees with Clang format.
Bug: 132420445
Change-Id: I41c6cc7ddad136ed7c4797dfa1204718a66ddfce
diff --git a/inc/hf/api.h b/inc/hf/api.h
index ebc533b..07b9061 100644
--- a/inc/hf/api.h
+++ b/inc/hf/api.h
@@ -60,14 +60,16 @@
struct spci_value api_spci_features(uint32_t function_id);
struct spci_value api_spci_run(spci_vm_id_t vm_id, spci_vcpu_index_t vcpu_idx,
const struct vcpu *current, struct vcpu **next);
-struct spci_value api_spci_mem_send(uint32_t share_func, ipaddr_t address,
- uint32_t page_count,
- uint32_t fragment_length, uint32_t length,
- spci_cookie_t cookie, struct vcpu *current,
+struct spci_value api_spci_mem_send(uint32_t share_func, uint32_t length,
+ uint32_t fragment_length, ipaddr_t address,
+ uint32_t page_count, struct vcpu *current,
struct vcpu **next);
-struct spci_value api_spci_mem_retrieve_req(
- ipaddr_t address, uint32_t page_count, uint32_t fragment_length,
- uint32_t length, spci_cookie_t cookie, struct vcpu *current);
+struct spci_value api_spci_mem_retrieve_req(uint32_t length,
+ uint32_t fragment_length,
+ ipaddr_t address,
+ uint32_t page_count,
+ struct vcpu *current);
struct spci_value api_spci_mem_relinquish(struct vcpu *current);
-struct spci_value api_spci_mem_reclaim(uint32_t handle, uint32_t flags,
+struct spci_value api_spci_mem_reclaim(spci_memory_handle_t handle,
+ spci_memory_region_flags_t flags,
struct vcpu *current);
diff --git a/inc/hf/spci_memory.h b/inc/hf/spci_memory.h
index 023a8ce..6956102 100644
--- a/inc/hf/spci_memory.h
+++ b/inc/hf/spci_memory.h
@@ -27,8 +27,7 @@
uint32_t share_func,
struct mpool *page_pool);
struct spci_value spci_memory_retrieve(
- struct vm_locked to_locked,
- struct spci_memory_retrieve_request *retrieve_request,
+ struct vm_locked to_locked, struct spci_memory_region *retrieve_request,
uint32_t retrieve_request_size, struct mpool *page_pool);
struct spci_value spci_memory_relinquish(
struct vm_locked from_locked,
diff --git a/inc/vmapi/hf/call.h b/inc/vmapi/hf/call.h
index d4119d6..1fa31cf 100644
--- a/inc/vmapi/hf/call.h
+++ b/inc/vmapi/hf/call.h
@@ -131,44 +131,36 @@
.arg4 = attributes});
}
-static inline struct spci_value spci_mem_donate(uint32_t fragment_length,
- uint32_t length,
- spci_cookie_t cookie)
+static inline struct spci_value spci_mem_donate(uint32_t length,
+ uint32_t fragment_length)
{
return spci_call((struct spci_value){.func = SPCI_MEM_DONATE_32,
- .arg3 = fragment_length,
- .arg4 = length,
- .arg5 = cookie});
+ .arg1 = length,
+ .arg2 = fragment_length});
}
-static inline struct spci_value spci_mem_lend(uint32_t fragment_length,
- uint32_t length,
- spci_cookie_t cookie)
+static inline struct spci_value spci_mem_lend(uint32_t length,
+ uint32_t fragment_length)
{
return spci_call((struct spci_value){.func = SPCI_MEM_LEND_32,
- .arg3 = fragment_length,
- .arg4 = length,
- .arg5 = cookie});
+ .arg1 = length,
+ .arg2 = fragment_length});
}
-static inline struct spci_value spci_mem_share(uint32_t fragment_length,
- uint32_t length,
- spci_cookie_t cookie)
+static inline struct spci_value spci_mem_share(uint32_t length,
+ uint32_t fragment_length)
{
return spci_call((struct spci_value){.func = SPCI_MEM_SHARE_32,
- .arg3 = fragment_length,
- .arg4 = length,
- .arg5 = cookie});
+ .arg1 = length,
+ .arg2 = fragment_length});
}
-static inline struct spci_value spci_mem_retrieve_req(uint32_t fragment_length,
- uint32_t length,
- spci_cookie_t cookie)
+static inline struct spci_value spci_mem_retrieve_req(uint32_t length,
+ uint32_t fragment_length)
{
return spci_call((struct spci_value){.func = SPCI_MEM_RETRIEVE_REQ_32,
- .arg3 = fragment_length,
- .arg4 = length,
- .arg5 = cookie});
+ .arg1 = length,
+ .arg2 = fragment_length});
}
static inline struct spci_value spci_mem_relinquish(void)
@@ -176,11 +168,13 @@
return spci_call((struct spci_value){.func = SPCI_MEM_RELINQUISH_32});
}
-static inline struct spci_value spci_mem_reclaim(uint32_t handle,
- uint32_t flags)
+static inline struct spci_value spci_mem_reclaim(
+ spci_memory_handle_t handle, spci_memory_region_flags_t flags)
{
- return spci_call((struct spci_value){
- .func = SPCI_MEM_RECLAIM_32, .arg1 = handle, .arg2 = flags});
+ return spci_call((struct spci_value){.func = SPCI_MEM_RECLAIM_32,
+ .arg1 = (uint32_t)handle,
+ .arg2 = (uint32_t)(handle >> 32),
+ .arg3 = flags});
}
/**
diff --git a/inc/vmapi/hf/spci.h b/inc/vmapi/hf/spci.h
index 9c10acf..887b745 100644
--- a/inc/vmapi/hf/spci.h
+++ b/inc/vmapi/hf/spci.h
@@ -62,9 +62,11 @@
#define SPCI_RETRY INT32_C(-7)
#define SPCI_ABORTED INT32_C(-8)
+/* clang-format on */
+
/* SPCI function specific constants. */
-#define SPCI_MSG_RECV_BLOCK 0x1
-#define SPCI_MSG_RECV_BLOCK_MASK 0x1
+#define SPCI_MSG_RECV_BLOCK 0x1
+#define SPCI_MSG_RECV_BLOCK_MASK 0x1
#define SPCI_MSG_SEND_NOTIFY 0x1
#define SPCI_MSG_SEND_NOTIFY_MASK 0x1
@@ -83,14 +85,22 @@
/* The maximum length possible for a single message. */
#define SPCI_MSG_PAYLOAD_MAX HF_MAILBOX_SIZE
-enum spci_memory_access {
- SPCI_MEMORY_RO_NX,
- SPCI_MEMORY_RO_X,
- SPCI_MEMORY_RW_NX,
- SPCI_MEMORY_RW_X,
+enum spci_data_access {
+ SPCI_DATA_ACCESS_NOT_SPECIFIED,
+ SPCI_DATA_ACCESS_RO,
+ SPCI_DATA_ACCESS_RW,
+ SPCI_DATA_ACCESS_RESERVED,
+};
+
+enum spci_instruction_access {
+ SPCI_INSTRUCTION_ACCESS_NOT_SPECIFIED,
+ SPCI_INSTRUCTION_ACCESS_NX,
+ SPCI_INSTRUCTION_ACCESS_X,
+ SPCI_INSTRUCTION_ACCESS_RESERVED,
};
enum spci_memory_type {
+ SPCI_MEMORY_NOT_SPECIFIED_MEM,
SPCI_MEMORY_DEVICE_MEM,
SPCI_MEMORY_NORMAL_MEM,
};
@@ -98,8 +108,8 @@
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_CACHE_RESERVED_1 = 0x2,
+ SPCI_MEMORY_CACHE_WRITE_BACK = 0x3,
SPCI_MEMORY_DEV_NGNRNE = 0x0,
SPCI_MEMORY_DEV_NGNRE = 0x1,
SPCI_MEMORY_DEV_NGRE = 0x2,
@@ -108,64 +118,83 @@
enum spci_memory_shareability {
SPCI_MEMORY_SHARE_NON_SHAREABLE,
- SPCI_MEMORY_RESERVED,
+ SPCI_MEMORY_SHARE_RESERVED,
SPCI_MEMORY_OUTER_SHAREABLE,
SPCI_MEMORY_INNER_SHAREABLE,
};
-#define SPCI_MEMORY_ACCESS_OFFSET (0x5U)
-#define SPCI_MEMORY_ACCESS_MASK ((0x3U) << SPCI_MEMORY_ACCESS_OFFSET)
+typedef uint8_t spci_memory_access_permissions_t;
+
+/**
+ * This corresponds to table 44 of the FF-A 1.0 EAC specification, "Memory
+ * region attributes descriptor".
+ */
+typedef uint8_t spci_memory_attributes_t;
+
+#define SPCI_DATA_ACCESS_OFFSET (0x0U)
+#define SPCI_DATA_ACCESS_MASK ((0x3U) << SPCI_DATA_ACCESS_OFFSET)
+
+#define SPCI_INSTRUCTION_ACCESS_OFFSET (0x2U)
+#define SPCI_INSTRUCTION_ACCESS_MASK ((0x3U) << SPCI_INSTRUCTION_ACCESS_OFFSET)
#define SPCI_MEMORY_TYPE_OFFSET (0x4U)
-#define SPCI_MEMORY_TYPE_MASK ((0x1U) << SPCI_MEMORY_TYPE_OFFSET)
+#define SPCI_MEMORY_TYPE_MASK ((0x3U) << SPCI_MEMORY_TYPE_OFFSET)
#define SPCI_MEMORY_CACHEABILITY_OFFSET (0x2U)
-#define SPCI_MEMORY_CACHEABILITY_MASK ((0x3U) <<\
- SPCI_MEMORY_CACHEABILITY_OFFSET)
+#define SPCI_MEMORY_CACHEABILITY_MASK \
+ ((0x3U) << SPCI_MEMORY_CACHEABILITY_OFFSET)
#define SPCI_MEMORY_SHAREABILITY_OFFSET (0x0U)
-#define SPCI_MEMORY_SHAREABILITY_MASK ((0x3U) <<\
- SPCI_MEMORY_SHAREABILITY_OFFSET)
+#define SPCI_MEMORY_SHAREABILITY_MASK \
+ ((0x3U) << SPCI_MEMORY_SHAREABILITY_OFFSET)
-#define LEND_ATTR_FUNCTION_SET(name, offset, mask) \
-static inline void spci_set_memory_##name##_attr(uint16_t *attr,\
- const enum spci_memory_##name perm)\
-{\
- *attr = (*attr & ~(mask)) | ((perm << offset) & mask);\
-}
+#define ATTR_FUNCTION_SET(name, container_type, offset, mask) \
+ static inline void spci_set_##name##_attr(container_type *attr, \
+ const enum spci_##name perm) \
+ { \
+ *attr = (*attr & ~(mask)) | ((perm << offset) & mask); \
+ }
-#define LEND_ATTR_FUNCTION_GET(name, offset, mask) \
-static inline enum spci_memory_##name spci_get_memory_##name##_attr(\
- uint16_t attr)\
-{\
- return (enum spci_memory_##name)((attr & mask) >> offset);\
-}
+#define ATTR_FUNCTION_GET(name, container_type, offset, mask) \
+ static inline enum spci_##name spci_get_##name##_attr( \
+ container_type attr) \
+ { \
+ return (enum spci_##name)((attr & mask) >> offset); \
+ }
-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)
+ATTR_FUNCTION_SET(data_access, spci_memory_access_permissions_t,
+ SPCI_DATA_ACCESS_OFFSET, SPCI_DATA_ACCESS_MASK)
+ATTR_FUNCTION_GET(data_access, spci_memory_access_permissions_t,
+ SPCI_DATA_ACCESS_OFFSET, SPCI_DATA_ACCESS_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)
+ATTR_FUNCTION_SET(instruction_access, spci_memory_access_permissions_t,
+ SPCI_INSTRUCTION_ACCESS_OFFSET, SPCI_INSTRUCTION_ACCESS_MASK)
+ATTR_FUNCTION_GET(instruction_access, spci_memory_access_permissions_t,
+ SPCI_INSTRUCTION_ACCESS_OFFSET, SPCI_INSTRUCTION_ACCESS_MASK)
-LEND_ATTR_FUNCTION_SET(cacheability, SPCI_MEMORY_CACHEABILITY_OFFSET,
- SPCI_MEMORY_CACHEABILITY_MASK)
+ATTR_FUNCTION_SET(memory_type, spci_memory_attributes_t,
+ SPCI_MEMORY_TYPE_OFFSET, SPCI_MEMORY_TYPE_MASK)
+ATTR_FUNCTION_GET(memory_type, spci_memory_attributes_t,
+ SPCI_MEMORY_TYPE_OFFSET, SPCI_MEMORY_TYPE_MASK)
-LEND_ATTR_FUNCTION_GET(cacheability, SPCI_MEMORY_CACHEABILITY_OFFSET,
- SPCI_MEMORY_CACHEABILITY_MASK)
+ATTR_FUNCTION_SET(memory_cacheability, spci_memory_attributes_t,
+ SPCI_MEMORY_CACHEABILITY_OFFSET,
+ SPCI_MEMORY_CACHEABILITY_MASK)
+ATTR_FUNCTION_GET(memory_cacheability, spci_memory_attributes_t,
+ SPCI_MEMORY_CACHEABILITY_OFFSET,
+ SPCI_MEMORY_CACHEABILITY_MASK)
-LEND_ATTR_FUNCTION_SET(shareability, SPCI_MEMORY_SHAREABILITY_OFFSET,
- SPCI_MEMORY_SHAREABILITY_MASK)
+ATTR_FUNCTION_SET(memory_shareability, spci_memory_attributes_t,
+ SPCI_MEMORY_SHAREABILITY_OFFSET,
+ SPCI_MEMORY_SHAREABILITY_MASK)
+ATTR_FUNCTION_GET(memory_shareability, spci_memory_attributes_t,
+ SPCI_MEMORY_SHAREABILITY_OFFSET,
+ SPCI_MEMORY_SHAREABILITY_MASK)
-LEND_ATTR_FUNCTION_GET(shareability, SPCI_MEMORY_SHAREABILITY_OFFSET,
- SPCI_MEMORY_SHAREABILITY_MASK)
-
-/* clang-format on */
-
-#define SPCI_MEMORY_HANDLE_ALLOCATOR_MASK ((spci_memory_handle_t)(1U << 31))
+#define SPCI_MEMORY_HANDLE_ALLOCATOR_MASK \
+ ((spci_memory_handle_t)(UINT64_C(1) << 63))
#define SPCI_MEMORY_HANDLE_ALLOCATOR_HYPERVISOR \
- ((spci_memory_handle_t)(1U << 31))
+ ((spci_memory_handle_t)(UINT64_C(1) << 63))
/** The ID of a VM. These are assigned sequentially starting with an offset. */
typedef uint16_t spci_vm_id_t;
@@ -174,13 +203,7 @@
* A globally-unique ID assigned by the hypervisor for a region of memory being
* sent between VMs.
*/
-typedef uint32_t spci_memory_handle_t;
-
-/**
- * A unique-per-VM ID used to associate fragments of a memory sharing message,
- * assigned by the sender of the message.
- */
-typedef uint32_t spci_cookie_t;
+typedef uint64_t spci_memory_handle_t;
/**
* A count of VMs. This has the same range as the VM IDs but we give it a
@@ -251,158 +274,28 @@
return ((uint32_t)vm_id << 16) | vcpu_index;
}
+/**
+ * A set of contiguous pages which is part of a memory region. This corresponds
+ * to table 40 of the FF-A 1.0 EAC specification, "Constituent memory region
+ * descriptor".
+ */
struct spci_memory_region_constituent {
/**
* The base IPA of the constituent memory region, aligned to 4 kiB page
* size granularity.
*/
- uint32_t address_low;
- uint32_t address_high;
+ uint64_t address;
/** The number of 4 kiB pages in the constituent memory region. */
uint32_t page_count;
/** Reserved field, must be 0. */
uint32_t reserved;
};
-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;
- /** Reserved field, must be 0. */
- uint32_t reserved_0;
- /** Reserved field, must be 0. */
- uint64_t reserved_1;
-};
-
-/** 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.
+ * A set of pages comprising a memory region. This corresponds to table 39 of
+ * the FF-A 1.0 EAC specification, "Composite memory region descriptor".
*/
-#define SPCI_MEMORY_REGION_FLAG_CLEAR 0x1
-
-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. */
- spci_memory_region_flags_t flags;
- /** Sender VM ID. */
- spci_vm_id_t sender;
- /** Reserved field, must be 0. */
- uint16_t reserved_0;
- /**
- * 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;
- /** Reserved field, must be 0. */
- uint32_t reserved_1;
- /**
- * 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[];
-};
-
-/**
- * Retrieval attributes for a single receiver. This corresponds to table 138 of
- * the SPCI beta specification, "Descriptor with properties to retrieve a memory
- * region".
- */
-struct spci_memory_retrieve_properties {
- struct spci_memory_region_attributes attributes;
- uint32_t page_count;
- uint32_t constituent_count;
- /** Reserved field, must be 0. */
- uint32_t reserved;
- struct spci_memory_region_constituent constituents[];
-};
-
-/**
- * Descriptor used for SPCI_MEM_RETRIEVE_REQ. This corresponds to table 137 of
- * the SPCI beta specification, "Descriptor to retrieve a donated, lent or
- * shared memory region".
- */
-struct spci_memory_retrieve_request {
- /** Globally unique handle to identify the memory transaction. */
- spci_memory_handle_t handle;
- /** ID of the VM which sent the memory. */
- spci_vm_id_t sender;
- /** Reserved field, must be 0. */
- uint16_t reserved_0;
- /** Function ID of the memory sharing operation. */
- uint32_t share_func;
- /**
- * An implementation defined value associated with the receiver and the
- * memory region.
- */
- uint32_t tag;
- /**
- * The number of descriptors to specify the attributes with which the
- * memory region will be mapped in the other recipients. Hafnium doesn't
- * support multi-way memory sharing so this should always be 0.
- */
- uint32_t attribute_count;
- /**
- * The offset in bytes from the base address of this
- * `spci_memory_retrieve_request` to the start of the first attribute
- * descriptor.
- */
- uint32_t attribute_offset;
- /**
- * The number of `spci_memory_retrieve_properties` entries included
- * in this retrieve request, i.e. the number of receivers including the
- * caller and any stream endpoints for which the caller is a proxy.
- * Hafnium doesn't support stream endpoints, so this should always be 1.
- */
- uint32_t retrieve_properties_count;
- /** Reserved field, must be 0. */
- uint32_t reserved_1;
- /*
- * 'Array' of `struct spci_memory_retrieve_properties` goes here, but it
- * is not included in the struct as the entries are variable length. Use
- * `spci_memory_retrieve_request_first_retrieve_properties` to get the
- * first one.
- */
-};
-
-/**
- * Receiver address range descriptor. This corresponds to table 144 of the SPCI
- * beta specification, "Descriptor with address ranges of retrieved memory
- * region", and is included as part of the `spci_retrieved_memory_region`.
- */
-struct spci_receiver_address_range {
- /** Receiver VM ID. */
- spci_vm_id_t receiver;
- /** Reserved field, must be 0. */
- uint16_t reserved_0;
+struct spci_composite_memory_region {
/**
* 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
@@ -415,101 +308,155 @@
*/
uint32_t constituent_count;
/** Reserved field, must be 0. */
- uint32_t reserved_1;
+ uint64_t reserved_0;
/** An array of `constituent_count` memory region constituents. */
struct spci_memory_region_constituent constituents[];
};
+/** Flags to indicate properties of receivers during memory region retrieval. */
+typedef uint8_t spci_memory_receiver_flags_t;
+
/**
- * Descriptor used for SPCI_MEM_RETRIEVE_RESP. This corresponds to table 143 of
- * the SPCI beta specification, "Encoding of mapped address ranges of retrieved
- * memory region".
+ * This corresponds to table 41 of the FF-A 1.0 EAC specification, "Memory
+ * access permissions descriptor".
*/
-struct spci_retrieved_memory_region {
+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 number of `spci_receiver_address_range` entries included
- * in this memory region.
+ * The permissions with which the memory region should be mapped in the
+ * receiver's page table.
+ */
+ spci_memory_access_permissions_t permissions;
+ /**
+ * Flags used during SPCI_MEM_RETRIEVE_REQ and SPCI_MEM_RETRIEVE_RESP
+ * for memory regions with multiple borrowers.
+ */
+ spci_memory_receiver_flags_t flags;
+};
+
+/** 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
+
+/**
+ * Whether the hypervisor may time slice the memory sharing or retrieval
+ * operation.
+ */
+#define SPCI_MEMORY_REGION_FLAG_TIME_SLICE 0x2
+
+/**
+ * Whether the hypervisor should clear the memory region after the receiver
+ * relinquishes it or is aborted.
+ */
+#define SPCI_MEMORY_REGION_FLAG_CLEAR_RELINQUISH 0x4
+
+#define SPCI_MEMORY_REGION_TRANSACTION_TYPE_MASK ((0x3U) << 3)
+#define SPCI_MEMORY_REGION_TRANSACTION_TYPE_UNSPECIFIED ((0x0U) << 3)
+#define SPCI_MEMORY_REGION_TRANSACTION_TYPE_SHARE ((0x1U) << 3)
+#define SPCI_MEMORY_REGION_TRANSACTION_TYPE_LEND ((0x2U) << 3)
+#define SPCI_MEMORY_REGION_TRANSACTION_TYPE_DONATE ((0x3U) << 3)
+
+/**
+ * This corresponds to table 42 of the FF-A 1.0 EAC specification, "Endpoint
+ * memory access descriptor".
+ */
+struct spci_memory_access {
+ struct spci_memory_region_attributes receiver_permissions;
+ /**
+ * Offset in bytes from the start of the outer `spci_memory_region` to
+ * an `spci_composite_memory_region` struct.
+ */
+ uint32_t composite_memory_region_offset;
+ uint64_t reserved_0;
+};
+
+/**
+ * Information about a set of pages which are being shared. This corresponds to
+ * table 45 of the FF-A 1.0 EAC specification, "Lend, donate or share memory
+ * transaction descriptor". Note that it is also used for retrieve requests and
+ * responses.
+ */
+struct spci_memory_region {
+ /**
+ * The ID of the VM which originally sent the memory region, i.e. the
+ * owner.
+ */
+ spci_vm_id_t sender;
+ spci_memory_attributes_t attributes;
+ /** Reserved field, must be 0. */
+ uint8_t reserved_0;
+ /** Flags to control behaviour of the transaction. */
+ spci_memory_region_flags_t flags;
+ spci_memory_handle_t handle;
+ /**
+ * An implementation defined value associated with the receiver and the
+ * memory region.
+ */
+ uint64_t tag;
+ /** Reserved field, must be 0. */
+ uint32_t reserved_1;
+ /**
+ * The number of `spci_memory_access` entries included in this
+ * transaction.
*/
uint32_t receiver_count;
- /** Reserved field, must be 0. */
- uint32_t reserved_0;
- /** Reserved field, must be 0. */
- uint64_t reserved_1;
- /*
- * 'Array' of `struct spci_receiver_address_range` goes here, but it is
- * not included in the struct as the entries are variable length. Use
- * `spci_retrieved_memory_region_first_receiver_range` to get the first
- * one.
+ /**
+ * An array of `attribute_count` endpoint memory access descriptors.
+ * Each one specifies a memory region offset, an endpoint and the
+ * attributes with which this memory region should be mapped in that
+ * endpoint's page table.
*/
+ struct spci_memory_access receivers[];
};
/**
* Descriptor used for SPCI_MEM_RELINQUISH requests. This corresponds to table
- * 146 of the SPCI beta specification, "Descriptor to relinquish a memory
+ * 150 of the FF-A 1.0 EAC specification, "Descriptor to relinquish a memory
* region".
*/
struct spci_mem_relinquish {
spci_memory_handle_t handle;
- uint32_t flags;
- spci_vm_id_t sender;
- uint16_t reserved;
+ spci_memory_region_flags_t flags;
uint32_t endpoint_count;
spci_vm_id_t endpoints[];
};
-static inline struct spci_memory_region_constituent
-spci_memory_region_constituent_init(uint64_t address, uint32_t page_count)
-{
- return (struct spci_memory_region_constituent){
- .address_high = (uint32_t)(address >> 32),
- .address_low = (uint32_t)address,
- .page_count = page_count,
- };
-}
-
-static inline uint64_t spci_memory_region_constituent_get_address(
- struct spci_memory_region_constituent *constituent)
-{
- return (uint64_t)constituent->address_high << 32 |
- constituent->address_low;
-}
-
/**
- * Gets the constituent array for an `spci_memory_region`.
+ * Gets the `spci_composite_memory_region` for the given receiver from an
+ * `spci_memory_region`, or NULL if it is not valid.
*/
-static inline struct spci_memory_region_constituent *
-spci_memory_region_get_constituents(struct spci_memory_region *memory_region)
+static inline struct spci_composite_memory_region *
+spci_memory_region_get_composite(struct spci_memory_region *memory_region,
+ uint32_t receiver_index)
{
- return (struct spci_memory_region_constituent
- *)((uint8_t *)memory_region +
- memory_region->constituent_offset);
+ uint32_t offset = memory_region->receivers[receiver_index]
+ .composite_memory_region_offset;
+
+ if (offset == 0) {
+ return NULL;
+ }
+
+ return (struct spci_composite_memory_region *)((uint8_t *)
+ memory_region +
+ offset);
}
-/**
- * Gets the first descriptor with address ranges of a retrieved memory region.
- *
- * Note that getting the second requires parsing the first, as they are variable
- * length due to the variable number of constituents.
- */
-static inline struct spci_receiver_address_range *
-spci_retrieved_memory_region_first_receiver_range(
- struct spci_retrieved_memory_region *memory_region)
+static inline uint32_t spci_mem_relinquish_init(
+ struct spci_mem_relinquish *relinquish_request,
+ spci_memory_handle_t handle, spci_memory_region_flags_t flags,
+ spci_vm_id_t sender)
{
- return (struct spci_receiver_address_range *)(memory_region + 1);
-}
-
-/**
- * Gets the first retrieval attributes descriptor of a memory region retrieval
- * request.
- *
- * Note that getting the second requires parsing the first, as they are variable
- * length due to the variable number of constituents.
- */
-static inline struct spci_memory_retrieve_properties *
-spci_memory_retrieve_request_first_retrieve_properties(
- struct spci_memory_retrieve_request *retrieve_request)
-{
- return (struct spci_memory_retrieve_properties *)(retrieve_request + 1);
+ relinquish_request->handle = handle;
+ relinquish_request->flags = flags;
+ relinquish_request->endpoint_count = 1;
+ relinquish_request->endpoints[0] = sender;
+ return sizeof(struct spci_mem_relinquish) + sizeof(spci_vm_id_t);
}
uint32_t spci_memory_region_init(
@@ -517,18 +464,21 @@
spci_vm_id_t receiver,
const struct spci_memory_region_constituent constituents[],
uint32_t constituent_count, uint32_t tag,
- spci_memory_region_flags_t flags, enum spci_memory_access access,
+ spci_memory_region_flags_t flags, enum spci_data_access data_access,
+ enum spci_instruction_access instruction_access,
enum spci_memory_type type, enum spci_memory_cacheability cacheability,
enum spci_memory_shareability shareability);
uint32_t spci_memory_retrieve_request_init(
- struct spci_memory_retrieve_request *request,
- spci_memory_handle_t handle, spci_vm_id_t sender, spci_vm_id_t receiver,
- uint32_t share_func, uint32_t tag, uint32_t page_count,
- enum spci_memory_access access, enum spci_memory_type type,
- enum spci_memory_cacheability cacheability,
+ struct spci_memory_region *memory_region, spci_memory_handle_t handle,
+ spci_vm_id_t sender, spci_vm_id_t receiver, uint32_t tag,
+ spci_memory_region_flags_t flags, enum spci_data_access data_access,
+ enum spci_instruction_access instruction_access,
+ enum spci_memory_type type, enum spci_memory_cacheability cacheability,
enum spci_memory_shareability shareability);
uint32_t spci_retrieved_memory_region_init(
- struct spci_retrieved_memory_region *response, size_t response_max_size,
- spci_vm_id_t receiver,
+ struct spci_memory_region *response, size_t response_max_size,
+ spci_vm_id_t sender, spci_memory_attributes_t attributes,
+ spci_memory_region_flags_t flags, spci_memory_handle_t handle,
+ spci_vm_id_t receiver, spci_memory_access_permissions_t permissions,
const struct spci_memory_region_constituent constituents[],
- uint32_t constituent_count, uint32_t page_count);
+ uint32_t constituent_count);