From e50c86f3d34029e521e6a92d061cec2cd0d0e931 Mon Sep 17 00:00:00 2001 From: Martin Lucina Date: Tue, 13 Oct 2015 16:10:24 +0200 Subject: [PATCH] Improve detection of pvclock There are two MSR variants, old-style and new-style. We want to prefer the new-style one, and neither if the relevant flags aren't set in CPUID. --- platform/hw/arch/x86/clock.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/platform/hw/arch/x86/clock.c b/platform/hw/arch/x86/clock.c index 2d7e052..4dbc8b0 100644 --- a/platform/hw/arch/x86/clock.c +++ b/platform/hw/arch/x86/clock.c @@ -340,17 +340,35 @@ pvclock_read_wall_clock(void) /* * Initialise PV clock. Returns zero if successful (PV clock is available). + * + * Source: Linux kernel, Documentation/virtual/kvm/{msr,cpuid}.txt */ static int pvclock_init(void) { + uint32_t eax, ebx, ecx, edx; + uint32_t msr_kvm_system_time, msr_kvm_wall_clock; if (hypervisor_detect() != HYPERVISOR_KVM) return 1; + /* + * Prefer new-style MSRs, and bail entirely if neither is indicated as + * available by CPUID. + */ + x86_cpuid(0x40000001, &eax, &ebx, &ecx, &edx); + if (eax & (1 << 3)) { + msr_kvm_system_time = 0x4b564d01; + msr_kvm_wall_clock = 0x4b564d00; + } + else if (eax & (1 << 0)) { + msr_kvm_system_time = 0x12; + msr_kvm_wall_clock = 0x11; + } + else + return 1; - /* Initialise MSR_KVM_SYSTEM_TIME_NEW and enable updates */ __asm__ __volatile("wrmsr" :: - "c" (0x4b564d01), + "c" (msr_kvm_system_time), "a" ((uint32_t)((uintptr_t)&pvclock_ti | 0x1)), #if defined(__x86_64__) "d" ((uint32_t)((uintptr_t)&pvclock_ti >> 32)) @@ -358,9 +376,8 @@ pvclock_init(void) "d" (0) #endif ); - /* Initialise MSR_KVM_WALL_CLOCK_NEW */ __asm__ __volatile("wrmsr" :: - "c" (0x4b564d00), + "c" (msr_kvm_wall_clock), "a" ((uint32_t)((uintptr_t)&pvclock_wc)), #if defined(__x86_64__) "d" ((uint32_t)((uintptr_t)&pvclock_wc >> 32)) -- 2.39.5