58 lines
1.6 KiB
Diff
58 lines
1.6 KiB
Diff
|
# HG changeset patch
|
||
|
# User Wei Huang <wei.huang2@amd.com>
|
||
|
# Date 1302076891 -3600
|
||
|
# Node ID 8fb61c9ebe499b576687907d164da07802414925
|
||
|
# Parent 97763efc41f9b664cf6f7db653c9c3f51e50b358
|
||
|
x86, amd, MTRR: correct DramModEn bit of SYS_CFG MSR
|
||
|
|
||
|
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>
|
||
|
|
||
|
--- a/xen/arch/x86/cpu/amd.c
|
||
|
+++ b/xen/arch/x86/cpu/amd.c
|
||
|
@@ -318,6 +318,32 @@ static void check_disable_c1e(unsigned i
|
||
|
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;
|
||
|
@@ -587,6 +613,8 @@ static void __devinit init_amd(struct cp
|
||
|
disable_c1_ramping();
|
||
|
|
||
|
set_cpuidmask(c);
|
||
|
+
|
||
|
+ check_syscfg_dram_mod_en();
|
||
|
}
|
||
|
|
||
|
static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
|