x86: unmask CPUID levels on Intel CPUs
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 30 Jul 2010 10:36:34 +0000 (11:36 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 30 Jul 2010 10:36:34 +0000 (11:36 +0100)
If the CPUID limit bit in MSR_IA32_MISC_ENABLE is set, clear it to
make all CPUID information available. This is required for some
features to work, such as MWAIT in cpuidle, get cpu topology, XSAVE,
etc.

Signed-off-by: Wei Gang <gang.wei@intel.com>
xen/arch/x86/cpu/intel.c
xen/include/asm-x86/msr-index.h

index 67a40beb42312cdd90e611c9b0770ef78c632f75..8a5a7c89bd985fd45f7a20e959782dd22772bebd 100644 (file)
@@ -90,6 +90,20 @@ void __devinit early_intel_workaround(struct cpuinfo_x86 *c)
        /* Netburst reports 64 bytes clflush size, but does IO in 128 bytes */
        if (c->x86 == 15 && c->x86_cache_alignment == 64)
                c->x86_cache_alignment = 128;
+
+       /* Unmask CPUID levels if masked: */
+       if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) {
+               u64 misc_enable;
+
+               rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
+
+               if (misc_enable & MSR_IA32_MISC_ENABLE_LIMIT_CPUID) {
+                       misc_enable &= ~MSR_IA32_MISC_ENABLE_LIMIT_CPUID;
+                       wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
+                       c->cpuid_level = cpuid_eax(0);
+                       printk("revised cpuid_level = %d\n", c->cpuid_level);
+               }
+       }
 }
 
 /*
index 150e19154f2ba7ce05e5f2d310d188ae05f8626d..813531bd8ef277ec6b736f2cd3c611451a9bb2c8 100644 (file)
 #define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL  (1<<11)
 #define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL (1<<12)
 #define MSR_IA32_MISC_ENABLE_MONITOR_ENABLE (1<<18)
+#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID  (1<<22)
 #define MSR_IA32_MISC_ENABLE_XTPR_DISABLE (1<<23)
 
 /* Intel Model 6 */