Implement ffa_mem_perm_get/set functions

Add functions for invoking FFA_MEM_PERM_GET and FFA_MEM_PERM_SET FF-A
1.1 interfaces. These calls can be used to query or change the access
rights of the memory regions of the SP. The patch includes tests and
mock implementations as well.

Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: I9e29551768951f6cd58aa57d18d3b65ad8e4f441
diff --git a/components/messaging/ffa/libsp/ffa.c b/components/messaging/ffa/libsp/ffa.c
index 6af0760..374e940 100644
--- a/components/messaging/ffa/libsp/ffa.c
+++ b/components/messaging/ffa/libsp/ffa.c
@@ -439,3 +439,37 @@
 	assert(result.a0 == FFA_SUCCESS_32);
 	return FFA_OK;
 }
+
+ffa_result ffa_mem_perm_get(const void *base_address, uint32_t *mem_perm)
+{
+	struct ffa_params result = {0};
+
+	ffa_svc(FFA_MEM_PERM_GET, (uintptr_t)base_address, 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);
+	*mem_perm = result.a2;
+	return FFA_OK;
+}
+
+ffa_result ffa_mem_perm_set(const void *base_address, uint32_t page_count,
+			    uint32_t mem_perm)
+{
+	struct ffa_params result = {0};
+
+	assert((mem_perm & FFA_MEM_PERM_RESERVED_MASK) == 0);
+
+	ffa_svc(FFA_MEM_PERM_SET, (uintptr_t)base_address, page_count, mem_perm,
+		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 6359263..ec5cb04 100644
--- a/components/messaging/ffa/libsp/include/ffa_api.h
+++ b/components/messaging/ffa/libsp/include/ffa_api.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause */
 /*
- * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
  */
 
 #ifndef LIBSP_INCLUDE_FFA_API_H_
@@ -292,6 +292,38 @@
 ffa_result ffa_mem_reclaim(uint64_t handle, uint32_t flags);
 
 /**
+ * @brief       Queries the memory attributes of a memory region. This function
+ *              can only access the regions of the SP's own translation regine.
+ *              Moreover this interface is only available in the boot phase,
+ *              i.e. before invoking FFA_MSG_WAIT interface.
+ *
+ * @param[in]   base_address    Base VA of a translation granule whose
+ *                              permission attributes must be returned.
+ * @param[out]  mem_perm        Permission attributes of the memory region
+ *
+ * @return      The FF-A error status code
+ */
+ffa_result ffa_mem_perm_get(const void *base_address, uint32_t *mem_perm);
+
+/**
+ * @brief       Sets the memory attributes of a memory regions. This function
+ *              can only access the regions of the SP's own translation regine.
+ *              Moreover this interface is only available in the boot phase,
+ *              i.e. before invoking FFA_MSG_WAIT interface.
+ *
+ * @param[in]   base_address    Base VA of a memory region whose permission
+ *                              attributes must be set.
+ * @param[in]   page_count      Number of translation granule size pages
+ *                              starting from the Base address whose permissions
+ *                              must be set.
+ * @param[in]   mem_perm        Permission attributes to be set for the memory
+ *                              region
+ * @return      The FF-A error status code
+ */
+ffa_result ffa_mem_perm_set(const void *base_address, uint32_t page_count,
+			    uint32_t mem_perm);
+
+/**
  * @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 4f2c457..95bcb0c 100644
--- a/components/messaging/ffa/libsp/include/ffa_api_defines.h
+++ b/components/messaging/ffa/libsp/include/ffa_api_defines.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause */
 /*
- * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
  */
 
 #ifndef LIBSP_INCLUDE_FFA_API_DEFINES_H_
@@ -55,6 +55,8 @@
 #define FFA_MEM_RECLAIM			UINT32_C(0x84000077)
 #define FFA_MEM_FRAG_RX			UINT32_C(0x8400007A)
 #define FFA_MEM_FRAG_TX			UINT32_C(0x8400007B)
+#define FFA_MEM_PERM_GET		UINT32_C(0x84000088)
+#define FFA_MEM_PERM_SET		UINT32_C(0x84000089)
 
 /* Special value for MBZ parameters */
 #define FFA_PARAM_MBZ			UINT32_C(0x0)
@@ -209,4 +211,30 @@
 #define FFA_RELINQUISH_FLAGS_ZERO_MEMORY_AFTER_RELINQUISH	BIT32(0)
 #define FFA_RELINQUISH_FLAGS_OPERATION_TIME_SLICING		BIT32(1)
 
+/* Flags for memory permission get/set */
+#ifndef FFA_MEM_PERM_PAGE_SIZE
+#define FFA_MEM_PERM_PAGE_SIZE				UINT32_C(4096)
+#endif /* FFA_MEM_PERM_PAGE_SIZE */
+
+#define FFA_MEM_PERM_PAGE_MASK				(FFA_MEM_PERM_PAGE_SIZE - 1)
+
+#define FFA_MEM_PERM_PAGE_COUNT_MAX			GENMASK_32(31, 0)
+
+#define FFA_MEM_PERM_DATA_ACCESS_PERM_INDEX		UINT32_C(2)
+#define FFA_MEM_PERM_DATA_ACCESS_PERM_SHIFT		UINT32_C(0)
+#define FFA_MEM_PERM_DATA_ACCESS_PERM_MASK		GENMASK_32(1, 0)
+
+#define FFA_MEM_PERM_DATA_ACCESS_PERM_NO_ACCESS		UINT32_C(0x00)
+#define FFA_MEM_PERM_DATA_ACCESS_PERM_RW		UINT32_C(0x01)
+#define FFA_MEM_PERM_DATA_ACCESS_PERM_RESERVED		UINT32_C(0x02)
+#define FFA_MEM_PERM_DATA_ACCESS_PERM_RO		UINT32_C(0x03)
+
+#define FFA_MEM_PERM_INSTRUCTION_ACCESS_PERM_INDEX	UINT32_C(2)
+#define FFA_MEM_PERM_INSTRUCTION_ACCESS_PERM_MASK	BIT(2)
+
+#define FFA_MEM_PERM_INSTRUCTION_ACCESS_PERM_X		UINT32_C(0x00)
+#define FFA_MEM_PERM_INSTRUCTION_ACCESS_PERM_NX		BIT(2)
+
+#define FFA_MEM_PERM_RESERVED_MASK			GENMASK_32(31, 3)
+
 #endif /* LIBSP_INCLUDE_FFA_API_DEFINES_H_ */
diff --git a/components/messaging/ffa/libsp/test/mock_ffa_api.cpp b/components/messaging/ffa/libsp/test/mock_ffa_api.cpp
index cf04c1b..ceebcbf 100644
--- a/components/messaging/ffa/libsp/test/mock_ffa_api.cpp
+++ b/components/messaging/ffa/libsp/test/mock_ffa_api.cpp
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-3-Clause
 /*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
  */
 
 #include <CppUTestExt/MockSupport.h>
@@ -451,3 +451,41 @@
 		.withUnsignedIntParameter("flags", flags)
 		.returnIntValue();
 }
+
+void expect_ffa_mem_perm_get(const void *base_address, const uint32_t *mem_perm,
+			     ffa_result result)
+{
+	mock().expectOneCall("ffa_mem_perm_get")
+		.withConstPointerParameter("base_address", base_address)
+		.withOutputParameterReturning("mem_perm", mem_perm,
+					      sizeof(*mem_perm))
+		.andReturnValue(result);
+}
+
+ffa_result ffa_mem_perm_get(const void *base_address, uint32_t *mem_perm)
+{
+	return mock().actualCall("ffa_mem_perm_get")
+		.withConstPointerParameter("base_address", base_address)
+		.withOutputParameter("mem_perm", mem_perm)
+		.returnIntValue();
+}
+
+void expect_ffa_mem_perm_set(const void *base_address, uint32_t page_count,
+			     uint32_t mem_perm, ffa_result result)
+{
+	mock().expectOneCall("ffa_mem_perm_set")
+		.withConstPointerParameter("base_address", base_address)
+		.withUnsignedIntParameter("page_count", page_count)
+		.withUnsignedIntParameter("mem_perm", mem_perm)
+		.andReturnValue(result);
+}
+
+ffa_result ffa_mem_perm_set(const void *base_address, uint32_t page_count,
+			    uint32_t mem_perm)
+{
+	return mock().actualCall("ffa_mem_perm_set")
+		.withConstPointerParameter("base_address", base_address)
+		.withUnsignedIntParameter("page_count", page_count)
+		.withUnsignedIntParameter("mem_perm", mem_perm)
+		.returnIntValue();
+}
diff --git a/components/messaging/ffa/libsp/test/mock_ffa_api.h b/components/messaging/ffa/libsp/test/mock_ffa_api.h
index 34a635c..b1c794f 100644
--- a/components/messaging/ffa/libsp/test/mock_ffa_api.h
+++ b/components/messaging/ffa/libsp/test/mock_ffa_api.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause */
 /*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
  */
 
 #ifndef LIBSP_TEST_MOCK_FFA_API_H_
@@ -80,4 +80,10 @@
 
 void expect_ffa_mem_reclaim(uint64_t handle, uint32_t flags, ffa_result result);
 
+void expect_ffa_mem_perm_get(const void *base_address, const uint32_t *mem_perm,
+			     ffa_result result);
+
+void expect_ffa_mem_perm_set(const void *base_address, uint32_t page_count,
+			     uint32_t mem_perm, ffa_result result);
+
 #endif /* FFA_LIBSP_TEST_MOCK_FFA_API_H_ */
diff --git a/components/messaging/ffa/libsp/test/test_ffa_api.cpp b/components/messaging/ffa/libsp/test/test_ffa_api.cpp
index dcde1d1..8fa261e 100644
--- a/components/messaging/ffa/libsp/test/test_ffa_api.cpp
+++ b/components/messaging/ffa/libsp/test/test_ffa_api.cpp
@@ -1137,7 +1137,7 @@
 	LONGS_EQUAL(0, result);
 }
 
-TEST(ffa_api, ffa_mem_reclaimerror)
+TEST(ffa_api, ffa_mem_reclaim_error)
 {
 	const uint64_t handle = 0x1234567812345678;
 	const uint32_t flags = 0x87654321;
@@ -1164,3 +1164,106 @@
 		ffa_mem_reclaim(handle, flags);
 	}
 }
+
+TEST(ffa_api, ffa_mem_perm_get)
+{
+	const void *base_addr = (const void *)0x01234567;
+	const uint32_t expected_mem_perm = 0x87654321;
+	uint32_t mem_perm = 0;
+
+	svc_result.a0 = 0x84000061;
+	svc_result.a2 = expected_mem_perm;
+	expect_ffa_svc(0x84000088, (uintptr_t)base_addr, 0, 0, 0, 0, 0, 0,
+		       &svc_result);
+
+	ffa_result result = ffa_mem_perm_get(base_addr, &mem_perm);
+	LONGS_EQUAL(0, result);
+	UNSIGNED_LONGS_EQUAL(expected_mem_perm, mem_perm);
+}
+
+TEST(ffa_api, ffa_mem_perm_get_error)
+{
+	const void *base_addr = (const void *)0x01234567;
+	const uint32_t expected_mem_perm = 0x87654321;
+	uint32_t mem_perm = 0;
+
+	setup_error_response(-1);
+	expect_ffa_svc(0x84000088, (uintptr_t)base_addr, 0, 0, 0, 0, 0, 0,
+		       &svc_result);
+
+	ffa_result result = ffa_mem_perm_get(base_addr, &mem_perm);
+	LONGS_EQUAL(-1, result);
+	UNSIGNED_LONGS_EQUAL(0, mem_perm);
+}
+
+TEST(ffa_api, ffa_mem_perm_get_unknown_response)
+{
+	const void *base_addr = (const void *)0x01234567;
+	const uint32_t expected_mem_perm = 0x87654321;
+	uint32_t mem_perm = 0;
+	assert_environment_t assert_env;
+
+	svc_result.a0 = 0x12345678;
+	expect_ffa_svc(0x84000088, (uintptr_t)base_addr, 0, 0, 0, 0, 0, 0,
+		       &svc_result);
+
+	if (SETUP_ASSERT_ENVIRONMENT(assert_env)) {
+		ffa_mem_perm_get(base_addr, &mem_perm);
+	}
+}
+
+TEST(ffa_api, ffa_mem_perm_set)
+{
+	const void *base_addr = (const void *)0x01234567;
+	const uint32_t page_count = 0x89abcdef;
+	const uint32_t mem_perm = 0x07;
+
+	svc_result.a0 = 0x84000061;
+	expect_ffa_svc(0x84000089, (uintptr_t)base_addr, page_count, mem_perm,
+		       0, 0, 0, 0, &svc_result);
+
+	ffa_result result = ffa_mem_perm_set(base_addr, page_count, mem_perm);
+	LONGS_EQUAL(0, result);
+}
+
+TEST(ffa_api, ffa_mem_perm_set_error)
+{
+	const void *base_addr = (const void *)0x01234567;
+	const uint32_t page_count = 0x89abcdef;
+	const uint32_t mem_perm = 0x07;
+
+	setup_error_response(-1);
+	expect_ffa_svc(0x84000089, (uintptr_t)base_addr, page_count, mem_perm,
+		       0, 0, 0, 0, &svc_result);
+
+	ffa_result result = ffa_mem_perm_set(base_addr, page_count, mem_perm);
+	LONGS_EQUAL(-1, result);
+}
+
+TEST(ffa_api, ffa_mem_perm_set_unknown_response)
+{
+	const void *base_addr = (const void *)0x01234567;
+	const uint32_t page_count = 0x89abcdef;
+	const uint32_t mem_perm = 0x07;
+	assert_environment_t assert_env;
+
+	svc_result.a0 = 0x12345678;
+	expect_ffa_svc(0x84000089, (uintptr_t)base_addr, page_count, mem_perm,
+		       0, 0, 0, 0, &svc_result);
+
+	if (SETUP_ASSERT_ENVIRONMENT(assert_env)) {
+		ffa_mem_perm_set(base_addr, page_count, mem_perm);
+	}
+}
+
+TEST(ffa_api, ffa_mem_perm_set_invalid_mem_perm)
+{
+	const void *base_addr = (const void *)0x01234567;
+	const uint32_t page_count = 0x89abcdef;
+	const uint32_t mem_perm = 0x08;
+	assert_environment_t assert_env;
+
+	if (SETUP_ASSERT_ENVIRONMENT(assert_env)) {
+		ffa_mem_perm_set(base_addr, page_count, mem_perm);
+	}
+}
\ No newline at end of file
diff --git a/components/messaging/ffa/libsp/test/test_mock_ffa_api.cpp b/components/messaging/ffa/libsp/test/test_mock_ffa_api.cpp
index 15b266a..ab33649 100644
--- a/components/messaging/ffa/libsp/test/test_mock_ffa_api.cpp
+++ b/components/messaging/ffa/libsp/test/test_mock_ffa_api.cpp
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-3-Clause
 /*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
  */
 
 #include <assert.h>
@@ -290,3 +290,24 @@
 	expect_ffa_mem_reclaim(handle, flags, result);
 	LONGS_EQUAL(result, ffa_mem_reclaim(handle, flags));
 }
+
+TEST(mock_ffa_api, ffa_mem_perm_get)
+{
+	const void *base_address = (const void *)0x01234567;
+	uint32_t expected_mem_perm = 0x89abcdef;
+	uint32_t mem_perm = 0;
+
+	expect_ffa_mem_perm_get(base_address, &expected_mem_perm, result);
+	LONGS_EQUAL(result, ffa_mem_perm_get(base_address, &mem_perm));
+	UNSIGNED_LONGS_EQUAL(expected_mem_perm, mem_perm);
+}
+
+TEST(mock_ffa_api, ffa_mem_perm_set)
+{
+	const void *base_address = (const void *)0x01234567;
+	const uint32_t page_count = 0x76543210;
+	const uint32_t mem_perm = 0x89abcdef;
+
+	expect_ffa_mem_perm_set(base_address, page_count, mem_perm, result);
+	LONGS_EQUAL(result, ffa_mem_perm_set(base_address, page_count, mem_perm));
+}