Commit 8c7bb723 authored by Avi Kivity's avatar Avi Kivity Committed by Linus Torvalds

[PATCH] KVM: MMU: Ignore pcd, pwt, and pat bits on ptes

The pcd, pwt, and pat bits on page table entries affect the cpu cache.  Since
the cache is a host resource, the guest should not be able to control it.
Moreover, the meaning of these bits changes depending on whether pat is
enabled or not.

So, force these bits to zero on shadow page table entries at all times.
Signed-off-by: default avatarAvi Kivity <avi@qumranet.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 0770b19b
...@@ -61,22 +61,9 @@ ...@@ -61,22 +61,9 @@
#define PT32_PTE_COPY_MASK \ #define PT32_PTE_COPY_MASK \
(PT_PRESENT_MASK | PT_PWT_MASK | PT_PCD_MASK | \ (PT_PRESENT_MASK | PT_ACCESSED_MASK | PT_DIRTY_MASK | PT_GLOBAL_MASK)
PT_ACCESSED_MASK | PT_DIRTY_MASK | PT_PAT_MASK | \
PT_GLOBAL_MASK )
#define PT32_NON_PTE_COPY_MASK \
(PT_PRESENT_MASK | PT_PWT_MASK | PT_PCD_MASK | \
PT_ACCESSED_MASK | PT_DIRTY_MASK)
#define PT64_PTE_COPY_MASK \
(PT64_NX_MASK | PT32_PTE_COPY_MASK)
#define PT64_NON_PTE_COPY_MASK \
(PT64_NX_MASK | PT32_NON_PTE_COPY_MASK)
#define PT64_PTE_COPY_MASK (PT64_NX_MASK | PT32_PTE_COPY_MASK)
#define PT_FIRST_AVAIL_BITS_SHIFT 9 #define PT_FIRST_AVAIL_BITS_SHIFT 9
#define PT64_SECOND_AVAIL_BITS_SHIFT 52 #define PT64_SECOND_AVAIL_BITS_SHIFT 52
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level) #define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
#define PT_LEVEL_MASK(level) PT64_LEVEL_MASK(level) #define PT_LEVEL_MASK(level) PT64_LEVEL_MASK(level)
#define PT_PTE_COPY_MASK PT64_PTE_COPY_MASK #define PT_PTE_COPY_MASK PT64_PTE_COPY_MASK
#define PT_NON_PTE_COPY_MASK PT64_NON_PTE_COPY_MASK
#elif PTTYPE == 32 #elif PTTYPE == 32
#define pt_element_t u32 #define pt_element_t u32
#define guest_walker guest_walker32 #define guest_walker guest_walker32
...@@ -43,7 +42,6 @@ ...@@ -43,7 +42,6 @@
#define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level) #define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
#define PT_LEVEL_MASK(level) PT32_LEVEL_MASK(level) #define PT_LEVEL_MASK(level) PT32_LEVEL_MASK(level)
#define PT_PTE_COPY_MASK PT32_PTE_COPY_MASK #define PT_PTE_COPY_MASK PT32_PTE_COPY_MASK
#define PT_NON_PTE_COPY_MASK PT32_NON_PTE_COPY_MASK
#else #else
#error Invalid PTTYPE value #error Invalid PTTYPE value
#endif #endif
...@@ -105,9 +103,7 @@ static void FNAME(set_pde)(struct kvm_vcpu *vcpu, u64 guest_pde, ...@@ -105,9 +103,7 @@ static void FNAME(set_pde)(struct kvm_vcpu *vcpu, u64 guest_pde,
if (PTTYPE == 32 && is_cpuid_PSE36()) if (PTTYPE == 32 && is_cpuid_PSE36())
gaddr |= (guest_pde & PT32_DIR_PSE36_MASK) << gaddr |= (guest_pde & PT32_DIR_PSE36_MASK) <<
(32 - PT32_DIR_PSE36_SHIFT); (32 - PT32_DIR_PSE36_SHIFT);
*shadow_pte = (guest_pde & (PT_NON_PTE_COPY_MASK | PT_GLOBAL_MASK)) | *shadow_pte = guest_pde & PT_PTE_COPY_MASK;
((guest_pde & PT_DIR_PAT_MASK) >>
(PT_DIR_PAT_SHIFT - PT_PAT_SHIFT));
set_pte_common(vcpu, shadow_pte, gaddr, set_pte_common(vcpu, shadow_pte, gaddr,
guest_pde & PT_DIRTY_MASK, access_bits); guest_pde & PT_DIRTY_MASK, access_bits);
} }
...@@ -162,6 +158,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, ...@@ -162,6 +158,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
u32 index = SHADOW_PT_INDEX(addr, level); u32 index = SHADOW_PT_INDEX(addr, level);
u64 *shadow_ent = ((u64 *)__va(shadow_addr)) + index; u64 *shadow_ent = ((u64 *)__va(shadow_addr)) + index;
pt_element_t *guest_ent; pt_element_t *guest_ent;
u64 shadow_pte;
if (is_present_pte(*shadow_ent) || is_io_pte(*shadow_ent)) { if (is_present_pte(*shadow_ent) || is_io_pte(*shadow_ent)) {
if (level == PT_PAGE_TABLE_LEVEL) if (level == PT_PAGE_TABLE_LEVEL)
...@@ -204,14 +201,11 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, ...@@ -204,14 +201,11 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
shadow_addr = kvm_mmu_alloc_page(vcpu, shadow_ent); shadow_addr = kvm_mmu_alloc_page(vcpu, shadow_ent);
if (!VALID_PAGE(shadow_addr)) if (!VALID_PAGE(shadow_addr))
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
if (!kvm_arch_ops->is_long_mode(vcpu) && level == 3) shadow_pte = shadow_addr | PT_PRESENT_MASK;
*shadow_ent = shadow_addr | if (vcpu->mmu.root_level > 3 || level != 3)
(*guest_ent & (PT_PRESENT_MASK | PT_PWT_MASK | PT_PCD_MASK)); shadow_pte |= PT_ACCESSED_MASK
else { | PT_WRITABLE_MASK | PT_USER_MASK;
*shadow_ent = shadow_addr | *shadow_ent = shadow_pte;
(*guest_ent & PT_NON_PTE_COPY_MASK);
*shadow_ent |= (PT_WRITABLE_MASK | PT_USER_MASK);
}
prev_shadow_ent = shadow_ent; prev_shadow_ent = shadow_ent;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment