]> www.infradead.org Git - nvme.git/commitdiff
KVM: arm64: Avoid BBM when changing only s/w bits in Stage-2 PTE
authorWill Deacon <will@kernel.org>
Tue, 23 Apr 2024 15:05:16 +0000 (16:05 +0100)
committerMarc Zyngier <maz@kernel.org>
Wed, 1 May 2024 15:46:58 +0000 (16:46 +0100)
Break-before-make (BBM) can be expensive, as transitioning via an
invalid mapping (i.e. the "break" step) requires the completion of TLB
invalidation and can also cause other agents to fault concurrently on
the invalid mapping.

Since BBM is not required when changing only the software bits of a PTE,
avoid the sequence in this case and just update the PTE directly.

Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Fuad Tabba <tabba@google.com>
Acked-by: Oliver Upton <oliver.upton@linux.dev>
Link: https://lore.kernel.org/r/20240423150538.2103045-9-tabba@google.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/hyp/pgtable.c

index da54bb31291069f6be450b05aa20aff9cb471ba5..d177a9f7a0977cad41e14a889dca68fea4de3550 100644 (file)
@@ -972,6 +972,21 @@ static int stage2_map_walker_try_leaf(const struct kvm_pgtable_visit_ctx *ctx,
        if (!stage2_pte_needs_update(ctx->old, new))
                return -EAGAIN;
 
+       /* If we're only changing software bits, then store them and go! */
+       if (!kvm_pgtable_walk_shared(ctx) &&
+           !((ctx->old ^ new) & ~KVM_PTE_LEAF_ATTR_HI_SW)) {
+               bool old_is_counted = stage2_pte_is_counted(ctx->old);
+
+               if (old_is_counted != stage2_pte_is_counted(new)) {
+                       if (old_is_counted)
+                               mm_ops->put_page(ctx->ptep);
+                       else
+                               mm_ops->get_page(ctx->ptep);
+               }
+               WARN_ON_ONCE(!stage2_try_set_pte(ctx, new));
+               return 0;
+       }
+
        if (!stage2_try_break_pte(ctx, data->mmu))
                return -EAGAIN;