aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-04-12 10:35:58 -0400
committerAvi Kivity <avi@qumranet.com>2007-05-03 03:52:29 -0400
commit417726a3fbecb2092f1054bbaee87bc442b05ef3 (patch)
tree4d9810766bba0c28ce408639b5d63b50d71533fd
parentd917a6b92d0d1e4e2b98e86c584bc9e643cd5117 (diff)
KVM: Handle partial pae pdptr
Some guests (Solaris) do not set up all four pdptrs, but leave some invalid. kvm incorrectly treated these as valid page directories, pinning the wrong pages and causing general confusion. Fix by checking the valid bit of a pae pdpte. This closes sourceforge bug 1698922. Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r--drivers/kvm/mmu.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index 8bdb9ca1811c..9ff74805c7d1 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -806,10 +806,12 @@ static void mmu_free_roots(struct kvm_vcpu *vcpu)
806 for (i = 0; i < 4; ++i) { 806 for (i = 0; i < 4; ++i) {
807 hpa_t root = vcpu->mmu.pae_root[i]; 807 hpa_t root = vcpu->mmu.pae_root[i];
808 808
809 ASSERT(VALID_PAGE(root)); 809 if (root) {
810 root &= PT64_BASE_ADDR_MASK; 810 ASSERT(VALID_PAGE(root));
811 page = page_header(root); 811 root &= PT64_BASE_ADDR_MASK;
812 --page->root_count; 812 page = page_header(root);
813 --page->root_count;
814 }
813 vcpu->mmu.pae_root[i] = INVALID_PAGE; 815 vcpu->mmu.pae_root[i] = INVALID_PAGE;
814 } 816 }
815 vcpu->mmu.root_hpa = INVALID_PAGE; 817 vcpu->mmu.root_hpa = INVALID_PAGE;
@@ -840,9 +842,13 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
840 hpa_t root = vcpu->mmu.pae_root[i]; 842 hpa_t root = vcpu->mmu.pae_root[i];
841 843
842 ASSERT(!VALID_PAGE(root)); 844 ASSERT(!VALID_PAGE(root));
843 if (vcpu->mmu.root_level == PT32E_ROOT_LEVEL) 845 if (vcpu->mmu.root_level == PT32E_ROOT_LEVEL) {
846 if (!is_present_pte(vcpu->pdptrs[i])) {
847 vcpu->mmu.pae_root[i] = 0;
848 continue;
849 }
844 root_gfn = vcpu->pdptrs[i] >> PAGE_SHIFT; 850 root_gfn = vcpu->pdptrs[i] >> PAGE_SHIFT;
845 else if (vcpu->mmu.root_level == 0) 851 } else if (vcpu->mmu.root_level == 0)
846 root_gfn = 0; 852 root_gfn = 0;
847 page = kvm_mmu_get_page(vcpu, root_gfn, i << 30, 853 page = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
848 PT32_ROOT_LEVEL, !is_paging(vcpu), 854 PT32_ROOT_LEVEL, !is_paging(vcpu),