diff options
author | Yinghai Lu <yhlu.kernel.send@gmail.com> | 2008-04-29 23:25:16 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2008-05-25 04:55:10 -0400 |
commit | 8a374026c265476b1acfc3c186a66d59ebdb2cda (patch) | |
tree | 85ae71ca6aa6851934d1880373bc8b9fa884e5ca /arch/x86 | |
parent | 42651f15824d003e8357693ab72c4dbb3e280836 (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')
-rw-r--r-- | arch/x86/kernel/cpu/mtrr/main.c | 44 | ||||
-rw-r--r-- | arch/x86/kernel/e820_32.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/e820_64.c | 3 |
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 9ab5c16b0d52..5a2a4c146333 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) | |||
1098 | static u64 __init real_trim_memory(unsigned long start_pfn, unsigned long limit_pfn) | 1098 | static u64 __init real_trim_memory(unsigned long start_pfn, unsigned long limit_pfn) |
1099 | { | 1099 | { |
1100 | u64 trim_start, trim_size; | 1100 | u64 trim_start, trim_size; |
1101 | trim_start = start_pfn; | 1101 | trim_start = start_pfn; |
1102 | trim_start <<= PAGE_SHIFT; | 1102 | trim_start <<= PAGE_SHIFT; |
1103 | trim_size = limit_pfn; | 1103 | trim_size = limit_pfn; |
1104 | trim_size <<= PAGE_SHIFT; | 1104 | trim_size <<= PAGE_SHIFT; |
1105 | trim_size -= trim_start; | 1105 | trim_size -= trim_start; |
1106 | |||
1106 | return update_memory_range(trim_start, trim_size, E820_RAM, | 1107 | return update_memory_range(trim_start, trim_size, E820_RAM, |
1107 | E820_RESERVED); | 1108 | E820_RESERVED); |
1108 | } | 1109 | } |
@@ -1124,7 +1125,6 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) | |||
1124 | struct res_range range[RANGE_NUM]; | 1125 | struct res_range range[RANGE_NUM]; |
1125 | int nr_range; | 1126 | int nr_range; |
1126 | u64 total_real_trim_size; | 1127 | u64 total_real_trim_size; |
1127 | int changed; | ||
1128 | 1128 | ||
1129 | /* extra one for all 0 */ | 1129 | /* extra one for all 0 */ |
1130 | int num[MTRR_NUM_TYPES + 1]; | 1130 | int num[MTRR_NUM_TYPES + 1]; |
@@ -1189,49 +1189,35 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) | |||
1189 | } | 1189 | } |
1190 | nr_range = x86_get_mtrr_mem_range(range, nr_range, 0, 0); | 1190 | nr_range = x86_get_mtrr_mem_range(range, nr_range, 0, 0); |
1191 | 1191 | ||
1192 | changed = 0; | ||
1193 | total_real_trim_size = 0; | ||
1194 | |||
1195 | /* check the top at first */ | ||
1196 | i = nr_range - 1; | ||
1197 | if (range[i].end + 1 < end_pfn) { | ||
1198 | total_real_trim_size += real_trim_memory(range[i].end + 1, end_pfn); | ||
1199 | } | ||
1200 | |||
1201 | if (total_real_trim_size) { | ||
1202 | printk(KERN_WARNING "WARNING: BIOS bug: CPU MTRRs don't cover" | ||
1203 | " all of memory, losing %lluMB of RAM.\n", | ||
1204 | total_real_trim_size >> 20); | ||
1205 | |||
1206 | WARN_ON(1); | ||
1207 | |||
1208 | printk(KERN_INFO "update e820 for mtrr -- end_pfn\n"); | ||
1209 | update_e820(); | ||
1210 | changed = 1; | ||
1211 | } | ||
1212 | |||
1213 | total_real_trim_size = 0; | 1192 | total_real_trim_size = 0; |
1193 | /* check the head */ | ||
1214 | if (range[0].start) | 1194 | if (range[0].start) |
1215 | total_real_trim_size += real_trim_memory(0, range[0].start); | 1195 | total_real_trim_size += real_trim_memory(0, range[0].start); |
1216 | 1196 | /* check the holes */ | |
1217 | for (i = 0; i < nr_range - 1; i--) { | 1197 | for (i = 0; i < nr_range - 1; i++) { |
1218 | if (range[i].end + 1 < range[i+1].start) | 1198 | if (range[i].end + 1 < range[i+1].start) |
1219 | total_real_trim_size += real_trim_memory(range[i].end + 1, range[i+1].start); | 1199 | total_real_trim_size += real_trim_memory(range[i].end + 1, range[i+1].start); |
1220 | } | 1200 | } |
1201 | /* check the top */ | ||
1202 | i = nr_range - 1; | ||
1203 | if (range[i].end + 1 < end_pfn) | ||
1204 | total_real_trim_size += real_trim_memory(range[i].end + 1, end_pfn); | ||
1221 | 1205 | ||
1222 | if (total_real_trim_size) { | 1206 | if (total_real_trim_size) { |
1223 | printk(KERN_WARNING "WARNING: BIOS bug: CPU MTRRs don't cover" | 1207 | printk(KERN_WARNING "WARNING: BIOS bug: CPU MTRRs don't cover" |
1224 | " all of memory, losing %lluMB of RAM.\n", | 1208 | " all of memory, losing %lluMB of RAM.\n", |
1225 | total_real_trim_size >> 20); | 1209 | total_real_trim_size >> 20); |
1226 | 1210 | ||
1227 | WARN_ON(1); | 1211 | if (enable_mtrr_cleanup < 1) |
1212 | WARN_ON(1); | ||
1228 | 1213 | ||
1229 | printk(KERN_INFO "update e820 for mtrr -- holes\n"); | 1214 | printk(KERN_INFO "update e820 for mtrr\n"); |
1230 | update_e820(); | 1215 | update_e820(); |
1231 | changed = 1; | 1216 | |
1217 | return 1; | ||
1232 | } | 1218 | } |
1233 | 1219 | ||
1234 | return changed; | 1220 | return 0; |
1235 | } | 1221 | } |
1236 | 1222 | ||
1237 | /** | 1223 | /** |
diff --git a/arch/x86/kernel/e820_32.c b/arch/x86/kernel/e820_32.c index 857f706273a8..751d517d802c 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, | |||
797 | if (ei->type != old_type) | 797 | if (ei->type != old_type) |
798 | continue; | 798 | continue; |
799 | /* totally covered? */ | 799 | /* totally covered? */ |
800 | if (ei->addr >= start && ei->size <= size) { | 800 | if (ei->addr >= start && |
801 | (ei->addr + ei->size) <= (start + size)) { | ||
801 | ei->type = new_type; | 802 | ei->type = new_type; |
802 | real_updated_size += ei->size; | 803 | real_updated_size += ei->size; |
803 | continue; | 804 | continue; |
diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c index 848b2cd2d1dd..c45b4dea4055 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, | |||
843 | if (ei->type != old_type) | 843 | if (ei->type != old_type) |
844 | continue; | 844 | continue; |
845 | /* totally covered? */ | 845 | /* totally covered? */ |
846 | if (ei->addr >= start && ei->size <= size) { | 846 | if (ei->addr >= start && |
847 | (ei->addr + ei->size) <= (start + size)) { | ||
847 | ei->type = new_type; | 848 | ei->type = new_type; |
848 | real_updated_size += ei->size; | 849 | real_updated_size += ei->size; |
849 | continue; | 850 | continue; |