Some latest Intel CPU models support cpuid feature mask.
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 9 Jul 2008 10:42:45 +0000 (11:42 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 9 Jul 2008 10:42:45 +0000 (11:42 +0100)
CPUID.1.EAX>0x00010674.CPUID mask feature is intended to be used to
limit the feature flags reported by CPUID.1.EDX:ECX.

Signed-off-by: Liping Ke <liping.ke@intel.com>
Signed-off-by: Jun Nakajima <nakajima.jun@intel.com>
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/cpu/intel.c
xen/include/asm-x86/msr-index.h

index 5fcad2403ad204dee881f6664dbde80ba0a7e914..1025097d21064b9b48f0f8a8e0c41b1b675628a5 100644 (file)
 
 extern int trap_init_f00f_bug(void);
 
+/*
+ * opt_cpuid_mask_ecx/edx: cpuid.1[ecx, edx] feature mask.
+ * For example, E8400[Intel Core 2 Duo Processor series] ecx = 0x0008E3FD, 
+ * edx = 0xBFEBFBFF when executing CPUID.EAX = 1 normally. If you want to
+ * 'rev down' to E8400, you can set these values in these Xen boot parameters.
+ */
+static unsigned int opt_cpuid_mask_ecx, opt_cpuid_mask_edx;
+integer_param("cpuid_mask_ecx", opt_cpuid_mask_ecx);
+integer_param("cpuid_mask_edx", opt_cpuid_mask_edx);
+
 #ifdef CONFIG_X86_INTEL_USERCOPY
 /*
  * Alignment at which movsl is preferred for bulk memory copies.
@@ -25,6 +35,25 @@ extern int trap_init_f00f_bug(void);
 struct movsl_mask movsl_mask __read_mostly;
 #endif
 
+static void __devinit set_cpuidmask(void)
+{
+       unsigned int eax, ebx, ecx, edx;
+
+       if (!(opt_cpuid_mask_ecx | opt_cpuid_mask_edx))
+               return;
+
+       cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
+       if (eax < 0x00010674) {
+               printk(XENLOG_ERR "Cannot set CPU feature mask on CPU#%d\n",
+                      smp_processor_id());
+               return;
+       }
+
+       wrmsr(MSR_IA32_CPUID_FEATURE_MASK1,
+             opt_cpuid_mask_ecx ? : ~0u,
+             opt_cpuid_mask_edx ? : ~0u);
+}
+
 void __devinit early_intel_workaround(struct cpuinfo_x86 *c)
 {
        if (c->x86_vendor != X86_VENDOR_INTEL)
@@ -158,6 +187,8 @@ static void __devinit init_intel(struct cpuinfo_x86 *c)
 
        detect_ht(c);
 
+       set_cpuidmask();
+
        /* Work around errata */
        Intel_errata_workarounds(c);
 
index 69221ced3fec23c40f3af77a76e12e6b7657055b..7e2164797e55d35f70fde56196c7db56548fddc5 100644 (file)
 #define MSR_P6_EVNTSEL0                        0x00000186
 #define MSR_P6_EVNTSEL1                        0x00000187
 
+/* MSR for cpuid feature mask */
+#define MSR_IA32_CPUID_FEATURE_MASK1   0x00000478
+
 /* MSRs & bits used for VMX enabling */
 #define MSR_IA32_VMX_BASIC                      0x480
 #define MSR_IA32_VMX_PINBASED_CTLS              0x481