diff -r cb4d42aaf673 xen/arch/x86/cpu/mtrr/generic.c --- a/xen/arch/x86/cpu/mtrr/generic.c Tue Mar 01 14:03:16 2011 -0600 +++ b/xen/arch/x86/cpu/mtrr/generic.c Tue Mar 01 15:31:36 2011 -0600 @@ -34,12 +34,38 @@ rdmsrl(MTRRphysMask_MSR(index), vr->mask); } + +/* + * 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 inline void amd_check_syscfg_dram_mod_en(void) +{ + uint64_t syscfg; + + 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) { + printk(KERN_ERR "MTRR: CPU %u: SYSCFG[MtrrFixDramModEn]" + " not cleared by BIOS, clearing this bit\n", + smp_processor_id()); + syscfg &= ~K8_MTRRFIXRANGE_DRAM_MODIFY; + wrmsr_safe(MSR_K8_SYSCFG, syscfg); + } +} + static void get_fixed_ranges(mtrr_type * frs) { uint64_t *p = (uint64_t *) frs; int i; + amd_check_syscfg_dram_mod_en(); + rdmsrl(MTRRfix64K_00000_MSR, p[0]); for (i = 0; i < 2; i++) @@ -146,7 +172,7 @@ if (msr_content != val) { if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && - boot_cpu_data.x86 == 15 && + boot_cpu_data.x86 >= 0xf && ((msrwords[0] | msrwords[1]) & K8_MTRR_RDMEM_WRMEM_MASK)) k8_enable_fixed_iorrs(); mtrr_wrmsr(msr, val);