diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/paging_tmpl.h | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 043330159179..ad75d77999d0 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h | |||
@@ -99,6 +99,7 @@ struct guest_walker { | |||
99 | pt_element_t prefetch_ptes[PTE_PREFETCH_NUM]; | 99 | pt_element_t prefetch_ptes[PTE_PREFETCH_NUM]; |
100 | gpa_t pte_gpa[PT_MAX_FULL_LEVELS]; | 100 | gpa_t pte_gpa[PT_MAX_FULL_LEVELS]; |
101 | pt_element_t __user *ptep_user[PT_MAX_FULL_LEVELS]; | 101 | pt_element_t __user *ptep_user[PT_MAX_FULL_LEVELS]; |
102 | bool pte_writable[PT_MAX_FULL_LEVELS]; | ||
102 | unsigned pt_access; | 103 | unsigned pt_access; |
103 | unsigned pte_access; | 104 | unsigned pte_access; |
104 | gfn_t gfn; | 105 | gfn_t gfn; |
@@ -235,6 +236,22 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu, | |||
235 | if (pte == orig_pte) | 236 | if (pte == orig_pte) |
236 | continue; | 237 | continue; |
237 | 238 | ||
239 | /* | ||
240 | * If the slot is read-only, simply do not process the accessed | ||
241 | * and dirty bits. This is the correct thing to do if the slot | ||
242 | * is ROM, and page tables in read-as-ROM/write-as-MMIO slots | ||
243 | * are only supported if the accessed and dirty bits are already | ||
244 | * set in the ROM (so that MMIO writes are never needed). | ||
245 | * | ||
246 | * Note that NPT does not allow this at all and faults, since | ||
247 | * it always wants nested page table entries for the guest | ||
248 | * page tables to be writable. And EPT works but will simply | ||
249 | * overwrite the read-only memory to set the accessed and dirty | ||
250 | * bits. | ||
251 | */ | ||
252 | if (unlikely(!walker->pte_writable[level - 1])) | ||
253 | continue; | ||
254 | |||
238 | ret = FNAME(cmpxchg_gpte)(vcpu, mmu, ptep_user, index, orig_pte, pte); | 255 | ret = FNAME(cmpxchg_gpte)(vcpu, mmu, ptep_user, index, orig_pte, pte); |
239 | if (ret) | 256 | if (ret) |
240 | return ret; | 257 | return ret; |
@@ -309,7 +326,8 @@ retry_walk: | |||
309 | goto error; | 326 | goto error; |
310 | real_gfn = gpa_to_gfn(real_gfn); | 327 | real_gfn = gpa_to_gfn(real_gfn); |
311 | 328 | ||
312 | host_addr = gfn_to_hva(vcpu->kvm, real_gfn); | 329 | host_addr = gfn_to_hva_prot(vcpu->kvm, real_gfn, |
330 | &walker->pte_writable[walker->level - 1]); | ||
313 | if (unlikely(kvm_is_error_hva(host_addr))) | 331 | if (unlikely(kvm_is_error_hva(host_addr))) |
314 | goto error; | 332 | goto error; |
315 | 333 | ||