Commit 8a374026 authored by Yinghai Lu's avatar Yinghai Lu Committed by Thomas Gleixner

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: default avatarYinghai Lu <yinghai.lu@gmail.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 42651f15
...@@ -1103,6 +1103,7 @@ static u64 __init real_trim_memory(unsigned long start_pfn, unsigned long limit_ ...@@ -1103,6 +1103,7 @@ static u64 __init real_trim_memory(unsigned long start_pfn, unsigned long limit_
trim_size = limit_pfn; trim_size = limit_pfn;
trim_size <<= PAGE_SHIFT; trim_size <<= PAGE_SHIFT;
trim_size -= trim_start; trim_size -= trim_start;
return update_memory_range(trim_start, trim_size, E820_RAM, return update_memory_range(trim_start, trim_size, E820_RAM,
E820_RESERVED); E820_RESERVED);
} }
...@@ -1124,7 +1125,6 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) ...@@ -1124,7 +1125,6 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn)
struct res_range range[RANGE_NUM]; struct res_range range[RANGE_NUM];
int nr_range; int nr_range;
u64 total_real_trim_size; u64 total_real_trim_size;
int changed;
/* extra one for all 0 */ /* extra one for all 0 */
int num[MTRR_NUM_TYPES + 1]; int num[MTRR_NUM_TYPES + 1];
...@@ -1189,49 +1189,35 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) ...@@ -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); 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; total_real_trim_size = 0;
/* check the head */
if (range[0].start) if (range[0].start)
total_real_trim_size += real_trim_memory(0, range[0].start); total_real_trim_size += real_trim_memory(0, range[0].start);
/* check the holes */
for (i = 0; i < nr_range - 1; i--) { for (i = 0; i < nr_range - 1; i++) {
if (range[i].end + 1 < range[i+1].start) if (range[i].end + 1 < range[i+1].start)
total_real_trim_size += real_trim_memory(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) { if (total_real_trim_size) {
printk(KERN_WARNING "WARNING: BIOS bug: CPU MTRRs don't cover" printk(KERN_WARNING "WARNING: BIOS bug: CPU MTRRs don't cover"
" all of memory, losing %lluMB of RAM.\n", " all of memory, losing %lluMB of RAM.\n",
total_real_trim_size >> 20); total_real_trim_size >> 20);
if (enable_mtrr_cleanup < 1)
WARN_ON(1); WARN_ON(1);
printk(KERN_INFO "update e820 for mtrr -- holes\n"); printk(KERN_INFO "update e820 for mtrr\n");
update_e820(); update_e820();
changed = 1;
return 1;
} }
return changed; return 0;
} }
/** /**
......
...@@ -797,7 +797,8 @@ u64 __init update_memory_range(u64 start, u64 size, unsigned old_type, ...@@ -797,7 +797,8 @@ u64 __init update_memory_range(u64 start, u64 size, unsigned old_type,
if (ei->type != old_type) if (ei->type != old_type)
continue; continue;
/* totally covered? */ /* totally covered? */
if (ei->addr >= start && ei->size <= size) { if (ei->addr >= start &&
(ei->addr + ei->size) <= (start + size)) {
ei->type = new_type; ei->type = new_type;
real_updated_size += ei->size; real_updated_size += ei->size;
continue; continue;
......
...@@ -843,7 +843,8 @@ u64 __init update_memory_range(u64 start, u64 size, unsigned old_type, ...@@ -843,7 +843,8 @@ u64 __init update_memory_range(u64 start, u64 size, unsigned old_type,
if (ei->type != old_type) if (ei->type != old_type)
continue; continue;
/* totally covered? */ /* totally covered? */
if (ei->addr >= start && ei->size <= size) { if (ei->addr >= start &&
(ei->addr + ei->size) <= (start + size)) {
ei->type = new_type; ei->type = new_type;
real_updated_size += ei->size; real_updated_size += ei->size;
continue; continue;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment