debuggers.hg
changeset 19614:ce273aa880e5
x86: Detect bogus BIOS e820 tables which are not fully covered as
cacheable (WB) by MTRRs. Fix up by truncating the memory map.
This fixes performance issues on certain systems.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
cacheable (WB) by MTRRs. Fix up by truncating the memory map.
This fixes performance issues on certain systems.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Fri Apr 24 17:51:56 2009 +0100 (2009-04-24) |
parents | dc5bd14a4675 |
children | 7809e0941b38 |
files | xen/arch/x86/e820.c |
line diff
1.1 --- a/xen/arch/x86/e820.c Fri Apr 24 13:46:17 2009 +0100 1.2 +++ b/xen/arch/x86/e820.c Fri Apr 24 17:51:56 2009 +0100 1.3 @@ -6,6 +6,9 @@ 1.4 #include <xen/dmi.h> 1.5 #include <asm/e820.h> 1.6 #include <asm/page.h> 1.7 +#include <asm/processor.h> 1.8 +#include <asm/mtrr.h> 1.9 +#include <asm/msr.h> 1.10 1.11 /* opt_mem: Limit of physical RAM. Any RAM beyond this point is ignored. */ 1.12 unsigned long long opt_mem; 1.13 @@ -345,6 +348,55 @@ static void __init clip_to_limit(uint64_ 1.14 } 1.15 } 1.16 1.17 +/* Conservative estimate of top-of-RAM by looking for MTRR WB regions. */ 1.18 +#define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg)) 1.19 +#define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1) 1.20 +static uint64_t mtrr_top_of_ram(void) 1.21 +{ 1.22 + uint32_t eax, ebx, ecx, edx; 1.23 + uint64_t mtrr_cap, mtrr_def, addr_mask, base, mask, top; 1.24 + unsigned int i, phys_bits = 36; 1.25 + 1.26 + /* Does the CPU support architectural MTRRs? */ 1.27 + cpuid(0x00000001, &eax, &ebx, &ecx, &edx); 1.28 + if ( !test_bit(X86_FEATURE_MTRR & 31, &edx) ) 1.29 + return 0; 1.30 + 1.31 + /* Find the physical address size for this CPU. */ 1.32 + cpuid(0x80000000, &eax, &ebx, &ecx, &edx); 1.33 + if ( eax >= 0x80000008 ) 1.34 + { 1.35 + cpuid(0x80000008, &eax, &ebx, &ecx, &edx); 1.36 + phys_bits = (uint8_t)eax; 1.37 + } 1.38 + addr_mask = ((1ull << phys_bits) - 1) & ~((1ull << 12) - 1); 1.39 + 1.40 + rdmsrl(MSR_MTRRcap, mtrr_cap); 1.41 + rdmsrl(MSR_MTRRdefType, mtrr_def); 1.42 + 1.43 + /* MTRRs enabled, and default memory type is not writeback? */ 1.44 + if ( !test_bit(11, &mtrr_def) || ((uint8_t)mtrr_def == MTRR_TYPE_WRBACK) ) 1.45 + return 0; 1.46 + 1.47 + /* 1.48 + * Find end of highest WB-type range. This is a conservative estimate 1.49 + * of the highest WB address since overlapping UC/WT ranges dominate. 1.50 + */ 1.51 + top = 0; 1.52 + for ( i = 0; i < (uint8_t)mtrr_cap; i++ ) 1.53 + { 1.54 + rdmsrl(MSR_MTRRphysBase(i), base); 1.55 + rdmsrl(MSR_MTRRphysMask(i), mask); 1.56 + if ( !test_bit(11, &mask) || ((uint8_t)base != MTRR_TYPE_WRBACK) ) 1.57 + continue; 1.58 + base &= addr_mask; 1.59 + mask &= addr_mask; 1.60 + top = max_t(uint64_t, top, ((base | ~mask) & addr_mask) + PAGE_SIZE); 1.61 + } 1.62 + 1.63 + return top; 1.64 +} 1.65 + 1.66 static void __init reserve_dmi_region(void) 1.67 { 1.68 u32 base, len; 1.69 @@ -357,6 +409,8 @@ static void __init reserve_dmi_region(vo 1.70 static void __init machine_specific_memory_setup( 1.71 struct e820entry *raw, int *raw_nr) 1.72 { 1.73 + uint64_t top_of_ram; 1.74 + 1.75 char nr = (char)*raw_nr; 1.76 sanitize_e820_map(raw, &nr); 1.77 *raw_nr = nr; 1.78 @@ -389,6 +443,10 @@ static void __init machine_specific_memo 1.79 #endif 1.80 1.81 reserve_dmi_region(); 1.82 + 1.83 + top_of_ram = mtrr_top_of_ram(); 1.84 + if ( top_of_ram ) 1.85 + clip_to_limit(top_of_ram, "MTRRs do not cover all of memory."); 1.86 } 1.87 1.88 int __init e820_change_range_type(