]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: arm64: nv: Fully update VNCR fixmap state in kvm_translate_vncr()
authorOliver Upton <oupton@kernel.org>
Tue, 2 Jun 2026 23:54:47 +0000 (16:54 -0700)
committerMarc Zyngier <maz@kernel.org>
Wed, 3 Jun 2026 20:06:43 +0000 (21:06 +0100)
kvm_translate_vncr() first invalidates the pseudo-TLB entry and
corresponding fixmap in anticipation of installing a new translation.

While the fixmap invalidation does clear the mapping from host stage-1,
it does not clear the L1_VNCR_MAPPED flag. Depending on the state of the
VNCR TLB at vcpu_put(), this could potentially precipitate a BUG_ON() if
vt->cpu is reset.

Share a helper with kvm_vcpu_put_hw_mmu(), ensuring that KVM's view of
the VNCR fixmap is in sync with the state of the VNCR TLB. Give it a
slightly verbose name to make it obvious that it is meant to be used
local to a CPU, unlike other VNCR TLB maintenance.

Fixes: 069a05e535496 ("KVM: arm64: nv: Handle VNCR_EL2-triggered faults")
Signed-off-by: Oliver Upton <oupton@kernel.org>
Link: https://patch.msgid.link/20260602235450.103057-3-oupton@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/nested.c

index 4fa82e96454dd61287faf9331d477389e2091cd1..d0545144eaac6eb4b1d6a6843b38151596e588d8 100644 (file)
@@ -797,18 +797,24 @@ void kvm_vcpu_load_hw_mmu(struct kvm_vcpu *vcpu)
        }
 }
 
+static void this_cpu_reset_vncr_fixmap(struct kvm_vcpu *vcpu)
+{
+       if (!host_data_test_flag(L1_VNCR_MAPPED))
+               return;
+
+       BUG_ON(vcpu->arch.vncr_tlb->cpu != smp_processor_id());
+       BUG_ON(is_hyp_ctxt(vcpu));
+
+       clear_fixmap(vncr_fixmap(vcpu->arch.vncr_tlb->cpu));
+       vcpu->arch.vncr_tlb->cpu = -1;
+       host_data_clear_flag(L1_VNCR_MAPPED);
+       atomic_dec(&vcpu->kvm->arch.vncr_map_count);
+}
+
 void kvm_vcpu_put_hw_mmu(struct kvm_vcpu *vcpu)
 {
        /* Unconditionally drop the VNCR mapping if we have one */
-       if (host_data_test_flag(L1_VNCR_MAPPED)) {
-               BUG_ON(vcpu->arch.vncr_tlb->cpu != smp_processor_id());
-               BUG_ON(is_hyp_ctxt(vcpu));
-
-               clear_fixmap(vncr_fixmap(vcpu->arch.vncr_tlb->cpu));
-               vcpu->arch.vncr_tlb->cpu = -1;
-               host_data_clear_flag(L1_VNCR_MAPPED);
-               atomic_dec(&vcpu->kvm->arch.vncr_map_count);
-       }
+       this_cpu_reset_vncr_fixmap(vcpu);
 
        /*
         * Keep a reference on the associated stage-2 MMU if the vCPU is
@@ -1282,7 +1288,8 @@ static int kvm_translate_vncr(struct kvm_vcpu *vcpu, bool *is_gmem)
         * We also prepare the next walk wilst we're at it.
         */
        scoped_guard(write_lock, &vcpu->kvm->mmu_lock) {
-               invalidate_vncr(vt);
+               this_cpu_reset_vncr_fixmap(vcpu);
+               vt->valid = false;
 
                vt->wi = (struct s1_walk_info) {
                        .regime = TR_EL20,