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: Yinghai Lu <yhlu.kernel@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
fc1c8925c8
commit
5dca6a1bb0
@ -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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
|||||||
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,
|
|||||||
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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user