Merge changes I5d06d118,Ic34acf62,Ice7bc03d

* changes:
  test(rmm): add test for multiple rec single cpu
  feat(rmm) : use shared data buf to pass arg to rec
  feat(rmm): add psci api to realms
diff --git a/include/runtime_services/host_realm_managment/host_shared_data.h b/include/runtime_services/host_realm_managment/host_shared_data.h
index fbeb257..4cb3c0a 100644
--- a/include/runtime_services/host_realm_managment/host_shared_data.h
+++ b/include/runtime_services/host_realm_managment/host_shared_data.h
@@ -63,7 +63,7 @@
  */
 enum host_param_index {
 	HOST_CMD_INDEX = 0U,
-	HOST_SLEEP_INDEX
+	HOST_ARG1_INDEX
 };
 
 enum host_call_cmd {
diff --git a/realm/aarch64/realm_entrypoint.S b/realm/aarch64/realm_entrypoint.S
index 73406f9..ab00989 100644
--- a/realm/aarch64/realm_entrypoint.S
+++ b/realm/aarch64/realm_entrypoint.S
@@ -16,6 +16,8 @@
 stacks_end:
 
 func realm_entrypoint
+	/* Save x0 - context_id */
+	mov	x20, x0
 	mrs	x0, mpidr_el1
 	mov_imm	x1, MPID_MASK
 	and	x0, x0, x1
@@ -26,6 +28,7 @@
 	/* mpidr 0 is assumed to be primary CPU, jump to warmboot otherwise */
 	cbnz	x0, realm_warmboot_endpoint
 
+	/* Primary CPU Only */
 	/* Clear BSS */
 	ldr	x0, =__REALM_BSS_START__
 	adr	x1, realm_entrypoint
@@ -53,7 +56,6 @@
 	add	x1, x1, x0
 	bl	fixup_gdt_reloc
 
-realm_warmboot_endpoint:
 	/* Initialize architectural state. */
 	bl	arch_init
 #if ENABLE_PAUTH
@@ -64,6 +66,15 @@
 	/* And jump to the C entrypoint. */
 	bl	realm_payload_main
 	b	loop
+
+realm_warmboot_endpoint:
+	/* Initialize architectural state. */
+	bl	arch_init
+#if ENABLE_PAUTH
+	bl	pauth_init_enable
+#endif
+	mov	x0, x20
+	b	realm_secondary_entrypoint
 endfunc realm_entrypoint
 
 /*
diff --git a/realm/include/realm_psci.h b/realm/include/realm_psci.h
new file mode 100644
index 0000000..ce41ffb
--- /dev/null
+++ b/realm/include/realm_psci.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+void realm_cpu_off(void);
+u_register_t realm_cpu_on(u_register_t mpidr, uintptr_t entrypoint,
+		u_register_t context_id);
+u_register_t realm_psci_affinity_info(u_register_t target_affinity,
+		uint32_t lowest_affinity_level);
+u_register_t realm_psci_features(uint32_t psci_func_id);
diff --git a/realm/realm.mk b/realm/realm.mk
index 77499d0..23ebc0c 100644
--- a/realm/realm.mk
+++ b/realm/realm.mk
@@ -31,6 +31,7 @@
 	realm_pauth.c							\
 	realm_payload_main.c						\
 	realm_pmuv3.c							\
+	realm_psci.c							\
 	realm_rsi.c							\
 	realm_shared_data.c						\
 	realm_sve.c							\
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
index 586d400..b8c27bd 100644
--- a/realm/realm_payload_main.c
+++ b/realm/realm_payload_main.c
@@ -25,7 +25,7 @@
  */
 static void realm_sleep_cmd(void)
 {
-	uint64_t sleep = realm_shared_data_get_my_host_val(HOST_SLEEP_INDEX);
+	uint64_t sleep = realm_shared_data_get_my_host_val(HOST_ARG1_INDEX);
 
 	realm_printf("Realm: going to sleep for %llums\n", sleep);
 	waitms(sleep);
diff --git a/realm/realm_psci.c b/realm/realm_psci.c
new file mode 100644
index 0000000..2a5b951
--- /dev/null
+++ b/realm/realm_psci.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <debug.h>
+#include <psci.h>
+#include <realm_def.h>
+#include <tftf_lib.h>
+
+typedef void (*secondary_ep_t)(u_register_t);
+static secondary_ep_t entrypoint[MAX_REC_COUNT];
+static u_register_t context_id[MAX_REC_COUNT];
+void realm_entrypoint(void);
+void realm_payload_main(void);
+
+void realm_cpu_off(void)
+{
+	smc_args args = { SMC_PSCI_CPU_OFF };
+
+	tftf_smc(&args);
+}
+
+u_register_t realm_cpu_on(u_register_t mpidr, uintptr_t ep, u_register_t cxt_id)
+{
+	smc_args args;
+	smc_ret_values ret_vals;
+
+
+	if (mpidr > MAX_REC_COUNT) {
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	if (entrypoint[mpidr] != NULL) {
+		return PSCI_E_ALREADY_ON;
+	}
+
+	args.fid = SMC_PSCI_CPU_ON;
+	args.arg1 = mpidr;
+	args.arg2 = (u_register_t)realm_entrypoint;
+	args.arg3 = cxt_id;
+	entrypoint[mpidr] = (secondary_ep_t)ep;
+	context_id[mpidr] = cxt_id;
+	ret_vals = tftf_smc(&args);
+	return ret_vals.ret0;
+}
+
+u_register_t realm_psci_affinity_info(u_register_t target_affinity,
+		uint32_t lowest_affinity_level)
+{
+	smc_args args;
+	smc_ret_values ret_vals;
+
+	args.fid = SMC_PSCI_AFFINITY_INFO;
+	args.arg1 = target_affinity;
+	args.arg2 = lowest_affinity_level;
+	ret_vals = tftf_smc(&args);
+	return ret_vals.ret0;
+}
+
+u_register_t realm_psci_features(uint32_t psci_func_id)
+{
+
+	smc_args args;
+	smc_ret_values ret_vals;
+
+	args.fid = SMC_PSCI_FEATURES;
+	args.arg1 = psci_func_id;
+	ret_vals = tftf_smc(&args);
+	return ret_vals.ret0;
+}
+
+void realm_secondary_entrypoint(u_register_t cxt_id)
+{
+	u_register_t my_mpidr;
+	secondary_ep_t ep;
+
+	my_mpidr = read_mpidr_el1() & MPID_MASK;
+	ep = entrypoint[my_mpidr];
+	if (ep != NULL) {
+		entrypoint[my_mpidr] = NULL;
+		context_id[my_mpidr] = 0;
+		(ep)(context_id[my_mpidr]);
+	} else {
+		/*
+		 * Host can execute Rec directly without CPU_ON
+		 * from Realm, if Rec is created RUNNABLE
+		 * Jump to main in this case.
+		 */
+		while (true) {
+			realm_payload_main();
+		}
+	}
+	realm_cpu_off();
+}
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c
new file mode 100644
index 0000000..bd120ca
--- /dev/null
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include <debug.h>
+#include <power_management.h>
+#include <psci.h>
+#include <test_helpers.h>
+
+#include <host_realm_helper.h>
+#include <host_realm_mem_layout.h>
+#include <host_realm_pmu.h>
+#include <host_shared_data.h>
+
+/*
+ * Test tries to create max Rec
+ * Enters all Rec from single CPU
+ */
+test_result_t host_realm_multi_rec_single_cpu(void)
+{
+	bool ret1, ret2;
+	u_register_t rec_flag[] = {RMI_RUNNABLE, RMI_RUNNABLE, RMI_RUNNABLE,
+	RMI_RUNNABLE, RMI_RUNNABLE, RMI_RUNNABLE, RMI_RUNNABLE, RMI_RUNNABLE};
+
+	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,
+			(u_register_t)(PAGE_POOL_MAX_SIZE +
+			NS_REALM_SHARED_MEM_SIZE),
+			(u_register_t)PAGE_POOL_MAX_SIZE,
+			0UL, rec_flag, MAX_REC_COUNT)) {
+		return TEST_RESULT_FAIL;
+	}
+	if (!host_create_shared_mem(NS_REALM_SHARED_MEM_BASE,
+			NS_REALM_SHARED_MEM_SIZE)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	for (unsigned int i = 0; i < MAX_REC_COUNT; i++) {
+		host_shared_data_set_host_val(i, HOST_ARG1_INDEX, 10U);
+		ret1 = host_enter_realm_execute(REALM_SLEEP_CMD, NULL,
+				RMI_EXIT_HOST_CALL, i);
+		if (!ret1) {
+			break;
+		}
+	}
+
+	ret2 = host_destroy_realm();
+
+	if (!ret1 || !ret2) {
+		ERROR("%s(): enter=%d destroy=%d\n",
+		__func__, ret1, ret2);
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
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 b2bf475..0732605 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
@@ -47,7 +47,7 @@
 		return TEST_RESULT_FAIL;
 	}
 
-	host_shared_data_set_host_val(0U, HOST_SLEEP_INDEX, SLEEP_TIME_MS);
+	host_shared_data_set_host_val(0U, HOST_ARG1_INDEX, SLEEP_TIME_MS);
 	ret1 = host_enter_realm_execute(REALM_SLEEP_CMD, NULL, RMI_EXIT_HOST_CALL, 0U);
 	ret2 = host_destroy_realm();
 
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_spm.c b/tftf/tests/runtime_services/realm_payload/host_realm_spm.c
index 04c7f7c..64de113 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_spm.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_spm.c
@@ -232,7 +232,7 @@
 	 * Spin Realm payload for REALM_TIME_SLEEP ms, This ensures secure wdog
 	 * timer triggers during this time.
 	 */
-	host_shared_data_set_host_val(0U, HOST_SLEEP_INDEX, REALM_TIME_SLEEP);
+	host_shared_data_set_host_val(0U, HOST_ARG1_INDEX, REALM_TIME_SLEEP);
 	host_enter_realm_execute(REALM_SLEEP_CMD, &realm_ptr, RMI_EXIT_FIQ, 0U);
 
 	/*
diff --git a/tftf/tests/tests-realm-payload.mk b/tftf/tests/tests-realm-payload.mk
index ee8ebc0..406fbb2 100644
--- a/tftf/tests/tests-realm-payload.mk
+++ b/tftf/tests/tests-realm-payload.mk
@@ -10,6 +10,7 @@
 
 TESTS_SOURCES	+=							\
 	$(addprefix tftf/tests/runtime_services/realm_payload/,		\
+		host_realm_payload_multiple_rec_tests.c			\
 		host_realm_payload_tests.c				\
 		host_realm_spm.c					\
 		host_realm_payload_sve_tests.c				\
diff --git a/tftf/tests/tests-realm-payload.xml b/tftf/tests/tests-realm-payload.xml
index 8498472..188ff29 100644
--- a/tftf/tests/tests-realm-payload.xml
+++ b/tftf/tests/tests-realm-payload.xml
@@ -10,6 +10,8 @@
   <testsuite name="Realm payload at EL1" description="Test Realm EL1 framework capabilities" >
 	  <testcase name="Realm EL1 creation and execution test"
 	  function="host_test_realm_create_enter" />
+	  <testcase name="Realm payload multi rec single cpu"
+	  function="host_realm_multi_rec_single_cpu" />
 	  <testcase name="Realm payload boot"
 	  function="host_realm_version_single_cpu" />
 	  <testcase name="Realm payload multi CPU request"