aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2009-03-13 00:35:18 -0400
committerIngo Molnar <mingo@elte.hu>2009-03-13 00:38:29 -0400
commit773e673de27297d07d852e7e9bfd1a695cae1da2 (patch)
tree9c8bbb21dffab028b494ebadae14a6900bf31afb /arch/x86
parent698609bdcd35d0641f4c6622c83680ab1a6d67cb (diff)
x86: fix e820_update_range()
Impact: fix left range size on head | commit 5c0e6f035df983210e4d22213aed624ced502d3d | x86: fix code paths used by update_mptable | Impact: fix crashes under Xen due to unrobust e820 code fixes one e820 bug, but introduces another bug. Need to update size for left range at first in case it is header. also add __e820_add_region take more parameter. Signed-off-by: Yinghai Lu <yinghai@kernel.org> Cc: jbeulich@novell.com LKML-Reference: <49B9E286.502@kernel.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kernel/e820.c45
1 files changed, 24 insertions, 21 deletions
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 3cf6681ac80d..95b81c18b6bc 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -110,19 +110,25 @@ int __init e820_all_mapped(u64 start, u64 end, unsigned type)
110/* 110/*
111 * Add a memory region to the kernel e820 map. 111 * Add a memory region to the kernel e820 map.
112 */ 112 */
113void __init e820_add_region(u64 start, u64 size, int type) 113static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
114 int type)
114{ 115{
115 int x = e820.nr_map; 116 int x = e820x->nr_map;
116 117
117 if (x == ARRAY_SIZE(e820.map)) { 118 if (x == ARRAY_SIZE(e820x->map)) {
118 printk(KERN_ERR "Ooops! Too many entries in the memory map!\n"); 119 printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
119 return; 120 return;
120 } 121 }
121 122
122 e820.map[x].addr = start; 123 e820x->map[x].addr = start;
123 e820.map[x].size = size; 124 e820x->map[x].size = size;
124 e820.map[x].type = type; 125 e820x->map[x].type = type;
125 e820.nr_map++; 126 e820x->nr_map++;
127}
128
129void __init e820_add_region(u64 start, u64 size, int type)
130{
131 __e820_add_region(&e820, start, size, type);
126} 132}
127 133
128void __init e820_print_map(char *who) 134void __init e820_print_map(char *who)
@@ -417,11 +423,11 @@ static int __init append_e820_map(struct e820entry *biosmap, int nr_map)
417 return __append_e820_map(biosmap, nr_map); 423 return __append_e820_map(biosmap, nr_map);
418} 424}
419 425
420static u64 __init e820_update_range_map(struct e820map *e820x, u64 start, 426static u64 __init __e820_update_range(struct e820map *e820x, u64 start,
421 u64 size, unsigned old_type, 427 u64 size, unsigned old_type,
422 unsigned new_type) 428 unsigned new_type)
423{ 429{
424 unsigned int i, x; 430 unsigned int i;
425 u64 real_updated_size = 0; 431 u64 real_updated_size = 0;
426 432
427 BUG_ON(old_type == new_type); 433 BUG_ON(old_type == new_type);
@@ -447,22 +453,19 @@ static u64 __init e820_update_range_map(struct e820map *e820x, u64 start,
447 if (final_start >= final_end) 453 if (final_start >= final_end)
448 continue; 454 continue;
449 455
450 x = e820x->nr_map; 456 __e820_add_region(e820x, final_start, final_end - final_start,
451 if (x == ARRAY_SIZE(e820x->map)) { 457 new_type);
452 printk(KERN_ERR "Too many memory map entries!\n");
453 break;
454 }
455 e820x->map[x].addr = final_start;
456 e820x->map[x].size = final_end - final_start;
457 e820x->map[x].type = new_type;
458 e820x->nr_map++;
459 458
460 real_updated_size += final_end - final_start; 459 real_updated_size += final_end - final_start;
461 460
461 /*
462 * left range could be head or tail, so need to update
463 * size at first.
464 */
465 ei->size -= final_end - final_start;
462 if (ei->addr < final_start) 466 if (ei->addr < final_start)
463 continue; 467 continue;
464 ei->addr = final_end; 468 ei->addr = final_end;
465 ei->size -= final_end - final_start;
466 } 469 }
467 return real_updated_size; 470 return real_updated_size;
468} 471}
@@ -470,13 +473,13 @@ static u64 __init e820_update_range_map(struct e820map *e820x, u64 start,
470u64 __init e820_update_range(u64 start, u64 size, unsigned old_type, 473u64 __init e820_update_range(u64 start, u64 size, unsigned old_type,
471 unsigned new_type) 474 unsigned new_type)
472{ 475{
473 return e820_update_range_map(&e820, start, size, old_type, new_type); 476 return __e820_update_range(&e820, start, size, old_type, new_type);
474} 477}
475 478
476static u64 __init e820_update_range_saved(u64 start, u64 size, 479static u64 __init e820_update_range_saved(u64 start, u64 size,
477 unsigned old_type, unsigned new_type) 480 unsigned old_type, unsigned new_type)
478{ 481{
479 return e820_update_range_map(&e820_saved, start, size, old_type, 482 return __e820_update_range(&e820_saved, start, size, old_type,
480 new_type); 483 new_type);
481} 484}
482 485