Commit 1bc26cb9 authored by Sean Christopherson's avatar Sean Christopherson
Browse files

KVM: x86/mmu: Precisely invalidate MMU root_role during CPUID update



Set kvm_mmu_page_role.invalid to mark the various MMU root_roles invalid
during CPUID update in order to force a refresh, instead of zeroing out
the entire role.  This fixes a bug where kvm_mmu_free_roots() incorrectly
thinks a root is indirect, i.e. not a TDP MMU, due to "direct" being
zeroed, which in turn causes KVM to take mmu_lock for write instead of
read.

Note, paving over the entire role was largely unintentional, commit
7a458f0e ("KVM: x86/mmu: remove extended bits from mmu_role, rename
field") simply missed that "invalid" could be set.

Fixes: 576a15de ("KVM: x86/mmu: Free TDP MMU roots while holding mmy_lock for read")
Reported-by: default avatar <syzbot+dc308fcfcd53f987de73@syzkaller.appspotmail.com>
Closes: https://lore.kernel.org/all/0000000000009b38080614c49bdb@google.com
Cc: Phi Nguyen <phind.uet@gmail.com>
Link: https://lore.kernel.org/r/20240408231115.1387279-1-seanjc@google.com


Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
parent bb9dc859
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -5576,9 +5576,9 @@ void kvm_mmu_after_set_cpuid(struct kvm_vcpu *vcpu)
	 * that problem is swept under the rug; KVM's CPUID API is horrific and
	 * it's all but impossible to solve it without introducing a new API.
	 */
	vcpu->arch.root_mmu.root_role.word = 0;
	vcpu->arch.guest_mmu.root_role.word = 0;
	vcpu->arch.nested_mmu.root_role.word = 0;
	vcpu->arch.root_mmu.root_role.invalid = 1;
	vcpu->arch.guest_mmu.root_role.invalid = 1;
	vcpu->arch.nested_mmu.root_role.invalid = 1;
	vcpu->arch.root_mmu.cpu_role.ext.valid = 0;
	vcpu->arch.guest_mmu.cpu_role.ext.valid = 0;
	vcpu->arch.nested_mmu.cpu_role.ext.valid = 0;