• Sean Christopherson's avatar
    KVM: nVMX: Do not clear CR3 load/store exiting bits if L1 wants 'em · 470750b3
    Sean Christopherson authored
    Keep CR3 load/store exiting enable as needed when running L2 in order to
    honor L1's desires.  This fixes a largely theoretical bug where L1 could
    intercept CR3 but not CR0.PG and end up not getting the desired CR3 exits
    when L2 enables paging.  In other words, the existing !is_paging() check
    inadvertantly handles the normal case for L2 where vmx_set_cr0() is
    called during VM-Enter, which is guaranteed to run with paging enabled,
    and thus will never clear the bits.
    
    Removing the !is_paging() check will also allow future consolidation and
    cleanup of the related code.  From a performance perspective, this is
    all a nop, as the VMCS controls shadow will optimize away the VMWRITE
    when the controls are in the desired state.
    
    Add a comment explaining why CR3 is intercepted, with a big disclaimer
    about not querying the old CR3.  Because vmx_set_cr0() is used for flows
    that are not directly tied to MOV CR3, e.g. vCPU RESET/INIT and nested
    VM-Enter, it's possible that is_paging() is not synchronized with CR3
    load/store exiting.  This is actually guaranteed in the current code, as
    KVM starts with CR3 interception disabled.  Obviously that can be fixed,
    but there's no good reason to play whack-a-mole, and it tends to end
    poorly, e.g. descriptor table exiting for UMIP emulation attempted to be
    precise in the past and ended up botching the interception toggling.
    
    Fixes: fe3ef05c ("KVM: nVMX: Prepare vmcs02 from vmcs01 and vmcs12")
    Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
    Message-Id: <20210713163324.627647-25-seanjc@google.com>
    Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
    470750b3
vmx.c 224 KB