Re: [PATCH v2 2/5] KVM: MMU: Convert remote flushes to kvm_mark_tlb_dirty() and a conditional flush

2012-05-22 Thread Takuya Yoshikawa
On Thu, 17 May 2012 13:24:41 +0300
Avi Kivity  wrote:

> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 2256f51..a2149d8 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -3130,7 +3130,9 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct 
> kvm_dirty_log *log)
>   kvm_mmu_write_protect_pt_masked(kvm, memslot, offset, mask);
>   }
>   if (is_dirty)
> - kvm_flush_remote_tlbs(kvm);
> + kvm_mark_tlb_dirty(kvm);
> +
> + kvm_cond_flush_remote_tlbs(kvm);
>  
>   spin_unlock(&kvm->mmu_lock);

Any reason not to move this flush outside of the mmu_lock in this
patch series?

Unlike other rmap write protections, this one seems to be simple.

Takuya
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 2/5] KVM: MMU: Convert remote flushes to kvm_mark_tlb_dirty() and a conditional flush

2012-05-21 Thread Marcelo Tosatti
On Thu, May 17, 2012 at 01:24:41PM +0300, Avi Kivity wrote:
> This allows us to later move the actual flush out of protection of the
> mmu spinlock, provided there are no additional dependencies.
> 
> Constructs of the form
> 
> if (pred)
> kvm_flush_remote_tlbs(kvm)
> 
> are converted to
> 
> if (pred)
> kvm_mark_tlb_dirty(kvm)
> 
> kvm_cond_flush_remote_tlbs(kvm)
> 
> so that if another thread caused pred to transition from true to false,
> but has not yet flushed the tlb, we notice it and flush it before proceeding.
> 
> Signed-off-by: Avi Kivity 
> ---
>  arch/ia64/kvm/kvm-ia64.c   |6 --
>  arch/x86/kvm/mmu.c |   45 
> +++-
>  arch/x86/kvm/paging_tmpl.h |4 +++-
>  arch/x86/kvm/x86.c |4 +++-
>  virt/kvm/kvm_main.c|4 +++-
>  5 files changed, 41 insertions(+), 22 deletions(-)
> 
> diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
> index bd77cb5..a4a92d8 100644
> --- a/arch/ia64/kvm/kvm-ia64.c
> +++ b/arch/ia64/kvm/kvm-ia64.c
> @@ -1628,7 +1628,8 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
>  
>  void kvm_arch_flush_shadow(struct kvm *kvm)
>  {
> - kvm_flush_remote_tlbs(kvm);
> + kvm_mark_tlb_dirty(kvm);
> + kvm_cond_flush_remote_tlbs(kvm);
>  }
>  
>  long kvm_arch_dev_ioctl(struct file *filp,
> @@ -1853,10 +1854,11 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
>  
>   /* If nothing is dirty, don't bother messing with page tables. */
>   if (is_dirty) {
> - kvm_flush_remote_tlbs(kvm);
> + kvm_mark_tlb_dirty(kvm);
>   n = kvm_dirty_bitmap_bytes(memslot);
>   memset(memslot->dirty_bitmap, 0, n);
>   }
> + kvm_cond_flush_remote_tlbs(kvm);
>   r = 0;
>  out:
>   mutex_unlock(&kvm->slots_lock);
> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
> index 07424cf..03a9c80 100644
> --- a/arch/x86/kvm/mmu.c
> +++ b/arch/x86/kvm/mmu.c
> @@ -1170,7 +1170,9 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned 
> long *rmapp,
>   }
>  
>   if (need_flush)
> - kvm_flush_remote_tlbs(kvm);
> + kvm_mark_tlb_dirty(kvm);
> +
> + kvm_cond_flush_remote_tlbs(kvm);
>  
>   return 0;
>  }
> @@ -1294,7 +1296,8 @@ static void rmap_recycle(struct kvm_vcpu *vcpu, u64 
> *spte, gfn_t gfn)
>   rmapp = gfn_to_rmap(vcpu->kvm, gfn, sp->role.level);
>  
>   kvm_unmap_rmapp(vcpu->kvm, rmapp, 0);
> - kvm_flush_remote_tlbs(vcpu->kvm);
> + kvm_mark_tlb_dirty(vcpu->kvm);
> + kvm_cond_flush_remote_tlbs(vcpu->kvm);
>  }
>  
>  int kvm_age_hva(struct kvm *kvm, unsigned long hva)
> @@ -1697,7 +1700,9 @@ static void mmu_sync_children(struct kvm_vcpu *vcpu,
>   protected |= rmap_write_protect(vcpu->kvm, sp->gfn);
>  
>   if (protected)
> - kvm_flush_remote_tlbs(vcpu->kvm);
> + kvm_mark_tlb_dirty(vcpu->kvm);
> +
> + kvm_cond_flush_remote_tlbs(vcpu->kvm);
>  
>   for_each_sp(pages, sp, parents, i) {
>   kvm_sync_page(vcpu, sp, &invalid_list);
> @@ -1786,7 +1791,8 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct 
> kvm_vcpu *vcpu,
>   &vcpu->kvm->arch.mmu_page_hash[kvm_page_table_hashfn(gfn)]);
>   if (!direct) {
>   if (rmap_write_protect(vcpu->kvm, gfn))
> - kvm_flush_remote_tlbs(vcpu->kvm);
> + kvm_mark_tlb_dirty(vcpu->kvm);
> + kvm_cond_flush_remote_tlbs(vcpu->kvm);
>   if (level > PT_PAGE_TABLE_LEVEL && need_sync)
>   kvm_sync_pages(vcpu, gfn);
>  
> @@ -1861,7 +1867,8 @@ static void drop_large_spte(struct kvm_vcpu *vcpu, u64 
> *sptep)
>   if (is_large_pte(*sptep)) {
>   drop_spte(vcpu->kvm, sptep);
>   --vcpu->kvm->stat.lpages;
> - kvm_flush_remote_tlbs(vcpu->kvm);
> + kvm_mark_tlb_dirty(vcpu->kvm);
> + kvm_cond_flush_remote_tlbs(vcpu->kvm);
>   }
>  }
>  
> @@ -1883,7 +1890,8 @@ static void validate_direct_spte(struct kvm_vcpu *vcpu, 
> u64 *sptep,
>   return;
>  
>   drop_parent_pte(child, sptep);
> - kvm_flush_remote_tlbs(vcpu->kvm);
> + kvm_mark_tlb_dirty(vcpu->kvm);
> + kvm_cond_flush_remote_tlbs(vcpu->kvm);
>   }
>  }
>  
> @@ -2021,7 +2029,8 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm,
>   if (list_empty(invalid_list))
>   return;
>  
> - kvm_flush_remote_tlbs(kvm);
> + kvm_mark_tlb_dirty(kvm);
> + kvm_cond_flush_remote_tlbs(kvm);
>  
>   if (atomic_read(&kvm->arch.reader_counter)) {
>   kvm_mmu_isolate_pages(invalid_list);
> @@ -2344,7 +2353,9 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
>* might be cached on a CPU's TLB.
>*/
>   if (is_writable_pte(entry) && !is_writable_pte(*sptep))
> -  

[PATCH v2 2/5] KVM: MMU: Convert remote flushes to kvm_mark_tlb_dirty() and a conditional flush

2012-05-17 Thread Avi Kivity
This allows us to later move the actual flush out of protection of the
mmu spinlock, provided there are no additional dependencies.

Constructs of the form

if (pred)
kvm_flush_remote_tlbs(kvm)

are converted to

if (pred)
kvm_mark_tlb_dirty(kvm)

kvm_cond_flush_remote_tlbs(kvm)

so that if another thread caused pred to transition from true to false,
but has not yet flushed the tlb, we notice it and flush it before proceeding.

Signed-off-by: Avi Kivity 
---
 arch/ia64/kvm/kvm-ia64.c   |6 --
 arch/x86/kvm/mmu.c |   45 +++-
 arch/x86/kvm/paging_tmpl.h |4 +++-
 arch/x86/kvm/x86.c |4 +++-
 virt/kvm/kvm_main.c|4 +++-
 5 files changed, 41 insertions(+), 22 deletions(-)

diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index bd77cb5..a4a92d8 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -1628,7 +1628,8 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 
 void kvm_arch_flush_shadow(struct kvm *kvm)
 {
-   kvm_flush_remote_tlbs(kvm);
+   kvm_mark_tlb_dirty(kvm);
+   kvm_cond_flush_remote_tlbs(kvm);
 }
 
 long kvm_arch_dev_ioctl(struct file *filp,
@@ -1853,10 +1854,11 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
 
/* If nothing is dirty, don't bother messing with page tables. */
if (is_dirty) {
-   kvm_flush_remote_tlbs(kvm);
+   kvm_mark_tlb_dirty(kvm);
n = kvm_dirty_bitmap_bytes(memslot);
memset(memslot->dirty_bitmap, 0, n);
}
+   kvm_cond_flush_remote_tlbs(kvm);
r = 0;
 out:
mutex_unlock(&kvm->slots_lock);
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 07424cf..03a9c80 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1170,7 +1170,9 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned 
long *rmapp,
}
 
if (need_flush)
-   kvm_flush_remote_tlbs(kvm);
+   kvm_mark_tlb_dirty(kvm);
+
+   kvm_cond_flush_remote_tlbs(kvm);
 
return 0;
 }
