fix(realm): fix calculation of Realm's REC index

This patch fixes the issues related to the calculation of
Realm's REC index based on the read value of MPIDR_EL1 register
and REC's mpidr parameter from the REC's index.
RMM reports MPIDR_EL1.Aff0 field matching RmiRecMpidr type
with [7:4] bits RES0, making MPIDR_EL1=0x80000100 represent
REC 16, but not 256 as it is implemented in the existing code.
The patch adds the following macros:
- RMI_REC_MPIDR(idx) which calculates RmiRecMpidr value based
on REC index.
- REC_IDX(mpidr) gets REC index from MPIDR_EL1.

Change-Id: Ieac473984f3a50d2815dcfe8d291d31bd70ebae7
Signed-off-by: AlexeiFedorov <Alexei.Fedorov@arm.com>
diff --git a/include/runtime_services/host_realm_managment/realm_def.h b/include/runtime_services/host_realm_managment/realm_def.h
index 2dd94d0..992ed9a 100644
--- a/include/runtime_services/host_realm_managment/realm_def.h
+++ b/include/runtime_services/host_realm_managment/realm_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -29,4 +29,76 @@
 #error "Undefined value for PAGE_SIZE"
 #endif
 
+/*
+ * 'MPIDR_EL1_AFF<n>_VAL_SHIFT' constants specify the left shift
+ * for affinity <n> value that gives the field's actual value.
+ */
+
+/* Aff0[3:0] - Affinity level 0
+ * For compatibility with GICv3 only Aff0[3:0] field is used,
+ * and Aff0[7:4] of MPIDR_EL1 value is RES0 to match RmiRecMpidr.
+ */
+#define MPIDR_EL1_AFF0_VAL_SHIFT	0
+
+/* Aff1[15:8] - Affinity level 1 */
+#define MPIDR_EL1_AFF1_VAL_SHIFT	4
+
+/* Aff2[23:16] - Affinity level 2 */
+#define MPIDR_EL1_AFF2_VAL_SHIFT	12
+
+/* Aff3[39:32] - Affinity level 3 */
+#define MPIDR_EL1_AFF3_VAL_SHIFT	20
+
+/*
+ * Extract the value of MPIDR_EL1.Aff<n> register field
+ * and shift it left so it can be evaluated directly.
+ */
+#define MPIDR_EL1_AFF(mpidr, n)	\
+	(MPIDR_AFF_ID(mpidr, n) << MPIDR_EL1_AFF##n##_VAL_SHIFT)
+
+/*
+ * Convert MPIDR_EL1 register type value
+ * Aff3[39:32].Aff2[23:16].Aff1[15:8].RES0[7:4].Aff0[3:0]
+ * to REC linear index
+ * Aff3[27:20].Aff2[19:12].Aff1[11:4].Aff0[3:0].
+ */
+#define REC_IDX(mpidr)				\
+		(MPIDR_EL1_AFF(mpidr, 0) |	\
+		 MPIDR_EL1_AFF(mpidr, 1) |	\
+		 MPIDR_EL1_AFF(mpidr, 2) |	\
+		 MPIDR_EL1_AFF(mpidr, 3))
+
+/*
+ * RmiRecMpidr type definitions.
+ *
+ * Aff0[3:0] - Affinity level 0
+ * For compatibility with GICv3 only Aff0[3:0] field is used,
+ * and Aff0[7:4] of a REC MPIDR value is RES0.
+ */
+#define RMI_MPIDR_AFF0_SHIFT		0
+#define RMI_MPIDR_AFF0_WIDTH		U(4)
+
+/* Aff1[15:8] - Affinity level 1 */
+#define RMI_MPIDR_AFF1_SHIFT		8
+#define RMI_MPIDR_AFF1_WIDTH		U(8)
+
+/* Aff2[23:16] - Affinity level 2 */
+#define RMI_MPIDR_AFF2_SHIFT		16
+#define RMI_MPIDR_AFF2_WIDTH		U(8)
+
+/* Aff3[31:24] - Affinity level 3 */
+#define RMI_MPIDR_AFF3_SHIFT		24
+#define RMI_MPIDR_AFF3_WIDTH		U(8)
+
+/*
+ * Convert REC linear index
+ * Aff3[27:20].Aff2[19:12].Aff1[11:4].Aff0[3:0]
+ * to RmiRecMpidr type value
+ * Aff3[31:24].Aff2[23:16].Aff1[15:8].RES0[7:4].Aff0[3:0].
+ */
+#define RMI_REC_MPIDR(idx)				\
+		(((idx) & MASK(RMI_MPIDR_AFF0)) |	\
+		(((idx) & ~MASK(RMI_MPIDR_AFF0)) << 	\
+		(RMI_MPIDR_AFF1_SHIFT - RMI_MPIDR_AFF0_WIDTH)));
+
 #endif /* REALM_DEF_H */
diff --git a/realm/aarch64/realm_entrypoint.S b/realm/aarch64/realm_entrypoint.S
index 1aff61e..7e535bb 100644
--- a/realm/aarch64/realm_entrypoint.S
+++ b/realm/aarch64/realm_entrypoint.S
@@ -19,8 +19,21 @@
 	/* Save x0 - context_id */
 	mov	x20, x0
 	mrs	x0, mpidr_el1
-	mov_imm	x1, MPID_MASK
-	and	x0, x0, x1
+
+	/*
+	 * Convert MPIDR_EL1 register type value
+	 * Aff3[39:32].Aff2[23:16].Aff1[15:8].RES0[7:4].Aff0[3:0]
+	 * to REC linear index
+	 * Aff3[27:20].Aff2[19:12].Aff1[11:4].Aff0[3:0].
+	 */
+	and	x1, x0, #(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT)	/* 0xff00000000 */
+	and	x0, x0, #((MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT) | \
+			  (MPIDR_AFFLVL_MASK << MPIDR_AFF1_SHIFT) | \
+			  (MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT))	/* 0xffffff */
+	orr	x1, x0, x1, lsr #(MPIDR_AFF3_SHIFT - MPIDR_AFF2_SHIFT - \
+				  MPIDR_AFF1_SHIFT - MPIDR_AFF0_SHIFT)	/* 8 */
+	and	x0, x0, #MPIDR_AFFLVL_MASK				/* 0xff */
+	orr	x0, x0, x1, lsr #(MPIDR_AFF1_SHIFT - RMI_MPIDR_AFF0_WIDTH)	/* 4 */
 
 	/* Setup the stack pointer */
 	bl	realm_setup_my_stack
