]> xenbits.xensource.com Git - xen.git/commitdiff
x86, amd, MTRR: correct DramModEn bit of SYS_CFG MSR
authorWei Huang <wei.huang2@amd.com>
Wed, 6 Apr 2011 08:01:31 +0000 (09:01 +0100)
committerWei Huang <wei.huang2@amd.com>
Wed, 6 Apr 2011 08:01:31 +0000 (09:01 +0100)
Some buggy BIOS might set SYS_CFG DramModEn bit to 1, which can cause
unexpected behavior on AMD platforms. This patch clears DramModEn bit
if it is 1.

Signed-off-by: Wei Huang <wei.huang2@amd.com>
xen/arch/x86/cpu/amd.c

index c1cba411b1cf04256bdea70e99390779169c7802..3533d3e404cfb2941f687d2ef86fb73da1edafd9 100644 (file)
@@ -300,6 +300,32 @@ static void check_disable_c1e(unsigned int port, u8 value)
                on_each_cpu(disable_c1e, NULL, 1);
 }
 
+/*
+ * BIOS is expected to clear MtrrFixDramModEn bit. According to AMD BKDG : 
+ * "The MtrrFixDramModEn bit should be set to 1 during BIOS initalization of 
+ * the fixed MTRRs, then cleared to 0 for operation."
+ */
+static void check_syscfg_dram_mod_en(void)
+{
+       uint64_t syscfg;
+       static bool_t printed = 0;
+
+       if (!((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
+               (boot_cpu_data.x86 >= 0x0f)))
+               return;
+
+       rdmsrl(MSR_K8_SYSCFG, syscfg);
+       if (!(syscfg & K8_MTRRFIXRANGE_DRAM_MODIFY))
+               return;
+
+       if (!test_and_set_bool(printed))
+               printk(KERN_ERR "MTRR: SYSCFG[MtrrFixDramModEn] not "
+                       "cleared by BIOS, clearing this bit\n");
+
+       syscfg &= ~K8_MTRRFIXRANGE_DRAM_MODIFY;
+       wrmsrl(MSR_K8_SYSCFG, syscfg);
+}
+
 static void __devinit init_amd(struct cpuinfo_x86 *c)
 {
        u32 l, h;
@@ -453,6 +479,8 @@ static void __devinit init_amd(struct cpuinfo_x86 *c)
                disable_c1_ramping();
 
        set_cpuidmask(c);
+
+       check_syscfg_dram_mod_en();
 }
 
 static struct cpu_dev amd_cpu_dev __cpuinitdata = {