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

v2:
Change function name to kvm_cpuid_get_intel_model and 
call the new vendor_intel()

Signed-off-by: Bandan Das <b...@redhat.com>
---
 arch/x86/include/uapi/asm/msr-index.h |  2 ++
 arch/x86/kvm/cpuid.c                  | 19 ++++++++++++++
 arch/x86/kvm/cpuid.h                  | 16 ++++++++++++
 arch/x86/kvm/x86.c                    | 48 +++++++++++++++++++++++++++++++++++
 4 files changed, 85 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..081461d 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -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_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..f9b2830 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 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_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:
+               bclk = BCLK_133_DEFAULT;
+               break;
+       case MODEL_SANDYBRIDGE_SANDY:
+       case MODEL_SANDYBRIDGE_E:
+       case MODEL_IVYBRIDGE_IVY:
+       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();
@@ -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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to