|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v3 36/41] x86/kvmclock: Get local APIC bus frequency from PV CPUID Timing Info
When running as a KVM guest with kvmclock support enabled, stuff the APIC
timer period/frequency with the local APIC bus frequency reported in
CPUID.0x40000010.EBX instead of trying to calibrate/guess the frequency.
See Documentation/virt/kvm/x86/cpuid.rst for details.
Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---
arch/x86/include/asm/kvm_para.h | 1 +
arch/x86/kernel/kvm.c | 19 ++++++++++++++++---
arch/x86/kernel/kvmclock.c | 13 +++++++++++--
3 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index 3f7f558b5b24..381d029b72e7 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -130,6 +130,7 @@ void kvmclock_init(void);
void kvmclock_cpu_action(enum kvm_guest_cpu_action action);
bool kvm_para_available(void);
unsigned int kvm_para_tsc_khz(void);
+unsigned int kvm_para_apic_bus_khz(void);
unsigned int kvm_arch_para_features(void);
unsigned int kvm_arch_para_hints(void);
void kvm_async_pf_task_wait_schedule(u32 token);
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 5cd92a0b156a..bfe36e361b3c 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -918,12 +918,25 @@ bool kvm_para_available(void)
}
EXPORT_SYMBOL_GPL(kvm_para_available);
-unsigned int kvm_para_tsc_khz(void)
+static bool kvm_cpuid_has_timing_info(void)
{
u32 base = kvm_cpuid_base();
- if (cpuid_eax(base) >= (base | KVM_CPUID_TIMING_INFO))
- return cpuid_eax(base | KVM_CPUID_TIMING_INFO);
+ return cpuid_eax(base) >= (base | KVM_CPUID_TIMING_INFO);
+}
+
+unsigned int kvm_para_tsc_khz(void)
+{
+ if (kvm_cpuid_has_timing_info())
+ return cpuid_eax(kvm_cpuid_base() | KVM_CPUID_TIMING_INFO);
+
+ return 0;
+}
+
+unsigned int kvm_para_apic_bus_khz(void)
+{
+ if (kvm_cpuid_has_timing_info())
+ return cpuid_ebx(kvm_cpuid_base() | KVM_CPUID_TIMING_INFO);
return 0;
}
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index 5ceba4f3836c..abcc5b36ea1d 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -200,10 +200,19 @@ void kvmclock_cpu_action(enum kvm_guest_cpu_action action)
*/
static unsigned long kvm_get_tsc_khz(void)
{
+#ifdef CONFIG_X86_LOCAL_APIC
+ u32 apic_khz = kvm_para_apic_bus_khz();
+
/*
- * If KVM advertises the frequency directly in CPUID, use that
- * instead of reverse-calculating it from the KVM clock data.
+ * Use the TSC frequency from KVM's (and other hypervisors') PV CPUID
+ * leaf when available, instead of reverse-calculating it from the KVM
+ * clock data. As a bonus, the CPUID leaf also includes the local APIC
+ * bus/timer frequency.
*/
+ if (apic_khz)
+ lapic_timer_period = apic_khz;
+#endif
+
return kvm_para_tsc_khz() ? : pvclock_tsc_khz(this_cpu_pvti());
}
--
2.54.0.563.g4f69b47b94-goog
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |