feat(rmm): modify API of RMI_RTT_INIT_RIPAS
This patch modifies API of RMI_RTT_INIT_RIPAS
command handler as per RMM Specification 1.0-eac1:
- 'base' and 'top' parameters are passed in arg1 and arg2.
- 'out_top' value is returned in X1.
Signed-off-by: AlexeiFedorov <Alexei.Fedorov@arm.com>
Change-Id: Ibcf6a20ecc1a991ca868928a240d3060cf74a45f
diff --git a/lib/measurement/include/measurement.h b/lib/measurement/include/measurement.h
index b20ff5e..417cfdd 100644
--- a/lib/measurement/include/measurement.h
+++ b/lib/measurement/include/measurement.h
@@ -100,18 +100,18 @@
SET_MEMBER(unsigned long len, 0x8, 0x10);
/* Current RIM value */
SET_MEMBER(unsigned char rim[MAX_MEASUREMENT_SIZE], 0x10, 0x50);
- /* IPA at which the RIPAS change occurred */
- SET_MEMBER(unsigned long ipa, 0x50, 0x58);
- /* RTT level at which the RIPAS change occurred */
- SET_MEMBER(unsigned char level, 0x58, 0x100);
+ /* Base IPA at which the RIPAS change occurred */
+ SET_MEMBER(unsigned long base, 0x50, 0x58);
+ /* Top IPA at which the RIPAS change occurred */
+ SET_MEMBER(unsigned char top, 0x58, 0x100);
};
COMPILER_ASSERT(sizeof(struct measurement_desc_ripas) == 0x100);
COMPILER_ASSERT(offsetof(struct measurement_desc_ripas, desc_type) == 0x0);
COMPILER_ASSERT(offsetof(struct measurement_desc_ripas, len) == 0x8);
COMPILER_ASSERT(offsetof(struct measurement_desc_ripas, rim) == 0x10);
-COMPILER_ASSERT(offsetof(struct measurement_desc_ripas, ipa) == 0x50);
-COMPILER_ASSERT(offsetof(struct measurement_desc_ripas, level) == 0x58);
+COMPILER_ASSERT(offsetof(struct measurement_desc_ripas, base) == 0x50);
+COMPILER_ASSERT(offsetof(struct measurement_desc_ripas, top) == 0x58);
/*
* Calculate the hash of data with algorithm hash_algo to the buffer `out`.
diff --git a/lib/smc/include/smc-rmi.h b/lib/smc/include/smc-rmi.h
index 731ad44..c798378 100644
--- a/lib/smc/include/smc-rmi.h
+++ b/lib/smc/include/smc-rmi.h
@@ -312,8 +312,11 @@
/*
* arg0 == RD address
- * arg1 == map address
- * arg2 == level
+ * arg1 == start address
+ * arg2 == end address
+ *
+ * ret1 == Top of the address range where the RIPAS was updated,
+ * if ret0 == RMI_SUCCESS
*/
#define SMC_RMM_RTT_INIT_RIPAS SMC64_RMI_FID(U(0x18))
diff --git a/plat/host/common/include/host_rmi_wrappers.h b/plat/host/common/include/host_rmi_wrappers.h
index d97e65c..f95d307 100644
--- a/plat/host/common/include/host_rmi_wrappers.h
+++ b/plat/host/common/include/host_rmi_wrappers.h
@@ -26,7 +26,7 @@
uintptr_t src, struct smc_result *ret);
void host_rmi_data_create_unknown(void *rd, uintptr_t data, uintptr_t ipa,
struct smc_result *ret);
-void host_rmi_rtt_init_ripas(void *rd, uintptr_t ipa, int64_t level,
+void host_rmi_rtt_init_ripas(void *rd, uintptr_t base, uintptr_t top,
struct smc_result *ret);
void host_rmi_data_destroy(void *rd, uintptr_t ipa, struct smc_result *ret);
diff --git a/plat/host/common/src/host_rmi_wrappers.c b/plat/host/common/src/host_rmi_wrappers.c
index e1ecb2e..131744c 100644
--- a/plat/host/common/src/host_rmi_wrappers.c
+++ b/plat/host/common/src/host_rmi_wrappers.c
@@ -133,12 +133,12 @@
ret);
}
-void host_rmi_rtt_init_ripas(void *rd, uintptr_t ipa, int64_t level,
+void host_rmi_rtt_init_ripas(void *rd, uintptr_t base, uintptr_t top,
struct smc_result *ret)
{
handle_ns_smc(SMC_RMM_RTT_INIT_RIPAS,
(uintptr_t)rd,
- ipa, level,
+ base, top,
0, 0, 0,
ret);
}
diff --git a/plat/host/host_build/src/host_setup.c b/plat/host/host_build/src/host_setup.c
index 4cfb51c..ef16e94 100644
--- a/plat/host/host_build/src/host_setup.c
+++ b/plat/host/host_build/src/host_setup.c
@@ -173,7 +173,9 @@
host_rmi_granule_delegate((void *)realm_buffer, &result);
CHECK_RMI_RESULT();
- host_rmi_rtt_init_ripas(rd, REALM_BUFFER_IPA, 3, &result);
+ host_rmi_rtt_init_ripas(rd, REALM_BUFFER_IPA,
+ REALM_BUFFER_IPA + GRANULE_SIZE,
+ &result);
CHECK_RMI_RESULT();
host_rmi_data_create_unknown(rd, realm_buffer, REALM_BUFFER_IPA, &result);
diff --git a/runtime/core/handler.c b/runtime/core/handler.c
index e4c0e1a..cd007ff 100644
--- a/runtime/core/handler.c
+++ b/runtime/core/handler.c
@@ -146,7 +146,7 @@
HANDLER(RTT_READ_ENTRY, 3, 4, smc_rtt_read_entry, false, true),
HANDLER(PSCI_COMPLETE, 2, 0, smc_psci_complete, true, true),
HANDLER(REC_AUX_COUNT, 1, 1, smc_rec_aux_count, true, true),
- HANDLER(RTT_INIT_RIPAS, 3, 0, smc_rtt_init_ripas, false, true),
+ HANDLER(RTT_INIT_RIPAS, 3, 1, smc_rtt_init_ripas, false, true),
HANDLER(RTT_SET_RIPAS, 4, 1, smc_rtt_set_ripas, false, true)
};
diff --git a/runtime/include/smc-handler.h b/runtime/include/smc-handler.h
index 460b9f4..fb42e6b 100644
--- a/runtime/include/smc-handler.h
+++ b/runtime/include/smc-handler.h
@@ -83,9 +83,10 @@
unsigned long smc_psci_complete(unsigned long calling_rec_addr,
unsigned long target_rec_addr);
-unsigned long smc_rtt_init_ripas(unsigned long rd_addr,
- unsigned long map_addr,
- unsigned long ulevel);
+void smc_rtt_init_ripas(unsigned long rd_addr,
+ unsigned long base,
+ unsigned long top,
+ struct smc_result *res);
void smc_rtt_set_ripas(unsigned long rd_addr,
unsigned long rec_addr,
diff --git a/runtime/rmi/rtt.c b/runtime/rmi/rtt.c
index f669cc5..a94d814 100644
--- a/runtime/rmi/rtt.c
+++ b/runtime/rmi/rtt.c
@@ -1088,16 +1088,16 @@
}
static void ripas_granule_measure(struct rd *rd,
- unsigned long ipa,
- unsigned long level)
+ unsigned long base,
+ unsigned long top)
{
struct measurement_desc_ripas measure_desc = {0};
/* Initialize the measurement descriptior structure */
measure_desc.desc_type = MEASURE_DESC_TYPE_RIPAS;
measure_desc.len = sizeof(struct measurement_desc_ripas);
- measure_desc.ipa = ipa;
- measure_desc.level = level;
+ measure_desc.base = base;
+ measure_desc.top = top;
(void)memcpy(measure_desc.rim,
&rd->measurement[RIM_MEASUREMENT_SLOT],
measurement_get_size(rd->algorithm));
@@ -1112,22 +1112,24 @@
rd->measurement[RIM_MEASUREMENT_SLOT]);
}
-unsigned long smc_rtt_init_ripas(unsigned long rd_addr,
- unsigned long map_addr,
- unsigned long ulevel)
+void smc_rtt_init_ripas(unsigned long rd_addr,
+ unsigned long base,
+ unsigned long top,
+ struct smc_result *res)
{
struct granule *g_rd, *g_rtt_root;
struct rd *rd;
- unsigned long ipa_bits;
+ unsigned long ipa_bits, addr, map_size;
struct rtt_walk wi;
unsigned long s2tte, *s2tt;
- unsigned long ret;
- long level = (long)ulevel;
+ long level;
+ unsigned int index;
int sl;
g_rd = find_lock_granule(rd_addr, GRANULE_STATE_RD);
if (g_rd == NULL) {
- return RMI_ERROR_INPUT;
+ res->x[0] = RMI_ERROR_INPUT;
+ return;
}
rd = granule_map(g_rd, SLOT_RD);
@@ -1135,19 +1137,23 @@
if (get_rd_state_locked(rd) != REALM_STATE_NEW) {
buffer_unmap(rd);
granule_unlock(g_rd);
- return RMI_ERROR_REALM;
+ res->x[0] = RMI_ERROR_REALM;
+ return;
}
- if (!validate_rtt_entry_cmds(map_addr, level, rd)) {
+ if (!validate_map_addr(base, RTT_PAGE_LEVEL, rd) ||
+ !validate_rtt_entry_cmds(top, RTT_PAGE_LEVEL, rd)) {
buffer_unmap(rd);
granule_unlock(g_rd);
- return RMI_ERROR_INPUT;
+ res->x[0] = RMI_ERROR_INPUT;
+ return;
}
- if (!addr_in_par(rd, map_addr)) {
+ if (!addr_in_par(rd, base) || !addr_in_par(rd, top)) {
buffer_unmap(rd);
granule_unlock(g_rd);
- return RMI_ERROR_INPUT;
+ res->x[0] = RMI_ERROR_INPUT;
+ return;
}
g_rtt_root = rd->s2_ctx.g_rtt;
@@ -1158,35 +1164,52 @@
granule_unlock(g_rd);
rtt_walk_lock_unlock(g_rtt_root, sl, ipa_bits,
- map_addr, level, &wi);
-
- if (wi.last_level != level) {
- ret = pack_return_code(RMI_ERROR_RTT, wi.last_level);
- goto out_unlock_llt;
- }
-
+ base, RTT_PAGE_LEVEL, &wi);
+ level = wi.last_level;
s2tt = granule_map(wi.g_llt, SLOT_RTT);
- s2tte = s2tte_read(&s2tt[wi.index]);
+ map_size = s2tte_map_size(level);
+ addr = base & ~(map_size - 1UL);
- if (s2tte_is_unassigned_empty(s2tte)) {
- s2tte = s2tte_create_unassigned_ram();
- s2tte_write(&s2tt[wi.index], s2tte);
- ripas_granule_measure(rd, map_addr, level);
- } else if (s2tte_is_unassigned_ram(s2tte)) {
- ripas_granule_measure(rd, map_addr, level);
- } else {
- ret = pack_return_code(RMI_ERROR_RTT, level);
+ /*
+ * If the RTTE covers a range below "base", we need to
+ * go deeper.
+ */
+ if (addr != base) {
+ res->x[0] = pack_return_code(RMI_ERROR_RTT,
+ (unsigned int)level);
goto out_unmap_llt;
}
- ret = RMI_SUCCESS;
+ for (index = wi.index; index < S2TTES_PER_S2TT;
+ index++, addr += map_size) {
+ unsigned long next = addr + map_size;
+
+ if (next > top) {
+ break;
+ }
+
+ s2tte = s2tte_read(&s2tt[index]);
+ if (s2tte_is_unassigned_empty(s2tte)) {
+ s2tte = s2tte_create_unassigned_ram();
+ s2tte_write(&s2tt[index], s2tte);
+ } else if (!s2tte_is_unassigned_ram(s2tte)) {
+ break;
+ }
+ ripas_granule_measure(rd, addr, next);
+ }
+
+ if (addr > base) {
+ res->x[0] = RMI_SUCCESS;
+ res->x[1] = addr;
+ } else {
+ res->x[0] = pack_return_code(RMI_ERROR_RTT,
+ (unsigned int)level);
+ }
out_unmap_llt:
buffer_unmap(s2tt);
-out_unlock_llt:
buffer_unmap(rd);
granule_unlock(wi.g_llt);
- return ret;
}
static void rtt_set_ripas_range(struct realm_s2_context *s2_ctx,