Commit 5dca6a1b authored by Yinghai Lu's avatar Yinghai Lu Committed by Ingo Molnar

x86: trim mtrr don't close gap for resource allocation.

fix the bug reported here:

	http://bugzilla.kernel.org/show_bug.cgi?id=10232

use update_memory_range() instead of add_memory_range() directly
to avoid closing the gap.

( the new code only affects and runs on systems where the MTRR
  workaround triggers. )
Signed-off-by: default avatarYinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent fc1c8925
...@@ -711,7 +711,8 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) ...@@ -711,7 +711,8 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn)
trim_size = end_pfn; trim_size = end_pfn;
trim_size <<= PAGE_SHIFT; trim_size <<= PAGE_SHIFT;
trim_size -= trim_start; trim_size -= trim_start;
add_memory_region(trim_start, trim_size, E820_RESERVED); update_memory_range(trim_start, trim_size, E820_RAM,
E820_RESERVED);
update_e820(); update_e820();
return 1; return 1;
} }
......
...@@ -749,6 +749,32 @@ static int __init parse_memmap(char *arg) ...@@ -749,6 +749,32 @@ static int __init parse_memmap(char *arg)
return 0; return 0;
} }
early_param("memmap", parse_memmap); early_param("memmap", parse_memmap);
void __init update_memory_range(u64 start, u64 size, unsigned old_type,
unsigned new_type)
{
int i;
BUG_ON(old_type == new_type);
for (i = 0; i < e820.nr_map; i++) {
struct e820entry *ei = &e820.map[i];
u64 final_start, final_end;
if (ei->type != old_type)
continue;
/* totally covered? */
if (ei->addr >= start && ei->size <= size) {
ei->type = new_type;
continue;
}
/* partially covered */
final_start = max(start, ei->addr);
final_end = min(start + size, ei->addr + ei->size);
if (final_start >= final_end)
continue;
add_memory_region(final_start, final_end - final_start,
new_type);
}
}
void __init update_e820(void) void __init update_e820(void)
{ {
u8 nr_map; u8 nr_map;
......
...@@ -744,6 +744,33 @@ void __init finish_e820_parsing(void) ...@@ -744,6 +744,33 @@ void __init finish_e820_parsing(void)
} }
} }
void __init update_memory_range(u64 start, u64 size, unsigned old_type,
unsigned new_type)
{
int i;
BUG_ON(old_type == new_type);
for (i = 0; i < e820.nr_map; i++) {
struct e820entry *ei = &e820.map[i];
u64 final_start, final_end;
if (ei->type != old_type)
continue;
/* totally covered? */
if (ei->addr >= start && ei->size <= size) {
ei->type = new_type;
continue;
}
/* partially covered */
final_start = max(start, ei->addr);
final_end = min(start + size, ei->addr + ei->size);
if (final_start >= final_end)
continue;
add_memory_region(final_start, final_end - final_start,
new_type);
}
}
void __init update_e820(void) void __init update_e820(void)
{ {
u8 nr_map; u8 nr_map;
......
...@@ -28,6 +28,8 @@ extern void find_max_pfn(void); ...@@ -28,6 +28,8 @@ extern void find_max_pfn(void);
extern void register_bootmem_low_pages(unsigned long max_low_pfn); extern void register_bootmem_low_pages(unsigned long max_low_pfn);
extern void add_memory_region(unsigned long long start, extern void add_memory_region(unsigned long long start,
unsigned long long size, int type); unsigned long long size, int type);
extern void update_memory_range(u64 start, u64 size, unsigned old_type,
unsigned new_type);
extern void e820_register_memory(void); extern void e820_register_memory(void);
extern void limit_regions(unsigned long long size); extern void limit_regions(unsigned long long size);
extern void print_memory_map(char *who); extern void print_memory_map(char *who);
......
...@@ -18,6 +18,8 @@ extern unsigned long find_e820_area(unsigned long start, unsigned long end, ...@@ -18,6 +18,8 @@ extern unsigned long find_e820_area(unsigned long start, unsigned long end,
unsigned size, unsigned long align); unsigned size, unsigned long align);
extern void add_memory_region(unsigned long start, unsigned long size, extern void add_memory_region(unsigned long start, unsigned long size,
int type); int type);
extern void update_memory_range(u64 start, u64 size, unsigned old_type,
unsigned new_type);
extern void setup_memory_region(void); extern void setup_memory_region(void);
extern void contig_e820_setup(void); extern void contig_e820_setup(void);
extern unsigned long e820_end_of_ram(void); extern unsigned long e820_end_of_ram(void);
......
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