test(realm): testcase for RMI_RTT_SET_RIPAS reject

Add testcase for realm to call rsi_ipa_state_set,
host will reject and call RMI_RTT_SET_RIPAS
re-enter rec with response RSI_REJECT

Change-Id: I6809fdabba580b23269aedc2aa844b15fbcce981
Signed-off-by: Shruti Gupta <shruti.gupta@arm.com>
diff --git a/include/runtime_services/host_realm_managment/host_realm_rmi.h b/include/runtime_services/host_realm_managment/host_realm_rmi.h
index 6f3f227..4f81042 100644
--- a/include/runtime_services/host_realm_managment/host_realm_rmi.h
+++ b/include/runtime_services/host_realm_managment/host_realm_rmi.h
@@ -411,6 +411,19 @@
 	}, 0x800, 0x1000);
 };
 
+/* Whether Host has completed emulation for an Emulatable Data Abort */
+#define REC_ENTRY_FLAG_EMUL_MMIO	(UL(1) << 0)
+
+/* Whether to inject a Synchronous External Abort into Realm */
+#define REC_ENTRY_FLAG_INJECT_SEA	(UL(1) << 1)
+
+/* Whether to trap WFI/WFE execution by Realm */
+#define REC_ENTRY_FLAG_TRAP_WFI		(UL(1) << 2)
+#define REC_ENTRY_FLAG_TRAP_WFE		(UL(1) << 3)
+
+/* Host response to RIPAS change request */
+#define REC_ENTRY_FLAG_RIPAS_RESPONSE_REJECT	(UL(1) << 4)
+
 /*
  * Structure contains data passed from the Host to the RMM on REC entry
  */
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 e674f46..57af48d 100644
--- a/include/runtime_services/host_realm_managment/host_shared_data.h
+++ b/include/runtime_services/host_realm_managment/host_shared_data.h
@@ -53,6 +53,7 @@
 	REALM_REQ_FPU_FILL_CMD,
 	REALM_REQ_FPU_CMP_CMD,
 	REALM_SET_RIPAS_CMD,
+	REALM_REJECT_SET_RIPAS_CMD,
 	REALM_SVE_RDVL,
 	REALM_SVE_ID_REGISTERS,
 	REALM_SVE_PROBE_VL,
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
index 9b2be83..5c488ee 100644
--- a/realm/realm_payload_main.c
+++ b/realm/realm_payload_main.c
@@ -101,6 +101,34 @@
 	return true;
 }
 
