KVM: x86: fix handling of role.cr4_pae and rename it to 'gpte_size'
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: 7dcd575520
("x86/kvm/mmu: check if tdp/shadow MMU reconfiguration is needed")
Reported-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Tested-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:

committed by
Paolo Bonzini

parent
552c69b1dc
commit
47c42e6b41
@@ -253,14 +253,14 @@ struct kvm_mmu_memory_cache {
|
||||
* kvm_memory_slot.arch.gfn_track which is 16 bits, so the role bits used
|
||||
* by indirect shadow page can not be more than 15 bits.
|
||||
*
|
||||
* Currently, we used 14 bits that are @level, @cr4_pae, @quadrant, @access,
|
||||
* Currently, we used 14 bits that are @level, @gpte_is_8_bytes, @quadrant, @access,
|
||||
* @nxe, @cr0_wp, @smep_andnot_wp and @smap_andnot_wp.
|
||||
*/
|
||||
union kvm_mmu_page_role {
|
||||
u32 word;
|
||||
struct {
|
||||
unsigned level:4;
|
||||
unsigned cr4_pae:1;
|
||||
unsigned gpte_is_8_bytes:1;
|
||||
unsigned quadrant:2;
|
||||
unsigned direct:1;
|
||||
unsigned access:3;
|
||||
|
Reference in New Issue
Block a user