aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/kvm/kvm.h2
-rw-r--r--drivers/kvm/mmu.c8
-rw-r--r--drivers/kvm/paging_tmpl.h7
3 files changed, 13 insertions, 4 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 7361c45d70c9..f5e343cb06b0 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -109,6 +109,7 @@ struct kvm_pte_chain {
109 * bits 4:7 - page table level for this shadow (1-4) 109 * bits 4:7 - page table level for this shadow (1-4)
110 * bits 8:9 - page table quadrant for 2-level guests 110 * bits 8:9 - page table quadrant for 2-level guests
111 * bit 16 - "metaphysical" - gfn is not a real page (huge page/real mode) 111 * bit 16 - "metaphysical" - gfn is not a real page (huge page/real mode)
112 * bits 17:18 - "access" - the user and writable bits of a huge page pde
112 */ 113 */
113union kvm_mmu_page_role { 114union kvm_mmu_page_role {
114 unsigned word; 115 unsigned word;
@@ -118,6 +119,7 @@ union kvm_mmu_page_role {
118 unsigned quadrant : 2; 119 unsigned quadrant : 2;
119 unsigned pad_for_nice_hex_output : 6; 120 unsigned pad_for_nice_hex_output : 6;
120 unsigned metaphysical : 1; 121 unsigned metaphysical : 1;
122 unsigned hugepage_access : 2;
121 }; 123 };
122}; 124};
123 125
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index 2930d7cc7c06..c738fb1cea30 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -568,6 +568,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
568 gva_t gaddr, 568 gva_t gaddr,
569 unsigned level, 569 unsigned level,
570 int metaphysical, 570 int metaphysical,
571 unsigned hugepage_access,
571 u64 *parent_pte) 572 u64 *parent_pte)
572{ 573{
573 union kvm_mmu_page_role role; 574 union kvm_mmu_page_role role;
@@ -581,6 +582,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
581 role.glevels = vcpu->mmu.root_level; 582 role.glevels = vcpu->mmu.root_level;
582 role.level = level; 583 role.level = level;
583 role.metaphysical = metaphysical; 584 role.metaphysical = metaphysical;
585 role.hugepage_access = hugepage_access;
584 if (vcpu->mmu.root_level <= PT32_ROOT_LEVEL) { 586 if (vcpu->mmu.root_level <= PT32_ROOT_LEVEL) {
585 quadrant = gaddr >> (PAGE_SHIFT + (PT64_PT_BITS * level)); 587 quadrant = gaddr >> (PAGE_SHIFT + (PT64_PT_BITS * level));
586 quadrant &= (1 << ((PT32_PT_BITS - PT64_PT_BITS) * level)) - 1; 588 quadrant &= (1 << ((PT32_PT_BITS - PT64_PT_BITS) * level)) - 1;
@@ -780,7 +782,7 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, hpa_t p)
780 >> PAGE_SHIFT; 782 >> PAGE_SHIFT;
781 new_table = kvm_mmu_get_page(vcpu, pseudo_gfn, 783 new_table = kvm_mmu_get_page(vcpu, pseudo_gfn,
782 v, level - 1, 784 v, level - 1,
783 1, &table[index]); 785 1, 0, &table[index]);
784 if (!new_table) { 786 if (!new_table) {
785 pgprintk("nonpaging_map: ENOMEM\n"); 787 pgprintk("nonpaging_map: ENOMEM\n");
786 return -ENOMEM; 788 return -ENOMEM;
@@ -835,7 +837,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
835 837
836 ASSERT(!VALID_PAGE(root)); 838 ASSERT(!VALID_PAGE(root));
837 page = kvm_mmu_get_page(vcpu, root_gfn, 0, 839 page = kvm_mmu_get_page(vcpu, root_gfn, 0,
838 PT64_ROOT_LEVEL, 0, NULL); 840 PT64_ROOT_LEVEL, 0, 0, NULL);
839 root = page->page_hpa; 841 root = page->page_hpa;
840 ++page->root_count; 842 ++page->root_count;
841 vcpu->mmu.root_hpa = root; 843 vcpu->mmu.root_hpa = root;
@@ -852,7 +854,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
852 root_gfn = 0; 854 root_gfn = 0;
853 page = kvm_mmu_get_page(vcpu, root_gfn, i << 30, 855 page = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
854 PT32_ROOT_LEVEL, !is_paging(vcpu), 856 PT32_ROOT_LEVEL, !is_paging(vcpu),
855 NULL); 857 0, NULL);
856 root = page->page_hpa; 858 root = page->page_hpa;
857 ++page->root_count; 859 ++page->root_count;
858 vcpu->mmu.pae_root[i] = root | PT_PRESENT_MASK; 860 vcpu->mmu.pae_root[i] = root | PT_PRESENT_MASK;
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index 17bd4400c92b..b94010dad809 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -247,6 +247,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
247 u64 shadow_pte; 247 u64 shadow_pte;
248 int metaphysical; 248 int metaphysical;
249 gfn_t table_gfn; 249 gfn_t table_gfn;
250 unsigned hugepage_access = 0;
250 251
251 if (is_present_pte(*shadow_ent) || is_io_pte(*shadow_ent)) { 252 if (is_present_pte(*shadow_ent) || is_io_pte(*shadow_ent)) {
252 if (level == PT_PAGE_TABLE_LEVEL) 253 if (level == PT_PAGE_TABLE_LEVEL)
@@ -276,6 +277,9 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
276 if (level - 1 == PT_PAGE_TABLE_LEVEL 277 if (level - 1 == PT_PAGE_TABLE_LEVEL
277 && walker->level == PT_DIRECTORY_LEVEL) { 278 && walker->level == PT_DIRECTORY_LEVEL) {
278 metaphysical = 1; 279 metaphysical = 1;
280 hugepage_access = *guest_ent;
281 hugepage_access &= PT_USER_MASK | PT_WRITABLE_MASK;
282 hugepage_access >>= PT_WRITABLE_SHIFT;
279 table_gfn = (*guest_ent & PT_BASE_ADDR_MASK) 283 table_gfn = (*guest_ent & PT_BASE_ADDR_MASK)
280 >> PAGE_SHIFT; 284 >> PAGE_SHIFT;
281 } else { 285 } else {
@@ -283,7 +287,8 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
283 table_gfn = walker->table_gfn[level - 2]; 287 table_gfn = walker->table_gfn[level - 2];
284 } 288 }
285 shadow_page = kvm_mmu_get_page(vcpu, table_gfn, addr, level-1, 289 shadow_page = kvm_mmu_get_page(vcpu, table_gfn, addr, level-1,
286 metaphysical, shadow_ent); 290 metaphysical, hugepage_access,
291 shadow_ent);
287 shadow_addr = shadow_page->page_hpa; 292 shadow_addr = shadow_page->page_hpa;
288 shadow_pte = shadow_addr | PT_PRESENT_MASK | PT_ACCESSED_MASK 293 shadow_pte = shadow_addr | PT_PRESENT_MASK | PT_ACCESSED_MASK
289 | PT_WRITABLE_MASK | PT_USER_MASK; 294 | PT_WRITABLE_MASK | PT_USER_MASK;