feat(realm): add support for RSI_IPA_STATE_GET/SET
Add support for realm API rsi_ipa_state_set, rsi_ipa_state_get
Add testcase for following
* Realm calls rsi_ipa_state_set to change RIPAS=RAM,
* Host accepts and call RMI_RTT_SET_RIPAS
* Realm verifies RIPAS change was successful
Change-Id: I4da6c7d25faa62afde1d0f682510bac6c8445821
Signed-off-by: Shruti Gupta <shruti.gupta@arm.com>
diff --git a/realm/include/realm_rsi.h b/realm/include/realm_rsi.h
index 547db0d..8436db9 100644
--- a/realm/include/realm_rsi.h
+++ b/realm/include/realm_rsi.h
@@ -100,6 +100,33 @@
* arg0 == struct rsi_realm_config address
*/
#define RSI_REALM_CONFIG SMC_RSI_FID(6U)
+#define RSI_IPA_STATE_SET SMC_RSI_FID(7U)
+#define RSI_IPA_STATE_GET SMC_RSI_FID(8U)
+
+typedef enum {
+ RSI_EMPTY = 0U,
+ RSI_RAM,
+ RSI_DESTROYED
+} rsi_ripas_type;
+
+typedef enum {
+ RSI_ACCEPT = 0U,
+ RSI_REJECT
+} rsi_ripas_respose_type;
+
+#define RSI_NO_CHANGE_DESTROYED 0UL
+#define RSI_CHANGE_DESTROYED 1UL
+
+/* Request RIPAS of a target IPA range to be changed to a specified value. */
+u_register_t rsi_ipa_state_set(u_register_t base,
+ u_register_t top,
+ rsi_ripas_type ripas,
+ u_register_t flag,
+ u_register_t *new_base,
+ rsi_ripas_respose_type *response);
+
+/* Request RIPAS of a target IPA */
+u_register_t rsi_ipa_state_get(u_register_t adr, rsi_ripas_type *ripas);
/* This function return RSI_ABI_VERSION */
u_register_t rsi_get_version(u_register_t req_ver);
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
index 563c643..9b2be83 100644
--- a/realm/realm_payload_main.c
+++ b/realm/realm_payload_main.c
@@ -20,7 +20,6 @@
static fpu_state_t rl_fpu_state_write;
static fpu_state_t rl_fpu_state_read;
-
/*
* This function reads sleep time in ms from shared buffer and spins PE
* in a loop for that time period.
@@ -61,6 +60,47 @@
return true;
}
+bool test_realm_set_ripas(void)
+{
+ u_register_t ret, base, new_base, top;
+ rsi_ripas_respose_type response;
+ rsi_ripas_type ripas;
+
+ base = realm_shared_data_get_my_host_val(HOST_ARG1_INDEX);
+ top = realm_shared_data_get_my_host_val(HOST_ARG2_INDEX);
+ realm_printf("base=0x%lx top =0x%lx\n", base, top);
+ ret = rsi_ipa_state_get(base, &ripas);
+ if (ripas != RSI_EMPTY) {
+ return false;
+ }
+
+ ret = rsi_ipa_state_set(base, top, RSI_RAM,
+ RSI_NO_CHANGE_DESTROYED, &new_base, &response);
+ if (ret != RSI_SUCCESS || response != RSI_ACCEPT) {
+ return false;
+ }
+ while (new_base < top) {
+ realm_printf("new_base=0x%lx top =0x%lx\n", new_base, top);
+ ret = rsi_ipa_state_set(new_base, top, RSI_RAM,
+ RSI_NO_CHANGE_DESTROYED, &new_base, &response);
+ if (ret != RSI_SUCCESS || response != RSI_ACCEPT) {
+ realm_printf("rsi_ipa_state_set failed\n");
+ return false;
+ }
+ }
+
+ /* Verify that RIAS has changed for range base-top. */
+ for (unsigned int i = 0U; (base + (PAGE_SIZE * i) < top); i++) {
+ ret = rsi_ipa_state_get(base + (PAGE_SIZE * i), &ripas);
+ if (ret != RSI_SUCCESS || ripas != RSI_RAM) {
+ realm_printf("rsi_ipa_state_get failed base=0x%lx, ripas=0x%x\n",
+ base + (PAGE_SIZE * i), ripas);
+ return false;
+ }
+ }
+ return true;
+}
+
/*
* 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,
@@ -122,6 +162,9 @@
test_succeed = !fpu_state_compare(&rl_fpu_state_write,
&rl_fpu_state_read);
break;
+ case REALM_SET_RIPAS_CMD:
+ test_succeed = test_realm_set_ripas();
+ break;
case REALM_SVE_RDVL:
test_succeed = test_realm_sve_rdvl();
break;
diff --git a/realm/realm_rsi.c b/realm/realm_rsi.c
index ba60ba8..04f57fc 100644
--- a/realm/realm_rsi.c
+++ b/realm/realm_rsi.c
@@ -51,3 +51,35 @@
tftf_smc(&(smc_args) {RSI_HOST_CALL, (u_register_t)&host_cal,
0UL, 0UL, 0UL, 0UL, 0UL, 0UL});
}
+
+/* This function will exit to the Host to request RIPAS CHANGE of IPA range */
+u_register_t rsi_ipa_state_set(u_register_t base,
+ u_register_t top,
+ rsi_ripas_type ripas,
+ u_register_t flag,
+ u_register_t *new_base,
+ rsi_ripas_respose_type *response)
+{
+ smc_ret_values res = {};
+
+ res = tftf_smc(&(smc_args)
+ {RSI_IPA_STATE_SET, base, top, ripas, flag});
+ if (res.ret0 == RSI_SUCCESS) {
+ *new_base = res.ret1;
+ *response = res.ret2;
+ }
+ return res.ret0;
+}
+
+/* This function will return RIPAS of IPA */
+u_register_t rsi_ipa_state_get(u_register_t adr, rsi_ripas_type *ripas)
+{
+ smc_ret_values res = {};
+
+ res = tftf_smc(&(smc_args)
+ {RSI_IPA_STATE_GET, adr});
+ if (res.ret0 == RSI_SUCCESS) {
+ *ripas = res.ret1;
+ }
+ return res.ret0;
+}