diff --git a/realm/realm_rsi.c b/realm/realm_rsi.c
index 04f57fc..cd4342f 100644
--- a/realm/realm_rsi.c
+++ b/realm/realm_rsi.c
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -47,7 +47,7 @@
 	struct rsi_host_call host_cal __aligned(sizeof(struct rsi_host_call));
 
 	host_cal.imm = exit_code;
-	host_cal.gprs[0] = read_mpidr_el1() & MPID_MASK;
+	host_cal.gprs[0] = read_mpidr_el1();
 	tftf_smc(&(smc_args) {RSI_HOST_CALL, (u_register_t)&host_cal,
 		0UL, 0UL, 0UL, 0UL, 0UL, 0UL});
 }
diff --git a/realm/realm_shared_data.c b/realm/realm_shared_data.c
index 2d09f78..2825796 100644
--- a/realm/realm_shared_data.c
+++ b/realm/realm_shared_data.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +8,7 @@
 #include <arch_helpers.h>
 #include <assert.h>
 #include <host_shared_data.h>
+#include <realm_def.h>
 
 /**
  *   @brief    - Returns the base address of the shared region
@@ -30,7 +31,7 @@
  */
 host_shared_data_t *realm_get_my_shared_structure(void)
 {
-	return &guest_shared_data[read_mpidr_el1() & MPID_MASK];
+	return &guest_shared_data[REC_IDX(read_mpidr_el1())];
 }
 
 /*
@@ -39,7 +40,7 @@
 u_register_t realm_shared_data_get_my_host_val(uint8_t index)
 {
 	assert(index < MAX_DATA_SIZE);
-	return guest_shared_data[read_mpidr_el1() & MPID_MASK].host_param_val[index];
+	return guest_shared_data[REC_IDX(read_mpidr_el1())].host_param_val[index];
 }
 
 /*
@@ -47,7 +48,7 @@
  */
 uint8_t realm_shared_data_get_my_realm_cmd(void)
 {
-	return guest_shared_data[read_mpidr_el1() & MPID_MASK].realm_cmd;
+	return guest_shared_data[REC_IDX(read_mpidr_el1())].realm_cmd;
 }
 
 /*
@@ -56,6 +57,6 @@
 void realm_shared_data_set_my_realm_val(uint8_t index, u_register_t val)
 {
 	assert(index < MAX_DATA_SIZE);
-	guest_shared_data[read_mpidr_el1() & MPID_MASK].realm_out_val[index] = val;
+	guest_shared_data[REC_IDX(read_mpidr_el1())].realm_out_val[index] = val;
 }
 
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c b/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c
index a99fcd5..80c83a5 100644
--- a/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c
+++ b/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -1039,9 +1039,10 @@
 		rec_params->pc = realm->par_base;
 		rec_params->flags = realm->rec_flag[i];
 
-		rec_params->mpidr = (u_register_t)i;
+		/* Convert REC index to RmiRecMpidr type */
+		rec_params->mpidr = RMI_REC_MPIDR((u_register_t)i);
 		rec_params->num_aux = realm->num_aux;
-		realm->mpidr[i] = (u_register_t)i;
+		realm->mpidr[i] = rec_params->mpidr;
 
 		/* Create REC  */
 		ret = host_rmi_rec_create(realm->rd, realm->rec[i],
@@ -1239,7 +1240,7 @@
 				re_enter_rec = true;
 				break;
 			case HOST_CALL_EXIT_PRINT_CMD:
-				realm_print_handler(realm, run->exit.gprs[0]);
+				realm_print_handler(realm, REC_IDX(run->exit.gprs[0]));
 				re_enter_rec = true;
 				break;
 			case HOST_CALL_EXIT_SUCCESS_CMD: