The RMM owns the stage 2 page tables for a realm, and KVM must request
that the RMM creates/destroys entries as necessary. The physical pages
to store the page tables are delegated to the realm as required, and can
be undelegated when no longer used.
Creating new RTTs is the easy part, tearing down is a little more
tricky. The result of realm_rtt_destroy() can be used to effectively
walk the tree and destroy the entries (undelegating pages that were
given to the realm).
Signed-off-by: Steven Price <steven.price@xxxxxxx>
Reviewed-by: Suzuki K Poulose <suzuki.poulose@xxxxxxx>
Reviewed-by: Gavin Shan <gshan@xxxxxxxxxx>
diff --git a/arch/arm64/kvm/rme.c b/arch/arm64/kvm/rme.c
index 73261b39f556..0f89295fa59c 100644
--- a/arch/arm64/kvm/rme.c
+++ b/arch/arm64/kvm/rme.c
@@ -17,6 +17,22 @@ static unsigned long rmm_feat_reg0;
#define RMM_PAGE_SHIFT 12
#define RMM_PAGE_SIZE BIT(RMM_PAGE_SHIFT)
+#define RMM_RTT_BLOCK_LEVEL 2
+#define RMM_RTT_MAX_LEVEL 3
+
+/* See ARM64_HW_PGTABLE_LEVEL_SHIFT() */
+#define RMM_RTT_LEVEL_SHIFT(l) \
+ ((RMM_PAGE_SHIFT - 3) * (4 - (l)) + 3)
+#define RMM_L2_BLOCK_SIZE BIT(RMM_RTT_LEVEL_SHIFT(2))
+
+static inline unsigned long rme_rtt_level_mapsize(int level)
+{
+ if (WARN_ON(level > RMM_RTT_MAX_LEVEL))
+ return RMM_PAGE_SIZE;
+
+ return (1UL << RMM_RTT_LEVEL_SHIFT(level));
+}
+
static bool rme_has_feature(unsigned long feature)
{
return !!u64_get_bits(rmm_feat_reg0, feature);
@@ -82,6 +98,126 @@ static int free_delegated_granule(phys_addr_t phys)
return 0;
}
+static void free_rtt(phys_addr_t phys)
+{
+ if (free_delegated_granule(phys))
+ return;
+
+ kvm_account_pgtable_pages(phys_to_virt(phys), -1);
+}
+
+static int realm_rtt_destroy(struct realm *realm, unsigned long addr,
+ int level, phys_addr_t *rtt_granule,
+ unsigned long *next_addr)
+{
+ unsigned long out_rtt;
+ int ret;
+
+ ret = rmi_rtt_destroy(virt_to_phys(realm->rd), addr, level,
+ &out_rtt, next_addr);
+
+ *rtt_granule = out_rtt;
+
+ return ret;
+
+static int realm_tear_down_rtt_range(struct realm *realm,
+ unsigned long start, unsigned long end)
+{