From mboxrd@z Thu Jan 1 00:00:00 1970 From: Sheng Yang Subject: Re: [PATCH] KVM: Ensure the exit frequency to QEmu for coalesced MMIO Date: Wed, 20 Jan 2010 16:38:23 +0800 Message-ID: <201001201638.23942.sheng@linux.intel.com> References: <1263976559-15480-1-git-send-email-sheng@linux.intel.com> Mime-Version: 1.0 Content-Type: Text/Plain; charset="iso-8859-15" Content-Transfer-Encoding: 7bit Cc: Avi Kivity , kvm@vger.kernel.org To: Marcelo Tosatti Return-path: Received: from mga05.intel.com ([192.55.52.89]:30245 "EHLO fmsmga101.fm.intel.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751683Ab0ATIix (ORCPT ); Wed, 20 Jan 2010 03:38:53 -0500 In-Reply-To: <1263976559-15480-1-git-send-email-sheng@linux.intel.com> Sender: kvm-owner@vger.kernel.org List-ID: On Wednesday 20 January 2010 16:35:59 Sheng Yang wrote: > The default action of calesced MMIO is, cache the writing in buffer, until: > 1. The buffer is full. > 2. Or the exit to QEmu due to other reasons. > > But this would result in a very late writing in some condition. > 1. The each time write to MMIO content is small. > 2. The writing interval is big. > 3. No need for input or accessing other devices frequently. "No need for exiting to the QEmu in a period" should be more precise... -- regards Yang, Sheng > > This issue was observed in a experimental embbed system. The test image > simply print "test" every 1 seconds. The output in QEmu meets expectation, > but the output in KVM is delayed for seconds. > > To solve this issue, a timeout is added, to ensure userspace exit freqency > is high enough(mostly target for video now) to write the buffered MMIO > data. Current the maximum exit interval is 1/25s(so 25 times exit to > userspace per second at least, pretty low compared to normal environment), > and reused KVM_EXIT_IRQ_WINDOW_OPEN as exit reason, for it would doing > nothing at all in userspace handler. > > Signed-off-by: Sheng Yang > --- > arch/x86/include/asm/kvm_host.h | 2 ++ > arch/x86/kvm/x86.c | 31 +++++++++++++++++++++++++++++++ > 2 files changed, 33 insertions(+), 0 deletions(-) > > diff --git a/arch/x86/include/asm/kvm_host.h > b/arch/x86/include/asm/kvm_host.h index a1f0b5d..eb8bb20 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -365,6 +365,8 @@ struct kvm_vcpu_arch { > unsigned long singlestep_rip; > /* fields used by HYPER-V emulation */ > u64 hv_vapic; > + > + ktime_t latest_userspace_exit_time; > }; > > struct kvm_mem_alias { > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 56a90a6..0b05f11 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -4339,6 +4339,20 @@ out: > return r; > } > > +#ifdef CONFIG_KVM_MMIO > + > +#define KVM_USERSPACE_MMIO_MAX_INTERVAL (NSEC_PER_SEC / 25) > +static bool mmio_need_exit_to_userspace(struct kvm_vcpu *vcpu) > +{ > + ktime_t gap, now = ktime_get(); > + > + gap = ktime_sub(now, vcpu->arch.latest_userspace_exit_time); > + if (ktime_to_ns(gap) > KVM_USERSPACE_MMIO_MAX_INTERVAL) > + return true; > + > + return false; > +} > +#endif > > static int __vcpu_run(struct kvm_vcpu *vcpu) > { > @@ -4404,6 +4418,10 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) > kvm_resched(vcpu); > vcpu->srcu_idx = srcu_read_lock(&kvm->srcu); > } > +#ifdef CONFIG_KVM_MMIO > + if (mmio_need_exit_to_userspace(vcpu)) > + r = 0; > +#endif > } > > srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx); > @@ -4463,6 +4481,16 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, > struct kvm_run *kvm_run) > > r = __vcpu_run(vcpu); > > +#ifdef CONFIG_KVM_MMIO > + if (mmio_need_exit_to_userspace(vcpu)) { > + /* Use KVM_EXIT_IRQ_WINDOW_OPEN because userspace would do > + * nothing to handle it */ > + kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN; > + r = 0; > + } > + vcpu->arch.latest_userspace_exit_time = ktime_get(); > +#endif > + > out: > if (vcpu->sigset_active) > sigprocmask(SIG_SETMASK, &sigsaved, NULL); > @@ -5455,6 +5483,9 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) > goto fail_mmu_destroy; > } > vcpu->arch.mcg_cap = KVM_MAX_MCE_BANKS; > +#ifdef CONFIG_KVM_MMIO > + vcpu->arch.latest_userspace_exit_time = ktime_get(); > +#endif > > return 0; >