[PATCH 02/20] KVM: arm64: Propagate host stage-2 annotated entries on block split
Vincent Donnefort <[email protected]> Mon, 3 Aug 2026 11:08:46 +0100
| Newsgroups | dev.linux.lists.kvmarm,org.infradead.lists.linux-arm-kernel |
|---|---|
| Message-ID | <[email protected]> |
Propagate ownership refcounts for invalid stage-2 entries mapped on block split. This intends to allow splitting host stage-2 blocks while keeping existing page ownership and metadata annotations. Signed-off-by: Vincent Donnefort <[email protected]> diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c index 34f78a58cded..0ca157ecee64 100644 --- a/arch/arm64/kvm/hyp/pgtable.c +++ b/arch/arm64/kvm/hyp/pgtable.c @@ -1033,15 +1033,28 @@ static int stage2_map_walk_table_pre(const struct kvm_pgtable_visit_ctx *ctx, static void stage2_map_prefault_idmap(const struct kvm_pgtable_visit_ctx *ctx, kvm_pte_t *ptep) { kvm_pte_t block_pte = ctx->old; + bool counted, valid; u64 pa; int i; - if (!kvm_pte_valid(block_pte)) + counted = stage2_pte_is_counted(block_pte); + valid = kvm_pte_valid(block_pte); + + if (!valid && !counted) + return; + + /* + * Shared walks not supported: cannot rollback refcounts on break + * failure. + */ + if (counted && WARN_ON_ONCE(kvm_pgtable_walk_shared(ctx))) 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); + kvm_pte_t pte = valid ? + kvm_init_valid_leaf_pte(pa, block_pte, ctx->level + 1) : + block_pte; /* * Skip ptes in the range being modified by the caller if we're @@ -1053,8 +1066,11 @@ static void stage2_map_prefault_idmap(const struct kvm_pgtable_visit_ctx *ctx, k * that should happen very infrequently. */ if ((ctx->level < (KVM_PGTABLE_LAST_LEVEL - 1)) || - (pa < ctx->addr) || (pa >= ctx->end)) + (pa < ctx->addr) || (pa >= ctx->end)) { *ptep = pte; + if (counted) + ctx->mm_ops->get_page(ptep); + } } } -- 2.55.0.508.g3f0d502094-goog