test(realm): add test for RSI_PLANE_REG_READ/WRITE command

test for RSI_PLANE_REG_READ/WRITE command

Signed-off-by: Shruti Gupta <shruti.gupta@arm.com>
Change-Id: I92e0aeef48c9b2abe26e5d3b2ea62669a22d4f8b
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index f4c1d87..90d4706 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -1705,4 +1705,72 @@
  ******************************************************************************/
 #define FPMR			S3_3_C4_C4_2
 
+/******************************************************************************
+ * Definitions of system register identifiers
+ *****************************************************************************/
+
+#define ESR_EL2_SYSREG_TRAP_OP0_SHIFT	20
+#define ESR_EL2_SYSREG_TRAP_OP0_WIDTH	U(2)
+
+#define ESR_EL2_SYSREG_TRAP_OP2_SHIFT	17
+#define ESR_EL2_SYSREG_TRAP_OP2_WIDTH	U(3)
+
+#define ESR_EL2_SYSREG_TRAP_OP1_SHIFT	14
+#define ESR_EL2_SYSREG_TRAP_OP1_WIDTH	U(3)
+
+#define ESR_EL2_SYSREG_TRAP_CRN_SHIFT	10
+#define ESR_EL2_SYSREG_TRAP_CRN_WIDTH	U(4)
+
+#define ESR_EL2_SYSREG_TRAP_CRM_SHIFT	1
+#define ESR_EL2_SYSREG_TRAP_CRM_WIDTH	U(4)
+
+#define SYSREG_ESR(op0, op1, crn, crm, op2) \
+		((UL(op0) << ESR_EL2_SYSREG_TRAP_OP0_SHIFT) | \
+		 (UL(op1) << ESR_EL2_SYSREG_TRAP_OP1_SHIFT) | \
+		 (UL(crn) << ESR_EL2_SYSREG_TRAP_CRN_SHIFT) | \
+		 (UL(crm) << ESR_EL2_SYSREG_TRAP_CRM_SHIFT) | \
+		 (UL(op2) << ESR_EL2_SYSREG_TRAP_OP2_SHIFT))
+
+#define SYSREG_ID_sp_el0			SYSREG_ESR(3, 0, 4, 1, 0)
+#define SYSREG_ID_sp_el1			SYSREG_ESR(3, 4, 4, 1, 0)
+#define SYSREG_ID_elr_el1			SYSREG_ESR(3, 0, 4, 0, 1)
+#define SYSREG_ID_spsr_el1			SYSREG_ESR(3, 0, 4, 0, 0)
+#define SYSREG_ID_pmcr_el0			SYSREG_ESR(3, 3, 9, 12, 0)
+#define SYSREG_ID_tpidrro_el0			SYSREG_ESR(3, 3, 13, 0, 3)
+#define SYSREG_ID_tpidr_el0			SYSREG_ESR(3, 3, 13, 0, 2)
+#define SYSREG_ID_csselr_el1			SYSREG_ESR(3, 2, 0, 0, 0)
+#define SYSREG_ID_sctlr_el1			SYSREG_ESR(3, 0, 1, 0, 0)
+#define SYSREG_ID_actlr_el1			SYSREG_ESR(3, 0, 1, 0, 1)
+#define SYSREG_ID_cpacr_el1			SYSREG_ESR(3, 0, 1, 0, 2)
+#define SYSREG_ID_zcr_el1			SYSREG_ESR(3, 0, 1, 2, 0)
+#define SYSREG_ID_ttbr0_el1			SYSREG_ESR(3, 0, 2, 0, 0)
+#define SYSREG_ID_ttbr1_el1			SYSREG_ESR(3, 0, 2, 0, 1)
+#define SYSREG_ID_tcr_el1			SYSREG_ESR(3, 0, 2, 0, 2)
+#define SYSREG_ID_esr_el1			SYSREG_ESR(3, 0, 5, 2, 0)
+#define SYSREG_ID_afsr0_el1			SYSREG_ESR(3, 0, 5, 1, 0)
+#define SYSREG_ID_afsr1_el1			SYSREG_ESR(3, 0, 5, 1, 1)
+#define SYSREG_ID_far_el1			SYSREG_ESR(3, 0, 6, 0, 0)
+#define SYSREG_ID_mair_el1			SYSREG_ESR(3, 0, 10, 2, 0)
+#define SYSREG_ID_vbar_el1			SYSREG_ESR(3, 0, 12, 0, 0)
+#define SYSREG_ID_contextidr_el1		SYSREG_ESR(3, 0, 13, 0, 1)
+#define SYSREG_ID_tpidr_el1			SYSREG_ESR(3, 0, 13, 0, 4)
+#define SYSREG_ID_amair_el1			SYSREG_ESR(3, 0, 10, 3, 0)
+#define SYSREG_ID_cntkctl_el1			SYSREG_ESR(3, 0, 14, 1, 0)
+#define SYSREG_ID_par_el1			SYSREG_ESR(3, 0, 7, 4, 0)
+#define SYSREG_ID_mdscr_el1			SYSREG_ESR(2, 0, 0, 2, 2)
+#define SYSREG_ID_mdccint_el1			SYSREG_ESR(2, 0, 0, 2, 0)
+#define SYSREG_ID_disr_el1			SYSREG_ESR(3, 0, 12, 1, 1)
+#define SYSREG_ID_mpam0_el1			SYSREG_ESR(3, 0, 10, 5, 1)
+#define SYSREG_ID_apiakeylo_el1			SYSREG_ESR(3, 0, 2,  1, 0)
+#define SYSREG_ID_apiakeyhi_el1			SYSREG_ESR(3, 0, 2,  1, 1)
+#define SYSREG_ID_apibkeylo_el1			SYSREG_ESR(3, 0, 2,  1, 2)
+#define SYSREG_ID_apibkeyhi_el1			SYSREG_ESR(3, 0, 2,  1, 3)
+#define SYSREG_ID_apdakeylo_el1			SYSREG_ESR(3, 0, 2,  2, 0)
+#define SYSREG_ID_apdakeyhi_el1			SYSREG_ESR(3, 0, 2,  2, 1)
+#define SYSREG_ID_apdbkeylo_el1			SYSREG_ESR(3, 0, 2,  2, 2)
+#define SYSREG_ID_apdbkeyhi_el1			SYSREG_ESR(3, 0, 2,  2, 3)
+#define SYSREG_ID_apgakeylo_el1			SYSREG_ESR(3, 0, 2,  3, 0)
+#define SYSREG_ID_apgakeyhi_el1			SYSREG_ESR(3, 0, 2,  3, 1)
+#define SYSREG_ID_mpamidr_el1			SYSREG_ESR(3, 0, 10, 4, 4)
+
 #endif /* ARCH_H */
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 05d22da..fecb27b 100644
--- a/include/runtime_services/host_realm_managment/host_shared_data.h
+++ b/include/runtime_services/host_realm_managment/host_shared_data.h
@@ -75,7 +75,8 @@
 	REALM_FEAT_DOUBLEFAULT2_TEST,
 	REALM_ATTESTATION,
 	REALM_ATTESTATION_FAULT,
-	REALM_ENTER_PLANE_N_CMD
+	REALM_ENTER_PLANE_N_CMD,
+	REALM_PLANE_N_REG_RW_CMD
 };
 
 /*
diff --git a/realm/include/realm_helpers.h b/realm/include/realm_helpers.h
index 9214564..7ed8f9b 100644
--- a/realm/include/realm_helpers.h
+++ b/realm/include/realm_helpers.h
@@ -34,6 +34,8 @@
 
 /* Function for initializing planes, called at Boot */
 void realm_plane_init(void);
+bool plane_common_init(u_register_t plane_index, u_register_t perm_index,
+		u_register_t base, rsi_plane_run *run);
 
 #endif /* REALM_HELPERS_H */
 
diff --git a/realm/include/realm_rsi.h b/realm/include/realm_rsi.h
index e72a769..06f857f 100644
--- a/realm/include/realm_rsi.h
+++ b/realm/include/realm_rsi.h
@@ -270,6 +270,12 @@
  */
 #define RSI_PLANE_REG_READ	SMC_RSI_FID(0x1EU)
 
+u_register_t rsi_plane_reg_read(u_register_t plane_index, u_register_t register_encoding,
+		u_register_t *value);
+
+u_register_t rsi_plane_reg_write(u_register_t plane_index, u_register_t register_encoding,
+		u_register_t value);
+
 /*
  * arg1 == plane index
  * arg2 == register encoding
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
index 4ad1b6c..aeadb9e 100644
--- a/realm/realm_payload_main.c
+++ b/realm/realm_payload_main.c
@@ -48,15 +48,102 @@
 static bool test_realm_enter_plane_n(void)
 {
 	u_register_t base, plane_index, perm_index, flags = 0U;
+	bool ret1;
 
 	plane_index = realm_shared_data_get_my_host_val(HOST_ARG1_INDEX);
 	base = realm_shared_data_get_my_host_val(HOST_ARG2_INDEX);
 	perm_index = plane_index + 1U;
 
+	ret1 = plane_common_init(plane_index, perm_index, base, &run);
+	if (!ret1) {
+		return ret1;
+	}
+
 	realm_printf("Entering plane %ld, ep=0x%lx run=0x%lx\n", plane_index, base, &run);
 	return realm_plane_enter(plane_index, perm_index, base, flags, &run);
 }
 
+static bool test_realm_enter_plane_n_reg_rw(void)
+{
+	u_register_t base, plane_index, perm_index, flags = 0U;
+	u_register_t reg1, reg2, reg3, reg4, ret;
+	bool ret1;
+
+	if (realm_is_plane0()) {
+		plane_index = realm_shared_data_get_my_host_val(HOST_ARG1_INDEX);
+		base = realm_shared_data_get_my_host_val(HOST_ARG2_INDEX);
+		perm_index = plane_index + 1U;
+
+		ret1 = plane_common_init(plane_index, perm_index, base, &run);
+		if (!ret1) {
+			return ret1;
+		}
+
+		realm_printf("Entering plane %ld, ep=0x%lx run=0x%lx\n", plane_index, base, &run);
+		ret = realm_plane_enter(plane_index, perm_index, base, flags, &run);
+		if (ret) {
+			/* get return value from plane1 */
+			reg1 = realm_shared_data_get_plane_n_val(plane_index,
+					REC_IDX(read_mpidr_el1()), HOST_ARG1_INDEX);
+
+			reg2 = realm_shared_data_get_plane_n_val(plane_index,
+					REC_IDX(read_mpidr_el1()), HOST_ARG2_INDEX);
+
+			realm_printf("P0 read 0x%lx 0x%lx\n", reg1, reg2);
+
+			/* read pauth register for plane1 */
+			ret = rsi_plane_reg_read(plane_index, SYSREG_ID_apiakeylo_el1, &reg3);
+			if ((ret != RSI_SUCCESS) || (reg1 != reg3)) {
+				realm_printf("pauth register mismatch 0x%lx 0x%lx\n", reg1, reg3);
+				return false;
+			}
+
+			/* read sctlr register for plane1 */
+			ret = rsi_plane_reg_read(plane_index, SYSREG_ID_sctlr_el1, &reg4);
+			if ((ret != RSI_SUCCESS) || (reg2 != reg4)) {
+				realm_printf("sctlr register mismatch 0x%lx 0x%lx\n", reg2, reg4);
+				return false;
+			}
+
+			/* write pauth register and verify it is same after exiting plane n */
+			ret = rsi_plane_reg_write(plane_index, SYSREG_ID_apibkeylo_el1, 0xABCD);
+			if (ret != RSI_SUCCESS) {
+				realm_printf("pauth register write failed\n");
+				return false;
+			}
+
+			/* enter plane n */
+			ret = realm_plane_enter(plane_index, perm_index, base, flags, &run);
+			if (ret) {
+				/* read pauth register for plane1 */
+				ret = rsi_plane_reg_read(plane_index, SYSREG_ID_apibkeylo_el1,
+						&reg3);
+
+				if ((ret != RSI_SUCCESS) || (reg3 != 0xABCD)) {
+					realm_printf("reg mismatch after write 0x%lx\n", reg3);
+					return false;
+				}
+			}
+
+			/* read sysreg not supported by rmm, expect error */
+			ret = rsi_plane_reg_read(plane_index, SYSREG_ID_mpamidr_el1, &reg3);
+			if (ret == RSI_SUCCESS) {
+				realm_printf("reg read should have failed\n");
+				return false;
+			}
+			return true;
+		}
+		return false;
+	} else {
+		realm_printf("PN set 0x%lx 0x%lx\n", read_apiakeylo_el1(), read_sctlr_el1());
+
+		/* return pauth and sctlr back to p0 */
+		realm_shared_data_set_my_realm_val(HOST_ARG1_INDEX, read_apiakeylo_el1());
+		realm_shared_data_set_my_realm_val(HOST_ARG2_INDEX, read_sctlr_el1());
+		return true;
+	}
+}
+
 /*
  * This function requests RSI/ABI version from RMM.
  */