@@ -1294,7 +1296,8 @@ static void rmap_recycle(struct kvm_vcpu *vcpu, u64 
*spte, gfn_t gfn)
rmapp = gfn_to_rmap(vcpu->kvm, gfn, sp->role.level);
 
kvm_unmap_rmapp(vcpu->kvm, rmapp, 0);
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_mark_tlb_dirty(vcpu->kvm);
+   kvm_cond_flush_remote_tlbs(vcpu->kvm);
 }
 
 int kvm_age_hva(struct kvm *kvm, unsigned long hva)
@@ -1697,7 +1700,9 @@ static void mmu_sync_children(struct kvm_vcpu *vcpu,
protected |= rmap_write_protect(vcpu->kvm, sp->gfn);
 
if (protected)
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_mark_tlb_dirty(vcpu->kvm);
+
+   kvm_cond_flush_remote_tlbs(vcpu->kvm);
 
for_each_sp(pages, sp, parents, i) {
kvm_sync_page(vcpu, sp, &invalid_list);
@@ -1786,7 +1791,8 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct 
kvm_vcpu *vcpu,
&vcpu->kvm->arch.mmu_page_hash[kvm_page_table_hashfn(gfn)]);
if (!direct) {
if (rmap_write_protect(vcpu->kvm, gfn))
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_mark_tlb_dirty(vcpu->kvm);
+   kvm_cond_flush_remote_tlbs(vcpu->kvm);
if (level > PT_PAGE_TABLE_LEVEL && need_sync)
kvm_sync_pages(vcpu, gfn);
 
@@ -1861,7 +1867,8 @@ static void drop_large_spte(struct kvm_vcpu *vcpu, u64 
*sptep)
if (is_large_pte(*sptep)) {
drop_spte(vcpu->kvm, sptep);
--vcpu->kvm->stat.lpages;
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_mark_tlb_dirty(vcpu->kvm);
+   kvm_cond_flush_remote_tlbs(vcpu->kvm);
}
 }
 
@@ -1883,7 +1890,8 @@ static void validate_direct_spte(struct kvm_vcpu *vcpu, 
u64 *sptep,
return;
 
drop_parent_pte(child, sptep);
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_mark_tlb_dirty(vcpu->kvm);
+   kvm_cond_flush_remote_tlbs(vcpu->kvm);
}
 }
 
@@ -2021,7 +2029,8 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm,
if (list_empty(invalid_list))
return;
 
-   kvm_flush_remote_tlbs(kvm);
+   kvm_mark_tlb_dirty(kvm);
+   kvm_cond_flush_remote_tlbs(kvm);
 
if (atomic_read(&kvm->arch.reader_counter)) {
kvm_mmu_isolate_pages(invalid_list);
@@ -2344,7 +2353,9 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 * might be cached on a CPU's TLB.
 */
if (is_writable_pte(entry) && !is_writable_pte(*sptep))
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_mark_tlb_dirty(vcpu->kvm);
+
+   kvm_cond_flush_remote_tlbs(vcpu->kvm);
 done:
return ret;
 }
@@ -2376,15 +2387,15 @@ static void mmu_set_spte(s