feat(rme): test access outside PAR from Plane N

Signed-off-by: Javier Almansa Sobrino <javier.almansasobrino@arm.com>
Change-Id: I3c5069e14fdf27e6c36bd1e0651ceff4ee7396ef
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
index 70687f1..248d191 100644
--- a/realm/realm_payload_main.c
+++ b/realm/realm_payload_main.c
@@ -336,6 +336,29 @@
 	return false;
 }
 
+static bool test_realm_plane_n_inst_fetch(void)
+{
+	u_register_t esr, far, test_ipa;
+
+	bool ret = test_realm_enter_plane_n();
+
+	if (!ret) {
+		ERROR("Failed to enter Plane N\n");
+		return false;
+	}
+
+	esr = run.exit.esr;
+	far = run.exit.far;
+	test_ipa = realm_shared_data_get_my_host_val(HOST_ARG2_INDEX);
+
+	if ((EC_BITS(esr) != EC_IABORT_LOWER_EL) || (far != test_ipa)) {
+		ERROR("Plane N: incorrect ESR=0x%lx FAR=0x%lx\n", esr, far);
+		return false;
+	}
+
+	return true;
+}
+
 static bool realm_exception_handler(void)
 {
 	u_register_t base, far, esr, elr;
@@ -348,11 +371,24 @@
 	if (far == base) {
 		/* Return ESR to Host */
 		realm_shared_data_set_my_realm_val(HOST_ARG2_INDEX, esr);
-		rsi_exit_to_host(HOST_CALL_EXIT_SUCCESS_CMD);
+		if (realm_is_plane0()) {
+			rsi_exit_to_host(HOST_CALL_EXIT_SUCCESS_CMD);
+		} else {
+			realm_shared_data_set_my_realm_val(HOST_ARG3_INDEX, far);
+			psi_exit_to_plane0(PSI_CALL_EXIT_SUCCESS_CMD,
+					0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
+		}
 	}
+
 	realm_printf("Realm Abort fail incorrect FAR=0x%lx ESR=0x%lx ELR=0x%lx\n",
 			far, esr, elr);
-	rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
+
+	if (realm_is_plane0()) {
+		rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
+	} else {
+		psi_exit_to_plane0(PSI_CALL_EXIT_FAILED_CMD,
+				0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
+	}
 
 	/* Should not return */
 	return false;
@@ -558,6 +594,9 @@
 		case REALM_WRITE_BRBCR_EL1:
 			test_succeed = test_realm_write_brbcr_el1_reg();
 			break;
+		case REALM_PLANE_N_INST_FETCH_ABORT:
+			test_succeed = test_realm_plane_n_inst_fetch();
+			break;
 		default:
 			realm_printf("%s() invalid cmd %u\n", __func__, cmd);
 			break;
diff --git a/realm/realm_plane.c b/realm/realm_plane.c
index 656c688..a29a1ca 100644
--- a/realm/realm_plane.c
+++ b/realm/realm_plane.c
@@ -150,6 +150,10 @@
 			ret = realm_exit_to_host_as_plane_n(HOST_CALL_EXIT_PRINT_CMD, plane_index);
 			run->enter.gprs[0] = ret;
 			return PSI_RETURN_TO_PN;
+		case PSI_CALL_EXIT_SUCCESS_CMD:
+		case PSI_CALL_EXIT_FAILED_CMD:
+			run->exit.gprs[0] = hvc_id;
+			return PSI_RETURN_TO_P0;
 		case PSI_P0_CALL:
 		default:
 			return PSI_RETURN_TO_P0;
@@ -207,8 +211,8 @@
 
 		ret = handle_plane_exit(plane_index, perm_index, run);
 
-		if (ret != PSI_RETURN_TO_PN) {
-			return true;
+		if (ret == PSI_RETURN_TO_P0) {
+			return !(run->exit.gprs[0] == PSI_CALL_EXIT_FAILED_CMD);
 		}
 	}
 }