lkml.org 
[lkml]   [2021]   [Sep]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    From
    SubjectRe: [PATCH v2 10/10] KVM: x86: WARN on non-zero CRs at RESET to detect improper initalization
    Date
    Sean Christopherson <seanjc@google.com> 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@redhat.com>
    > Signed-off-by: Sean Christopherson <seanjc@google.com>
    > ---
    > 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@redhat.com>

    --
    Vitaly

    \
     
     \ /
      Last update: 2021-09-21 16:00    [W:4.420 / U:0.148 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site