libsp: Implement memory management interfaces.
The patch contains the implementation of the FF-A memory management
interfaces including donate, lend, share, retrieve, relinquish and
reclaim.
Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: I7280395f397f0f76e793632364969ffaa4a4d5b9
diff --git a/components/messaging/ffa/libsp/ffa.c b/components/messaging/ffa/libsp/ffa.c
index 011d941..648d3c8 100644
--- a/components/messaging/ffa/libsp/ffa.c
+++ b/components/messaging/ffa/libsp/ffa.c
@@ -276,3 +276,146 @@
return FFA_OK;
}
+
+ffa_result ffa_mem_donate(uint32_t total_length, uint32_t fragment_length,
+ void *buffer_address, uint32_t page_count,
+ uint64_t *handle)
+{
+ struct ffa_params result = {0};
+
+ ffa_svc(FFA_MEM_DONATE_32, total_length, fragment_length,
+ (uintptr_t)buffer_address, page_count, FFA_PARAM_MBZ,
+ FFA_PARAM_MBZ, FFA_PARAM_MBZ, &result);
+
+ if (result.a0 == FFA_ERROR) {
+ *handle = 0U;
+ return ffa_get_errorcode(&result);
+ }
+
+ assert(result.a0 == FFA_SUCCESS_32);
+ *handle = reg_pair_to_64(result.a3, result.a2);
+ return FFA_OK;
+}
+
+ffa_result ffa_mem_donate_rxtx(uint32_t total_length, uint32_t fragment_length,
+ uint64_t *handle)
+{
+ return ffa_mem_donate(total_length, fragment_length, NULL, 0, handle);
+}
+
+ffa_result ffa_mem_lend(uint32_t total_length, uint32_t fragment_length,
+ void *buffer_address, uint32_t page_count,
+ uint64_t *handle)
+{
+ struct ffa_params result = {0};
+
+ ffa_svc(FFA_MEM_LEND_32, total_length, fragment_length,
+ (uintptr_t)buffer_address, page_count, FFA_PARAM_MBZ,
+ FFA_PARAM_MBZ, FFA_PARAM_MBZ, &result);
+
+ if (result.a0 == FFA_ERROR) {
+ *handle = 0U;
+ return ffa_get_errorcode(&result);
+ }
+
+ assert(result.a0 == FFA_SUCCESS_32);
+ *handle = reg_pair_to_64(result.a3, result.a2);
+ return FFA_OK;
+}
+
+ffa_result ffa_mem_lend_rxtx(uint32_t total_length, uint32_t fragment_length,
+ uint64_t *handle)
+{
+ return ffa_mem_lend(total_length, fragment_length, NULL, 0, handle);
+}
+
+ffa_result ffa_mem_share(uint32_t total_length, uint32_t fragment_length,
+ void *buffer_address, uint32_t page_count,
+ uint64_t *handle)
+{
+ struct ffa_params result = {0};
+
+ ffa_svc(FFA_MEM_SHARE_32, total_length, fragment_length,
+ (uintptr_t)buffer_address, page_count, FFA_PARAM_MBZ,
+ FFA_PARAM_MBZ, FFA_PARAM_MBZ, &result);
+
+ if (result.a0 == FFA_ERROR) {
+ *handle = 0U;
+ return ffa_get_errorcode(&result);
+ }
+
+ assert(result.a0 == FFA_SUCCESS_32);
+ *handle = reg_pair_to_64(result.a3, result.a2);
+ return FFA_OK;
+}
+
+ffa_result ffa_mem_share_rxtx(uint32_t total_length, uint32_t fragment_length,
+ uint64_t *handle)
+{
+ return ffa_mem_share(total_length, fragment_length, NULL, 0, handle);
+}
+
+ffa_result ffa_mem_retrieve_req(uint32_t total_length, uint32_t fragment_length,
+ void *buffer_address, uint32_t page_count,
+ uint32_t *resp_total_length,
+ uint32_t *resp_fragment_length)
+{
+ struct ffa_params result = {0};
+
+ ffa_svc(FFA_MEM_RETRIEVE_REQ_32, total_length, fragment_length,
+ (uintptr_t)buffer_address, page_count, FFA_PARAM_MBZ,
+ FFA_PARAM_MBZ, FFA_PARAM_MBZ, &result);
+
+ if (result.a0 == FFA_ERROR) {
+ *resp_total_length = 0U;
+ *resp_fragment_length = 0U;
+ return ffa_get_errorcode(&result);
+ }
+
+ assert(result.a0 == FFA_MEM_RETRIEVE_RESP);
+ *resp_total_length = result.a1;
+ *resp_fragment_length = result.a2;
+ return FFA_OK;
+}
+
+ffa_result ffa_mem_retrieve_req_rxtx(uint32_t total_length,
+ uint32_t fragment_length,
+ uint32_t *resp_total_length,
+ uint32_t *resp_fragment_length)
+{
+ return ffa_mem_retrieve_req(total_length, fragment_length, NULL, 0,
+ resp_total_length, resp_fragment_length);
+}
+
+ffa_result ffa_mem_relinquish(void)
+{
+ struct ffa_params result = {0};
+
+ ffa_svc(FFA_MEM_RELINQUISH, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+ FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+ &result);
+
+ if (result.a0 == FFA_ERROR)
+ return ffa_get_errorcode(&result);
+
+ assert(result.a0 == FFA_SUCCESS_32);
+ return FFA_OK;
+}
+
+ffa_result ffa_mem_reclaim(uint64_t handle, uint32_t flags)
+{
+ struct ffa_params result = {0};
+ uint32_t handle_hi = 0;
+ uint32_t handle_lo = 0;
+
+ reg_pair_from_64(handle, &handle_hi, &handle_lo);
+
+ ffa_svc(FFA_MEM_RECLAIM, handle_lo, handle_hi, flags, FFA_PARAM_MBZ,
+ FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, &result);
+
+ if (result.a0 == FFA_ERROR)
+ return ffa_get_errorcode(&result);
+
+ assert(result.a0 == FFA_SUCCESS_32);
+ return FFA_OK;
+}
diff --git a/components/messaging/ffa/libsp/include/ffa_api.h b/components/messaging/ffa/libsp/include/ffa_api.h
index ac7a7b3..6359263 100644
--- a/components/messaging/ffa/libsp/include/ffa_api.h
+++ b/components/messaging/ffa/libsp/include/ffa_api.h
@@ -160,6 +160,138 @@
uint32_t a4, struct ffa_direct_msg *msg);
/**
+ * Memory management interfaces
+ *
+ * @note Functions with _rxtx suffix use the RX/TX buffers mapped by
+ * ffa_rxtx_map to transmit memory descriptors instead of an distinct buffer
+ * allocated by the owner.
+ */
+
+/**
+ * @brief Starts a transaction to transfer of ownership of a memory region
+ * from a Sender endpoint to a Receiver endpoint.
+ *
+ * @param[in] total_length Total length of the memory transaction
+ * descriptor in bytes
+ * @param[in] fragment_length Length in bytes of the memory transaction
+ * descriptor passed in this ABI invocation
+ * @param[in] buffer_address Base address of a buffer allocated by the Owner
+ * and distinct from the TX buffer
+ * @param[in] page_count Number of 4K pages in the buffer allocated by
+ * the Owner and distinct from the TX buffer
+ * @param[out] handle Globally unique Handle to identify the memory
+ * region upon successful transmission of the
+ * transaction descriptor.
+ *
+ * @return The FF-A error status code
+ */
+ffa_result ffa_mem_donate(uint32_t total_length, uint32_t fragment_length,
+ void *buffer_address, uint32_t page_count,
+ uint64_t *handle);
+
+ffa_result ffa_mem_donate_rxtx(uint32_t total_length, uint32_t fragment_length,
+ uint64_t *handle);
+
+/**
+ * @brief Starts a transaction to transfer an Owner’s access to a memory
+ * region and grant access to it to one or more Borrowers.
+ *
+ * @param[in] total_length Total length of the memory transaction
+ * descriptor in bytes
+ * @param[in] fragment_length Length in bytes of the memory transaction
+ * descriptor passed in this ABI invocation
+ * @param[in] buffer_address Base address of a buffer allocated by the Owner
+ * and distinct from the TX buffer
+ * @param[in] page_count Number of 4K pages in the buffer allocated by
+ * the Owner and distinct from the TX buffer
+ * @param[out] handle Globally unique Handle to identify the memory
+ * region upon successful transmission of the
+ * transaction descriptor.
+ *
+ * @return The FF-A error status code
+ */
+ffa_result ffa_mem_lend(uint32_t total_length, uint32_t fragment_length,
+ void *buffer_address, uint32_t page_count,
+ uint64_t *handle);
+
+ffa_result ffa_mem_lend_rxtx(uint32_t total_length, uint32_t fragment_length,
+ uint64_t *handle);
+
+/**
+ * @brief Starts a transaction to grant access to a memory region to one or
+ * more Borrowers.
+ *
+ * @param[in] total_length Total length of the memory transaction
+ * descriptor in bytes
+ * @param[in] fragment_length Length in bytes of the memory transaction
+ * descriptor passed in this ABI invocation
+ * @param[in] buffer_address Base address of a buffer allocated by the Owner
+ * and distinct from the TX buffer
+ * @param[in] page_count Number of 4K pages in the buffer allocated by
+ * the Owner and distinct from the TX buffer
+ * @param[out] handle Globally unique Handle to identify the memory
+ * region upon successful transmission of the
+ * transaction descriptor.
+ *
+ * @return The FF-A error status code
+ */
+ffa_result ffa_mem_share(uint32_t total_length, uint32_t fragment_length,
+ void *buffer_address, uint32_t page_count,
+ uint64_t *handle);
+
+ffa_result ffa_mem_share_rxtx(uint32_t total_length, uint32_t fragment_length,
+ uint64_t *handle);
+
+/**
+ * @brief Requests completion of a donate, lend or share memory management
+ * transaction.
+ *
+ * @param[in] total_length Total length of the memory transaction
+ * descriptor in bytes
+ * @param[in] fragment_length Length in bytes of the memory transaction
+ * descriptor passed in this ABI invocation
+ * @param[in] buffer_address Base address of a buffer allocated by the
+ * Owner and distinct from the TX buffer
+ * @param[in] page_count Number of 4K pages in the buffer allocated
+ * by the Owner and distinct from the TX
+ * buffer
+ * @param[out] resp_total_length Total length of the response memory
+ * transaction descriptor in bytes
+ * @param[out] resp_fragment_length Length in bytes of the response memory
+ * transaction descriptor passed in this ABI
+ * invocation
+ *
+ * @return The FF-A error status code
+ */
+ffa_result ffa_mem_retrieve_req(uint32_t total_length, uint32_t fragment_length,
+ void *buffer_address, uint32_t page_count,
+ uint32_t *resp_total_length,
+ uint32_t *resp_fragment_length);
+
+ffa_result ffa_mem_retrieve_req_rxtx(uint32_t total_length,
+ uint32_t fragment_length,
+ uint32_t *resp_total_length,
+ uint32_t *resp_fragment_length);
+
+/**
+ * @brief Starts a transaction to transfer access to a shared or lent
+ * memory region from a Borrower back to its Owner.
+ *
+ * @return The FF-A error status code
+ */
+ffa_result ffa_mem_relinquish(void);
+
+/**
+ * @brief Restores exclusive access to a memory region back to its Owner.
+ *
+ * @param[in] handle Globally unique Handle to identify the memory region
+ * @param[in] flags Flags for modifying the reclaim behavior
+ *
+ * @return The FF-A error status code
+ */
+ffa_result ffa_mem_reclaim(uint64_t handle, uint32_t flags);
+
+/**
* @brief Interrupt handler prototype. Must be implemented by another
* component.
*
diff --git a/components/messaging/ffa/libsp/include/ffa_api_defines.h b/components/messaging/ffa/libsp/include/ffa_api_defines.h
index 5a7f8f4..4f2c457 100644
--- a/components/messaging/ffa/libsp/include/ffa_api_defines.h
+++ b/components/messaging/ffa/libsp/include/ffa_api_defines.h
@@ -120,4 +120,93 @@
#define FFA_MSG_SEND_DIRECT_RESP_DEST_ID_MASK GENMASK_32(15, 0)
#define FFA_MSG_SEND_DIRECT_RESP_DEST_ID_SHIFT UINT32_C(0)
+/* Table 5.15: Memory access permissions descriptor */
+
+/* Memory access permissions */
+#define FFA_MEM_ACCESS_PERM_INSTRUCTION_MASK GENMASK_32(1, 0)
+#define FFA_MEM_ACCESS_PERM_INSTRUCTION_SHIFT UINT32_C(2)
+
+#define FFA_MEM_ACCESS_PERM_INSTRUCTION_NOT_SPECIFIED UINT32_C(0x00)
+#define FFA_MEM_ACCESS_PERM_INSTRUCTION_NOT_EXECUTABLE UINT32_C(0x01)
+#define FFA_MEM_ACCESS_PERM_INSTRUCTION_EXECUTABLE UINT32_C(0x02)
+
+#define FFA_MEM_ACCESS_PERM_DATA_MASK GENMASK_32(1, 0)
+#define FFA_MEM_ACCESS_PERM_DATA_SHIFT UINT32_C(0)
+
+#define FFA_MEM_ACCESS_PERM_DATA_NOT_SPECIFIED UINT32_C(0x00)
+#define FFA_MEM_ACCESS_PERM_DATA_READ_ONLY UINT32_C(0x01)
+#define FFA_MEM_ACCESS_PERM_DATA_READ_WRITE UINT32_C(0x02)
+
+#define FFA_MEM_ACCESS_PERM_FLAGS_NON_RETRIEVAL_BORROWER BIT(0)
+
+/* Table 5.18: Memory region attributes descriptor */
+
+/* Memory type */
+#define FFA_MEM_REGION_ATTR_MEMORY_TYPE_MASK GENMASK_32(1, 0)
+#define FFA_MEM_REGION_ATTR_MEMORY_TYPE_SHIFT UINT32_C(4)
+
+#define FFA_MEM_REGION_ATTR_MEMORY_TYPE_NOT_SPECIFIED UINT32_C(0x00)
+#define FFA_MEM_REGION_ATTR_MEMORY_TYPE_DEVICE UINT32_C(0x01)
+#define FFA_MEM_REGION_ATTR_MEMORY_TYPE_NORMAL UINT32_C(0x02)
+
+/* Cacheability */
+#define FFA_MEM_REGION_ATTR_CACHEABILITY_MASK GENMASK_32(1, 0)
+#define FFA_MEM_REGION_ATTR_CACHEABILITY_SHIFT UINT32_C(2)
+
+#define FFA_MEM_REGION_ATTR_CACHEABILITY_NON_CACHEABLE UINT32_C(0x01)
+#define FFA_MEM_REGION_ATTR_CACHEABILITY_WRITE_BACK UINT32_C(0x03)
+
+/* Device memory attributes */
+#define FFA_MEM_REGION_ATTR_DEVICE_MEM_ATTR_MASK GENMASK_32(1, 0)
+#define FFA_MEM_REGION_ATTR_DEVICE_MEM_ATTR_SHIFT UINT32_C(2)
+
+#define FFA_MEM_REGION_ATTR_DEVICE_MEM_ATTR_NGNRNE UINT32_C(0x00)
+#define FFA_MEM_REGION_ATTR_DEVICE_MEM_ATTR_NGNRE UINT32_C(0x01)
+#define FFA_MEM_REGION_ATTR_DEVICE_MEM_ATTR_NGRE UINT32_C(0x02)
+#define FFA_MEM_REGION_ATTR_DEVICE_MEM_ATTR_GRE UINT32_C(0x03)
+
+/* Shareability */
+#define FFA_MEM_REGION_ATTR_SHAREABILITY_MASK GENMASK_32(1, 0)
+#define FFA_MEM_REGION_ATTR_SHAREABILITY_SHIFT UINT32_C(0)
+
+#define FFA_MEM_REGION_ATTR_SHAREABILITY_NON_SHAREABLE UINT32_C(0x00)
+#define FFA_MEM_REGION_ATTR_SHAREABILITY_OUTER_SHAREABLE UINT32_C(0x02)
+#define FFA_MEM_REGION_ATTR_SHAREABILITY_INNER_SHAREABLE UINT32_C(0x03)
+
+/* Table 5.19: Lend, donate or share memory transaction descriptor */
+
+#define FFA_MEM_TRANSACTION_PAGE_SIZE UINT32_C(4096)
+#define FFA_MEM_TRANSACTION_PAGE_MASK GENMASK_64(11, 0)
+
+/* Flags for donate, lend, share */
+
+#define FFA_MEM_TRANSACTION_FLAGS_ZERO_MEMORY BIT32(0)
+#define FFA_MEM_TRANSACTION_FLAGS_OPERATION_TIME_SLICING BIT32(1)
+
+/* Flags for retrieve request */
+#define FFA_MEM_TRANSACTION_FLAGS_ZERO_MEMORY_BEFORE_RETRIEVE BIN32(0)
+/* FFA_MEM_TRANSACTION_FLAGS_OPERATION_TIME_SLICING is available too */
+#define FFA_MEM_TRANSACTION_FLAGS_ZERO_MEMORY_AFTER_RELINQIUSH BIT32(2)
+
+#define FFA_MEM_TRANSACTION_FLAGS_TYPE_MASK GENMASK_32(1, 0)
+#define FFA_MEM_TRANSACTION_FLAGS_TYPE_SHIFT UINT32_C(3)
+
+#define FFA_MEM_TRANSACTION_FLAGS_TYPE_RELAYER_SPECIFIES UINT32_C(0x00)
+#define FFA_MEM_TRANSACTION_FLAGS_TYPE_SHARE UINT32_C(0x01)
+#define FFA_MEM_TRANSACTION_FLAGS_TYPE_LEND UINT32_C(0x02)
+#define FFA_MEM_TRANSACTION_FLAGS_TYPE_DONATE UINT32_C(0x03)
+
+#define FFA_MEM_TRANSACTION_FLAGS_ALIGNMENT_HINT_MASK GENMASK_32(3, 0)
+#define FFA_MEM_TRANSACTION_FLAGS_ALIGNMENT_HINT_SHIFT UINT32_C(5)
+
+#define FFA_MEM_TRANSACTION_FLAGS_ALIGNMENT_HINT_VALID BIT32(9)
+
+/* Flags for retrieve response */
+/* FFA_MEM_TRANSACTION_FLAGS_ZERO_MEMORY is available too */
+/* FFA_MEM_TRANSACTION_FLAGS_TYPE_* is available too */
+
+/* Table 11.25: Descriptor to relinquish a memory region */
+#define FFA_RELINQUISH_FLAGS_ZERO_MEMORY_AFTER_RELINQUISH BIT32(0)
+#define FFA_RELINQUISH_FLAGS_OPERATION_TIME_SLICING BIT32(1)
+
#endif /* LIBSP_INCLUDE_FFA_API_DEFINES_H_ */
diff --git a/components/messaging/ffa/libsp/include/ffa_api_types.h b/components/messaging/ffa/libsp/include/ffa_api_types.h
index 94845ae..3686e2e 100644
--- a/components/messaging/ffa/libsp/include/ffa_api_types.h
+++ b/components/messaging/ffa/libsp/include/ffa_api_types.h
@@ -83,4 +83,70 @@
uint32_t args[5];
};
+/**
+ * Memory management transaction types
+ */
+
+/**
+ * @brief Table 5.14: Constituent memory region descriptor
+ */
+struct ffa_constituent_mem_region_desc {
+ uint64_t address;
+ uint32_t page_count;
+ uint32_t reserved_mbz;
+} __packed;
+
+/**
+ * @brief Table 5.13: Composite memory region descriptor
+ */
+struct ffa_composite_mem_region_desc {
+ uint32_t total_page_count;
+ uint32_t address_range_count;
+ uint64_t reserved_mbz;
+ struct ffa_constituent_mem_region_desc constituent_mem_region_desc[];
+} __packed;
+
+/**
+ * @brief Table 5.15: Memory access permissions descriptor
+ */
+struct ffa_mem_access_perm_desc {
+ uint16_t endpoint_id;
+ uint8_t mem_access_permissions;
+ uint8_t flags;
+} __packed;
+
+/**
+ * @brief Table 5.16: Endpoint memory access descriptor
+ */
+struct ffa_mem_access_desc {
+ struct ffa_mem_access_perm_desc mem_access_perm_desc;
+ uint32_t composite_mem_region_desc_offset;
+ uint64_t reserved_mbz;
+} __packed;
+
+/**
+ * @brief Table 5.19: Lend, donate or share memory transaction descriptor
+ */
+struct ffa_mem_transaction_desc {
+ uint16_t sender_id;
+ uint8_t mem_region_attr;
+ uint8_t reserved_mbz0;
+ uint32_t flags;
+ uint64_t handle;
+ uint64_t tag;
+ uint32_t reserved_mbz1;
+ uint32_t mem_access_desc_count;
+ struct ffa_mem_access_desc mem_access_desc[];
+} __packed;
+
+/**
+ * @brief Table 11.25: Descriptor to relinquish a memory region
+ */
+struct ffa_mem_relinquish_desc {
+ uint64_t handle;
+ uint32_t flags;
+ uint32_t endpoint_count;
+ uint16_t endpoints[];
+} __packed;
+
#endif /* LIBSP_INCLUDE_FFA_API_TYPES_H_ */