If clear, this page corresponds to a guest page table denoted by the gfn
     field.
   role.quadrant:
-    When role.cr4_pae=0, the guest uses 32-bit gptes while the host uses 64-bit
+    When role.gpte_is_8_bytes=0, the guest uses 32-bit gptes while the host uses 64-bit
     sptes.  That means a guest page table contains more ptes than the host,
     so multiple shadow pages are needed to shadow one guest page.
     For first-level shadow pages, role.quadrant can be 0 or 1 and denotes the
     The page is invalid and should not be used.  It is a root page that is
     currently pinned (by a cpu hardware register pointing to it); once it is
     unpinned it will be destroyed.
-  role.cr4_pae:
-    Contains the value of cr4.pae for which the page is valid (e.g. whether
-    32-bit or 64-bit gptes are in use).
+  role.gpte_is_8_bytes:
+    Reflects the size of the guest PTE for which the page is valid, i.e. '1'
+    if 64-bit gptes are in use, '0' if 32-bit gptes are in use.
   role.nxe:
     Contains the value of efer.nxe for which the page is valid.
   role.cr0_wp:
     Contains the value of cr4.smap && !cr0.wp for which the page is valid
     (pages for which this is true are different from other pages; see the
     treatment of cr0.wp=0 below).
+  role.ept_sp:
+    This is a virtual flag to denote a shadowed nested EPT page.  ept_sp
+    is true if "cr0_wp && smap_andnot_wp", an otherwise invalid combination.
   role.smm:
     Is 1 if the page is valid in system management mode.  This field
     determines which of the kvm_memslots array was used to build this
 
 
 static const union kvm_mmu_page_role mmu_base_role_mask = {
        .cr0_wp = 1,
-       .cr4_pae = 1,
+       .gpte_is_8_bytes = 1,
        .nxe = 1,
        .smep_andnot_wp = 1,
        .smap_andnot_wp = 1,
 static void kvm_mmu_commit_zap_page(struct kvm *kvm,
                                    struct list_head *invalid_list);
 
+
 #define for_each_valid_sp(_kvm, _sp, _gfn)                             \
        hlist_for_each_entry(_sp,                                       \
          &(_kvm)->arch.mmu_page_hash[kvm_page_table_hashfn(_gfn)], hash_link) \
        for_each_valid_sp(_kvm, _sp, _gfn)                              \
                if ((_sp)->gfn != (_gfn) || (_sp)->role.direct) {} else
 
+static inline bool is_ept_sp(struct kvm_mmu_page *sp)
+{
+       return sp->role.cr0_wp && sp->role.smap_andnot_wp;
+}
+
 /* @sp->gfn should be write-protected at the call site */
 static bool __kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
                            struct list_head *invalid_list)
 {
-       if (sp->role.cr4_pae != !!is_pae(vcpu)
-           || vcpu->arch.mmu->sync_page(vcpu, sp) == 0) {
+       if ((!is_ept_sp(sp) && sp->role.gpte_is_8_bytes != !!is_pae(vcpu)) ||
+           vcpu->arch.mmu->sync_page(vcpu, sp) == 0) {
                kvm_mmu_prepare_zap_page(vcpu->kvm, sp, invalid_list);
                return false;
        }
        role.level = level;
        role.direct = direct;
        if (role.direct)
-               role.cr4_pae = 0;
+               role.gpte_is_8_bytes = true;
        role.access = access;
        if (!vcpu->arch.mmu->direct_map
            && vcpu->arch.mmu->root_level <= PT32_ROOT_LEVEL) {
 
        role.base.access = ACC_ALL;
        role.base.nxe = !!is_nx(vcpu);
-       role.base.cr4_pae = !!is_pae(vcpu);
        role.base.cr0_wp = is_write_protection(vcpu);
        role.base.smm = is_smm(vcpu);
        role.base.guest_mode = is_guest_mode(vcpu);
        role.base.ad_disabled = (shadow_accessed_mask == 0);
        role.base.level = kvm_x86_ops->get_tdp_level(vcpu);
        role.base.direct = true;
+       role.base.gpte_is_8_bytes = true;
 
        return role;
 }
        role.base.smap_andnot_wp = role.ext.cr4_smap &&
                !is_write_protection(vcpu);
        role.base.direct = !is_paging(vcpu);
+       role.base.gpte_is_8_bytes = !!is_pae(vcpu);
 
        if (!is_long_mode(vcpu))
                role.base.level = PT32E_ROOT_LEVEL;
                                   bool execonly)
 {
        union kvm_mmu_role role = {0};
-       union kvm_mmu_page_role root_base = vcpu->arch.root_mmu.mmu_role.base;
 
-       /* Legacy paging and SMM flags are inherited from root_mmu */
-       role.base.smm = root_base.smm;
-       role.base.nxe = root_base.nxe;
-       role.base.cr0_wp = root_base.cr0_wp;
-       role.base.smep_andnot_wp = root_base.smep_andnot_wp;
-       role.base.smap_andnot_wp = root_base.smap_andnot_wp;
+       /* SMM flag is inherited from root_mmu */
+       role.base.smm = vcpu->arch.root_mmu.mmu_role.base.smm;
 
        role.base.level = PT64_ROOT_4LEVEL;
+       role.base.gpte_is_8_bytes = true;
        role.base.direct = false;
        role.base.ad_disabled = !accessed_dirty;
        role.base.guest_mode = true;
        role.base.access = ACC_ALL;
 
+       /*
+        * WP=1 and NOT_WP=1 is an impossible combination, use WP and the
+        * SMAP variation to denote shadow EPT entries.
+        */
+       role.base.cr0_wp = true;
+       role.base.smap_andnot_wp = true;
+
        role.ext = kvm_calc_mmu_role_ext(vcpu);
        role.ext.execonly = execonly;
 
                 gpa, bytes, sp->role.word);
 
        offset = offset_in_page(gpa);
-       pte_size = sp->role.cr4_pae ? 8 : 4;
+       pte_size = sp->role.gpte_is_8_bytes ? 8 : 4;
 
        /*
         * Sometimes, the OS only writes the last one bytes to update status
        page_offset = offset_in_page(gpa);
        level = sp->role.level;
        *nspte = 1;
-       if (!sp->role.cr4_pae) {
+       if (!sp->role.gpte_is_8_bytes) {
                page_offset <<= 1;      /* 32->64 */
                /*
                 * A 32-bit pde maps 4MB while the shadow pdes map