From: David Woodhouse <[email protected]> The Xen CPUID leaf 3, sub-leaf 0, ECX provides the guest TSC frequency in kHz directly. Use it when available instead of reverse-calculating the frequency from the pvclock tsc_to_system_mul and tsc_shift values, which loses precision.
This mirrors the equivalent change for KVM guests using the generic 0x40000010 timing leaf. Signed-off-by: David Woodhouse <[email protected]> --- arch/x86/kvm/x86.c | 3 +-- arch/x86/xen/time.c | 12 ++++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index c15303963686..ac982652e5e0 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3469,7 +3469,6 @@ static void kvm_setup_guest_pvclock(struct pvclock_vcpu_time_info *ref_hv_clock, int kvm_guest_time_update(struct kvm_vcpu *v) { struct pvclock_vcpu_time_info hv_clock = {}; - unsigned long flags; u64 tgt_tsc_hz; unsigned seq; struct kvm_vcpu_arch *vcpu = &v->arch; @@ -10162,7 +10161,7 @@ static void kvm_hyperv_tsc_notifier(void) kvm_caps.max_guest_tsc_khz = tsc_khz; list_for_each_entry(kvm, &vm_list, vm_list) { - __kvm_start_pvclock_update(kvm); + __kvm_start_pvclock_update(kvm, NULL); pvclock_update_vm_gtod_copy(kvm); kvm_end_pvclock_update(kvm); } diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 6f9f665bb7ae..862b8e9e8405 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -41,8 +41,20 @@ static unsigned long xen_tsc_khz(void) { struct pvclock_vcpu_time_info *info = &HYPERVISOR_shared_info->vcpu_info[0].time; + u32 eax, ebx, ecx, edx; + u32 base = xen_cpuid_base(); setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ); + + /* + * If Xen provides the guest TSC frequency directly in CPUID + * (leaf 3, sub-leaf 0, ECX), use that instead of reverse- + * calculating from the pvclock mul/shift. + */ + cpuid_count(base + 3, 0, &eax, &ebx, &ecx, &edx); + if (ecx) + return ecx; + return pvclock_tsc_khz(info); } -- 2.51.0

