diff options
-rw-r--r-- | drivers/kvm/mmu.c | 5 | ||||
-rw-r--r-- | drivers/kvm/paging_tmpl.h | 31 |
2 files changed, 13 insertions, 23 deletions
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c index d046ba80776..e6616a6c9ce 100644 --- a/drivers/kvm/mmu.c +++ b/drivers/kvm/mmu.c | |||
@@ -199,6 +199,11 @@ static int is_writeble_pte(unsigned long pte) | |||
199 | return pte & PT_WRITABLE_MASK; | 199 | return pte & PT_WRITABLE_MASK; |
200 | } | 200 | } |
201 | 201 | ||
202 | static int is_dirty_pte(unsigned long pte) | ||
203 | { | ||
204 | return pte & PT_DIRTY_MASK; | ||
205 | } | ||
206 | |||
202 | static int is_io_pte(unsigned long pte) | 207 | static int is_io_pte(unsigned long pte) |
203 | { | 208 | { |
204 | return pte & PT_SHADOW_IO_MARK; | 209 | return pte & PT_SHADOW_IO_MARK; |
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h index 8e1e4ca6ea4..da36e48fd02 100644 --- a/drivers/kvm/paging_tmpl.h +++ b/drivers/kvm/paging_tmpl.h | |||
@@ -144,6 +144,10 @@ static int FNAME(walk_addr)(struct guest_walker *walker, | |||
144 | if (walker->level == PT_PAGE_TABLE_LEVEL) { | 144 | if (walker->level == PT_PAGE_TABLE_LEVEL) { |
145 | walker->gfn = (*ptep & PT_BASE_ADDR_MASK) | 145 | walker->gfn = (*ptep & PT_BASE_ADDR_MASK) |
146 | >> PAGE_SHIFT; | 146 | >> PAGE_SHIFT; |
147 | if (write_fault && !is_dirty_pte(*ptep)) { | ||
148 | mark_page_dirty(vcpu->kvm, table_gfn); | ||
149 | *ptep |= PT_DIRTY_MASK; | ||
150 | } | ||
147 | break; | 151 | break; |
148 | } | 152 | } |
149 | 153 | ||
@@ -153,6 +157,10 @@ static int FNAME(walk_addr)(struct guest_walker *walker, | |||
153 | walker->gfn = (*ptep & PT_DIR_BASE_ADDR_MASK) | 157 | walker->gfn = (*ptep & PT_DIR_BASE_ADDR_MASK) |
154 | >> PAGE_SHIFT; | 158 | >> PAGE_SHIFT; |
155 | walker->gfn += PT_INDEX(addr, PT_PAGE_TABLE_LEVEL); | 159 | walker->gfn += PT_INDEX(addr, PT_PAGE_TABLE_LEVEL); |
160 | if (write_fault && !is_dirty_pte(*ptep)) { | ||
161 | mark_page_dirty(vcpu->kvm, table_gfn); | ||
162 | *ptep |= PT_DIRTY_MASK; | ||
163 | } | ||
156 | break; | 164 | break; |
157 | } | 165 | } |
158 | 166 | ||
@@ -194,12 +202,6 @@ err: | |||
194 | return 0; | 202 | return 0; |
195 | } | 203 | } |
196 | 204 | ||
197 | static void FNAME(mark_pagetable_dirty)(struct kvm *kvm, | ||
198 | struct guest_walker *walker) | ||
199 | { | ||
200 | mark_page_dirty(kvm, walker->table_gfn[walker->level - 1]); | ||
201 | } | ||
202 | |||
203 | static void FNAME(set_pte_common)(struct kvm_vcpu *vcpu, | 205 | static void FNAME(set_pte_common)(struct kvm_vcpu *vcpu, |
204 | u64 *shadow_pte, | 206 | u64 *shadow_pte, |
205 | gpa_t gaddr, | 207 | gpa_t gaddr, |
@@ -221,23 +223,6 @@ static void FNAME(set_pte_common)(struct kvm_vcpu *vcpu, | |||
221 | __FUNCTION__, *shadow_pte, (u64)gpte, access_bits, | 223 | __FUNCTION__, *shadow_pte, (u64)gpte, access_bits, |
222 | write_fault, user_fault, gfn); | 224 | write_fault, user_fault, gfn); |
223 | 225 | ||
224 | if (write_fault && !dirty) { | ||
225 | pt_element_t *guest_ent, *tmp = NULL; | ||
226 | |||
227 | if (walker->ptep) | ||
228 | guest_ent = walker->ptep; | ||
229 | else { | ||
230 | tmp = kmap_atomic(walker->page, KM_USER0); | ||
231 | guest_ent = &tmp[walker->index]; | ||
232 | } | ||
233 | |||
234 | *guest_ent |= PT_DIRTY_MASK; | ||
235 | if (!walker->ptep) | ||
236 | kunmap_atomic(tmp, KM_USER0); | ||
237 | dirty = 1; | ||
238 | FNAME(mark_pagetable_dirty)(vcpu->kvm, walker); | ||
239 | } | ||
240 | |||
241 | /* | 226 | /* |
242 | * We don't set the accessed bit, since we sometimes want to see | 227 | * We don't set the accessed bit, since we sometimes want to see |
243 | * whether the guest actually used the pte (in order to detect | 228 | * whether the guest actually used the pte (in order to detect |