Skip to content

Commit

Permalink
KVM: Move guest pte dirty bit management to the guest pagetable walker
Browse files Browse the repository at this point in the history
This is more consistent with the accessed bit management, and makes the dirty
bit available earlier for other purposes.

Signed-off-by: Avi Kivity <avi@qumranet.com>
  • Loading branch information
Avi Kivity committed Jan 30, 2008
1 parent 4a4c992 commit e3c5e7e
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 23 deletions.
5 changes: 5 additions & 0 deletions drivers/kvm/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ static int is_writeble_pte(unsigned long pte)
return pte & PT_WRITABLE_MASK;
}

static int is_dirty_pte(unsigned long pte)
{
return pte & PT_DIRTY_MASK;
}

static int is_io_pte(unsigned long pte)
{
return pte & PT_SHADOW_IO_MARK;
Expand Down
31 changes: 8 additions & 23 deletions drivers/kvm/paging_tmpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ static int FNAME(walk_addr)(struct guest_walker *walker,
if (walker->level == PT_PAGE_TABLE_LEVEL) {
walker->gfn = (*ptep & PT_BASE_ADDR_MASK)
>> PAGE_SHIFT;
if (write_fault && !is_dirty_pte(*ptep)) {
mark_page_dirty(vcpu->kvm, table_gfn);
*ptep |= PT_DIRTY_MASK;
}
break;
}

Expand All @@ -153,6 +157,10 @@ static int FNAME(walk_addr)(struct guest_walker *walker,
walker->gfn = (*ptep & PT_DIR_BASE_ADDR_MASK)
>> PAGE_SHIFT;
walker->gfn += PT_INDEX(addr, PT_PAGE_TABLE_LEVEL);
if (write_fault && !is_dirty_pte(*ptep)) {
mark_page_dirty(vcpu->kvm, table_gfn);
*ptep |= PT_DIRTY_MASK;
}
break;
}

Expand Down Expand Up @@ -194,12 +202,6 @@ static int FNAME(walk_addr)(struct guest_walker *walker,
return 0;
}

static void FNAME(mark_pagetable_dirty)(struct kvm *kvm,
struct guest_walker *walker)
{
mark_page_dirty(kvm, walker->table_gfn[walker->level - 1]);
}

static void FNAME(set_pte_common)(struct kvm_vcpu *vcpu,
u64 *shadow_pte,
gpa_t gaddr,
Expand All @@ -221,23 +223,6 @@ static void FNAME(set_pte_common)(struct kvm_vcpu *vcpu,
__FUNCTION__, *shadow_pte, (u64)gpte, access_bits,
write_fault, user_fault, gfn);

if (write_fault && !dirty) {
pt_element_t *guest_ent, *tmp = NULL;

if (walker->ptep)
guest_ent = walker->ptep;
else {
tmp = kmap_atomic(walker->page, KM_USER0);
guest_ent = &tmp[walker->index];
}

*guest_ent |= PT_DIRTY_MASK;
if (!walker->ptep)
kunmap_atomic(tmp, KM_USER0);
dirty = 1;
FNAME(mark_pagetable_dirty)(vcpu->kvm, walker);
}

/*
* We don't set the accessed bit, since we sometimes want to see
* whether the guest actually used the pte (in order to detect
Expand Down

0 comments on commit e3c5e7e

Please sign in to comment.