From 14ec92518e82158b36455dc6fd90dec28718ba0f Mon Sep 17 00:00:00 2001 From: Balazs Gerofi Date: Thu, 26 May 2016 01:11:08 +0900 Subject: [PATCH] KVM support: detect KVM and avoid touching unimplemented MSRs --- arch/x86/kernel/cpu.c | 27 +++++++++++++++++++++++++++ arch/x86/kernel/perfctr.c | 4 ++++ 2 files changed, 31 insertions(+) diff --git a/arch/x86/kernel/cpu.c b/arch/x86/kernel/cpu.c index 4fbb4c24..7f847fbb 100644 --- a/arch/x86/kernel/cpu.c +++ b/arch/x86/kernel/cpu.c @@ -79,6 +79,7 @@ static unsigned int (*lapic_read)(int reg); static void (*lapic_icr_write)(unsigned int h, unsigned int l); static void (*lapic_wait_icr_idle)(void); void (*x86_issue_ipi)(unsigned int apicid, unsigned int low); +int running_on_kvm(void); void init_processors_local(int max_id); void assign_processor_id(void); @@ -454,6 +455,8 @@ void init_pstate_and_turbo(void) uint64_t value; uint64_t eax, ecx; + if (running_on_kvm()) return; + asm volatile("cpuid" : "=a" (eax), "=c" (ecx) : "a" (0x6) : "%rbx", "%rdx"); if (!(ecx & 0x01)) { /* P-states and/or Turbo Boost are not supported. */ @@ -619,6 +622,9 @@ static void init_smp_processor(void) reload_gdt(&v->gdt_ptr); set_kstack((unsigned long)get_x86_this_cpu_kstack()); + + /* MSR_IA32_TSC_AUX on KVM seems broken */ + if (running_on_kvm()) return; #define MSR_IA32_TSC_AUX 0xc0000103 wrmsr(MSR_IA32_TSC_AUX, node_cpu); } @@ -1740,4 +1746,25 @@ out: return error; } /* arch_get_cpu_mapping() */ +#define KVM_CPUID_SIGNATURE 0x40000000 + +int running_on_kvm(void) { + static const char signature[12] = "KVMKVMKVM\0\0"; + const uint32_t *sigptr = (const uint32_t *)signature; + uint64_t op; + uint64_t eax; + uint64_t ebx; + uint64_t ecx; + uint64_t edx; + + op = KVM_CPUID_SIGNATURE; + asm volatile("cpuid" : "=a"(eax),"=b"(ebx),"=c"(ecx),"=d"(edx) : "a" (op)); + + if (ebx == sigptr[0] && ecx == sigptr[1] && edx == sigptr[2]) { + return 1; + } + + return 0; +} + /*** end of file ***/ diff --git a/arch/x86/kernel/perfctr.c b/arch/x86/kernel/perfctr.c index e587a449..c4bbc4a4 100644 --- a/arch/x86/kernel/perfctr.c +++ b/arch/x86/kernel/perfctr.c @@ -14,6 +14,7 @@ #include extern unsigned int *x86_march_perfmap; +extern int running_on_kvm(void); #define X86_CR4_PCE 0x00000100 @@ -22,6 +23,9 @@ void x86_init_perfctr(void) unsigned long reg; unsigned long value = 0; + /* Do not do it on KVM */ + if (running_on_kvm()) return; + /* Allow PMC to be read from user space */ asm volatile("movq %%cr4, %0" : "=r"(reg)); reg |= X86_CR4_PCE;