@@ -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
@@ -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;
@@ -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)
@@ -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;
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@redhat.com> --- 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(+)