[PATCH 01/20] KVM: arm64: Prefault host stage-2 entries on block split
Vincent Donnefort
vdonnefort at google.com
Mon Aug 3 03:08:45 PDT 2026
From: Keir Fraser <keirf at google.com>
For the host stage-2 that is idmap, we can avoid lazy-mapping on block
splitting by propagate existing valid mappings to neighbouring entries
of the new table.
Co-developed-by: Quentin Perret <qperret at google.com>
Signed-off-by: Keir Fraser <keirf at google.com>
Signed-off-by: Vincent Donnefort <vdonnefort at google.com>
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index b74dd5ce1efd..34f78a58cded 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -1030,10 +1030,39 @@ static int stage2_map_walk_table_pre(const struct kvm_pgtable_visit_ctx *ctx,
return 0;
}
+static void stage2_map_prefault_idmap(const struct kvm_pgtable_visit_ctx *ctx, kvm_pte_t *ptep)
+{
+ kvm_pte_t block_pte = ctx->old;
+ u64 pa;
+ int i;
+
+ if (!kvm_pte_valid(block_pte))
+ return;
+
+ pa = ALIGN_DOWN(ctx->addr, kvm_granule_size(ctx->level));
+ for (i = 0; i < PTRS_PER_PTE; ++i, ++ptep, pa += kvm_granule_size(ctx->level + 1)) {
+ kvm_pte_t pte = kvm_init_valid_leaf_pte(pa, block_pte, ctx->level + 1);
+
+ /*
+ * Skip ptes in the range being modified by the caller if we're
+ * installing last level entries. Otherwise, we need to
+ * temporarily put in a valid mapping to make sure the
+ * prefaulting logic is triggered on the next
+ * stage2_map_walk_leaf(). This adds an unnecessary TLBI as
+ * we'll presumably re-break the freshly installed block, but
+ * that should happen very infrequently.
+ */
+ if ((ctx->level < (KVM_PGTABLE_LAST_LEVEL - 1)) ||
+ (pa < ctx->addr) || (pa >= ctx->end))
+ *ptep = pte;
+ }
+}
+
static int stage2_map_walk_leaf(const struct kvm_pgtable_visit_ctx *ctx,
struct stage2_map_data *data)
{
struct kvm_pgtable_mm_ops *mm_ops = ctx->mm_ops;
+ struct kvm_pgtable *pgt = data->mmu->pgt;
kvm_pte_t *childp, new;
int ret;
@@ -1051,6 +1080,9 @@ static int stage2_map_walk_leaf(const struct kvm_pgtable_visit_ctx *ctx,
if (!childp)
return -ENOMEM;
+ if (pgt->flags & KVM_PGTABLE_S2_IDMAP)
+ stage2_map_prefault_idmap(ctx, childp);
+
if (!stage2_try_break_pte(ctx, data->mmu)) {
mm_ops->put_page(childp);
return -EAGAIN;
--
2.55.0.508.g3f0d502094-goog
More information about the linux-arm-kernel
mailing list