Commit 0293615f authored by Glauber Costa's avatar Glauber Costa Committed by Avi Kivity

x86: KVM guest: use paravirt function to calculate cpu khz

We're currently facing timing problems in guests that do
calibration under heavy load, and then the load vanishes.
This means we'll have a much lower lpj than we actually should,
and delays end up taking less time than they should, which is a
nasty bug.

Solution is to pass on the lpj value from host to guest, and have it
preset.
Signed-off-by: default avatarGlauber Costa <gcosta@redhat.com>
Signed-off-by: default avatarAvi Kivity <avi@qumranet.com>
parent 3807f345
...@@ -78,6 +78,34 @@ static cycle_t kvm_clock_read(void) ...@@ -78,6 +78,34 @@ static cycle_t kvm_clock_read(void)
return ret; return ret;
} }
/*
* If we don't do that, there is the possibility that the guest
* will calibrate under heavy load - thus, getting a lower lpj -
* and execute the delays themselves without load. This is wrong,
* because no delay loop can finish beforehand.
* Any heuristics is subject to fail, because ultimately, a large
* poll of guests can be running and trouble each other. So we preset
* lpj here
*/
static unsigned long kvm_get_tsc_khz(void)
{
return preset_lpj;
}
static void kvm_get_preset_lpj(void)
{
struct pvclock_vcpu_time_info *src;
unsigned long khz;
u64 lpj;
src = &per_cpu(hv_clock, 0);
khz = pvclock_tsc_khz(src);
lpj = ((u64)khz * 1000);
do_div(lpj, HZ);
preset_lpj = lpj;
}
static struct clocksource kvm_clock = { static struct clocksource kvm_clock = {
.name = "kvm-clock", .name = "kvm-clock",
.read = kvm_clock_read, .read = kvm_clock_read,
...@@ -153,6 +181,7 @@ void __init kvmclock_init(void) ...@@ -153,6 +181,7 @@ void __init kvmclock_init(void)
pv_time_ops.get_wallclock = kvm_get_wallclock; pv_time_ops.get_wallclock = kvm_get_wallclock;
pv_time_ops.set_wallclock = kvm_set_wallclock; pv_time_ops.set_wallclock = kvm_set_wallclock;
pv_time_ops.sched_clock = kvm_clock_read; pv_time_ops.sched_clock = kvm_clock_read;
pv_time_ops.get_tsc_khz = kvm_get_tsc_khz;
#ifdef CONFIG_X86_LOCAL_APIC #ifdef CONFIG_X86_LOCAL_APIC
pv_apic_ops.setup_secondary_clock = kvm_setup_secondary_clock; pv_apic_ops.setup_secondary_clock = kvm_setup_secondary_clock;
#endif #endif
...@@ -163,6 +192,7 @@ void __init kvmclock_init(void) ...@@ -163,6 +192,7 @@ void __init kvmclock_init(void)
#ifdef CONFIG_KEXEC #ifdef CONFIG_KEXEC
machine_ops.crash_shutdown = kvm_crash_shutdown; machine_ops.crash_shutdown = kvm_crash_shutdown;
#endif #endif
kvm_get_preset_lpj();
clocksource_register(&kvm_clock); clocksource_register(&kvm_clock);
} }
} }
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