@@ -300,6 +387,9 @@
 		case REALM_ENTER_PLANE_N_CMD:
 			test_succeed = test_realm_enter_plane_n();
 			break;
+		case REALM_PLANE_N_REG_RW_CMD:
+			test_succeed = test_realm_enter_plane_n_reg_rw();
+			break;
 		case REALM_MULTIPLE_REC_PSCI_DENIED_CMD:
 			test_succeed = test_realm_multiple_rec_psci_denied_cmd();
 			break;
diff --git a/realm/realm_plane.c b/realm/realm_plane.c
index 9a604c6..c7225ed 100644
--- a/realm/realm_plane.c
+++ b/realm/realm_plane.c
@@ -135,7 +135,7 @@
 	return PSI_RETURN_TO_P0;
 }
 
-static bool plane_common_init(u_register_t plane_index,
+bool plane_common_init(u_register_t plane_index,
 		u_register_t perm_index,
 		u_register_t base,
 		rsi_plane_run *run)
@@ -161,12 +161,6 @@
 		rsi_plane_run *run)
 {
 	u_register_t ret;
-	bool ret1;
-
-	ret1 = plane_common_init(plane_index, perm_index, base, run);
-	if (!ret1) {
-		return ret1;
-	}
 
 	run->enter.flags = flags;
 
diff --git a/realm/realm_rsi.c b/realm/realm_rsi.c
index b2505cc..4e223ca 100644
--- a/realm/realm_rsi.c
+++ b/realm/realm_rsi.c
@@ -199,3 +199,28 @@
 			{RSI_PLANE_ENTER, plane_index, plane_run});
 	return res.ret0;
 }
+
+u_register_t rsi_plane_reg_read(u_register_t plane_index,
+				u_register_t register_encoding,
+				u_register_t *value)
+{
+	smc_ret_values res = {};
+
+	res = tftf_smc(&(smc_args)
+			{RSI_PLANE_REG_READ, plane_index, register_encoding});
+	if (res.ret0 == RSI_SUCCESS) {
+		*value = res.ret1;
+	}
+	return res.ret0;
+}
+
+u_register_t rsi_plane_reg_write(u_register_t plane_index,
+				 u_register_t register_encoding,
+				 u_register_t value)
+{
+	smc_ret_values res = {};
+
+	res = tftf_smc(&(smc_args)
+			{RSI_PLANE_REG_WRITE, plane_index, register_encoding, value});
+	return res.ret0;
+}
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 f1ea9ef..0c7289a 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
@@ -50,6 +50,63 @@
 }
 
 /*
+ * @Test_Aim@ Test RSI_PLANE_REG_READ/WRITE
+ */
+test_result_t host_test_realm_create_planes_register_rw(void)
+{
+	bool ret1, ret2;
+	u_register_t rec_flag[MAX_REC_COUNT];
+	struct realm realm;
+	u_register_t feature_flag = 0UL;
+	long sl = RTT_MIN_LEVEL;
+	struct rmi_rec_run *run;
+
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+	if (!are_planes_supported()) {
+		return TEST_RESULT_SKIPPED;
+	}
+
+	if (is_feat_52b_on_4k_2_supported() == true) {
+		feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
+		sl = RTT_MIN_LEVEL_LPA2;
+	}
+
+	for (unsigned int i = 0U; i < MAX_REC_COUNT; i++) {
+		rec_flag[i] = RMI_RUNNABLE;
+	}
+
+	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
+			feature_flag, sl, rec_flag, 1U, 1U)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	/* CMD for Plane N */
+	host_shared_data_set_realm_cmd(&realm, REALM_PLANE_N_REG_RW_CMD, 1U, 0U);
+
+	run = (struct rmi_rec_run *)realm.run[0U];
+
+	host_realm_set_aux_plane_args(&realm, 1U);
+	ret1 = host_enter_realm_execute(&realm, REALM_PLANE_N_REG_RW_CMD,
+			RMI_EXIT_HOST_CALL, 0U);
+
+	if (run->exit.exit_reason != RMI_EXIT_HOST_CALL) {
+		ERROR("Rec0 error exit=0x%lx ret1=%d HPFAR=0x%lx \
+				esr=0x%lx far=0x%lx\n",
+				run->exit.exit_reason, ret1,
+				run->exit.hpfar,
+				run->exit.esr, run->exit.far);
+	}
+	ret2 = host_destroy_realm(&realm);
+
+	if (!ret1 || !ret2) {
+		ERROR("%s(): enter=%d destroy=%d\n",
+		__func__, ret1, ret2);
+		return TEST_RESULT_FAIL;
+	}
+	return host_cmp_result();
+}
+/*
  * @Test_Aim@ Test realm payload creation with 3 Aux Planes, enter all Planes
  * Host cannot enter Aux Planes directly,
  * Host will enter P0, P0 will enter aux plane
diff --git a/tftf/tests/tests-realm-payload.xml b/tftf/tests/tests-realm-payload.xml
index ea0d27c..7cc7866 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 Planes execution test"
 	  function="host_test_realm_create_planes_enter" />
+	  <testcase name="Realm Planes register read/write test"
+	  function="host_test_realm_create_planes_register_rw" />
 	  <testcase name="Realm EL1 creation and execution test"
 	  function="host_test_realm_create_enter" />
 	  <testcase name="Realm RTT fold unfold test Unassigned Empty"