Sean Christopherson <seanjc@xxxxxxxxxx> writes: > 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. Just to make the picture complete, according to TLFS, Enlightened VMCS must also be zero allocated and the encoding is known. Still a 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 aff48baa34c0 ("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: aff48baa34c0 ("KVM: Fetch guest cr3 from hardware on demand") > Fixes: 6de4f3ada40b ("KVM: Cache pdptrs") > Fixes: 6de12732c42c ("KVM: VMX: Optimize vmx_get_rflags()") > Fixes: 2fb92db1ec08 ("KVM: VMX: Cache vmcs segment fields") > Fixes: bd31fe495d0d ("KVM: VMX: Add proper cache tracking for CR0") > Fixes: f98c1e77127d ("KVM: VMX: Add proper cache tracking for CR4") > Fixes: 5addc235199f ("KVM: VMX: Cache vmcs.EXIT_QUALIFICATION using arch avail_reg flags") > Fixes: 8791585837f6 ("KVM: VMX: Cache vmcs.EXIT_INTR_INFO using arch avail_reg flags") > Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx> > --- > arch/x86/kvm/x86.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 86539c1686fa..e77a5bf2d940 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -10656,6 +10656,8 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) > int r; > > vcpu->arch.last_vmentry_cpu = -1; > + vcpu->arch.regs_avail = ~0; > + vcpu->arch.regs_dirty = ~0; > > if (!irqchip_in_kernel(vcpu->kvm) || kvm_vcpu_is_reset_bsp(vcpu)) > vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; Reviewed-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> -- Vitaly