]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: arm64: Always invalidate TLB for stage-2 permission faults
authorOliver Upton <oliver.upton@linux.dev>
Fri, 22 Sep 2023 22:32:29 +0000 (22:32 +0000)
committerOliver Upton <oliver.upton@linux.dev>
Mon, 30 Oct 2023 20:12:46 +0000 (20:12 +0000)
It is possible for multiple vCPUs to fault on the same IPA and attempt
to resolve the fault. One of the page table walks will actually update
the PTE and the rest will return -EAGAIN per our race detection scheme.
KVM elides the TLB invalidation on the racing threads as the return
value is nonzero.

Before commit a12ab1378a88 ("KVM: arm64: Use local TLBI on permission
relaxation") KVM always used broadcast TLB invalidations when handling
permission faults, which had the convenient property of making the
stage-2 updates visible to all CPUs in the system. However now we do a
local invalidation, and TLBI elision leads to the vCPU thread faulting
again on the stale entry. Remember that the architecture permits the TLB
to cache translations that precipitate a permission fault.

Invalidate the TLB entry responsible for the permission fault if the
stage-2 descriptor has been relaxed, regardless of which thread actually
did the job.

Acked-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20230922223229.1608155-1-oliver.upton@linux.dev
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/kvm/hyp/pgtable.c

index f155b8c9e98c7fbf1298f4ecf64c6826c76fdb23..28688875179327f27530448f282f87c8c66171a3 100644 (file)
@@ -1314,7 +1314,7 @@ int kvm_pgtable_stage2_relax_perms(struct kvm_pgtable *pgt, u64 addr,
        ret = stage2_update_leaf_attrs(pgt, addr, 1, set, clr, NULL, &level,
                                       KVM_PGTABLE_WALK_HANDLE_FAULT |
                                       KVM_PGTABLE_WALK_SHARED);
-       if (!ret)
+       if (!ret || ret == -EAGAIN)
                kvm_call_hyp(__kvm_tlb_flush_vmid_ipa_nsh, pgt->mmu, addr, level);
        return ret;
 }