aboutsummaryrefslogtreecommitdiff
path: root/arch/x86/kernel
diff options
context:
space:
mode:
authorYinghai Lu <yhlu.kernel.send@gmail.com>2008-04-29 20:25:16 -0700
committerThomas Gleixner <tglx@linutronix.de>2008-05-25 10:55:10 +0200
commit8a374026c265476b1acfc3c186a66d59ebdb2cda (patch)
tree85ae71ca6aa6851934d1880373bc8b9fa884e5ca /arch/x86/kernel
parent42651f15824d003e8357693ab72c4dbb3e280836 (diff)
x86: fix trimming e820 with MTRR holes. - fix
v2: process hole then end_pfn fix update_memory_range with whole cover comparing Signed-off-by: Yinghai Lu <yinghai.lu@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/cpu/mtrr/main.c44
-rw-r--r--arch/x86/kernel/e820_32.c3
-rw-r--r--arch/x86/kernel/e820_64.c3
3 files changed, 19 insertions, 31 deletions
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index 9ab5c16b0d5..5a2a4c14633 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -1098,11 +1098,12 @@ int __init amd_special_default_mtrr(void)
static u64 __init real_trim_memory(unsigned long start_pfn, unsigned long limit_pfn)
{
u64 trim_start, trim_size;
- trim_start = start_pfn;
+ trim_start = start_pfn;
trim_start <<= PAGE_SHIFT;
trim_size = limit_pfn;
trim_size <<= PAGE_SHIFT;
trim_size -= trim_start;
+
return update_memory_range(trim_start, trim_size, E820_RAM,
E820_RESERVED);
}
@@ -1124,7 +1125,6 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn)
struct res_range range[RANGE_NUM];
int nr_range;
u64 total_real_trim_size;
- int changed;
/* extra one for all 0 */
int num[MTRR_NUM_TYPES + 1];
@@ -1189,49 +1189,35 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn)
}
nr_range = x86_get_mtrr_mem_range(range, nr_range, 0, 0);
- changed = 0;
- total_real_trim_size = 0;
-
- /* check the top at first */
- i = nr_range - 1;
- if (range[i].end + 1 < end_pfn) {
- total_real_trim_size += real_trim_memory(range[i].end + 1, end_pfn);
- }
-
- if (total_real_trim_size) {
- printk(KERN_WARNING "WARNING: BIOS bug: CPU MTRRs don't cover"
- " all of memory, losing %lluMB of RAM.\n",
- total_real_trim_size >> 20);
-
- WARN_ON(1);
-
- printk(KERN_INFO "update e820 for mtrr -- end_pfn\n");
- update_e820();
- changed = 1;
- }
-
total_real_trim_size = 0;
+ /* check the head */
if (range[0].start)
total_real_trim_size += real_trim_memory(0, range[0].start);
-
- for (i = 0; i < nr_range - 1; i--) {
+ /* check the holes */
+ for (i = 0; i < nr_range - 1; i++) {
if (range[i].end + 1 < range[i+1].start)
total_real_trim_size += real_trim_memory(range[i].end + 1, range[i+1].start);
}
+ /* check the top */
+ i = nr_range - 1;
+ if (range[i].end + 1 < end_pfn)
+ total_real_trim_size += real_trim_memory(range[i].end + 1, end_pfn);
if (total_real_trim_size) {
printk(KERN_WARNING "WARNING: BIOS bug: CPU MTRRs don't cover"
" all of memory, losing %lluMB of RAM.\n",
total_real_trim_size >> 20);
- WARN_ON(1);
+ if (enable_mtrr_cleanup < 1)
+ WARN_ON(1);
- printk(KERN_INFO "update e820 for mtrr -- holes\n");
+ printk(KERN_INFO "update e820 for mtrr\n");
update_e820();
- changed = 1;
+
+ return 1;
}
- return changed;
+ return 0;
}
/**
diff --git a/arch/x86/kernel/e820_32.c b/arch/x86/kernel/e820_32.c
index 857f706273a..751d517d802 100644
--- a/arch/x86/kernel/e820_32.c
+++ b/arch/x86/kernel/e820_32.c
@@ -797,7 +797,8 @@ u64 __init update_memory_range(u64 start, u64 size, unsigned old_type,
if (ei->type != old_type)
continue;
/* totally covered? */
- if (ei->addr >= start && ei->size <= size) {
+ if (ei->addr >= start &&
+ (ei->addr + ei->size) <= (start + size)) {
ei->type = new_type;
real_updated_size += ei->size;
continue;
diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c
index 848b2cd2d1d..c45b4dea405 100644
--- a/arch/x86/kernel/e820_64.c
+++ b/arch/x86/kernel/e820_64.c
@@ -843,7 +843,8 @@ u64 __init update_memory_range(u64 start, u64 size, unsigned old_type,
if (ei->type != old_type)
continue;
/* totally covered? */
- if (ei->addr >= start && ei->size <= size) {
+ if (ei->addr >= start &&
+ (ei->addr + ei->size) <= (start + size)) {
ei->type = new_type;
real_updated_size += ei->size;
continue;