Merge "feat: tftf realm extension"
diff --git a/docs/about/features.rst b/docs/about/features.rst
index dbaec12..dbdb324 100644
--- a/docs/about/features.rst
+++ b/docs/about/features.rst
@@ -19,6 +19,7 @@
 -  `Firmware update`_ (or recovery mode)
 -  `EL3 payload boot flow`_
 -  Secure partition support
+-  `True Random Number Generator Firmware Interface (TRNG_FW)`_
 
 These tests are not a compliance test suite for the Arm interface standards used
 in TF-A (such as PSCI).
@@ -55,3 +56,4 @@
 .. _TSP: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/bl32/tsp
 .. _Firmware update: https://trustedfirmware-a.readthedocs.io/en/latest/components/firmware-update.html
 .. _EL3 payload boot flow: https://trustedfirmware-a.readthedocs.io/en/latest/design/alt-boot-flows.html#el3-payloads-alternative-boot-flow
+.. _TRNG_FW: https://developer.arm.com/documentation/den0098/latest
diff --git a/include/runtime_services/arm_arch_svc.h b/include/runtime_services/arm_arch_svc.h
index 36b4448..0d2eb38 100644
--- a/include/runtime_services/arm_arch_svc.h
+++ b/include/runtime_services/arm_arch_svc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,5 +12,6 @@
 #define SMCCC_ARCH_SOC_ID	0x80000002
 #define SMCCC_ARCH_WORKAROUND_1	0x80008000
 #define SMCCC_ARCH_WORKAROUND_2	0x80007FFF
+#define SMCCC_ARCH_WORKAROUND_3	0x80003FFF
 
 #endif /* __ARM_ARCH_SVC_H__ */
diff --git a/include/runtime_services/trng.h b/include/runtime_services/trng.h
index a5d8e4d..41600b4 100644
--- a/include/runtime_services/trng.h
+++ b/include/runtime_services/trng.h
@@ -42,12 +42,12 @@
 #define SMC_TRNG_RND				0x84000053
 #define TRNG_MAX_BITS				U(96)
 #define TRNG_ENTROPY_MASK			U(0xFFFFFFFF)
-#endif
+#endif  /* __aarch64__ */
 
 /*
  * Number of TRNG calls defined in the TRNG specification.
  */
-#define TRNG_NUM_CALLS				4
+#define TRNG_NUM_CALLS				(4U)
 
 #ifndef __ASSEMBLY__
 typedef struct {
@@ -67,17 +67,16 @@
 /*******************************************************************************
  * TRNG version
  ******************************************************************************/
-#define TRNG_MAJOR_VER_SHIFT	(16)
-#define TRNG_VERSION(major, minor)	((major << TRNG_MAJOR_VER_SHIFT) \
-					| minor)
+#define TRNG_MAJOR_VER_SHIFT	        (16)
+#define TRNG_VERSION(major, minor)	((major << TRNG_MAJOR_VER_SHIFT)| minor)
 
 /*******************************************************************************
  * TRNG error codes
  ******************************************************************************/
-#define TRNG_E_SUCCESS		(0)
-#define TRNG_E_NOT_SUPPORTED	(-1)
-#define TRNG_E_INVALID_PARAMS	(-2)
-#define TRNG_E_NO_ENTOPY	(-3)
-#define TRNG_E_NOT_IMPLEMENTED	(-4)
+#define TRNG_E_SUCCESS			(0)
+#define TRNG_E_NOT_SUPPORTED		(-1)
+#define TRNG_E_INVALID_PARAMS		(-2)
+#define TRNG_E_NO_ENTROPY		(-3)
+#define TRNG_E_NOT_IMPLEMENTED		(-4)
 
 #endif /* __TRNG_H__ */
diff --git a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_3.c b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_3.c
new file mode 100644
index 0000000..ebf40a5
--- /dev/null
+++ b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_3.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <arm_arch_svc.h>
+#include <debug.h>
+#include <plat_topology.h>
+#include <power_management.h>
+#include <psci.h>
+#include <smccc.h>
+#include <string.h>
+#include <tftf_lib.h>
+
+#ifdef __aarch64__
+#define CORTEX_A57_MIDR	0x410FD070
+#define CORTEX_A72_MIDR	0x410FD080
+#define CORTEX_A73_MIDR	0x410FD090
+#define CORTEX_A75_MIDR	0x410FD0A0
+
+static int cortex_a57_test(void);
+static int cortex_a73_test(void);
+static int cortex_a75_test(void);
+static int csv2_test(void);
+
+static struct ent {
+	unsigned int midr;
+	int (*wa_required)(void);
+} entries[] = {
+	{ .midr = CORTEX_A57_MIDR, .wa_required = cortex_a57_test },
+	{ .midr = CORTEX_A72_MIDR, .wa_required = csv2_test },
+	{ .midr = CORTEX_A73_MIDR, .wa_required = cortex_a73_test },
+	{ .midr = CORTEX_A75_MIDR, .wa_required = cortex_a75_test }
+};
+
+static int cortex_a57_test(void)
+{
+	return 1;
+}
+
+static int cortex_a73_test(void)
+{
+	return 1;
+}
+
+static int cortex_a75_test(void)
+{
+	return 1;
+}
+
+static int csv2_test(void)
+{
+	uint64_t pfr0;
+
+	pfr0 = read_id_aa64pfr0_el1() >> ID_AA64PFR0_CSV2_SHIFT;
+	if ((pfr0 & ID_AA64PFR0_CSV2_MASK) == 1) {
+		return 0;
+	}
+	return 1;
+}
+
+static test_result_t test_smccc_entrypoint(void)
+{
+	smc_args args;
+	smc_ret_values ret;
+	int32_t expected_ver;
+	unsigned int my_midr, midr_mask;
+	int wa_required;
+	size_t i;
+
+	/* Check if SMCCC version is at least v1.1 */
+	expected_ver = MAKE_SMCCC_VERSION(1, 1);
+	memset(&args, 0, sizeof(args));
+	args.fid = SMCCC_VERSION;
+	ret = tftf_smc(&args);
+	if ((int32_t)ret.ret0 < expected_ver) {
+		tftf_testcase_printf("Unexpected SMCCC version: 0x%x\n",
+		       (int)ret.ret0);
+		return TEST_RESULT_SKIPPED;
+	}
+
+	/* Check if SMCCC_ARCH_WORKAROUND_3 is required or not */
+	memset(&args, 0, sizeof(args));
+	args.fid = SMCCC_ARCH_FEATURES;
+	args.arg1 = SMCCC_ARCH_WORKAROUND_3;
+	ret = tftf_smc(&args);
+	if ((int)ret.ret0 == -1) {
+		tftf_testcase_printf("SMCCC_ARCH_WORKAROUND_3 is not implemented\n");
+		return TEST_RESULT_SKIPPED;
+	}
+
+	/* If the call returns 0, it means the workaround is required */
+	if ((int)ret.ret0 == 0) {
+		wa_required = 1;
+	} else {
+		wa_required = 0;
+	}
+
+	/* Check if the SMC return value matches our expectations */
+	my_midr = (unsigned int)read_midr_el1();
+	midr_mask = (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) | (MIDR_PN_MASK << MIDR_PN_SHIFT);
+	for (i = 0; i < ARRAY_SIZE(entries); i++) {
+		struct ent *entp = &entries[i];
+
+		if ((my_midr & midr_mask) == (entp->midr & midr_mask)) {
+			if (entp->wa_required() != wa_required) {
+				return TEST_RESULT_FAIL;
+			}
+			break;
+		}
+	}
+	if ((i == ARRAY_SIZE(entries)) && wa_required) {
+		tftf_testcase_printf("TFTF workaround table out of sync with TF-A\n");
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Invoke the workaround to make sure nothing nasty happens */
+	memset(&args, 0, sizeof(args));
+	args.fid = SMCCC_ARCH_WORKAROUND_3;
+	tftf_smc(&args);
+	return TEST_RESULT_SUCCESS;
+}
+
+test_result_t test_smccc_arch_workaround_3(void)
+{
+	u_register_t lead_mpid, target_mpid;
+	int cpu_node, ret;
+
+	lead_mpid = read_mpidr_el1() & MPID_MASK;
+
+	/* Power on all the non-lead cores. */
+	for_each_cpu(cpu_node) {
+		target_mpid = tftf_get_mpidr_from_node(cpu_node);
+		if (lead_mpid == target_mpid) {
+			continue;
+		}
+		ret = tftf_cpu_on(target_mpid,
+		    (uintptr_t)test_smccc_entrypoint, 0);
+		if (ret != PSCI_E_SUCCESS) {
+			ERROR("CPU ON failed for 0x%llx\n",
+			    (unsigned long long)target_mpid);
+			return TEST_RESULT_FAIL;
+		}
+		/*
+		 * Wait for test_smccc_entrypoint to return
+		 * and the CPU to power down
+		 */
+		while (tftf_psci_affinity_info(target_mpid, MPIDR_AFFLVL0) !=
+			PSCI_STATE_OFF) {
+			continue;
+		}
+	}
+
+	return test_smccc_entrypoint();
+}
+#else
+test_result_t test_smccc_arch_workaround_3(void)
+{
+	INFO("%s skipped on AArch32\n", __func__);
+	return TEST_RESULT_SKIPPED;
+}
+#endif
diff --git a/tftf/tests/runtime_services/standard_service/trng/api_tests/test_trng.c b/tftf/tests/runtime_services/standard_service/trng/api_tests/test_trng.c
index 64b8db7..72a4ec5 100644
--- a/tftf/tests/runtime_services/standard_service/trng/api_tests/test_trng.c
+++ b/tftf/tests/runtime_services/standard_service/trng/api_tests/test_trng.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -29,7 +29,6 @@
 		return TEST_RESULT_SKIPPED;
 	}
 
