To emulate MSR_PLATFORM_INFO, we divide guest virtual_tsc_khz by the base clock - which is guest CPU model dependent. The relevant bits in this emulated MSR are : Max Non-Turbo Ratio (15:8) - virtual_tsc_khz/bclk Max Effi Ratio (47:40) - virtual_tsc_khz/bclk Prog Ratio Limit for Trubo (28) - 0 Prog TDC-TDP Limit for Turbo (29) - 0 Signed-off-by: Bandan Das <bsd@xxxxxxxxxx> --- v3: Change bclk to base_clock_khz v2: Change function name to kvm_cpuid_get_intel_model and call the new vendor_intel() arch/x86/include/uapi/asm/msr-index.h | 2 ++ arch/x86/kvm/cpuid.c | 19 ++++++++++++++ arch/x86/kvm/cpuid.h | 13 ++++++++++ arch/x86/kvm/x86.c | 48 +++++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+) diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h index 2af848d..b0268d5 100644 --- a/arch/x86/include/uapi/asm/msr-index.h +++ b/arch/x86/include/uapi/asm/msr-index.h @@ -331,6 +331,8 @@ #define MSR_IA32_MISC_ENABLE 0x000001a0 +#define MSR_IA32_PLATFORM_INFO 0x000000ce + #define MSR_IA32_TEMPERATURE_TARGET 0x000001a2 #define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0 diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index a20ecb5..ae970d3 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -608,6 +608,25 @@ struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, } EXPORT_SYMBOL_GPL(kvm_find_cpuid_entry); +u8 kvm_cpuid_get_intel_model(struct kvm_vcpu *vcpu) +{ + struct kvm_cpuid_entry2 *best; + u8 cpuid_model, cpuid_extmodel; + + best = kvm_find_cpuid_entry(vcpu, 0, 0); + if (!vendor_intel(best->ebx, best->ecx, best->edx)) + return CPUID_MODEL_UNKNOWN; + + best = kvm_find_cpuid_entry(vcpu, 1, 0); + + cpuid_model = (best->eax >> 4) & 0xf; + cpuid_extmodel = (best->eax >> 16) & 0xf; + + cpuid_model += (cpuid_extmodel << 4); + + return cpuid_model; +} + int cpuid_maxphyaddr(struct kvm_vcpu *vcpu) { struct kvm_cpuid_entry2 *best; diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index b7fd079..2613f37 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -3,6 +3,18 @@ #include "x86.h" +#define MODEL_NEHALEM_CLARKSFIELD 0x1e /* Core i7 and Ex BCLK: 133Mhz */ +#define MODEL_NEHALEM_BLOOMFIELD 0x1a /* Core i7 Xeon 3000 BCLK: 133 Mhz */ +#define MODEL_NEHALEM_EX 0x2e /* Core i7 and i5 Nehalem BCLK: 133 Mhz */ +#define MODEL_WESTMERE_ARRANDALE 0x25 /* Celeron/Pentium/Core i3/i5/i7 BCLK: 133 Mhz */ +#define MODEL_WESTMERE_EX 0x2f /* Xeon E7 BCLK: 133 Mhz */ +#define MODEL_WESTMERE_GULFTOWN 0x2c /* Core i7 Xeon 3000 BCLK: 133 Mhz */ +#define MODEL_SANDYBRIDGE_SANDY 0x2a /* Core/Celeron/Pentium/Xeon BCLK: 133 Mhz */ +#define MODEL_SANDYBRIDGE_E 0x2d /* Core i7 and Ex BCLK: 100 Mhz */ +#define MODEL_IVYBRIDGE_IVY 0x3a /* Core i3/i5/i7 (Ex) and Xeon E3 BCLK: 100 Mhz */ +#define MODEL_HASWELL_HASWELL 0x3c /* BCLK: 100 Mhz */ +#define CPUID_MODEL_UNKNOWN 0x0 /* Everything else */ + void kvm_update_cpuid(struct kvm_vcpu *vcpu); struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, u32 function, u32 index); @@ -18,6 +30,7 @@ int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid, struct kvm_cpuid_entry2 __user *entries); void kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); +u8 kvm_cpuid_get_intel_model(struct kvm_vcpu *vcpu); static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 094b5d9..06c40e6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -239,6 +239,49 @@ void kvm_set_shared_msr(unsigned slot, u64 value, u64 mask) } EXPORT_SYMBOL_GPL(kvm_set_shared_msr); +static u64 kvm_get_platform_info(struct kvm_vcpu *vcpu) +{ + u8 cpumodel; + u32 base_clock_khz; + + /* + * Programmable Ratio Limit for Turbo Mode (bit 28): 0 + * Programmable TDC-TDP Limit for Turbo Mode (bit 29): 0 + */ + u64 platform_info = 0, max_nonturbo_ratio = 0, max_effi_ratio = 0; + + cpumodel = kvm_cpuid_get_intel_model(vcpu); + + switch (cpumodel) { + case MODEL_NEHALEM_CLARKSFIELD: + case MODEL_NEHALEM_BLOOMFIELD: + case MODEL_NEHALEM_EX: + case MODEL_WESTMERE_ARRANDALE: + case MODEL_WESTMERE_GULFTOWN: + case MODEL_WESTMERE_EX: + base_clock_khz = (133 * 1000); + break; + case MODEL_SANDYBRIDGE_SANDY: + case MODEL_SANDYBRIDGE_E: + case MODEL_IVYBRIDGE_IVY: + case MODEL_HASWELL_HASWELL: + base_clock_khz = (100 * 1000); + break; + default: + base_clock_khz = 0; + break; + } + + if (base_clock_khz) { + max_nonturbo_ratio = max_effi_ratio + = (u8)(vcpu->arch.virtual_tsc_khz / base_clock_khz); + platform_info = (max_effi_ratio << 40) + | (max_nonturbo_ratio << 8); + } + + return platform_info; +} + static void drop_user_return_notifiers(void *ignore) { unsigned int cpu = smp_processor_id(); @@ -1974,6 +2017,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) case MSR_IA32_MISC_ENABLE: vcpu->arch.ia32_misc_enable_msr = data; break; + case MSR_IA32_PLATFORM_INFO: + return 1; case MSR_KVM_WALL_CLOCK_NEW: case MSR_KVM_WALL_CLOCK: vcpu->kvm->arch.wall_clock = data; @@ -2339,6 +2384,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) case MSR_IA32_MISC_ENABLE: data = vcpu->arch.ia32_misc_enable_msr; break; + case MSR_IA32_PLATFORM_INFO: + data = kvm_get_platform_info(vcpu); + break; case MSR_IA32_PERF_STATUS: /* TSC increment by tick */ data = 1000ULL; -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html