diff options
Diffstat (limited to 'drivers/kvm/paging_tmpl.h')
-rw-r--r-- | drivers/kvm/paging_tmpl.h | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h index f3bcee904651..73ffbffb1097 100644 --- a/drivers/kvm/paging_tmpl.h +++ b/drivers/kvm/paging_tmpl.h | |||
@@ -148,8 +148,7 @@ static int FNAME(walk_addr)(struct guest_walker *walker, | |||
148 | break; | 148 | break; |
149 | } | 149 | } |
150 | 150 | ||
151 | if (walker->level != 3 || is_long_mode(vcpu)) | 151 | walker->inherited_ar &= walker->table[index]; |
152 | walker->inherited_ar &= walker->table[index]; | ||
153 | table_gfn = (*ptep & PT_BASE_ADDR_MASK) >> PAGE_SHIFT; | 152 | table_gfn = (*ptep & PT_BASE_ADDR_MASK) >> PAGE_SHIFT; |
154 | paddr = safe_gpa_to_hpa(vcpu, *ptep & PT_BASE_ADDR_MASK); | 153 | paddr = safe_gpa_to_hpa(vcpu, *ptep & PT_BASE_ADDR_MASK); |
155 | kunmap_atomic(walker->table, KM_USER0); | 154 | kunmap_atomic(walker->table, KM_USER0); |
@@ -248,6 +247,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, | |||
248 | u64 shadow_pte; | 247 | u64 shadow_pte; |
249 | int metaphysical; | 248 | int metaphysical; |
250 | gfn_t table_gfn; | 249 | gfn_t table_gfn; |
250 | unsigned hugepage_access = 0; | ||
251 | 251 | ||
252 | if (is_present_pte(*shadow_ent) || is_io_pte(*shadow_ent)) { | 252 | if (is_present_pte(*shadow_ent) || is_io_pte(*shadow_ent)) { |
253 | if (level == PT_PAGE_TABLE_LEVEL) | 253 | if (level == PT_PAGE_TABLE_LEVEL) |
@@ -277,6 +277,9 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, | |||
277 | if (level - 1 == PT_PAGE_TABLE_LEVEL | 277 | if (level - 1 == PT_PAGE_TABLE_LEVEL |
278 | && walker->level == PT_DIRECTORY_LEVEL) { | 278 | && walker->level == PT_DIRECTORY_LEVEL) { |
279 | 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; | ||
280 | table_gfn = (*guest_ent & PT_BASE_ADDR_MASK) | 283 | table_gfn = (*guest_ent & PT_BASE_ADDR_MASK) |
281 | >> PAGE_SHIFT; | 284 | >> PAGE_SHIFT; |
282 | } else { | 285 | } else { |
@@ -284,7 +287,8 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, | |||
284 | table_gfn = walker->table_gfn[level - 2]; | 287 | table_gfn = walker->table_gfn[level - 2]; |
285 | } | 288 | } |
286 | 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, |
287 | metaphysical, shadow_ent); | 290 | metaphysical, hugepage_access, |
291 | shadow_ent); | ||
288 | shadow_addr = shadow_page->page_hpa; | 292 | shadow_addr = shadow_page->page_hpa; |
289 | shadow_pte = shadow_addr | PT_PRESENT_MASK | PT_ACCESSED_MASK | 293 | shadow_pte = shadow_addr | PT_PRESENT_MASK | PT_ACCESSED_MASK |
290 | | PT_WRITABLE_MASK | PT_USER_MASK; | 294 | | PT_WRITABLE_MASK | PT_USER_MASK; |
@@ -444,7 +448,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, | |||
444 | if (is_io_pte(*shadow_pte)) | 448 | if (is_io_pte(*shadow_pte)) |
445 | return 1; | 449 | return 1; |
446 | 450 | ||
447 | ++kvm_stat.pf_fixed; | 451 | ++vcpu->stat.pf_fixed; |
448 | kvm_mmu_audit(vcpu, "post page fault (fixed)"); | 452 | kvm_mmu_audit(vcpu, "post page fault (fixed)"); |
449 | 453 | ||
450 | return write_pt; | 454 | return write_pt; |