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,