Sean Christopherson <seanjc@xxxxxxxxxx> writes: > WARN if CR0, CR3, or CR4 are non-zero at RESET, which given the current > KVM implementation, really means WARN if they're not zeroed at vCPU > creation. VMX in particular has several ->set_*() flows that read other > registers to handle side effects, and because those flows are common to > RESET and INIT, KVM subtly relies on emulated/virtualized registers to be > zeroed at vCPU creation in order to do the right thing at RESET. > > Use CRs as a sentinel because they are most likely to be written as side > effects, and because KVM specifically needs CR0.PG and CR0.PE to be '0' > to correctly reflect the state of the vCPU's MMU. CRs are also loaded > and stored from/to the VMCS, and so adds some level of coverage to verify > that KVM doesn't conflate zero-allocating the VMCS with properly > initializing the VMCS with VMWRITEs. > > Note, '0' is somewhat arbitrary, vCPU creation can technically stuff any > value for a register so long as it's coherent with respect to the current > vCPU state. In practice, '0' works for all registers and is convenient. > > Suggested-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> > Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx> > --- > arch/x86/kvm/x86.c | 10 ++++++++++ > 1 file changed, 10 insertions(+) > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index ec61b90d9b73..4e25baac3977 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -10800,6 +10800,16 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) > unsigned long new_cr0; > u32 eax, dummy; > > + /* > + * Several of the "set" flows, e.g. ->set_cr0(), read other registers > + * to handle side effects. RESET emulation hits those flows and relies > + * on emulated/virtualized registers, including those that are loaded > + * into hardware, to be zeroed at vCPU creation. Use CRs as a sentinel > + * to detect improper or missing initialization. > + */ > + WARN_ON_ONCE(!init_event && > + (old_cr0 || kvm_read_cr3(vcpu) || kvm_read_cr4(vcpu))); > + > kvm_lapic_reset(vcpu, init_event); > > vcpu->arch.hflags = 0; Reviewed-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> -- Vitaly