libsp: Add high level RXTX buffer handling interface.

This layer provides functions for mapping, unmapping and accessing
FF-A RXTX buffers. It allows other high level interfaces (like memory
management) to use the RXTX buffers internally without the need for
forwarding the RXTX buffer information externally by the user.

Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: I946bcbf818599b2eb12f6ff029f9fc429ccb12b7
diff --git a/components/messaging/ffa/libsp/component.cmake b/components/messaging/ffa/libsp/component.cmake
index c20f899..60bc507 100644
--- a/components/messaging/ffa/libsp/component.cmake
+++ b/components/messaging/ffa/libsp/component.cmake
@@ -12,6 +12,7 @@
 	"${CMAKE_CURRENT_LIST_DIR}/aarch64/ffa_syscalls_a64.S"
 	"${CMAKE_CURRENT_LIST_DIR}/ffa.c"
 	"${CMAKE_CURRENT_LIST_DIR}/ffa_interrupt_handler.c"
+	"${CMAKE_CURRENT_LIST_DIR}/sp_rxtx.c"
 	)
 
 set_property(TARGET ${TGT} PROPERTY PUBLIC_HEADER
@@ -22,6 +23,7 @@
 	${CMAKE_CURRENT_LIST_DIR}/include/sp_api_defines.h
 	${CMAKE_CURRENT_LIST_DIR}/include/sp_api_types.h
 	${CMAKE_CURRENT_LIST_DIR}/include/sp_api.h
+	${CMAKE_CURRENT_LIST_DIR}/include/sp_rxtx.h
 	)
 
 
diff --git a/components/messaging/ffa/libsp/include/sp_api_defines.h b/components/messaging/ffa/libsp/include/sp_api_defines.h
index c1426ee..9a80559 100644
--- a/components/messaging/ffa/libsp/include/sp_api_defines.h
+++ b/components/messaging/ffa/libsp/include/sp_api_defines.h
@@ -21,5 +21,8 @@
 /** SP API call result codes */
 #define SP_RESULT_OK			(0)
 #define SP_RESULT_FFA(res)		(res)
+#define SP_RESULT_INTERNAL_ERROR	SP_RESULT_CREATE(-1)
+#define SP_RESULT_INVALID_PARAMETERS	SP_RESULT_CREATE(-2)
+#define SP_RESULT_INVALID_STATE		SP_RESULT_CREATE(-3)
 
 #endif /* LIBSP_INCLUDE_SP_API_DEFINES_H_ */
