feat(lfa): add multi-CPU test for LFA of RMM

Add LFA testing on multiple CPUs. Executed full LFA
test for RMM live activation.

Signed-off-by: Manish V Badarkhe <Manish.Badarkhe@arm.com>
Change-Id: I22f9ec7185adddc91b8f5c5ebae9128f31ef0e2a
diff --git a/tftf/tests/runtime_services/lfa/test_lfa_multi_cpu.c b/tftf/tests/runtime_services/lfa/test_lfa_multi_cpu.c
new file mode 100644
index 0000000..59fe81f
--- /dev/null
+++ b/tftf/tests/runtime_services/lfa/test_lfa_multi_cpu.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <events.h>
+#include <lfa.h>
+#include <plat_topology.h>
+#include <platform.h>
+#include <power_management.h>
+#include <psci.h>
+#include <spinlock.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+
+#define RMM_X1	UL(0x564bf212a662076c)
+#define RMM_X2	UL(0xd90636638fbacb92)
+
+static uint64_t fw_id;
+
+/*
+ * Test entry point function for non-lead CPUs.
+ * Specified by the lead CPU when bringing up other CPUs.
+ */
+static test_result_t non_lead_cpu_fn(void)
+{
+	smc_args args = { .fid = LFA_ACTIVATE, .arg1 = fw_id };
+	smc_ret_values ret;
+
+	ret = tftf_smc(&args);
+	if (ret.ret0 != SMC_OK) {
+		tftf_testcase_printf("%s: LFA_ACTIVATE error: 0x%08lx\n",
+				     __func__, ret.ret0);
+		return TEST_RESULT_FAIL;
+	}
+	return TEST_RESULT_SUCCESS;
+}
+
+static test_result_t test_lfa_activate_flow(uint64_t uuid1, uint64_t uuid2)
+{
+	unsigned int lead_mpid;
+	unsigned int cpu_mpid, cpu_node;
+	int psci_ret;
+
+	lead_mpid = read_mpidr_el1() & MPID_MASK;
+
+	SKIP_TEST_IF_LESS_THAN_N_CPUS(2);
+
+	smc_args args = { .fid = LFA_GET_INFO, .arg1 = 0 };
+	smc_ret_values ret;
+	uint64_t i, j;
+	bool found = false;
+
+	ret = tftf_smc(&args);
+	if (ret.ret0 != SMC_OK) {
+		tftf_testcase_printf("%s: LFA_GET_INFO error: 0x%08lx\n",
+				     __func__, ret.ret0);
+		return TEST_RESULT_FAIL;
+	}
+	j = ret.ret1;
+
+	for (i = 0U; i < j; i++) {
+		args.fid = LFA_GET_INVENTORY;
+		args.arg1 = i;
+		ret = tftf_smc(&args);
+		if (ret.ret0 != 0) {
+			tftf_testcase_printf("%s: LFA_GET_INVENTORY error: 0x%08lx\n",
+					     __func__, ret.ret0);
+			return TEST_RESULT_FAIL;
+		}
+		tftf_testcase_printf("ID %lld: 0x%16lx 0x%16lx - capable: %s, pending: %s\n",
+			i, ret.ret1, ret.ret2,
+			(ret.ret4 & 0x1) ? "yes" : "no",
+			(ret.ret4 & 0x2) ? "yes" : "no");
+
+		if ((ret.ret1 == uuid1) && (ret.ret2 == uuid2)) {
+			found = true;
+			fw_id = i;
+		}
+	}
+
+	if (found == false) {
+		tftf_testcase_printf("%s: Firmware not found\n", __func__);
+		return TEST_RESULT_SKIPPED;
+	}
+
+	args.fid = LFA_PRIME;
+	args.arg1 = fw_id;
+	ret = tftf_smc(&args);
+	if (ret.ret0 != SMC_OK) {
+		tftf_testcase_printf("%s: LFA_PRIME error: 0x%08lx\n",
+				     __func__, ret.ret0);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Power on all CPUs */
+	for_each_cpu(cpu_node) {
+		cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
+		/* Skip lead CPU as it is already powered on */
+		if (cpu_mpid == lead_mpid)
+			continue;
+
+		psci_ret = tftf_cpu_on(cpu_mpid, (uintptr_t) non_lead_cpu_fn, 0);
+		if (psci_ret != PSCI_E_SUCCESS) {
+			tftf_testcase_printf(
+				"Failed to power on CPU 0x%x (%d)\n",
+				cpu_mpid, psci_ret);
+			return TEST_RESULT_SKIPPED;
+		}
+	}
+
+	args.fid = LFA_ACTIVATE;
+	args.arg1 = fw_id;
+	ret = tftf_smc(&args);
+	if (ret.ret0 != SMC_OK) {
+		tftf_testcase_printf("%s: LFA_ACTIVATE error: 0x%08lx\n", __func__, ret.ret0);
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
+
+/*
+ * @Test_Aim@ Test RMM Live activation.
+ */
+test_result_t test_lfa_activate_rmm(void)
+{
+	return test_lfa_activate_flow(RMM_X1, RMM_X2);
+}
diff --git a/tftf/tests/tests-lfa.mk b/tftf/tests/tests-lfa.mk
index a66dd53..1b42bf5 100644
--- a/tftf/tests/tests-lfa.mk
+++ b/tftf/tests/tests-lfa.mk
@@ -5,5 +5,6 @@
 #
 
 TESTS_SOURCES	+=	$(addprefix tftf/tests/runtime_services/lfa/,	\
-			test_lfa_single_cpu.c				\
+				test_lfa_single_cpu.c			\
+				test_lfa_multi_cpu.c			\
 )
diff --git a/tftf/tests/tests-lfa.xml b/tftf/tests/tests-lfa.xml
index 77222c7..4b584c7 100644
--- a/tftf/tests/tests-lfa.xml
+++ b/tftf/tests/tests-lfa.xml
@@ -15,5 +15,6 @@
      <testcase name="Prime" function="test_lfa_prime" />
      <testcase name="Activate" function="test_lfa_activate" />
      <testcase name="Cancel" function="test_lfa_cancel" />
+     <testcase name="RMM Live Activation" function="test_lfa_activate_rmm" />
   </testsuite>
 </testsuites>