aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-02-19 07:37:46 -0500
committerAvi Kivity <avi@qumranet.com>2007-03-04 04:12:39 -0500
commitbf3f8e86c2e22b9bd1375be1bbbd67384dba4342 (patch)
tree0c0435a394885d1e679025a6a39c29f90b6282af /drivers
parentbb648a0d22908116b4ef168935a160d7f17c4e6d (diff)
KVM: mmu: add missing dirty page tracking cases
We fail to mark a page dirty in three cases: - setting the accessed bit in a pte - setting the dirty bit in a pte - emulating a write into a pagetable This fix adds the missing cases. Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/kvm/paging_tmpl.h15
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index b6b90e9e1301..6507ccb1ea2a 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -128,8 +128,10 @@ static int FNAME(walk_addr)(struct guest_walker *walker,
128 goto access_error; 128 goto access_error;
129#endif 129#endif
130 130
131 if (!(*ptep & PT_ACCESSED_MASK)) 131 if (!(*ptep & PT_ACCESSED_MASK)) {
132 *ptep |= PT_ACCESSED_MASK; /* avoid rmw */ 132 mark_page_dirty(vcpu->kvm, table_gfn);
133 *ptep |= PT_ACCESSED_MASK;
134 }
133 135
134 if (walker->level == PT_PAGE_TABLE_LEVEL) { 136 if (walker->level == PT_PAGE_TABLE_LEVEL) {
135 walker->gfn = (*ptep & PT_BASE_ADDR_MASK) 137 walker->gfn = (*ptep & PT_BASE_ADDR_MASK)
@@ -185,6 +187,12 @@ static void FNAME(release_walker)(struct guest_walker *walker)
185 kunmap_atomic(walker->table, KM_USER0); 187 kunmap_atomic(walker->table, KM_USER0);
186} 188}
187 189
190static void FNAME(mark_pagetable_dirty)(struct kvm *kvm,
191 struct guest_walker *walker)
192{
193 mark_page_dirty(kvm, walker->table_gfn[walker->level - 1]);
194}
195
188static void FNAME(set_pte)(struct kvm_vcpu *vcpu, u64 guest_pte, 196static void FNAME(set_pte)(struct kvm_vcpu *vcpu, u64 guest_pte,
189 u64 *shadow_pte, u64 access_bits, gfn_t gfn) 197 u64 *shadow_pte, u64 access_bits, gfn_t gfn)
190{ 198{
@@ -348,12 +356,15 @@ static int FNAME(fix_write_pf)(struct kvm_vcpu *vcpu,
348 } else if (kvm_mmu_lookup_page(vcpu, gfn)) { 356 } else if (kvm_mmu_lookup_page(vcpu, gfn)) {
349 pgprintk("%s: found shadow page for %lx, marking ro\n", 357 pgprintk("%s: found shadow page for %lx, marking ro\n",
350 __FUNCTION__, gfn); 358 __FUNCTION__, gfn);
359 mark_page_dirty(vcpu->kvm, gfn);
360 FNAME(mark_pagetable_dirty)(vcpu->kvm, walker);
351 *guest_ent |= PT_DIRTY_MASK; 361 *guest_ent |= PT_DIRTY_MASK;
352 *write_pt = 1; 362 *write_pt = 1;
353 return 0; 363 return 0;
354 } 364 }
355 mark_page_dirty(vcpu->kvm, gfn); 365 mark_page_dirty(vcpu->kvm, gfn);
356 *shadow_ent |= PT_WRITABLE_MASK; 366 *shadow_ent |= PT_WRITABLE_MASK;
367 FNAME(mark_pagetable_dirty)(vcpu->kvm, walker);
357 *guest_ent |= PT_DIRTY_MASK; 368 *guest_ent |= PT_DIRTY_MASK;
358 rmap_add(vcpu, shadow_ent); 369 rmap_add(vcpu, shadow_ent);
359 370