kvm: add support for reading tsc frequency from kvmclock

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 20200310102248.28412-4-kraxel@redhat.com
This commit is contained in:
Gerd Hoffmann 2020-03-10 11:22:48 +01:00
parent 34160e0525
commit b3fa857752
2 changed files with 56 additions and 0 deletions

View File

@ -75,6 +75,48 @@ static void kvm_detect(void)
}
}
#define KVM_FEATURE_CLOCKSOURCE 0
#define KVM_FEATURE_CLOCKSOURCE2 3
#define MSR_KVM_SYSTEM_TIME 0x12
#define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01
#define PVCLOCK_TSC_STABLE_BIT (1 << 0)
struct pvclock_vcpu_time_info *kvmclock;
static void kvmclock_init(void)
{
unsigned int eax, ebx, ecx, edx, msr;
if (!runningOnKVM())
return;
cpuid(KVM_CPUID_SIGNATURE + 0x01, &eax, &ebx, &ecx, &edx);
if (eax & (1 << KVM_FEATURE_CLOCKSOURCE2))
msr = MSR_KVM_SYSTEM_TIME_NEW;
else if (eax & (1 << KVM_FEATURE_CLOCKSOURCE))
msr = MSR_KVM_SYSTEM_TIME;
else
return;
kvmclock = memalign_low(sizeof(*kvmclock), 32);
memset(kvmclock, 0, sizeof(*kvmclock));
u32 value = (u32)(kvmclock);
dprintf(1, "kvmclock: at 0x%x (msr 0x%x)\n", value, msr);
wrmsr(msr, value | 0x01);
if (!(kvmclock->flags & PVCLOCK_TSC_STABLE_BIT))
return;
u32 MHz = (1000 << 16) / (kvmclock->tsc_to_system_mul >> 16);
if (kvmclock->tsc_shift < 0)
MHz <<= -kvmclock->tsc_shift;
else
MHz >>= kvmclock->tsc_shift;
dprintf(1, "kvmclock: stable tsc, %d MHz\n", MHz);
tsctimer_setfreq(MHz * 1000, "kvmclock");
}
static void qemu_detect(void)
{
if (!CONFIG_QEMU_HARDWARE)
@ -163,6 +205,8 @@ qemu_platform_setup(void)
return;
}
kvmclock_init();
// Initialize pci
pci_setup();
smm_device_setup();

View File

@ -5,6 +5,18 @@
#include "biosvar.h" // GET_GLOBAL
#include "romfile.h" // struct romfile_s
// kvmclock
struct pvclock_vcpu_time_info {
u32 version;
u32 pad0;
u64 tsc_timestamp;
u64 system_time;
u32 tsc_to_system_mul;
s8 tsc_shift;
u8 flags;
u8 pad[2];
} __attribute__((__packed__)); /* 32 bytes */
// Types of paravirtualized platforms.
#define PF_QEMU (1<<0)
#define PF_XEN (1<<1)