KVM: x86: Force TLB flush on userspace changes to special registers
authorMichal Luczaj <mhal@rbox.co>
Mon, 14 Aug 2023 22:08:36 +0000 (00:08 +0200)
committerSean Christopherson <seanjc@google.com>
Wed, 27 Sep 2023 19:58:33 +0000 (12:58 -0700)
Userspace can directly modify the content of vCPU's CR0, CR3, and CR4 via
KVM_SYNC_X86_SREGS and KVM_SET_SREGS{,2}. Make sure that KVM flushes guest
TLB entries and paging-structure caches if a (partial) guest TLB flush is
architecturally required based on the CRn changes.  To keep things simple,
flush whenever KVM resets the MMU context, i.e. if any bits in CR0, CR3,
CR4, or EFER are modified.  This is extreme overkill, but stuffing state
from userspace is not such a hot path that preserving guest TLB state is a
priority.

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Michal Luczaj <mhal@rbox.co>
Link: https://lore.kernel.org/r/20230814222358.707877-3-mhal@rbox.co
[sean: call out that the flushing on MMU context resets is for simplicity]
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/x86.c

index d960d4094a0bf5e3e8e81aa2dd38b0ebb2f1d61e..ec728aef9acccfd428c690937b48dee0d97c3a36 100644 (file)
@@ -11564,8 +11564,10 @@ static int __set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
        if (ret)
                return ret;
 
-       if (mmu_reset_needed)
+       if (mmu_reset_needed) {
                kvm_mmu_reset_context(vcpu);
+               kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu);
+       }
 
        max_bits = KVM_NR_INTERRUPTS;
        pending_vec = find_first_bit(
@@ -11606,8 +11608,10 @@ static int __set_sregs2(struct kvm_vcpu *vcpu, struct kvm_sregs2 *sregs2)
                mmu_reset_needed = 1;
                vcpu->arch.pdptrs_from_userspace = true;
        }
-       if (mmu_reset_needed)
+       if (mmu_reset_needed) {
                kvm_mmu_reset_context(vcpu);
+               kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu);
+       }
        return 0;
 }