diff options
| author | Yinghai Lu <yhlu.kernel.send@gmail.com> | 2008-03-18 19:44:19 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-03-21 12:06:15 -0400 |
| commit | 5dca6a1bb014875a17289fdaae8c31e0a3641c99 (patch) | |
| tree | c6cb1eab44e92cedbfcee707de6ed2ad960e20e6 | |
| parent | fc1c8925c8210009c1fc5d909d189252d8fb4fb2 (diff) | |
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>
| -rw-r--r-- | arch/x86/kernel/cpu/mtrr/main.c | 3 | ||||
| -rw-r--r-- | arch/x86/kernel/e820_32.c | 26 | ||||
| -rw-r--r-- | arch/x86/kernel/e820_64.c | 27 | ||||
| -rw-r--r-- | include/asm-x86/e820_32.h | 2 | ||||
| -rw-r--r-- | include/asm-x86/e820_64.h | 2 |
5 files changed, 59 insertions, 1 deletions
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index be83336fddba..a6450b3ae759 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c | |||
| @@ -711,7 +711,8 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) | |||
| 711 | trim_size = end_pfn; | 711 | trim_size = end_pfn; |
| 712 | trim_size <<= PAGE_SHIFT; | 712 | trim_size <<= PAGE_SHIFT; |
| 713 | trim_size -= trim_start; | 713 | trim_size -= trim_start; |
| 714 | add_memory_region(trim_start, trim_size, E820_RESERVED); | 714 | update_memory_range(trim_start, trim_size, E820_RAM, |
| 715 | E820_RESERVED); | ||
| 715 | update_e820(); | 716 | update_e820(); |
| 716 | return 1; | 717 | return 1; |
| 717 | } | 718 | } |
diff --git a/arch/x86/kernel/e820_32.c b/arch/x86/kernel/e820_32.c index 4e16ef4a2659..80444c5c9b14 100644 --- a/arch/x86/kernel/e820_32.c +++ b/arch/x86/kernel/e820_32.c | |||
| @@ -749,6 +749,32 @@ static int __init parse_memmap(char *arg) | |||
| 749 | return 0; | 749 | return 0; |
| 750 | } | 750 | } |
| 751 | early_param("memmap", parse_memmap); | 751 | early_param("memmap", parse_memmap); |
| 752 | void __init update_memory_range(u64 start, u64 size, unsigned old_type, | ||
| 753 | unsigned new_type) | ||
| 754 | { | ||
| 755 | int i; | ||
| 756 | |||
| 757 | BUG_ON(old_type == new_type); | ||
| 758 | |||
| 759 | for (i = 0; i < e820.nr_map; i++) { | ||
| 760 | struct e820entry *ei = &e820.map[i]; | ||
| 761 | u64 final_start, final_end; | ||
| 762 | if (ei->type != old_type) | ||
| 763 | continue; | ||
| 764 | /* totally covered? */ | ||
| 765 | if (ei->addr >= start && ei->size <= size) { | ||
| 766 | ei->type = new_type; | ||
| 767 | continue; | ||
| 768 | } | ||
| 769 | /* partially covered */ | ||
| 770 | final_start = max(start, ei->addr); | ||
| 771 | final_end = min(start + size, ei->addr + ei->size); | ||
| 772 | if (final_start >= final_end) | ||
| 773 | continue; | ||
| 774 | add_memory_region(final_start, final_end - final_start, | ||
| 775 | new_type); | ||
| 776 | } | ||
| 777 | } | ||
| 752 | void __init update_e820(void) | 778 | void __init update_e820(void) |
| 753 | { | 779 | { |
| 754 | u8 nr_map; | 780 | u8 nr_map; |
diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c index 9f65b4cc323c..9be697126013 100644 --- a/arch/x86/kernel/e820_64.c +++ b/arch/x86/kernel/e820_64.c | |||
| @@ -744,6 +744,33 @@ void __init finish_e820_parsing(void) | |||
| 744 | } | 744 | } |
| 745 | } | 745 | } |
| 746 | 746 | ||
| 747 | void __init update_memory_range(u64 start, u64 size, unsigned old_type, | ||
| 748 | unsigned new_type) | ||
| 749 | { | ||
| 750 | int i; | ||
| 751 | |||
| 752 | BUG_ON(old_type == new_type); | ||
| 753 | |||
| 754 | for (i = 0; i < e820.nr_map; i++) { | ||
| 755 | struct e820entry *ei = &e820.map[i]; | ||
| 756 | u64 final_start, final_end; | ||
| 757 | if (ei->type != old_type) | ||
| 758 | continue; | ||
| 759 | /* totally covered? */ | ||
| 760 | if (ei->addr >= start && ei->size <= size) { | ||
| 761 | ei->type = new_type; | ||
| 762 | continue; | ||
| 763 | } | ||
| 764 | /* partially covered */ | ||
| 765 | final_start = max(start, ei->addr); | ||
| 766 | final_end = min(start + size, ei->addr + ei->size); | ||
| 767 | if (final_start >= final_end) | ||
| 768 | continue; | ||
| 769 | add_memory_region(final_start, final_end - final_start, | ||
| 770 | new_type); | ||
| 771 | } | ||
| 772 | } | ||
| 773 | |||
| 747 | void __init update_e820(void) | 774 | void __init update_e820(void) |
| 748 | { | 775 | { |
| 749 | u8 nr_map; | 776 | u8 nr_map; |
diff --git a/include/asm-x86/e820_32.h b/include/asm-x86/e820_32.h index f1da7ebd1905..e7207a6de3e0 100644 --- a/include/asm-x86/e820_32.h +++ b/include/asm-x86/e820_32.h | |||
| @@ -28,6 +28,8 @@ extern void find_max_pfn(void); | |||
| 28 | extern void register_bootmem_low_pages(unsigned long max_low_pfn); | 28 | extern void register_bootmem_low_pages(unsigned long max_low_pfn); |
| 29 | extern void add_memory_region(unsigned long long start, | 29 | extern void add_memory_region(unsigned long long start, |
| 30 | unsigned long long size, int type); | 30 | unsigned long long size, int type); |
| 31 | extern void update_memory_range(u64 start, u64 size, unsigned old_type, | ||
| 32 | unsigned new_type); | ||
| 31 | extern void e820_register_memory(void); | 33 | extern void e820_register_memory(void); |
| 32 | extern void limit_regions(unsigned long long size); | 34 | extern void limit_regions(unsigned long long size); |
| 33 | extern void print_memory_map(char *who); | 35 | extern void print_memory_map(char *who); |
diff --git a/include/asm-x86/e820_64.h b/include/asm-x86/e820_64.h index a560c4f5d500..22ede73ae724 100644 --- a/include/asm-x86/e820_64.h +++ b/include/asm-x86/e820_64.h | |||
| @@ -18,6 +18,8 @@ extern unsigned long find_e820_area(unsigned long start, unsigned long end, | |||
| 18 | unsigned size, unsigned long align); | 18 | unsigned size, unsigned long align); |
| 19 | extern void add_memory_region(unsigned long start, unsigned long size, | 19 | extern void add_memory_region(unsigned long start, unsigned long size, |
| 20 | int type); | 20 | int type); |
| 21 | extern void update_memory_range(u64 start, u64 size, unsigned old_type, | ||
| 22 | unsigned new_type); | ||
| 21 | extern void setup_memory_region(void); | 23 | extern void setup_memory_region(void); |
| 22 | extern void contig_e820_setup(void); | 24 | extern void contig_e820_setup(void); |
| 23 | extern unsigned long e820_end_of_ram(void); | 25 | extern unsigned long e820_end_of_ram(void); |