diff --git a/components/messaging/ffa/libsp/include/sp_rxtx.h b/components/messaging/ffa/libsp/include/sp_rxtx.h
new file mode 100644
index 0000000..a5b0f6a
--- /dev/null
+++ b/components/messaging/ffa/libsp/include/sp_rxtx.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ */
+
+#ifndef LIBSP_INCLUDE_SP_RXTX_H_
+#define LIBSP_INCLUDE_SP_RXTX_H_
+
+/**
+ * @file  sp_rxtx.h
+ * @brief The functions of this file provide a higher API for the FF-A RXTX
+ *        buffer handling.
+ */
+
+#include "sp_api_defines.h"
+#include "sp_api_types.h"
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief      Maps the RX/TX buffer pair in the callee's translation regime.
+ *
+ * @param[in]  tx_buffer  The transmit buffer
+ * @param[in]  rx_buffer  The receive buffer
+ * @param[in]  size       The buffer size
+ *
+ * @return     The SP API result
+ */
+sp_result sp_rxtx_buffer_map(void *tx_buffer, const void *rx_buffer,
+			     size_t size);
+
+/**
+ * @brief      Unmaps the RX/TX buffer pair in the callee's translation regime.
+ *
+ * @return     The SP API result
+ */
+sp_result sp_rxtx_buffer_unmap(void);
+
+/**
+ * @brief      Queries the required alignment boundary of the RXTX buffers.
+ *
+ * @param[out] alignment  The minimal buffer size and alignment boundary
+ *
+ * @return     The SP API result
+ */
+sp_result sp_rxtx_buffer_alignment_boundary_get(uintptr_t *alignment);
+
+/**
+ * @brief      Queries the RX buffer's address and size.
+ *
+ * @param[out] buffer  The buffer address
+ * @param[out] size    The buffer size
+ *
+ * @return     The SP API result
+ */
+sp_result sp_rxtx_buffer_rx_get(const void **buffer, size_t *size);
+
+/**
+ * @brief      Queries the TX buffer's address and size.
+ *
+ * @param      buffer  The buffer address
+ * @param      size    The buffer size
+ *
+ * @return     The SP API result
+ */
+sp_result sp_rxtx_buffer_tx_get(void **buffer, size_t *size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBSP_INCLUDE_SP_RXTX_H_ */
diff --git a/components/messaging/ffa/libsp/sp_rxtx.c b/components/messaging/ffa/libsp/sp_rxtx.c
new file mode 100644
index 0000000..a3de270
--- /dev/null
+++ b/components/messaging/ffa/libsp/sp_rxtx.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ */
+
+#include "sp_rxtx.h"
+#include "ffa_api.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <stdlib.h>
+
+void *ffa_tx_buffer;
+const void *ffa_rx_buffer;
+size_t ffa_rxtx_size;
+
+sp_result sp_rxtx_buffer_map(void *tx_buffer, const void *rx_buffer,
+			     size_t size)
+{
+	uintptr_t alignment_mask = 0;
+	sp_result sp_res = SP_RESULT_OK;
+	ffa_result result = FFA_OK;
+	uint32_t page_count = 0;
+
+	/* Checking for invalid parameters*/
+	if (!tx_buffer || !rx_buffer || !size)
+		return SP_RESULT_INVALID_PARAMETERS;
+
+	/* Checking if the buffers are already mapped */
+	if (ffa_rxtx_size)
+		return SP_RESULT_INVALID_STATE;
+
+	/* Querying alignment size */
+	sp_res = sp_rxtx_buffer_alignment_boundary_get(&alignment_mask);
+	if (sp_res != SP_RESULT_OK)
+		return sp_res;
+
+	/* Creating a binary mask from the size */
+	alignment_mask = alignment_mask - 1;
+
+	/* Checking buffer and size alignment */
+	if (((uintptr_t)tx_buffer & alignment_mask) != 0 ||
+	    ((uintptr_t)rx_buffer & alignment_mask) != 0 ||
+	    (size & alignment_mask) != 0)
+		return SP_RESULT_INVALID_PARAMETERS;
+
+	/* Checking max page count for RXTX buffers */
+	page_count = size / FFA_RXTX_MAP_PAGE_SIZE;
+	if (page_count >= FFA_RXTX_MAP_PAGE_COUNT_MAX)
+		return SP_RESULT_INVALID_PARAMETERS;
+
+	/* Mapping the buffers */
+	result = ffa_rxtx_map(tx_buffer, rx_buffer, page_count);
+	if (result != FFA_OK)
+		return SP_RESULT_FFA(result);
+
+	/* Storing the buffer pointers and size internally */
+	ffa_tx_buffer = tx_buffer;
+	ffa_rx_buffer = rx_buffer;
+	ffa_rxtx_size = size;
+
+	return SP_RESULT_OK;
+}
+
+sp_result sp_rxtx_buffer_unmap(void)
+{
+	ffa_result result = FFA_OK;
+	uint16_t id = 0;
+
+	/* Checking if the buffers are not yet mapped */
+	if (!ffa_rxtx_size)
+		return SP_RESULT_INVALID_STATE;
+
+	result = ffa_id_get(&id);
+	if (result != FFA_OK)
+		return SP_RESULT_FFA(result);
+
+	/* Unmapping the buffers */
+	result = ffa_rxtx_unmap(id);
+	if (result != FFA_OK)
+		return SP_RESULT_FFA(result);
+
+	/* Clearing internally stored buffer pointers and size */
+	ffa_tx_buffer = NULL;
+	ffa_rx_buffer = NULL;
+	ffa_rxtx_size = 0;
+
+	return SP_RESULT_OK;
+}
+
+sp_result sp_rxtx_buffer_alignment_boundary_get(uintptr_t *alignment)
+{
+	struct ffa_interface_properties interface_props = {0};
+	uint32_t *props = NULL;
+	ffa_result result = FFA_OK;
+	uint32_t granularity = 0;
+
+	/* Checking for invalid parameters */
+	if (!alignment)
+		return SP_RESULT_INVALID_PARAMETERS;
+
+	/* Querying FFX_RXTX_MAP features */
+	result = ffa_features(FFA_RXTX_MAP_32, &interface_props);
+	if (result != FFA_OK) {
+		*alignment = 0;
+		return SP_RESULT_FFA(result);
+	}
+
+	props = interface_props.interface_properties;
+	granularity = props[FFA_FEATURES_RXTX_MAP_GRANULARITY_INDEX];
+	granularity = (granularity >> FFA_FEATURES_RXTX_MAP_GRANULARITY_SHIFT) &
+		      FFA_FEATURES_RXTX_MAP_GRANULARITY_MASK;
+
+	switch (granularity) {
+	case FFA_FEATURES_RXTX_MAP_GRANULARITY_4K:
+		*alignment = 4 * 1024;
+		break;
+
+	case FFA_FEATURES_RXTX_MAP_GRANULARITY_64K:
+		*alignment = 64 * 1024;
+		break;
+
+	case FFA_FEATURES_RXTX_MAP_GRANULARITY_16K:
+		*alignment = 16 * 1024;
+		break;
+
+	default:
+		*alignment = 0;
+		return SP_RESULT_INTERNAL_ERROR;
+	}
+
+	return SP_RESULT_OK;
+}
+
+sp_result sp_rxtx_buffer_rx_get(const void **buffer, size_t *size)
+{
+	if (!buffer || !size)
+		return SP_RESULT_INVALID_PARAMETERS;
+
+	if (!ffa_rxtx_size)
+		return SP_RESULT_INVALID_STATE;
+
+	*buffer = ffa_rx_buffer;
+	*size = ffa_rxtx_size;
+
+	return SP_RESULT_OK;
+}
+
+sp_result sp_rxtx_buffer_tx_get(void **buffer, size_t *size)
+{
+	if (!buffer || !size)
+		return SP_RESULT_INVALID_PARAMETERS;
+
+	if (!ffa_rxtx_size)
+		return SP_RESULT_INVALID_STATE;
+
+	*buffer = ffa_tx_buffer;
+	*size = ffa_rxtx_size;
+
+	return SP_RESULT_OK;
+}