linux/arch/x86/kvm
Sean Christopherson 0aa1837533 KVM: x86: Properly reset MMU context at vCPU RESET/INIT
Reset the MMU context at vCPU INIT (and RESET for good measure) if CR0.PG
was set prior to INIT.  Simply re-initializing the current MMU is not
sufficient as the current root HPA may not be usable in the new context.
E.g. if TDP is disabled and INIT arrives while the vCPU is in long mode,
KVM will fail to switch to the 32-bit pae_root and bomb on the next
VM-Enter due to running with a 64-bit CR3 in 32-bit mode.

This bug was papered over in both VMX and SVM, but still managed to rear
its head in the MMU role on VMX.  Because EFER.LMA=1 requires CR0.PG=1,
kvm_calc_shadow_mmu_root_page_role() checks for EFER.LMA without first
checking CR0.PG.  VMX's RESET/INIT flow writes CR0 before EFER, and so
an INIT with the vCPU in 64-bit mode will cause the hack-a-fix to
generate the wrong MMU role.

In VMX, the INIT issue is specific to running without unrestricted guest
since unrestricted guest is available if and only if EPT is enabled.
Commit 8668a3c468 ("KVM: VMX: Reset mmu context when entering real
mode") resolved the issue by forcing a reset when entering emulated real
mode.

In SVM, commit ebae871a50 ("kvm: svm: reset mmu on VCPU reset") forced
a MMU reset on every INIT to workaround the flaw in common x86.  Note, at
the time the bug was fixed, the SVM problem was exacerbated by a complete
lack of a CR4 update.

The vendor resets will be reverted in future patches, primarily to aid
bisection in case there are non-INIT flows that rely on the existing VMX
logic.

Because CR0.PG is unconditionally cleared on INIT, and because CR0.WP and
all CR4/EFER paging bits are ignored if CR0.PG=0, simply checking that
CR0.PG was '1' prior to INIT/RESET is sufficient to detect a required MMU
context reset.

Cc: stable@vger.kernel.org
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20210622175739.3610207-4-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2021-06-24 18:00:35 -04:00
..
mmu KVM: x86/mmu: Treat NX as used (not reserved) for all !TDP shadow MMUs 2021-06-24 18:00:35 -04:00
svm KVM: x86: Print CPU of last attempted VM-entry when dumping VMCS/VMCB 2021-06-24 04:31:13 -04:00
vmx KVM: nVMX: Handle split-lock #AC exceptions that happen in L2 2021-06-24 04:31:16 -04:00
cpuid.c KVM: x86: Fix fall-through warnings for Clang 2021-06-10 07:48:45 -04:00
cpuid.h KVM: x86: Move reverse CPUID helpers to separate header file 2021-04-26 05:27:13 -04:00
debugfs.c KVM: nVMX: nSVM: Add a new VCPU statistic to show if VCPU is in guest mode 2021-06-17 13:09:36 -04:00
emulate.c KVM: x86: Drop "pre_" from enter/leave_smm() helpers 2021-06-17 13:09:35 -04:00
fpu.h KVM: x86: Move FPU register accessors into fpu.h 2021-06-17 13:09:24 -04:00
hyperv.c KVM: nVMX: Sync all PGDs on nested transition with shadow paging 2021-06-17 13:09:51 -04:00
hyperv.h KVM: x86: hyper-v: Introduce KVM_CAP_HYPERV_ENFORCE_CPUID 2021-06-17 13:09:38 -04:00
i8254.c kvm: i8254: remove redundant assignment to pointer s 2020-06-11 12:35:18 -04:00
i8254.h
i8259.c KVM: x86: Refactor picdev_write() to prevent Spectre-v1/L1TF attacks 2020-01-27 19:59:37 +01:00
ioapic.c KVM: ioapic: break infinite recursion on lazy EOI 2020-10-24 04:42:06 -04:00
ioapic.h kvm/x86: Remove redundant function implementations 2020-05-27 13:11:10 -04:00
irq_comm.c x86: Fix various typos in comments 2021-03-18 15:31:53 +01:00
irq.c KVM: x86/xen: Add event channel interrupt vector upcall 2021-02-04 14:19:39 +00:00
irq.h kvm/x86: Remove redundant function implementations 2020-05-27 13:11:10 -04:00
Kconfig kvm: x86: implement KVM PM-notifier 2021-06-17 13:09:33 -04:00
kvm_cache_regs.h KVM: x86: Introduce KVM_GET_SREGS2 / KVM_SET_SREGS2 2021-06-17 13:09:47 -04:00
kvm_emulate.h KVM: x86: Drop "pre_" from enter/leave_smm() helpers 2021-06-17 13:09:35 -04:00
kvm_onhyperv.c KVM: x86: hyper-v: Move the remote TLB flush logic out of vmx 2021-06-17 13:09:36 -04:00
kvm_onhyperv.h KVM: x86: hyper-v: Move the remote TLB flush logic out of vmx 2021-06-17 13:09:36 -04:00
lapic.c KVM: LAPIC: Keep stored TMCCT register value 0 after KVM_SET_LAPIC 2021-06-17 14:26:11 -04:00
lapic.h KVM: x86: Add a return code to kvm_apic_accept_events 2021-06-17 13:09:31 -04:00
Makefile KVM: stats: Add fd-based API to read binary stats data 2021-06-24 11:47:57 -04:00
mmu.h KVM: x86: Drop pointless @reset_roots from kvm_init_mmu() 2021-06-17 13:09:54 -04:00
mtrr.c KVM: x86: Add helper to consolidate "raw" reserved GPA mask calculations 2021-02-04 09:27:30 -05:00
pmu.c KVM: x86: use static calls to reduce kvm_x86_ops overhead 2021-02-04 05:27:30 -05:00
pmu.h x86: Fix various typos in comments 2021-03-18 15:31:53 +01:00
reverse_cpuid.h KVM: SEV: Mask CPUID[0x8000001F].eax according to supported features 2021-04-26 05:27:15 -04:00
trace.h KVM: x86: Rename SMM tracepoint to make it reflect reality 2021-06-17 13:09:35 -04:00
tss.h
x86.c KVM: x86: Properly reset MMU context at vCPU RESET/INIT 2021-06-24 18:00:35 -04:00
x86.h KVM: x86: Consolidate guest enter/exit logic to common helpers 2021-05-05 22:54:12 +02:00
xen.c KVM: x86: Rename GPR accessors to make mode-aware variants the defaults 2021-04-26 05:27:13 -04:00
xen.h KVM: x86/xen: Add support for vCPU runstate information 2021-03-02 14:30:54 -05:00