[PATCH] KVM: MMU: Use the guest pdptrs instead of mapping cr3 in pae mode
This lets us not write protect a partial page, and is anyway what a real processor does. Signed-off-by: Avi Kivity <avi@qumranet.com> Acked-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
17ac10ad2b
commit
1b0973bd8f
|
@ -1491,6 +1491,8 @@ static int kvm_dev_ioctl_set_sregs(struct kvm *kvm, struct kvm_sregs *sregs)
|
|||
|
||||
mmu_reset_needed |= vcpu->cr4 != sregs->cr4;
|
||||
kvm_arch_ops->set_cr4(vcpu, sregs->cr4);
|
||||
if (!is_long_mode(vcpu) && is_pae(vcpu))
|
||||
load_pdptrs(vcpu, vcpu->cr3);
|
||||
|
||||
if (mmu_reset_needed)
|
||||
kvm_mmu_reset_context(vcpu);
|
||||
|
|
|
@ -67,18 +67,28 @@ static void FNAME(walk_addr)(struct guest_walker *walker,
|
|||
hpa_t hpa;
|
||||
struct kvm_memory_slot *slot;
|
||||
pt_element_t *ptep;
|
||||
pt_element_t root;
|
||||
|
||||
walker->level = vcpu->mmu.root_level;
|
||||
walker->table_gfn = (vcpu->cr3 & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
|
||||
walker->table = NULL;
|
||||
root = vcpu->cr3;
|
||||
#if PTTYPE == 64
|
||||
if (!is_long_mode(vcpu)) {
|
||||
walker->ptep = &vcpu->pdptrs[(addr >> 30) & 3];
|
||||
root = *walker->ptep;
|
||||
if (!(root & PT_PRESENT_MASK))
|
||||
return;
|
||||
--walker->level;
|
||||
}
|
||||
#endif
|
||||
walker->table_gfn = (root & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
|
||||
slot = gfn_to_memslot(vcpu->kvm, walker->table_gfn);
|
||||
hpa = safe_gpa_to_hpa(vcpu, vcpu->cr3 & PT64_BASE_ADDR_MASK);
|
||||
hpa = safe_gpa_to_hpa(vcpu, root & PT64_BASE_ADDR_MASK);
|
||||
walker->table = kmap_atomic(pfn_to_page(hpa >> PAGE_SHIFT), KM_USER0);
|
||||
|
||||
ASSERT((!is_long_mode(vcpu) && is_pae(vcpu)) ||
|
||||
(vcpu->cr3 & ~(PAGE_MASK | CR3_FLAGS_MASK)) == 0);
|
||||
|
||||
walker->table = (pt_element_t *)( (unsigned long)walker->table |
|
||||
(unsigned long)(vcpu->cr3 & ~(PAGE_MASK | CR3_FLAGS_MASK)) );
|
||||
walker->inherited_ar = PT_USER_MASK | PT_WRITABLE_MASK;
|
||||
|
||||
for (;;) {
|
||||
|
@ -89,11 +99,8 @@ static void FNAME(walk_addr)(struct guest_walker *walker,
|
|||
ASSERT(((unsigned long)walker->table & PAGE_MASK) ==
|
||||
((unsigned long)ptep & PAGE_MASK));
|
||||
|
||||
/* Don't set accessed bit on PAE PDPTRs */
|
||||
if (vcpu->mmu.root_level != 3 || walker->level != 3)
|
||||
if ((*ptep & (PT_PRESENT_MASK | PT_ACCESSED_MASK))
|
||||
== PT_PRESENT_MASK)
|
||||
*ptep |= PT_ACCESSED_MASK;
|
||||
if (is_present_pte(*ptep) && !(*ptep & PT_ACCESSED_MASK))
|
||||
*ptep |= PT_ACCESSED_MASK;
|
||||
|
||||
if (!is_present_pte(*ptep) ||
|
||||
walker->level == PT_PAGE_TABLE_LEVEL ||
|
||||
|
@ -116,7 +123,8 @@ static void FNAME(walk_addr)(struct guest_walker *walker,
|
|||
|
||||
static void FNAME(release_walker)(struct guest_walker *walker)
|
||||
{
|
||||
kunmap_atomic(walker->table, KM_USER0);
|
||||
if (walker->table)
|
||||
kunmap_atomic(walker->table, KM_USER0);
|
||||
}
|
||||
|
||||
static void FNAME(set_pte)(struct kvm_vcpu *vcpu, u64 guest_pte,
|
||||
|
|
Loading…
Reference in New Issue