Commit 6e35994d authored by Bharat Bhushan's avatar Bharat Bhushan Committed by Alexander Graf

KVM: PPC: Use clockevent multiplier and shifter for decrementer

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: default avatarBharat Bhushan <bharat.bhushan@freescale.com>
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
parent cc902ad4
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
extern unsigned long tb_ticks_per_jiffy; extern unsigned long tb_ticks_per_jiffy;
extern unsigned long tb_ticks_per_usec; extern unsigned long tb_ticks_per_usec;
extern unsigned long tb_ticks_per_sec; extern unsigned long tb_ticks_per_sec;
extern struct clock_event_device decrementer_clockevent;
struct rtc_time; struct rtc_time;
extern void to_tm(int tim, struct rtc_time * tm); extern void to_tm(int tim, struct rtc_time * tm);
......
...@@ -100,7 +100,7 @@ static int decrementer_set_next_event(unsigned long evt, ...@@ -100,7 +100,7 @@ static int decrementer_set_next_event(unsigned long evt,
static void decrementer_set_mode(enum clock_event_mode mode, static void decrementer_set_mode(enum clock_event_mode mode,
struct clock_event_device *dev); struct clock_event_device *dev);
static struct clock_event_device decrementer_clockevent = { struct clock_event_device decrementer_clockevent = {
.name = "decrementer", .name = "decrementer",
.rating = 200, .rating = 200,
.irq = 0, .irq = 0,
...@@ -108,6 +108,7 @@ static struct clock_event_device decrementer_clockevent = { ...@@ -108,6 +108,7 @@ static struct clock_event_device decrementer_clockevent = {
.set_mode = decrementer_set_mode, .set_mode = decrementer_set_mode,
.features = CLOCK_EVT_FEAT_ONESHOT, .features = CLOCK_EVT_FEAT_ONESHOT,
}; };
EXPORT_SYMBOL(decrementer_clockevent);
DEFINE_PER_CPU(u64, decrementers_next_tb); DEFINE_PER_CPU(u64, decrementers_next_tb);
static DEFINE_PER_CPU(struct clock_event_device, decrementers); static DEFINE_PER_CPU(struct clock_event_device, decrementers);
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/kvm_host.h> #include <linux/kvm_host.h>
#include <linux/clockchips.h>
#include <asm/reg.h> #include <asm/reg.h>
#include <asm/time.h> #include <asm/time.h>
...@@ -104,8 +105,12 @@ void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) ...@@ -104,8 +105,12 @@ void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
*/ */
dec_time = vcpu->arch.dec; 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); dec_nsec = do_div(dec_time, NSEC_PER_SEC);
hrtimer_start(&vcpu->arch.dec_timer, hrtimer_start(&vcpu->arch.dec_timer,
ktime_set(dec_time, dec_nsec), HRTIMER_MODE_REL); ktime_set(dec_time, dec_nsec), HRTIMER_MODE_REL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment