• S
    KVM: x86: fix handling of role.cr4_pae and rename it to 'gpte_size' · 47c42e6b
    Sean Christopherson 提交于
    The cr4_pae flag is a bit of a misnomer, its purpose is really to track
    whether the guest PTE that is being shadowed is a 4-byte entry or an
    8-byte entry.  Prior to supporting nested EPT, the size of the gpte was
    reflected purely by CR4.PAE.  KVM fudged things a bit for direct sptes,
    but it was mostly harmless since the size of the gpte never mattered.
    Now that a spte may be tracking an indirect EPT entry, relying on
    CR4.PAE is wrong and ill-named.
    
    For direct shadow pages, force the gpte_size to '1' as they are always
    8-byte entries; EPT entries can only be 8-bytes and KVM always uses
    8-byte entries for NPT and its identity map (when running with EPT but
    not unrestricted guest).
    
    Likewise, nested EPT entries are always 8-bytes.  Nested EPT presents a
    unique scenario as the size of the entries are not dictated by CR4.PAE,
    but neither is the shadow page a direct map.  To handle this scenario,
    set cr0_wp=1 and smap_andnot_wp=1, an otherwise impossible combination,
    to denote a nested EPT shadow page.  Use the information to avoid
    incorrectly zapping an unsync'd indirect page in __kvm_sync_page().
    
    Providing a consistent and accurate gpte_size fixes a bug reported by
    Vitaly where fast_cr3_switch() always fails when switching from L2 to
    L1 as kvm_mmu_get_page() would force role.cr4_pae=0 for direct pages,
    whereas kvm_calc_mmu_role_common() would set it according to CR4.PAE.
    
    Fixes: 7dcd5755 ("x86/kvm/mmu: check if tdp/shadow MMU reconfiguration is needed")
    Reported-by: NVitaly Kuznetsov <vkuznets@redhat.com>
    Tested-by: NVitaly Kuznetsov <vkuznets@redhat.com>
    Signed-off-by: NSean Christopherson <sean.j.christopherson@intel.com>
    Signed-off-by: NPaolo Bonzini <pbonzini@redhat.com>
    47c42e6b
mmu.txt 20.1 KB