KVM: PPC: Use clockevent multiplier and shifter for decrementer
authorBharat Bhushan <r65777@freescale.com>
Wed, 18 Apr 2012 06:01:19 +0000 (06:01 +0000)
committerAlexander Graf <agraf@suse.de>
Sun, 6 May 2012 14:19:07 +0000 (16:19 +0200)
Time for which the hrtimer is started for decrementer emulation is calculated
using tb_ticks_per_usec. While hrtimer uses the clockevent for DEC
reprogramming (if needed) and which calculate timebase ticks using the
multiplier and shifter mechanism implemented within clockevent layer.

It was observed that this conversion (timebase->time->timebase) are not
correct because the mechanism are not consistent.
In our setup it adds 2% jitter.

With this patch clockevent multiplier and shifter mechanism are used when
starting hrtimer for decrementer emulation. Now the jitter is < 0.5%.

Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
arch/powerpc/include/asm/time.h
arch/powerpc/kernel/time.c
arch/powerpc/kvm/emulate.c

index 2136f58a54e80a32fd014dd66b84196b9f0bc1df..3b4b4a8da922fc4801d51bae86fc8e2b8e810108 100644 (file)
@@ -23,6 +23,7 @@
 extern unsigned long tb_ticks_per_jiffy;
 extern unsigned long tb_ticks_per_usec;
 extern unsigned long tb_ticks_per_sec;
+extern struct clock_event_device decrementer_clockevent;
 
 struct rtc_time;
 extern void to_tm(int tim, struct rtc_time * tm);
index 2c42cd72d0f5b1a33eb501da54a8e5edbb08e63e..99a995c2a3f2496da4e2e48e807b7354488ff2c7 100644 (file)
@@ -100,7 +100,7 @@ static int decrementer_set_next_event(unsigned long evt,
 static void decrementer_set_mode(enum clock_event_mode mode,
                                 struct clock_event_device *dev);
 
-static struct clock_event_device decrementer_clockevent = {
+struct clock_event_device decrementer_clockevent = {
        .name           = "decrementer",
        .rating         = 200,
        .irq            = 0,
@@ -108,6 +108,7 @@ static struct clock_event_device decrementer_clockevent = {
        .set_mode       = decrementer_set_mode,
        .features       = CLOCK_EVT_FEAT_ONESHOT,
 };
+EXPORT_SYMBOL(decrementer_clockevent);
 
 DEFINE_PER_CPU(u64, decrementers_next_tb);
 static DEFINE_PER_CPU(struct clock_event_device, decrementers);
index afc9154f1aef1bbff29fe1d7fa70d425061a70c9..b5872f61a213dce852a64a4d2f3b3c3a3356b92a 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kvm_host.h>
+#include <linux/clockchips.h>
 
 #include <asm/reg.h>
 #include <asm/time.h>
@@ -104,8 +105,12 @@ void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
         */
 
        dec_time = vcpu->arch.dec;
-       dec_time *= 1000;
-       do_div(dec_time, tb_ticks_per_usec);
+       /*
+        * Guest timebase ticks at the same frequency as host decrementer.
+        * So use the host decrementer calculations for decrementer emulation.
+        */
+       dec_time = dec_time << decrementer_clockevent.shift;
+       do_div(dec_time, decrementer_clockevent.mult);
        dec_nsec = do_div(dec_time, NSEC_PER_SEC);
        hrtimer_start(&vcpu->arch.dec_timer,
                ktime_set(dec_time, dec_nsec), HRTIMER_MODE_REL);