Merge changes from topic "jc/toolchain_update_2.9"

* changes:
  feat(build): add support for new binutils versions
  docs: update toolchain requirements documentation
diff --git a/include/common/test_helpers.h b/include/common/test_helpers.h
index fdc5401..5af4d19 100644
--- a/include/common/test_helpers.h
+++ b/include/common/test_helpers.h
@@ -358,6 +358,33 @@
 		}								\
 	} while (false)
 
+#define SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP()				\
+	do {									\
+		u_register_t retrmm;						\
+										\
+		if (!get_armv9_2_feat_rme_support()) {				\
+			tftf_testcase_printf("FEAT_RME not supported\n");	\
+			return TEST_RESULT_SKIPPED;				\
+		}								\
+										\
+		host_rmi_init_cmp_result();					\
+		retrmm = host_rmi_version();					\
+										\
+		VERBOSE("RMM version is: %lu.%lu\n",				\
+			RMI_ABI_VERSION_GET_MAJOR(retrmm),			\
+			RMI_ABI_VERSION_GET_MINOR(retrmm));			\
+										\
+		/*								\
+		 * TODO: Remove this once SMC_RMM_REALM_CREATE is implemented	\
+		 * in TRP. For the moment skip the test if RMM is TRP, TRP	\
+		 * version is always 0.						\
+		 */								\
+		if (retrmm == 0U) {						\
+			tftf_testcase_printf("RMM is TRP\n");			\
+			return TEST_RESULT_SKIPPED;				\
+		}								\
+	} while (false)
+
 /* Helper macro to verify if system suspend API is supported */
 #define is_psci_sys_susp_supported()	\
 		(tftf_get_psci_feature_info(SMC_PSCI_SYSTEM_SUSPEND)		\
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 1cbe3c3..0e2903e 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -1218,10 +1218,18 @@
  * FEAT_HCX - Extended Hypervisor Configuration Register
  ******************************************************************************/
 #define HCRX_EL2		S3_4_C1_C2_2
+#define HCRX_EL2_MSCEn_BIT	(UL(1) << 11)
+#define HCRX_EL2_MCE2_BIT	(UL(1) << 10)
+#define HCRX_EL2_CMOW_BIT	(UL(1) << 9)
+#define HCRX_EL2_VFNMI_BIT	(UL(1) << 8)
+#define HCRX_EL2_VINMI_BIT	(UL(1) << 7)
+#define HCRX_EL2_TALLINT_BIT	(UL(1) << 6)
+#define HCRX_EL2_SMPME_BIT	(UL(1) << 5)
 #define HCRX_EL2_FGTnXS_BIT	(UL(1) << 4)
 #define HCRX_EL2_FnXS_BIT	(UL(1) << 3)
 #define HCRX_EL2_EnASR_BIT	(UL(1) << 2)
 #define HCRX_EL2_EnALS_BIT	(UL(1) << 1)
 #define HCRX_EL2_EnAS0_BIT	(UL(1) << 0)
+#define HCRX_EL2_INIT_VAL	ULL(0x0)
 
 #endif /* ARCH_H */
diff --git a/tftf/tests/extensions/hcx/test_hcx.c b/tftf/tests/extensions/hcx/test_hcx.c
index ebc6e81..3621f21 100644
--- a/tftf/tests/extensions/hcx/test_hcx.c
+++ b/tftf/tests/extensions/hcx/test_hcx.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,16 +13,32 @@
 test_result_t test_feat_hcx_enabled(void)
 {
 #ifdef __aarch64__
+	u_register_t hcrx_el2;
+
 	/* Make sure FEAT_HCX is supported. */
 	if (!get_feat_hcx_support()) {
 		return TEST_RESULT_SKIPPED;
 	}
 
 	/* Attempt to read HCRX_EL2, if not enabled this should trap to EL3. */
-	read_hcrx_el2();
+	hcrx_el2 = read_hcrx_el2();
 
-	/* If we make it this far, the test was successful. */
-	return TEST_RESULT_SUCCESS;
+	/*
+	 * If we make it this far, access to HCRX_EL2 was not trapped, and
+	 * therefore FEAT_HCX is supported.
+	 */
+	if (hcrx_el2 == HCRX_EL2_INIT_VAL) {
+		/*
+		 * If the value of the register is the reset value, the test
+		 * passed.
+		 */
+		return TEST_RESULT_SUCCESS;
+	}
+	/*
+	 * Otherwise, the test fails, as the HCRX_EL2 register has
+	 * not been initialized properly.
+	 */
+	return TEST_RESULT_FAIL;
 #else
 	/* Skip test if AArch32 */
 	return TEST_RESULT_SKIPPED;
diff --git a/tftf/tests/misc_tests/test_invalid_access.c b/tftf/tests/misc_tests/test_invalid_access.c
index 9cbd8f2..7325ace 100644
--- a/tftf/tests/misc_tests/test_invalid_access.c
+++ b/tftf/tests/misc_tests/test_invalid_access.c
@@ -230,25 +230,7 @@
 	test_result_t result = TEST_RESULT_FAIL;
 	static char rd[GRANULE_SIZE] __aligned(GRANULE_SIZE);
 
-	if (get_armv9_2_feat_rme_support() == 0U) {
-		return TEST_RESULT_SKIPPED;
-	}
-
-	host_rmi_init_cmp_result();
-
-	retrmm = host_rmi_version();
-
-	VERBOSE("RMM version is: %lu.%lu\n",
-			RMI_ABI_VERSION_GET_MAJOR(retrmm),
-			RMI_ABI_VERSION_GET_MINOR(retrmm));
-
-	/*
-	 * TODO: Remove this once SMC_RMM_REALM_CREATE is implemented in TRP
-	 * For the moment skip the test if RMM is TRP, TRP version is always null.
-	 */
-	if (retrmm == 0U) {
-		return TEST_RESULT_SKIPPED;
-	}
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
 
 	retrmm = host_rmi_granule_delegate((u_register_t)&rd[0]);
 	if (retrmm != 0UL) {
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
index 55a333a..ae62336 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
@@ -12,6 +12,7 @@
 #include <irq.h>
 #include <drivers/arm/arm_gic.h>
 #include <drivers/arm/gic_v3.h>
+#include <test_helpers.h>
 
 #include <host_realm_helper.h>
 #include <host_realm_mem_layout.h>
@@ -28,26 +29,8 @@
 test_result_t host_test_realm_create_enter(void)
 {
 	bool ret1, ret2;
-	u_register_t retrmm;
 
-	if (get_armv9_2_feat_rme_support() == 0U) {
-		INFO("platform doesn't support RME\n");
-		return TEST_RESULT_SKIPPED;
-	}
-
-	host_rmi_init_cmp_result();
-
-	retrmm = host_rmi_version();
-	VERBOSE("RMM version is: %lu.%lu\n",
-			RMI_ABI_VERSION_GET_MAJOR(retrmm),
-			RMI_ABI_VERSION_GET_MINOR(retrmm));
-	/*
-	 * Skip the test if RMM is TRP, TRP version is always null.
-	 */
-	if (retrmm == 0UL) {
-		INFO("Test case not supported for TRP as RMM\n");
-		return TEST_RESULT_SKIPPED;
-	}
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
 
 	if (!host_create_realm_payload((u_register_t)REALM_IMAGE_BASE,
 			(u_register_t)PAGE_POOL_BASE,
@@ -135,27 +118,9 @@
 static test_result_t host_test_realm_pmuv3(uint8_t cmd)
 {
 	struct realm *realm_ptr;
-	u_register_t retrmm;
 	bool ret1, ret2;
 
-	if (get_armv9_2_feat_rme_support() == 0U) {
-		INFO("platform doesn't support RME\n");
-		return TEST_RESULT_SKIPPED;
-	}
-
-	host_rmi_init_cmp_result();
-
-	retrmm = host_rmi_version();
-	VERBOSE("RMM version is: %lu.%lu\n",
-			RMI_ABI_VERSION_GET_MAJOR(retrmm),
-			RMI_ABI_VERSION_GET_MINOR(retrmm));
-	/*
-	 * Skip the test if RMM is TRP, TRP version is always null.
-	 */
-	if (retrmm == 0UL) {
-		INFO("Test case not supported for TRP as RMM\n");
-		return TEST_RESULT_SKIPPED;
-	}
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
 
 	host_set_pmu_state();
 
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c b/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
index ea33587..9418b57 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
@@ -24,6 +24,7 @@
 
 /* Memory section to be used for memory share operations */
 static __aligned(PAGE_SIZE) uint8_t share_page[PAGE_SIZE];
+static __aligned(PAGE_SIZE) uint8_t consecutive_donate_page[PAGE_SIZE];
 
 static bool check_written_words(uint32_t *ptr, uint32_t word, uint32_t wcount)
 {
@@ -39,6 +40,67 @@
 	return true;
 }
 
+static bool test_memory_send_expect_denied(uint32_t mem_func,
+					   void *mem_ptr,
+					   ffa_id_t borrower)
+{
+	struct ffa_value ret;
+	struct mailbox_buffers mb;
+	struct ffa_memory_region_constituent constituents[] = {
+						{(void *)mem_ptr, 1, 0}
+					};
+	ffa_memory_handle_t handle;
+
+	const uint32_t constituents_count = sizeof(constituents) /
+			sizeof(struct ffa_memory_region_constituent);
+	GET_TFTF_MAILBOX(mb);
+
+	handle = memory_init_and_send((struct ffa_memory_region *)mb.send,
+					MAILBOX_SIZE, SENDER, borrower,
+					constituents, constituents_count,
+					mem_func, &ret);
+
+	if (handle != FFA_MEMORY_HANDLE_INVALID) {
+		ERROR("Received a valid FF-A memory handle, and that isn't"
+		       " expected.\n");
+		return false;
+	}
+
+	if (!is_expected_ffa_error(ret, FFA_ERROR_DENIED)) {
+		return false;
+	}
+
+	return true;
+}
+
+/**
+ * Test invocation to FF-A memory sharing interfaces that should return in an
+ * error.
+ */
+test_result_t test_share_forbidden_ranges(void)
+{
+	const uintptr_t forbidden_address[] = {
+		/* Cactus SP memory. */
+		(uintptr_t)0x7200000,
+		/* SPMC Memory. */
+		(uintptr_t)0x6000000,
+		/* NS memory defined in cactus tertiary. */
+		(uintptr_t)0x0000880080001000,
+	};
+
+	CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
+
+	for (unsigned i = 0; i < 3; i++) {
+		if (!test_memory_send_expect_denied(
+			FFA_MEM_SHARE_SMC32, (void *)forbidden_address[i],
+			RECEIVER)) {
+			return TEST_RESULT_FAIL;
+		}
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
+
 /**
  * Tests that it is possible to share memory with SWd from NWd.
  * After calling the respective memory send API, it will expect a reply from
@@ -57,7 +119,9 @@
  * Hypervisor (sitting in EL2) would relinquish access from EL1/EL0
  * FF-A endpoint at relevant moment.
  */
-static test_result_t test_memory_send_sp(uint32_t mem_func)
+static test_result_t test_memory_send_sp(uint32_t mem_func, ffa_id_t borrower,
+					 struct ffa_memory_region_constituent *constituents,
+					 size_t constituents_count)
 {
 	struct ffa_value ret;
 	ffa_memory_handle_t handle;
@@ -74,17 +138,16 @@
 
 	GET_TFTF_MAILBOX(mb);
 
-	struct ffa_memory_region_constituent constituents[] = {
-						{(void *)share_page, 1, 1}
-					};
+	if (constituents_count != 1) {
+		WARN("Test expects constituents_count to be 1\n");
+	}
 
-	const uint32_t constituents_count = sizeof(constituents) /
-			sizeof(struct ffa_memory_region_constituent);
-
-	VERBOSE("TFTF - Address: %p\n", constituents[0].address);
+	for (size_t i = 0; i < constituents_count; i++) {
+		VERBOSE("TFTF - Address: %p\n", constituents[0].address);
+	}
 
 	handle = memory_init_and_send((struct ffa_memory_region *)mb.send,
-					MAILBOX_SIZE, SENDER, RECEIVER,
+					MAILBOX_SIZE, SENDER, borrower,
 					constituents, constituents_count,
 					mem_func, &ret);
 
@@ -96,7 +159,7 @@
 
 	ptr = (uint32_t *)constituents[0].address;
 
-	ret = cactus_mem_send_cmd(SENDER, RECEIVER, mem_func, handle, 0,
+	ret = cactus_mem_send_cmd(SENDER, borrower, mem_func, handle, 0,
 				  true, nr_words_to_write);
 
 	if (!is_ffa_direct_response(ret)) {
@@ -125,17 +188,77 @@
 
 test_result_t test_mem_share_sp(void)
 {
-	return test_memory_send_sp(FFA_MEM_SHARE_SMC32);
+	struct ffa_memory_region_constituent constituents[] = {
+		{(void *)share_page, 1, 0}
+	};
+
+	const uint32_t constituents_count = sizeof(constituents) /
+				sizeof(struct ffa_memory_region_constituent);
+
+	return test_memory_send_sp(FFA_MEM_SHARE_SMC32, RECEIVER, constituents,
+				   constituents_count);
 }
 
 test_result_t test_mem_lend_sp(void)
 {
-	return test_memory_send_sp(FFA_MEM_LEND_SMC32);
+	struct ffa_memory_region_constituent constituents[] = {
+		{(void *)share_page, 1, 0}
+	};
+
+	const uint32_t constituents_count = sizeof(constituents) /
+				sizeof(struct ffa_memory_region_constituent);
+
+	return test_memory_send_sp(FFA_MEM_LEND_SMC32, RECEIVER, constituents,
+				   constituents_count);
 }
 
 test_result_t test_mem_donate_sp(void)
 {
-	return test_memory_send_sp(FFA_MEM_DONATE_SMC32);
+	struct ffa_memory_region_constituent constituents[] = {
+		{(void *)share_page, 1, 0}
+	};
+	const uint32_t constituents_count = sizeof(constituents) /
+				sizeof(struct ffa_memory_region_constituent);
+	return test_memory_send_sp(FFA_MEM_DONATE_SMC32, RECEIVER, constituents,
+				   constituents_count);
+}
+
+test_result_t test_consecutive_donate(void)
+{
+	struct ffa_memory_region_constituent constituents[] = {
+		{(void *)consecutive_donate_page, 1, 0}
+	};
+	const uint32_t constituents_count = sizeof(constituents) /
+				sizeof(struct ffa_memory_region_constituent);
+
+	CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
+
+	test_result_t ret = test_memory_send_sp(FFA_MEM_DONATE_SMC32, SP_ID(1),
+						constituents,
+						constituents_count);
+
+	if (ret != TEST_RESULT_SUCCESS) {
+		ERROR("Failed at first attempting of sharing.\n");
+		return TEST_RESULT_FAIL;
+	}
+
+	if (!test_memory_send_expect_denied(FFA_MEM_DONATE_SMC32,
+					    consecutive_donate_page,
+					    SP_ID(1))) {
+		ERROR("Memory was successfully donated again from the NWd, to "
+		      "the same borrower.\n");
+		return TEST_RESULT_FAIL;
+	}
+
+	if (!test_memory_send_expect_denied(FFA_MEM_DONATE_SMC32,
+					    consecutive_donate_page,
+					    SP_ID(2))) {
+		ERROR("Memory was successfully donated again from the NWd, to "
+		      "another borrower.\n");
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
 }
 
 /*
diff --git a/tftf/tests/tests-invalid-access.xml b/tftf/tests/tests-invalid-access.xml
index 60d9a2b..17bb50a 100644
--- a/tftf/tests/tests-invalid-access.xml
+++ b/tftf/tests/tests-invalid-access.xml
@@ -16,8 +16,6 @@
                 function="s_memory_cannot_be_accessed_in_ns" />
       <testcase name="Access Secure memory from Realm world"
                 function="s_memory_cannot_be_accessed_in_rl" />
-      <testcase name="Access from a SP to a Root region"
-                function="rt_memory_cannot_be_accessed_in_s" />
       <testcase name="Access Root memory from Realm world"
                 function="rt_memory_cannot_be_accessed_in_rl" />
   </testsuite>
diff --git a/tftf/tests/tests-spm.xml b/tftf/tests/tests-spm.xml
index 6f6fb75..6c701ce 100644
--- a/tftf/tests/tests-spm.xml
+++ b/tftf/tests/tests-spm.xml
@@ -92,6 +92,10 @@
                function="test_req_mem_share_sp_to_vm" />
      <testcase name="Request Lend Memory SP-to-VM"
                function="test_req_mem_lend_sp_to_vm" />
+     <testcase name="Share forbidden memory with SP"
+               function="test_share_forbidden_ranges" />
+     <testcase name="Donate consecutively"
+               function="test_consecutive_donate" />
   </testsuite>
 
   <testsuite name="SIMD,SVE Registers context"