@@ -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,24 @@ struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu,
}
EXPORT_SYMBOL_GPL(kvm_find_cpuid_entry);
+u8 kvm_guest_vcpu_model(struct kvm_vcpu *vcpu)
+{
+ struct kvm_cpuid_entry2 *best;
+ u8 cpuid_model, cpuid_extmodel;
+
+ if (!vendor_intel(vcpu))
+ 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,21 @@
#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 */
+
+#define BCLK_133_DEFAULT (133 * 1000)
+#define BCLK_100_DEFAULT (100 * 1000)
+
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 +33,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_guest_vcpu_model(struct kvm_vcpu *vcpu);
static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu)
@@ -236,6 +236,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 bclk;
+
+ /*
+ * 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_guest_vcpu_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:
+ bclk = BCLK_133_DEFAULT;
+ break;
+ case MODEL_SANDYBRIDGE_SANDYBRIDGE:
+ case MODEL_SANDYBRIDGE_E:
+ case MODEL_IVYBRIDGE_IVYBRIDGE:
+ case MODEL_HASWELL_HASWELL:
+ bclk = BCLK_100_DEFAULT;
+ break;
+ default:
+ bclk = 0;
+ break;
+ }
+
+ if (bclk) {
+ max_nonturbo_ratio = max_effi_ratio
+ = (u8)(vcpu->arch.virtual_tsc_khz / bclk);
+ 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();
@@ -1971,6 +2014,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;
@@ -2336,6 +2381,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> --- arch/x86/include/uapi/asm/msr-index.h | 2 ++ arch/x86/kvm/cpuid.c | 18 +++++++++++++ arch/x86/kvm/cpuid.h | 16 ++++++++++++ arch/x86/kvm/x86.c | 48 +++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+)