aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYinghai Lu <yhlu.kernel.send@gmail.com>2008-04-29 23:25:16 -0400
committerThomas Gleixner <tglx@linutronix.de>2008-05-25 04:55:10 -0400
commit8a374026c265476b1acfc3c186a66d59ebdb2cda (patch)
tree85ae71ca6aa6851934d1880373bc8b9fa884e5ca
parent42651f15824d003e8357693ab72c4dbb3e280836 (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>
-rw-r--r--arch/x86/kernel/cpu/mtrr/main.c44
-rw-r--r--arch/x86/kernel/e820_32.c3
-rw-r--r--arch/x86/kernel/e820_64.c3
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)
1098static u64 __init real_trim_memory(unsigned long start_pfn, unsigned long limit_pfn) 1098static 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;