• Sean Christopherson's avatar
    KVM: x86: Mark all registers as avail/dirty at vCPU creation · 7117003f
    Sean Christopherson authored
    Mark all registers as available and dirty at vCPU creation, as the vCPU has
    obviously not been loaded into hardware, let alone been given the chance to
    be modified in hardware.  On SVM, reading from "uninitialized" hardware is
    a non-issue as VMCBs are zero allocated (thus not truly uninitialized) and
    hardware does not allow for arbitrary field encoding schemes.
    
    On VMX, backing memory for VMCSes is also zero allocated, but true
    initialization of the VMCS _technically_ requires VMWRITEs, as the VMX
    architectural specification technically allows CPU implementations to
    encode fields with arbitrary schemes.  E.g. a CPU could theoretically store
    the inverted value of every field, which would result in VMREAD to a
    zero-allocated field returns all ones.
    
    In practice, only the AR_BYTES fields are known to be manipulated by
    hardware during VMREAD/VMREAD; no known hardware or VMM (for nested VMX)
    does fancy encoding of cacheable field values (CR0, CR3, CR4, etc...).  In
    other words, this is technically a bug fix, but practically speakings it's
    a glorified nop.
    
    Failure to mark registers as available has been a lurking bug for quite
    some time.  The original register caching supported only GPRs (+RIP, which
    is kinda sorta a GPR), with the masks initialized at ->vcpu_reset().  That
    worked because the two cacheable registers, RIP and RSP, are generally
    speaking not read as side effects in other flows.
    
    Arguably, commit aff48baa ("KVM: Fetch guest cr3 from hardware on
    demand") was the first instance of failure to mark regs available.  While
    _just_ marking CR3 available during vCPU creation wouldn't have fixed the
    VMREAD from an uninitialized VMCS bug because ept_update_paging_mode_cr0()
    unconditionally read vmcs.GUEST_CR3, marking CR3 _and_ intentionally not
    reading GUEST_CR3 when it's available would have avoided VMREAD to a
    technically-uninitialized VMCS.
    
    Fixes: aff48baa ("KVM: Fetch guest cr3 from hardware on demand")
    Fixes: 6de4f3ad ("KVM: Cache pdptrs")
    Fixes: 6de12732 ("KVM: VMX: Optimize vmx_get_rflags()")
    Fixes: 2fb92db1 ("KVM: VMX: Cache vmcs segment fields")
    Fixes: bd31fe49 ("KVM: VMX: Add proper cache tracking for CR0")
    Fixes: f98c1e77 ("KVM: VMX: Add proper cache tracking for CR4")
    Fixes: 5addc235 ("KVM: VMX: Cache vmcs.EXIT_QUALIFICATION using arch avail_reg flags")
    Fixes: 87915858 ("KVM: VMX: Cache vmcs.EXIT_INTR_INFO using arch avail_reg flags")
    Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
    Message-Id: <20210921000303.400537-2-seanjc@google.com>
    Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
    7117003f
x86.c 324 KB