public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Andrew Theurer <habanero@linux.vnet.ibm.com>
To: Avi Kivity <avi@redhat.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>,
	Andrea Arcangeli <aarcange@redhat.com>,
	kvm@vger.kernel.org
Subject: Re: [PATCH] KVM: Defer remote tlb flushes on invlpg (v3)
Date: Thu, 19 Mar 2009 08:46:04 -0500	[thread overview]
Message-ID: <49C24C9C.9080101@linux.vnet.ibm.com> (raw)
In-Reply-To: <1237468666-30700-1-git-send-email-avi@redhat.com>

Avi Kivity wrote:
> KVM currently flushes the tlbs on all cpus when emulating invlpg.  This
> is because at the time of invlpg we lose track of the page, and leaving
> stale tlb entries could cause the guest to access the page when it is
> later freed (say after being swapped out).
>
> However we have a second change to flush the tlbs, when an mmu notifier is
> called to let us know the host pte has been invalidated.  We can safely
> defer the flush to this point, which occurs much less frequently.  Of course,
> we still do a local tlb flush when emulating invlpg.
>   
I should be able to run some performance comparisons with this in the 
next day or two.

-Andrew
> Signed-off-by: Avi Kivity <avi@redhat.com>
> ---
>
> Changes from v2:
> - dropped remote flushes from guest pagetable write protect paths
> - fixed up memory barriers
> - use existing local tlb flush in invlpg, no need to add another one
>
>  arch/x86/kvm/mmu.c         |    3 +--
>  arch/x86/kvm/paging_tmpl.h |    5 +----
>  include/linux/kvm_host.h   |    2 ++
>  virt/kvm/kvm_main.c        |   17 +++++++++++------
>  4 files changed, 15 insertions(+), 12 deletions(-)
>
> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
> index 2a36f7f..f0ea56c 100644
> --- a/arch/x86/kvm/mmu.c
> +++ b/arch/x86/kvm/mmu.c
> @@ -1184,8 +1184,7 @@ static void mmu_sync_children(struct kvm_vcpu *vcpu,
>  		for_each_sp(pages, sp, parents, i)
>  			protected |= rmap_write_protect(vcpu->kvm, sp->gfn);
>
> -		if (protected)
> -			kvm_flush_remote_tlbs(vcpu->kvm);
> +		kvm_flush_remote_tlbs_cond(vcpu->kvm, protected);
>
>  		for_each_sp(pages, sp, parents, i) {
>  			kvm_sync_page(vcpu, sp);
> diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
> index 855eb71..2273b26 100644
> --- a/arch/x86/kvm/paging_tmpl.h
> +++ b/arch/x86/kvm/paging_tmpl.h
> @@ -445,7 +445,6 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva)
>  	gpa_t pte_gpa = -1;
>  	int level;
>  	u64 *sptep;
> -	int need_flush = 0;
>
>  	spin_lock(&vcpu->kvm->mmu_lock);
>
> @@ -465,7 +464,7 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva)
>  				rmap_remove(vcpu->kvm, sptep);
>  				if (is_large_pte(*sptep))
>  					--vcpu->kvm->stat.lpages;
> -				need_flush = 1;
> +				vcpu->kvm->remote_tlbs_dirty = true;
>  			}
>  			set_shadow_pte(sptep, shadow_trap_nonpresent_pte);
>  			break;
> @@ -475,8 +474,6 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva)
>  			break;
>  	}
>
> -	if (need_flush)
> -		kvm_flush_remote_tlbs(vcpu->kvm);
>  	spin_unlock(&vcpu->kvm->mmu_lock);
>
>  	if (pte_gpa == -1)
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 11eb702..b779c57 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -125,6 +125,7 @@ struct kvm_kernel_irq_routing_entry {
>  struct kvm {
>  	struct mutex lock; /* protects the vcpus array and APIC accesses */
>  	spinlock_t mmu_lock;
> +	bool remote_tlbs_dirty;
>  	struct rw_semaphore slots_lock;
>  	struct mm_struct *mm; /* userspace tied to this vm */
>  	int nmemslots;
> @@ -235,6 +236,7 @@ void kvm_resched(struct kvm_vcpu *vcpu);
>  void kvm_load_guest_fpu(struct kvm_vcpu *vcpu);
>  void kvm_put_guest_fpu(struct kvm_vcpu *vcpu);
>  void kvm_flush_remote_tlbs(struct kvm *kvm);
> +void kvm_flush_remote_tlbs_cond(struct kvm *kvm, bool cond);
>  void kvm_reload_remote_mmus(struct kvm *kvm);
>
>  long kvm_arch_dev_ioctl(struct file *filp,
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 68b217e..12afa50 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -758,10 +758,18 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req)
>
>  void kvm_flush_remote_tlbs(struct kvm *kvm)
>  {
> +	kvm->remote_tlbs_dirty = false;
> +	smp_wmb();
>  	if (make_all_cpus_request(kvm, KVM_REQ_TLB_FLUSH))
>  		++kvm->stat.remote_tlb_flush;
>  }
>
> +void kvm_flush_remote_tlbs_cond(struct kvm *kvm, bool cond)
> +{
> +	if (cond || kvm->remote_tlbs_dirty)
> +		kvm_flush_remote_tlbs(kvm);
> +}
> +
>  void kvm_reload_remote_mmus(struct kvm *kvm)
>  {
>  	make_all_cpus_request(kvm, KVM_REQ_MMU_RELOAD);
> @@ -841,8 +849,7 @@ static void kvm_mmu_notifier_invalidate_page(struct mmu_notifier *mn,
>  	spin_unlock(&kvm->mmu_lock);
>
>  	/* we've to flush the tlb before the pages can be freed */
> -	if (need_tlb_flush)
> -		kvm_flush_remote_tlbs(kvm);
> +	kvm_flush_remote_tlbs_cond(kvm, need_tlb_flush);
>
>  }
>
> @@ -866,8 +873,7 @@ static void kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
>  	spin_unlock(&kvm->mmu_lock);
>
>  	/* we've to flush the tlb before the pages can be freed */
> -	if (need_tlb_flush)
> -		kvm_flush_remote_tlbs(kvm);
> +	kvm_flush_remote_tlbs_cond(kvm, need_tlb_flush);
>  }
>
>  static void kvm_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
> @@ -907,8 +913,7 @@ static int kvm_mmu_notifier_clear_flush_young(struct mmu_notifier *mn,
>  	young = kvm_age_hva(kvm, address);
>  	spin_unlock(&kvm->mmu_lock);
>
> -	if (young)
> -		kvm_flush_remote_tlbs(kvm);
> +	kvm_flush_remote_tlbs_cond(kvm, young);
>
>  	return young;
>  }
>   



  reply	other threads:[~2009-03-19 13:46 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-19 13:17 [PATCH] KVM: Defer remote tlb flushes on invlpg (v3) Avi Kivity
2009-03-19 13:46 ` Andrew Theurer [this message]
2009-03-19 14:03   ` Avi Kivity
2009-03-29 10:36 ` Avi Kivity
2009-04-11 16:48   ` [PATCH] KVM: Defer remote tlb flushes on invlpg (v4) Andrea Arcangeli
2009-04-12 22:31     ` Marcelo Tosatti
2009-04-18 15:34       ` Andrea Arcangeli
2009-04-19 17:54         ` Marcelo Tosatti
2009-04-20 13:01           ` Andrea Arcangeli

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=49C24C9C.9080101@linux.vnet.ibm.com \
    --to=habanero@linux.vnet.ibm.com \
    --cc=aarcange@redhat.com \
    --cc=avi@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=mtosatti@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox