diff mbox

[v3,2/2] kvm: x86: emulate MSR_PLATFORM_INFO

Message ID 1371832163-2083-3-git-send-email-bsd@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Bandan Das June 21, 2013, 4:29 p.m. UTC
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(+)
diff mbox

Patch

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;