diff mbox

arm/arm64: KVM: Propertly account for guest CPU time

Message ID 1432817349-17917-1-git-send-email-christoffer.dall@linaro.org
State New
Headers show

Commit Message

Christoffer Dall May 28, 2015, 12:49 p.m. UTC
Until now we have been calling kvm_guest_exit after re-enabling
interrupts when we come back from the guest, but this has the
unfortunate effect that CPU time accounting done in the context of timer
interrupts doesn't properly notice that the time since the last tick was
spent in the guest.

Inspired by the comment in the x86 code, simply move the
kvm_guest_exit() call below the local_irq_enable() call and change
__kvm_guest_exit() to kvm_guest_exit(), because we are now calling this
function with interrupts enabled.  Note that AFAIU we don't need an
explicit barrier like x86 because the arm/arm64 implementation of
local_irq_(en/dis)able has an implicit barrier.

At the same time, move the trace_kvm_exit() call outside of the atomic
section, since there is no reason for us to do that with interrupts
disabled.

Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
This patch is based on kvm/queue, because it has the kvm_guest_enter/exit
rework recently posted by Christian Borntraeger.  I hope I got the logic
of this wrong, there were 2 slightly worrying facts about this:

First, we now enable and disable and enable interrupts on each exit
path, but I couldn't see any performance overhead on hackbench - yes the
only benchmark we care abotu.

Second, looking at the power and mips code, they seem to also call
kvm_guest_exit() before enabling interrupts, so I don't understand how
guest CPU time accounting works on those architectures.

 arch/arm/kvm/arm.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

Comments

Christoffer Dall May 28, 2015, 1:04 p.m. UTC | #1
On Thu, May 28, 2015 at 02:49:09PM +0200, Christoffer Dall wrote:
> Until now we have been calling kvm_guest_exit after re-enabling
> interrupts when we come back from the guest, but this has the
> unfortunate effect that CPU time accounting done in the context of timer
> interrupts doesn't properly notice that the time since the last tick was
> spent in the guest.
> 
> Inspired by the comment in the x86 code, simply move the
> kvm_guest_exit() call below the local_irq_enable() call and change
> __kvm_guest_exit() to kvm_guest_exit(), because we are now calling this
> function with interrupts enabled.  Note that AFAIU we don't need an
> explicit barrier like x86 because the arm/arm64 implementation of
> local_irq_(en/dis)able has an implicit barrier.
> 
> At the same time, move the trace_kvm_exit() call outside of the atomic
> section, since there is no reason for us to do that with interrupts
> disabled.
> 
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> ---
> This patch is based on kvm/queue, because it has the kvm_guest_enter/exit
> rework recently posted by Christian Borntraeger.  I hope I got the logic
> of this wrong, there were 2 slightly worrying facts about this:

Of course this should have been:

"I hope I got the logic of this *right*, but there..."

Damn it!
-Christoffer
diff mbox

Patch

diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index e41cb11..bd0e463 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -559,8 +559,10 @@  int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		ret = kvm_call_hyp(__kvm_vcpu_run, vcpu);
 
 		vcpu->mode = OUTSIDE_GUEST_MODE;
-		__kvm_guest_exit();
-		trace_kvm_exit(kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu));
+		/*
+		 * Back from guest
+		 *************************************************************/
+
 		/*
 		 * We may have taken a host interrupt in HYP mode (ie
 		 * while executing the guest). This interrupt is still
@@ -574,8 +576,14 @@  int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		local_irq_enable();
 
 		/*
-		 * Back from guest
-		 *************************************************************/
+		 * We do local_irq_enable() before calling kvm_guest_exit so
+		 * that the cputime accounting done in the context of timer
+		 * interrupts properly accounts time spent in the guest as
+		 * guest time.
+		 */
+		kvm_guest_exit();
+		trace_kvm_exit(kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu));
+
 
 		kvm_timer_sync_hwstate(vcpu);
 		kvm_vgic_sync_hwstate(vcpu);