Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b0973bd authored by Avi Kivity's avatar Avi Kivity Committed by Linus Torvalds
Browse files

[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: default avatarAvi Kivity <avi@qumranet.com>
Acked-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 17ac10ad
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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);
+18 −10
Original line number Diff line number Diff line
@@ -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,10 +99,7 @@ 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)
		if (is_present_pte(*ptep) && !(*ptep &  PT_ACCESSED_MASK))
			*ptep |= PT_ACCESSED_MASK;

		if (!is_present_pte(*ptep) ||
@@ -116,6 +123,7 @@ static void FNAME(walk_addr)(struct guest_walker *walker,

static void FNAME(release_walker)(struct guest_walker *walker)
{
	if (walker->table)
		kunmap_atomic(walker->table, KM_USER0);
}