KVM support: detect KVM and avoid touching unimplemented MSRs
This commit is contained in:
@@ -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_icr_write)(unsigned int h, unsigned int l);
|
||||||
static void (*lapic_wait_icr_idle)(void);
|
static void (*lapic_wait_icr_idle)(void);
|
||||||
void (*x86_issue_ipi)(unsigned int apicid, unsigned int low);
|
void (*x86_issue_ipi)(unsigned int apicid, unsigned int low);
|
||||||
|
int running_on_kvm(void);
|
||||||
|
|
||||||
void init_processors_local(int max_id);
|
void init_processors_local(int max_id);
|
||||||
void assign_processor_id(void);
|
void assign_processor_id(void);
|
||||||
@@ -454,6 +455,8 @@ void init_pstate_and_turbo(void)
|
|||||||
uint64_t value;
|
uint64_t value;
|
||||||
uint64_t eax, ecx;
|
uint64_t eax, ecx;
|
||||||
|
|
||||||
|
if (running_on_kvm()) return;
|
||||||
|
|
||||||
asm volatile("cpuid" : "=a" (eax), "=c" (ecx) : "a" (0x6) : "%rbx", "%rdx");
|
asm volatile("cpuid" : "=a" (eax), "=c" (ecx) : "a" (0x6) : "%rbx", "%rdx");
|
||||||
if (!(ecx & 0x01)) {
|
if (!(ecx & 0x01)) {
|
||||||
/* P-states and/or Turbo Boost are not supported. */
|
/* P-states and/or Turbo Boost are not supported. */
|
||||||
@@ -619,6 +622,9 @@ static void init_smp_processor(void)
|
|||||||
reload_gdt(&v->gdt_ptr);
|
reload_gdt(&v->gdt_ptr);
|
||||||
|
|
||||||
set_kstack((unsigned long)get_x86_this_cpu_kstack());
|
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
|
#define MSR_IA32_TSC_AUX 0xc0000103
|
||||||
wrmsr(MSR_IA32_TSC_AUX, node_cpu);
|
wrmsr(MSR_IA32_TSC_AUX, node_cpu);
|
||||||
}
|
}
|
||||||
@@ -1740,4 +1746,25 @@ out:
|
|||||||
return error;
|
return error;
|
||||||
} /* arch_get_cpu_mapping() */
|
} /* 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 ***/
|
/*** end of file ***/
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <registers.h>
|
#include <registers.h>
|
||||||
|
|
||||||
extern unsigned int *x86_march_perfmap;
|
extern unsigned int *x86_march_perfmap;
|
||||||
|
extern int running_on_kvm(void);
|
||||||
|
|
||||||
#define X86_CR4_PCE 0x00000100
|
#define X86_CR4_PCE 0x00000100
|
||||||
|
|
||||||
@@ -22,6 +23,9 @@ void x86_init_perfctr(void)
|
|||||||
unsigned long reg;
|
unsigned long reg;
|
||||||
unsigned long value = 0;
|
unsigned long value = 0;
|
||||||
|
|
||||||
|
/* Do not do it on KVM */
|
||||||
|
if (running_on_kvm()) return;
|
||||||
|
|
||||||
/* Allow PMC to be read from user space */
|
/* Allow PMC to be read from user space */
|
||||||
asm volatile("movq %%cr4, %0" : "=r"(reg));
|
asm volatile("movq %%cr4, %0" : "=r"(reg));
|
||||||
reg |= X86_CR4_PCE;
|
reg |= X86_CR4_PCE;
|
||||||
|
|||||||
Reference in New Issue
Block a user