+bool test_realm_reject_set_ripas(void)
+{
+	u_register_t ret, base, new_base;
+	rsi_ripas_respose_type response;
+	rsi_ripas_type ripas;
+
+	base = realm_shared_data_get_my_host_val(HOST_ARG1_INDEX);
+	ret = rsi_ipa_state_get(base, &ripas);
+	if (ret != RSI_SUCCESS || ripas != RSI_EMPTY) {
+		realm_printf("Wrong initial ripas=0x%lx\n", ripas);
+		return false;
+	}
+	ret = rsi_ipa_state_set(base, base + PAGE_SIZE, RSI_RAM,
+		RSI_NO_CHANGE_DESTROYED, &new_base, &response);
+	if (ret == RSI_SUCCESS && response == RSI_REJECT) {
+		realm_printf("rsi_ipa_state_set passed response = %d\n", response);
+		ret = rsi_ipa_state_get(base, &ripas);
+		if (ret == RSI_SUCCESS && ripas == RSI_EMPTY) {
+			return true;
+		} else {
+			realm_printf("rsi_ipa_state_get failed ripas = %d\n", ripas);
+			return false;
+		}
+	}
+	realm_printf("rsi_ipa_state_set failed ret=0x%lx, response = %d\n", ret, response);
+	return false;
+}
+
 /*
  * This is the entry function for Realm payload, it first requests the shared buffer
  * IPA address from Host using HOST_CALL/RSI, it reads the command to be executed,
@@ -162,6 +190,9 @@
 			test_succeed = !fpu_state_compare(&rl_fpu_state_write,
 							  &rl_fpu_state_read);
 			break;
+		case REALM_REJECT_SET_RIPAS_CMD:
+			test_succeed = test_realm_reject_set_ripas();
+			break;
 		case REALM_SET_RIPAS_CMD:
 			test_succeed = test_realm_set_ripas();
 			break;
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 0fd65fd..1948c1f 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
@@ -513,3 +513,74 @@
 	page_free(base);
 	return host_call_result;
 }
+
+/*
+ * Test set_ripas reject functionality in Realm
+ * Test allocates PAGE and passes to Realm
+ * Realm: verifies that initial RIPAS of page is EMPTY
+ * Realm: requests RIPAS Change to RAM
+ * Host: changes rejects RIPAS change and enters Realm
+ * Realm: verifies REJECT response
+ * Realm: verifies PAGE  has RIPAS=EMPTY
+ */
+
+test_result_t host_realm_reject_set_ripas(void)
+{
+	bool ret1, ret2;
+	u_register_t ret, exit_reason;
+	unsigned int host_call_result = TEST_RESULT_FAIL;
+	struct realm realm;
+	struct rmi_rec_run *run;
+	u_register_t rec_flag[1] = {RMI_RUNNABLE}, base;
+
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
+			(u_register_t)PAGE_POOL_BASE,
+			(u_register_t)PAGE_POOL_MAX_SIZE,
+			0UL, rec_flag, 1U)) {
+		return TEST_RESULT_FAIL;
+	}
+	if (!host_create_shared_mem(&realm, NS_REALM_SHARED_MEM_BASE,
+			NS_REALM_SHARED_MEM_SIZE)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	base = (u_register_t)page_alloc(PAGE_SIZE);
+
+	ret = host_realm_map_protected_data(true, &realm, base, PAGE_SIZE, base);
+	if (ret != RMI_SUCCESS) {
+		ERROR("host_realm_map_protected_data failede\n");
+		goto destroy_realm;
+	}
+	host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base);
+	ret1 = host_enter_realm_execute(&realm, REALM_REJECT_SET_RIPAS_CMD,
+			RMI_EXIT_RIPAS_CHANGE, 0U);
+
+	if (!ret1) {
+		ERROR("Rec did not request RIPAS change\n");
+		goto destroy_realm;
+	}
+	run = (struct rmi_rec_run *)realm.run[0];
+	if (run->exit.ripas_base != base) {
+		ERROR("Rec requested wrong exit.ripas_base\n");
+		goto destroy_realm;
+	}
+	run->entry.flags = REC_ENTRY_FLAG_RIPAS_RESPONSE_REJECT;
+	ret = host_realm_rec_enter(&realm, &exit_reason, &host_call_result, 0U);
+	if (ret != RMI_SUCCESS || exit_reason != RMI_EXIT_HOST_CALL) {
+		ERROR("Re-enter rec failed exit_reason=0x%lx", exit_reason);
+	}
+
+destroy_realm:
+	ret2 = host_destroy_realm(&realm);
+
+	if (!ret2) {
+		ERROR("%s(): destroy=%d\n",
+		__func__, ret2);
+		return TEST_RESULT_FAIL;
+	}
+
+	return host_call_result;
+}
+
diff --git a/tftf/tests/tests-realm-payload.xml b/tftf/tests/tests-realm-payload.xml
index bcc72ec..dbd9cd5 100644
--- a/tftf/tests/tests-realm-payload.xml
+++ b/tftf/tests/tests-realm-payload.xml
@@ -44,6 +44,8 @@
 	  function="host_realm_fpu_access_in_rl_ns_se" />
 	  <testcase name="Realm request set_ripas"
 	  function="host_realm_set_ripas" />
+	  <testcase name="Realm reject set_ripas"
+	  function="host_realm_reject_set_ripas" />
 	  <!-- Test case related to SVE support and SIMD state -->
 	  <testcase name="Check RMI reports proper SVE VL"
 	  function="host_check_rmi_reports_proper_sve_vl" />