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_ */