-
 	if (version < TRNG_VERSION(1, 0)) {
 		return TEST_RESULT_FAIL;
 	}
@@ -51,8 +50,7 @@
 		return TEST_RESULT_SKIPPED;
 	}
 
-	if (!(tftf_trng_feature_implemented(SMC_TRNG_VERSION) &&
-	      tftf_trng_feature_implemented(SMC_TRNG_FEATURES) &&
+	if (!(tftf_trng_feature_implemented(SMC_TRNG_FEATURES) &&
 	      tftf_trng_feature_implemented(SMC_TRNG_UUID) &&
 	      tftf_trng_feature_implemented(SMC_TRNG_RND))) {
 		return TEST_RESULT_FAIL;
@@ -75,6 +73,11 @@
 		return TEST_RESULT_SKIPPED;
 	}
 
+	/* Ensure function is implemented before requesting Entropy */
+	if (!(tftf_trng_feature_implemented(SMC_TRNG_RND))) {
+		return TEST_RESULT_FAIL;
+	}
+
 	/* Test invalid entropy sizes */
 	rnd_out = tftf_trng_rnd(U(0));
 	if (rnd_out.ret0 != TRNG_E_INVALID_PARAMS) {
@@ -97,7 +100,7 @@
 	/* For N = 1, all returned entropy bits should be 0
 	 * except the least significant bit */
 	rnd_out = tftf_trng_rnd(U(1));
-	if (rnd_out.ret0 == TRNG_E_NO_ENTOPY) {
+	if (rnd_out.ret0 == TRNG_E_NO_ENTROPY) {
 		WARN("There is not a single bit of entropy\n");
 		return TEST_RESULT_SKIPPED;
 	}
@@ -116,7 +119,7 @@
 
 	/* For N = MAX_BITS-1, the most significant bit should be 0 */
 	rnd_out = tftf_trng_rnd(TRNG_MAX_BITS - U(1));
-	if (rnd_out.ret0 == TRNG_E_NO_ENTOPY) {
+	if (rnd_out.ret0 == TRNG_E_NO_ENTROPY) {
 		WARN("There is not a single bit of entropy\n");
 		return TEST_RESULT_SKIPPED;
 	}
diff --git a/tftf/tests/tests-cpu-extensions.mk b/tftf/tests/tests-cpu-extensions.mk
index 061ab7e..3616cf4 100644
--- a/tftf/tests/tests-cpu-extensions.mk
+++ b/tftf/tests/tests-cpu-extensions.mk
@@ -23,4 +23,5 @@
 	runtime_services/arm_arch_svc/smccc_arch_soc_id.c		\
 	runtime_services/arm_arch_svc/smccc_arch_workaround_1.c		\
 	runtime_services/arm_arch_svc/smccc_arch_workaround_2.c		\
+	runtime_services/arm_arch_svc/smccc_arch_workaround_3.c		\
 )
diff --git a/tftf/tests/tests-cpu-extensions.xml b/tftf/tests/tests-cpu-extensions.xml
index bc84659..d45cf62 100644
--- a/tftf/tests/tests-cpu-extensions.xml
+++ b/tftf/tests/tests-cpu-extensions.xml
@@ -34,6 +34,7 @@
   <testsuite name="ARM_ARCH_SVC" description="Arm Architecture Service tests">
      <testcase name="SMCCC_ARCH_WORKAROUND_1 test" function="test_smccc_arch_workaround_1" />
      <testcase name="SMCCC_ARCH_WORKAROUND_2 test" function="test_smccc_arch_workaround_2" />
+     <testcase name="SMCCC_ARCH_WORKAROUND_3 test" function="test_smccc_arch_workaround_3" />
      <testcase name="SMCCC_ARCH_SOC_ID test" function="test_smccc_arch_soc_id" />
   </testsuite>
 
diff --git a/tftf/tests/tests-trng.mk b/tftf/tests/tests-trng.mk
index d284296..abeb5b5 100644
--- a/tftf/tests/tests-trng.mk
+++ b/tftf/tests/tests-trng.mk
@@ -1,7 +1,10 @@
 #
-# Copyright (c) 2021, Arm Limited. All rights reserved.
+# Copyright (c) 2021-2022, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-TESTS_SOURCES	+= tftf/tests/runtime_services/standard_service/trng/api_tests/test_trng.c
+TESTS_SOURCES	+=							\
+	$(addprefix tftf/tests/runtime_services/standard_service/,	\
+		/trng/api_tests/test_trng.c				\
+	)