KVM: MMU: fix kvm_mmu_slot_remove_write_access
PATCH 1/10 KVM: MMU: fix kvm_mmu_slot_remove_write_access
Only remove write access in the last sptes
--- arch/x86/kvm/mmu.c | 9 +++++++-- 1 files changed, 7 insertions(+), 2 deletions(-)
arch/x86/kvm/mmu.c +7 -2
@@ -3540,12 +3540,17 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot) pt = sp->spt;for (i =0 ; i <PT64_ENT_PER_PAGE ; ++i) { -if (sp->role.level !=PT_PAGE_TABLE_LEVEL - &&is_large_pte (pt[i])) { +if (!is_shadow_present_pte (pt[i]) || + !is_last_spte (pt[i], sp->role.level)) +continue ; + +if (is_large_pte (pt[i])) {drop_spte (kvm, &pt[i], shadow_trap_nonpresent_pte); --kvm->stat.lpages; +continue ; } +/* avoid RMW */ if (is_writable_pte (pt[i]))update_spte (&pt[i], pt[i] & ~PT_WRITABLE_MASK );
Signature · 1 line
1.7.4
PATCH 2/10 KVM: MMU: fix kvm_mmu_get_spte_hierarchy
Don not walk to the next level if spte is mapping to the large page
--- arch/x86/kvm/mmu.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
arch/x86/kvm/mmu.c +2 -1
@@ -3819,7 +3819,8 @@ int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4])for_each_shadow_entry (vcpu, addr, iterator) { sptes[iterator.level-1 ] = *iterator.sptep; nr_sptes++; -if (!is_shadow_present_pte (*iterator.sptep)) +if (!is_shadow_present_pte (*iterator.sptep) || +is_last_spte (*iterator.sptep, iterator.level))break ; }spin_unlock (&vcpu->kvm->mmu_lock);
Signature · 1 line
1.7.4
Re: [PATCH 2/10] KVM: MMU: fix kvm_mmu_get_spte_hierarchy
Quoted 12 lines · Xiao Guangrong
Don not walk to the next level if spte is mapping to the large page
Signed-off-by Xiao Guangrong <[email protected]>--- arch/x86/kvm/mmu.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)arch/x86/kvm/mmu.c +0
-0
arch/x86/kvm/mmu.c int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4]) · line 3826
Quoted 9 lines
arch/x86/kvm/mmu.c +2
-1@@ -3819,7 +3819,8 @@ int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4])for_each_shadow_entry (vcpu, addr, iterator) { sptes[iterator.level-1 ] = *iterator.sptep; nr_sptes++; -if (!is_shadow_present_pte (*iterator.sptep)) +if (!is_shadow_present_pte (*iterator.sptep) || +is_last_spte (*iterator.sptep, iterator.level))break ; }spin_unlock (&vcpu->kvm->mmu_lock);
shadow_walk_okay covers that case.
Re: [PATCH 2/10] KVM: MMU: fix kvm_mmu_get_spte_hierarchy
Quoted 8 lines · Marcelo Tosatti
Quoted 7 lines · Xiao Guangrong
Don not walk to the next level if spte is mapping to the large page
Signed-off-by Xiao Guangrong <[email protected]>--- arch/x86/kvm/mmu.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
Quoted 17 lines
Quoted 5 lines
arch/x86/kvm/mmu.c +0
-0arch/x86/kvm/mmu.c int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4]) · line 3826
Quoted 9 lines
arch/x86/kvm/mmu.c +2
-1@@ -3819,7 +3819,8 @@ int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4])for_each_shadow_entry (vcpu, addr, iterator) { sptes[iterator.level-1 ] = *iterator.sptep; nr_sptes++; -if (!is_shadow_present_pte (*iterator.sptep)) +if (!is_shadow_present_pte (*iterator.sptep) || +is_last_spte (*iterator.sptep, iterator.level))break ; }spin_unlock (&vcpu->kvm->mmu_lock);
shadow_walk_okaycovers that case.
We can get the large mapping pte in the loop:
static bool shadow_walk_okay(struct kvm_shadow_walk_iterator *iterator)
{
if (iterator->level < PT_PAGE_TABLE_LEVEL)
return false;
if (iterator->level == PT_PAGE_TABLE_LEVEL)
if (is_large_pte(*iterator->sptep))
return false;
......
}if level > 1 and pte.pse is set, it will return true.
And, i think this judgment is useless:
if (iterator->level == PT_PAGE_TABLE_LEVEL) if (is_large_pte(*iterator->sptep)) return false;
since if level = 1, the pte bit7 is PAT.
Re: [PATCH 2/10] KVM: MMU: fix kvm_mmu_get_spte_hierarchy
Quoted 16 lines · Xiao Guangrong
We can get the large mapping pte in the loop:
static bool
shadow_walk_okay(struct kvm_shadow_walk_iterator *iterator){ if (iterator->level< PT_PAGE_TABLE_LEVEL) return false; if (iterator->level == PT_PAGE_TABLE_LEVEL) if (is_large_pte(*iterator->sptep)) return false; ...... }
Quoted 7 lines
if level> 1 and pte.pse is set, it will return true.
And, i think this judgment is useless:
if (iterator->level == PT_PAGE_TABLE_LEVEL) if (is_large_pte(*iterator->sptep)) return false;since if level = 1, the pte bit7 is PAT.
Right, the logic is inverted. I'll fix it up.
Signature · 1 line
error compiling committee.c: too many arguments to function
PATCH 3/10 KVM: MMU: set spte accessed bit properly
In reply to Xiao GuangrongSet spte accessed bit only if guest_initiated == 1 that means the really accessed
--- arch/x86/kvm/mmu.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/x86/kvm/mmu.c +1 -1
@@ -3307,11 +3307,11 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,spin_lock (&vcpu->kvm->mmu_lock);if (atomic_read (&vcpu->kvm->arch.invlpg_counter) != invlpg_counter) gentry =0 ; -kvm_mmu_access_page (vcpu, gfn);kvm_mmu_free_some_pages (vcpu); ++vcpu->kvm->stat.mmu_pte_write;trace_kvm_mmu_audit (vcpu,AUDIT_PRE_PTE_WRITE );if (guest_initiated) { +kvm_mmu_access_page (vcpu, gfn);if (gfn == vcpu->arch.last_pt_write_gfn && !last_updated_pte_accessed (vcpu)) { ++vcpu->arch.last_pt_write_count;
Signature · 1 line
1.7.4
PATCH 4/10 KVM: fix rcu usage in init_rmode_* functions
In reply to Xiao Guangrongfix:
[ 3494.671786] stack backtrace: [ 3494.671789] Pid: 10527, comm: qemu-system-x86 Not tainted 2.6.38-rc6+ #23 [ 3494.671790] Call Trace: [ 3494.671796] [<ffffffff8107d15f>] ? lockdep_rcu_dereference+0x9d/0xa5 [ 3494.671826] [<ffffffffa03498be>] ? kvm_memslots+0x6b/0x73 [kvm] [ 3494.671834] [<ffffffffa03499be>] ? gfn_to_memslot+0x16/0x4f [kvm] [ 3494.671843] [<ffffffffa0349a0d>] ? gfn_to_hva+0x16/0x27 [kvm] [ 3494.671851] [<ffffffffa034c1c4>] ? kvm_write_guest_page+0x31/0x83 [kvm] [ 3494.671861] [<ffffffffa034c230>] ? kvm_clear_guest_page+0x1a/0x1c [kvm] [ 3494.671867] [<ffffffffa015e321>] ? vmx_set_tss_addr+0x83/0x122 [kvm_intel]
and:
[ 8328.789599] stack backtrace: [ 8328.789601] Pid: 18736, comm: qemu-system-x86 Not tainted 2.6.38-rc6+ #23 [ 8328.789603] Call Trace: [ 8328.789609] [<ffffffff8107d15f>] ? lockdep_rcu_dereference+0x9d/0xa5 [ 8328.789621] [<ffffffffa03988be>] ? kvm_memslots+0x6b/0x73 [kvm] [ 8328.789628] [<ffffffffa03989be>] ? gfn_to_memslot+0x16/0x4f [kvm] [ 8328.789635] [<ffffffffa0398a0d>] ? gfn_to_hva+0x16/0x27 [kvm] [ 8328.789643] [<ffffffffa039b1c4>] ? kvm_write_guest_page+0x31/0x83 [kvm] [ 8328.789699] [<ffffffffa039b230>] ? kvm_clear_guest_page+0x1a/0x1c [kvm] [ 8328.789713] [<ffffffffa0206d0e>] ? vmx_create_vcpu+0x316/0x3c8 [kvm_intel]
--- arch/x86/kvm/vmx.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-)
arch/x86/kvm/vmx.c +7 -3
@@ -2399,9 +2399,10 @@ static int init_rmode_tss(struct kvm *kvm) {gfn_t fn =rmode_tss_base (kvm) >>PAGE_SHIFT ;u16 data =0 ; -int ret =0 ; -int r; +int r, idx, ret =0 ; + idx =srcu_read_lock (&kvm->srcu); + fn =rmode_tss_base (kvm) >>PAGE_SHIFT ; r =kvm_clear_guest_page (kvm, fn,0 ,PAGE_SIZE );if (r <0 ) goto out;
@@ -2425,12 +2426,13 @@ static int init_rmode_tss(struct kvm *kvm) ret =1 ; out: +srcu_read_unlock (&kvm->srcu, idx);return ret; }static int init_rmode_identity_map (struct kvm *kvm) { -int i, r, ret; +int i, idx, r, ret;pfn_t identity_map_pfn;u32 tmp;
@@ -2445,6 +2447,7 @@ static int init_rmode_identity_map(struct kvm *kvm)return 1 ; ret =0 ; identity_map_pfn = kvm->arch.ept_identity_map_addr >>PAGE_SHIFT ; + idx =srcu_read_lock (&kvm->srcu); r =kvm_clear_guest_page (kvm, identity_map_pfn,0 ,PAGE_SIZE );if (r <0 ) goto out;
@@ -2460,6 +2463,7 @@ static int init_rmode_identity_map(struct kvm *kvm) kvm->arch.ept_identity_pagetable_done = true; ret =1 ; out: +srcu_read_unlock (&kvm->srcu, idx);return ret; }
Signature · 1 line
1.7.4
Re: [PATCH 4/10] KVM: fix rcu usage in init_rmode_* functions
Quoted 34 lines · Xiao Guangrong
fix:
[ 3494.671786] stack backtrace: [ 3494.671789] Pid: 10527, comm: qemu-system-x86 Not tainted 2.6.38-rc6+ #23 [ 3494.671790] Call Trace: [ 3494.671796] [<ffffffff8107d15f>] ? lockdep_rcu_dereference+0x9d/0xa5 [ 3494.671826] [<ffffffffa03498be>] ? kvm_memslots+0x6b/0x73 [kvm] [ 3494.671834] [<ffffffffa03499be>] ? gfn_to_memslot+0x16/0x4f [kvm] [ 3494.671843] [<ffffffffa0349a0d>] ? gfn_to_hva+0x16/0x27 [kvm] [ 3494.671851] [<ffffffffa034c1c4>] ? kvm_write_guest_page+0x31/0x83 [kvm] [ 3494.671861] [<ffffffffa034c230>] ? kvm_clear_guest_page+0x1a/0x1c [kvm] [ 3494.671867] [<ffffffffa015e321>] ? vmx_set_tss_addr+0x83/0x122 [kvm_intel]and:
[ 8328.789599] stack backtrace: [ 8328.789601] Pid: 18736, comm: qemu-system-x86 Not tainted 2.6.38-rc6+ #23 [ 8328.789603] Call Trace: [ 8328.789609] [<ffffffff8107d15f>] ? lockdep_rcu_dereference+0x9d/0xa5 [ 8328.789621] [<ffffffffa03988be>] ? kvm_memslots+0x6b/0x73 [kvm] [ 8328.789628] [<ffffffffa03989be>] ? gfn_to_memslot+0x16/0x4f [kvm] [ 8328.789635] [<ffffffffa0398a0d>] ? gfn_to_hva+0x16/0x27 [kvm] [ 8328.789643] [<ffffffffa039b1c4>] ? kvm_write_guest_page+0x31/0x83 [kvm] [ 8328.789699] [<ffffffffa039b230>] ? kvm_clear_guest_page+0x1a/0x1c [kvm] [ 8328.789713] [<ffffffffa0206d0e>] ? vmx_create_vcpu+0x316/0x3c8 [kvm_intel]Signed-off-by Xiao Guangrong <[email protected]>--- arch/x86/kvm/vmx.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-)arch/x86/kvm/vmx.c +0
-0
arch/x86/kvm/vmx.c static int init_rmode_tss(struct kvm *kvm) · line 2400
Quoted 2 lines
arch/x86/kvm/vmx.c +0
-0@@ -2399,9 +2399,10 @@ static int init_rmode_tss(struct kvm *kvm) {gfn_t fn =rmode_tss_base (kvm) >>PAGE_SHIFT ;
I bet you also wanted to remove this initialization.
arch/x86/kvm/vmx.c static int init_rmode_tss(struct kvm *kvm) · line 2408
Quoted 10 lines
arch/x86/kvm/vmx.c +3
-2u16 data =0 ; -int ret =0 ; -int r; +int r, idx, ret =0 ; + idx =srcu_read_lock (&kvm->srcu); + fn =rmode_tss_base (kvm) >>PAGE_SHIFT ; r =kvm_clear_guest_page (kvm, fn,0 ,PAGE_SIZE );if (r <0 ) goto out;
Jan
Signature · 2 lines
Siemens AG, Corporate Technology, CT T DE IT 1 Corporate Competence Center Embedded Linux
Re: [PATCH 4/10] KVM: fix rcu usage in init_rmode_* functions
Quoted 30 lines · Jan Kiszka
Quoted 29 lines · Xiao Guangrong
fix:
[ 3494.671786] stack backtrace: [ 3494.671789] Pid: 10527, comm: qemu-system-x86 Not tainted 2.6.38-rc6+ #23 [ 3494.671790] Call Trace: [ 3494.671796] [<ffffffff8107d15f>] ? lockdep_rcu_dereference+0x9d/0xa5 [ 3494.671826] [<ffffffffa03498be>] ? kvm_memslots+0x6b/0x73 [kvm] [ 3494.671834] [<ffffffffa03499be>] ? gfn_to_memslot+0x16/0x4f [kvm] [ 3494.671843] [<ffffffffa0349a0d>] ? gfn_to_hva+0x16/0x27 [kvm] [ 3494.671851] [<ffffffffa034c1c4>] ? kvm_write_guest_page+0x31/0x83 [kvm] [ 3494.671861] [<ffffffffa034c230>] ? kvm_clear_guest_page+0x1a/0x1c [kvm] [ 3494.671867] [<ffffffffa015e321>] ? vmx_set_tss_addr+0x83/0x122 [kvm_intel]and:
[ 8328.789599] stack backtrace: [ 8328.789601] Pid: 18736, comm: qemu-system-x86 Not tainted 2.6.38-rc6+ #23 [ 8328.789603] Call Trace: [ 8328.789609] [<ffffffff8107d15f>] ? lockdep_rcu_dereference+0x9d/0xa5 [ 8328.789621] [<ffffffffa03988be>] ? kvm_memslots+0x6b/0x73 [kvm] [ 8328.789628] [<ffffffffa03989be>] ? gfn_to_memslot+0x16/0x4f [kvm] [ 8328.789635] [<ffffffffa0398a0d>] ? gfn_to_hva+0x16/0x27 [kvm] [ 8328.789643] [<ffffffffa039b1c4>] ? kvm_write_guest_page+0x31/0x83 [kvm] [ 8328.789699] [<ffffffffa039b230>] ? kvm_clear_guest_page+0x1a/0x1c [kvm] [ 8328.789713] [<ffffffffa0206d0e>] ? vmx_create_vcpu+0x316/0x3c8 [kvm_intel]Signed-off-by Xiao Guangrong <[email protected]>--- arch/x86/kvm/vmx.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-)
Quoted 10 lines
arch/x86/kvm/vmx.c static int init_rmode_tss(struct kvm *kvm) · line 2400
Quoted 7 lines
arch/x86/kvm/vmx.c +0
-0@@ -2399,9 +2399,10 @@ static int init_rmode_tss(struct kvm *kvm) {gfn_t fn =rmode_tss_base (kvm) >>PAGE_SHIFT ;I bet you also wanted to remove this initialization.
Ouch, thank you for reminding me of that!
PATCH 5/10 KVM: MMU: move mmu pages calculated out of mmu lock
In reply to Xiao Guangrongkvm_mmu_calculate_mmu_pages need to walk all memslots and it's protected by kvm->slots_lock, so move it out of mmu spinlock
--- arch/x86/kvm/x86.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
arch/x86/kvm/x86.c +5 -5
@@ -6105,7 +6105,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, int user_alloc) { -int npages = mem->memory_size >>PAGE_SHIFT ; +int nr_mmu_pages =0 , npages = mem->memory_size >>PAGE_SHIFT ;if (!user_alloc && !old.user_alloc && old.rmap && !npages) {int ret;
@@ -6120,12 +6120,12 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, "failed to munmap memory\n"); } +if (!kvm->arch.n_requested_mmu_pages) + nr_mmu_pages =kvm_mmu_calculate_mmu_pages (kvm); +spin_lock (&kvm->mmu_lock); -if (!kvm->arch.n_requested_mmu_pages) { -unsigned int nr_mmu_pages =kvm_mmu_calculate_mmu_pages (kvm); +if (nr_mmu_pages)kvm_mmu_change_mmu_pages (kvm, nr_mmu_pages); - } -kvm_mmu_slot_remove_write_access (kvm, mem->slot);spin_unlock (&kvm->mmu_lock); }
Signature · 1 line
1.7.4
PATCH 6/10 KVM: MMU: don not record gfn in kvm_mmu_pte_write
In reply to Xiao GuangrongNo need to record the gfn to verifier the pte has the same mode as current vcpu, it's because we only speculatively update the pte only if the pte and vcpu have the same mode
--- arch/x86/include/asm/kvm_host.h | 1 - arch/x86/kvm/mmu.c | 6 ++---- arch/x86/kvm/paging_tmpl.h | 2 -- 3 files changed, 2 insertions(+), 7 deletions(-)
arch/x86/include/asm/kvm_host.h +0 -1
@@ -336,7 +336,6 @@ struct kvm_vcpu_arch {gfn_t last_pte_gfn;struct { -gfn_t gfn;/* presumed gfn during guest pte update */ pfn_t pfn;/* pfn corresponding to that gfn */ unsigned long mmu_seq; } update_pte;
arch/x86/kvm/mmu.c +2 -4
@@ -3228,7 +3228,6 @@ static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,kvm_release_pfn_clean (pfn);return ; } - vcpu->arch.update_pte.gfn = gfn; vcpu->arch.update_pte.pfn = pfn; }
@@ -3275,9 +3274,8 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,/* * Assume that the pte write on a page table of the same type -* as the current vcpu paging mode. This is nearly always true -* (might be false while changing modes). Note it is verified later -* by update_pte(). +* as the current vcpu paging mode since we update the sptes only +* when they have the same mode. */ if ((is_pae (vcpu) && bytes ==4 ) || !new) {/* Handle a 32-bit guest writing two halves of a 64-bit gpte */
arch/x86/kvm/paging_tmpl.h +0 -2
@@ -339,8 +339,6 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,pgprintk ("%s: gpte %llx spte %p\n" , __func__, (u64 )gpte, spte); pte_access = sp->role.access &FNAME (gpte_access)(vcpu, gpte); -if (gpte_to_gfn (gpte) != vcpu->arch.update_pte.gfn) -return ; pfn = vcpu->arch.update_pte.pfn;if (is_error_pfn (pfn))return ;
Signature · 1 line
1.7.4
Re: [PATCH 6/10] KVM: MMU: don not record gfn in kvm_mmu_pte_write
Quoted 3 lines · Xiao Guangrong
No need to record the gfn to verifier the pte has the same mode as current vcpu, it's because we only speculatively update the pte only if the pte and vcpu have the same mode
True. We can, as an additional cleanup, change mmu_pte_write_new_pte() to just do vcpu->arch.mmu.update_spte(...) instead of the if ().
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [PATCH 6/10] KVM: MMU: don not record gfn in kvm_mmu_pte_write
Quoted 7 lines · Avi Kivity
Quoted 3 lines · Xiao Guangrong
No need to record the gfn to verifier the pte has the same mode as current vcpu, it's because we only speculatively update the pte only if the pte and vcpu have the same mode
True. We can, as an additional cleanup, change
mmu_pte_write_new_pte()to just dovcpu->arch.mmu.update_pte(...)instead of the if ().
Also, we can remove the pfn guessing and to it in FNAME(update_pte), using gfn_to_pfn_atomic().
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [PATCH 6/10] KVM: MMU: don not record gfn in kvm_mmu_pte_write
Quoted 11 lines · Avi Kivity
Quoted 7 lines · Avi Kivity
Quoted 3 lines · Xiao Guangrong
No need to record the gfn to verifier the pte has the same mode as current vcpu, it's because we only speculatively update the pte only if the pte and vcpu have the same mode
True. We can, as an additional cleanup, change
mmu_pte_write_new_pte()to just dovcpu->arch.mmu.update_pte(...)instead of the if ().Also, we can remove the pfn guessing and to it in
FNAME(update_pte), usinggfn_to_pfn_atomic().
OK, i'll do these in the next version, thanks!
PATCH 7/10 KVM: MMU: introduce a common function to get no-dirty-logged slot
In reply to Xiao Guangrongpte_prefetch_gfn_to_memslot and mapping_level_dirty_bitmap have the same operation, so integrated
--- arch/x86/kvm/mmu.c | 26 ++++++++++++++++++-------- 1 files changed, 18 insertions(+), 8 deletions(-)
arch/x86/kvm/mmu.c +18 -8
@@ -554,13 +554,24 @@ static int host_mapping_level(struct kvm *kvm, gfn_t gfn)return ret; } -static bool mapping_level_dirty_bitmap (struct kvm_vcpu *vcpu,gfn_t large_gfn) +static struct kvm_memory_slot * +gfn_to_memslot_dirty_bitmap (struct kvm_vcpu *vcpu,gfn_t gfn,bool no_dirty_log) {struct kvm_memory_slot *slot; - slot =gfn_to_memslot (vcpu->kvm, large_gfn); -if (slot && slot->dirty_bitmap) -return true; -return false; + + slot =gfn_to_memslot (vcpu->kvm, gfn); +if (!slot) +return NULL ; + +if (no_dirty_log && slot->dirty_bitmap) +return NULL ; + +return slot; +} + +static bool mapping_level_dirty_bitmap (struct kvm_vcpu *vcpu,gfn_t large_gfn) +{ +return !!gfn_to_memslot_dirty_bitmap (vcpu, large_gfn, true); }static int mapping_level (struct kvm_vcpu *vcpu,gfn_t large_gfn)
@@ -2155,9 +2166,8 @@ pte_prefetch_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn, bool no_dirty_log) {struct kvm_memory_slot *slot; - slot =gfn_to_memslot (vcpu->kvm, gfn); -if (!slot || slot->flags &KVM_MEMSLOT_INVALID || - (no_dirty_log && slot->dirty_bitmap)) + slot =gfn_to_memslot_dirty_bitmap (vcpu, gfn, no_dirty_log); +if (slot && slot->flags &KVM_MEMSLOT_INVALID ) slot =NULL ;return slot;
Signature · 1 line
1.7.4
Re: [PATCH 7/10] KVM: MMU: introduce a common function to get no-dirty-logged slot
Quoted 30 lines · Xiao Guangrong
pte_prefetch_gfn_to_memslotandmapping_level_dirty_bitmaphave the same operation, so integratedSigned-off-by Xiao Guangrong<[email protected]>--- arch/x86/kvm/mmu.c | 26 ++++++++++++++++++-------- 1 files changed, 18 insertions(+), 8 deletions(-)arch/x86/kvm/mmu.c +7
-5@@ -554,13 +554,24 @@ static int host_mapping_level(struct kvm *kvm, gfn_t gfn)return ret; } -static bool mapping_level_dirty_bitmap (struct kvm_vcpu *vcpu,gfn_t large_gfn) +static struct kvm_memory_slot * +gfn_to_memslot_dirty_bitmap (struct kvm_vcpu *vcpu,gfn_t gfn,bool no_dirty_log) {struct kvm_memory_slot *slot; - slot =gfn_to_memslot (vcpu->kvm, large_gfn); -if (slot&& slot->dirty_bitmap) -return true; -return false; + + slot =gfn_to_memslot (vcpu->kvm, gfn); +if (!slot) +return NULL ; +
arch/x86/kvm/mmu.c static int host_mapping_level(struct kvm *kvm, gfn_t gfn) · line 575
Quoted 10 lines
arch/x86/kvm/mmu.c +9
-0+if (no_dirty_log&& slot->dirty_bitmap) +return NULL ; + +return slot; +} + +static bool mapping_level_dirty_bitmap (struct kvm_vcpu *vcpu,gfn_t large_gfn) +{ +return !!gfn_to_memslot_dirty_bitmap (vcpu, large_gfn, true); }
!! !needed.
Quoted 4 lines
arch/x86/kvm/mmu.c +0
-0static int mapping_level (struct kvm_vcpu *vcpu,gfn_t large_gfn)@@ -2155,9 +2166,8 @@ pte_prefetch_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn, bool no_dirty_log) {
arch/x86/kvm/mmu.c pte_prefetch_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn, bool no_dirty_log) · line 2173
Quoted 10 lines
arch/x86/kvm/mmu.c +2
-3struct kvm_memory_slot *slot; - slot =gfn_to_memslot (vcpu->kvm, gfn); -if (!slot || slot->flags&KVM_MEMSLOT_INVALID || - (no_dirty_log&& slot->dirty_bitmap)) + slot =gfn_to_memslot_dirty_bitmap (vcpu, gfn, no_dirty_log); +if (slot&& slot->flags&KVM_MEMSLOT_INVALID ) slot =NULL ;return slot;
For a unification this adds a lot of code... I think the result is more complicated than the starting point.
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [PATCH 7/10] KVM: MMU: introduce a common function to get no-dirty-logged slot
Quoted 12 lines · Avi Kivity
Quoted 12 lines
static int
mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn)arch/x86/kvm/mmu.c +2
-3@@ -2155,9 +2166,8 @@ pte_prefetch_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn, bool no_dirty_log) {struct kvm_memory_slot *slot; - slot =gfn_to_memslot (vcpu->kvm, gfn); -if (!slot || slot->flags&KVM_MEMSLOT_INVALID || - (no_dirty_log&& slot->dirty_bitmap)) + slot =gfn_to_memslot_dirty_bitmap (vcpu, gfn, no_dirty_log); +if (slot&& slot->flags&KVM_MEMSLOT_INVALID ) slot =NULL ;
Quoted 4 lines
arch/x86/kvm/mmu.c pte_prefetch_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn, bool no_dirty_log) · line 2173
Quoted 1 line
arch/x86/kvm/mmu.c +0
-0return slot;For a unification this adds a lot of code... I think the result is more complicated than the starting point.
After more thinking, i think we can move 'slot->flags& KVM_MEMSLOT_INVALID' into the common function, since the later gva_to_pfn also can filter this out.
PATCH 8/10 KVM: MMU: cleanup page alloc and free
In reply to Xiao GuangrongUsing __get_free_page instead of alloc_page and page_address, using free_page instead of __free_page and virt_to_page
--- arch/x86/kvm/mmu.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
arch/x86/kvm/mmu.c +5 -5
@@ -379,15 +379,15 @@ static void mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc,static int mmu_topup_memory_cache_page (struct kvm_mmu_memory_cache *cache,int min) { -struct page *page; +void *page;if (cache->nobjs >= min)return 0 ;while (cache->nobjs <ARRAY_SIZE (cache->objects)) { - page =alloc_page (GFP_KERNEL ); + page = (void *)__get_free_page (GFP_KERNEL );if (!page)return -ENOMEM ; - cache->objects[cache->nobjs++] =page_address (page); + cache->objects[cache->nobjs++] = page; }return 0 ; }
@@ -1043,9 +1043,9 @@ static void kvm_mmu_free_page(struct kvm *kvm, struct kvm_mmu_page *sp)ASSERT (is_empty_shadow_page (sp->spt));hlist_del (&sp->hash_link);list_del (&sp->link); -__free_page (virt_to_page (sp->spt)); +free_page ((unsigned long )sp->spt);if (!sp->role.direct) -__free_page (virt_to_page (sp->gfns)); +free_page ((unsigned long )sp->gfns);kmem_cache_free (mmu_page_header_cache, sp);kvm_mod_used_mmu_pages (kvm,-1 ); }
Signature · 1 line
1.7.4
PATCH 9/10 KVM: MMU: remove unused macros
In reply to Xiao GuangrongThese macros are not used, so removed
--- arch/x86/kvm/mmu.c | 5 ----- arch/x86/kvm/paging_tmpl.h | 3 --- 2 files changed, 0 insertions(+), 8 deletions(-)
arch/x86/kvm/mmu.c +0 -5
@@ -111,9 +111,6 @@ module_param(oos_shadow, bool, 0644);#define PT64_LEVEL_SHIFT (level) \ (PAGE_SHIFT + (level - 1) * PT64_LEVEL_BITS) -#define PT64_LEVEL_MASK (level) \ - (((1ULL << PT64_LEVEL_BITS) - 1) << PT64_LEVEL_SHIFT(level)) -#define PT64_INDEX (address, level)\ (((address) >> PT64_LEVEL_SHIFT(level)) & ((1 << PT64_LEVEL_BITS) - 1))
@@ -123,8 +120,6 @@ module_param(oos_shadow, bool, 0644);#define PT32_LEVEL_SHIFT (level) \ (PAGE_SHIFT + (level - 1) * PT32_LEVEL_BITS) -#define PT32_LEVEL_MASK (level) \ - (((1ULL << PT32_LEVEL_BITS) - 1) << PT32_LEVEL_SHIFT(level))#define PT32_LVL_OFFSET_MASK (level) \ (PT32_BASE_ADDR_MASK & ((1ULL << (PAGE_SHIFT + (((level) - 1) \ * PT32_LEVEL_BITS))) - 1))
arch/x86/kvm/paging_tmpl.h +0 -3
@@ -31,7 +31,6 @@#define PT_LVL_ADDR_MASK (lvl) PT64_LVL_ADDR_MASK(lvl)#define PT_LVL_OFFSET_MASK (lvl) PT64_LVL_OFFSET_MASK(lvl)#define PT_INDEX (addr, level) PT64_INDEX(addr, level) -#define PT_LEVEL_MASK (level) PT64_LEVEL_MASK(level)#define PT_LEVEL_BITS PT64_LEVEL_BITS#ifdef CONFIG_X86_64 #define PT_MAX_FULL_LEVELS 4
@@ -48,7 +47,6 @@#define PT_LVL_ADDR_MASK (lvl) PT32_LVL_ADDR_MASK(lvl)#define PT_LVL_OFFSET_MASK (lvl) PT32_LVL_OFFSET_MASK(lvl)#define PT_INDEX (addr, level) PT32_INDEX(addr, level) -#define PT_LEVEL_MASK (level) PT32_LEVEL_MASK(level)#define PT_LEVEL_BITS PT32_LEVEL_BITS#define PT_MAX_FULL_LEVELS 2#define CMPXCHG cmpxchg
@@ -827,7 +825,6 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)#undef FNAME#undef PT_BASE_ADDR_MASK#undef PT_INDEX -#undef PT_LEVEL_MASK#undef PT_LVL_ADDR_MASK#undef PT_LVL_OFFSET_MASK#undef PT_LEVEL_BITS
Signature · 1 line
1.7.4
PATCH 10/10 KVM: cleanup memslot_id function
In reply to Xiao GuangrongWe can get memslot id from memslot->id directly
--- include/linux/kvm_host.h | 7 ++++++- virt/kvm/kvm_main.c | 17 ----------------- 2 files changed, 6 insertions(+), 18 deletions(-)
include/linux/kvm_host.h +6 -1
@@ -365,7 +365,6 @@ pfn_t gfn_to_pfn_prot(struct kvm *kvm, gfn_t gfn, bool write_fault, bool *writable);pfn_t gfn_to_pfn_memslot (struct kvm *kvm,struct kvm_memory_slot *slot,gfn_t gfn); -int memslot_id (struct kvm *kvm,gfn_t gfn);void kvm_release_pfn_dirty (pfn_t );void kvm_release_pfn_clean (pfn_t pfn);void kvm_set_pfn_dirty (pfn_t pfn);
@@ -388,6 +387,12 @@ int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,int kvm_clear_guest_page (struct kvm *kvm,gfn_t gfn,int offset,int len);int kvm_clear_guest (struct kvm *kvm,gpa_t gpa,unsigned long len);struct kvm_memory_slot *gfn_to_memslot (struct kvm *kvm,gfn_t gfn); + +static inline int memslot_id (struct kvm *kvm,gfn_t gfn) +{ +return gfn_to_memslot (kvm, gfn)->id; +} +int kvm_is_visible_gfn (struct kvm *kvm,gfn_t gfn);unsigned long kvm_host_page_size (struct kvm *kvm,gfn_t gfn);void mark_page_dirty (struct kvm *kvm,gfn_t gfn);
virt/kvm/kvm_main.c +0 -17
@@ -997,23 +997,6 @@ out:return size; } -int memslot_id (struct kvm *kvm,gfn_t gfn) -{ -int i; -struct kvm_memslots *slots =kvm_memslots (kvm); -struct kvm_memory_slot *memslot =NULL ; - -for (i =0 ; i < slots->nmemslots; ++i) { - memslot = &slots->memslots[i]; - -if (gfn >= memslot->base_gfn - && gfn < memslot->base_gfn + memslot->npages) -break ; - } - -return memslot - slots->memslots; -} -static unsigned long gfn_to_hva_many (struct kvm_memory_slot *slot,gfn_t gfn,gfn_t *nr_pages) {
Signature · 1 line
1.7.4
Re: [PATCH 10/10] KVM: cleanup memslot_id function
Quoted 6 lines · Xiao Guangrong
We can get memslot id from
memslot->iddirectlyinclude/linux/kvm_host.h +0
-0@@ -388,6 +387,12 @@ int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,int kvm_clear_guest_page (struct kvm *kvm,gfn_t gfn,int offset,int len);int kvm_clear_guest (struct kvm *kvm,gpa_t gpa,unsigned long len);
include/linux/kvm_host.h int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc, · line 398
Quoted 10 lines
include/linux/kvm_host.h +6
-0struct kvm_memory_slot *gfn_to_memslot (struct kvm *kvm,gfn_t gfn); + +static inline int memslot_id (struct kvm *kvm,gfn_t gfn) +{ +return gfn_to_memslot (kvm, gfn)->id; +} +int kvm_is_visible_gfn (struct kvm *kvm,gfn_t gfn);unsigned long kvm_host_page_size (struct kvm *kvm,gfn_t gfn);void mark_page_dirty (struct kvm *kvm,gfn_t gfn);
Please put the function near the other inlines.
Signature · 1 line
error compiling committee.c: too many arguments to function
Avi Kivity
AppliedQuoted 1 line · Xiao Guangrong
Only remove write access in the last sptes
Thanks, applied patches 1, 3, 5, 6, 8, and 9.
Signature · 1 line
error compiling committee.c: too many arguments to function