aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/e820.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/e820.c')
-rw-r--r--arch/x86/kernel/e820.c53
1 files changed, 37 insertions, 16 deletions
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 508bec1cee27..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 int i; 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);
@@ -429,7 +435,7 @@ static u64 __init e820_update_range_map(struct e820map *e820x, u64 start,
429 if (size > (ULLONG_MAX - start)) 435 if (size > (ULLONG_MAX - start))
430 size = ULLONG_MAX - start; 436 size = ULLONG_MAX - start;
431 437
432 for (i = 0; i < e820.nr_map; i++) { 438 for (i = 0; i < e820x->nr_map; i++) {
433 struct e820entry *ei = &e820x->map[i]; 439 struct e820entry *ei = &e820x->map[i];
434 u64 final_start, final_end; 440 u64 final_start, final_end;
435 if (ei->type != old_type) 441 if (ei->type != old_type)
@@ -446,10 +452,16 @@ static u64 __init e820_update_range_map(struct e820map *e820x, u64 start,
446 final_end = min(start + size, ei->addr + ei->size); 452 final_end = min(start + size, ei->addr + ei->size);
447 if (final_start >= final_end) 453 if (final_start >= final_end)
448 continue; 454 continue;
449 e820_add_region(final_start, final_end - final_start, 455
450 new_type); 456 __e820_add_region(e820x, final_start, final_end - final_start,
457 new_type);
458
451 real_updated_size += final_end - final_start; 459 real_updated_size += final_end - final_start;
452 460
461 /*
462 * left range could be head or tail, so need to update
463 * size at first.
464 */
453 ei->size -= final_end - final_start; 465 ei->size -= final_end - final_start;
454 if (ei->addr < final_start) 466 if (ei->addr < final_start)
455 continue; 467 continue;
@@ -461,13 +473,13 @@ static u64 __init e820_update_range_map(struct e820map *e820x, u64 start,
461u64 __init e820_update_range(u64 start, u64 size, unsigned old_type, 473u64 __init e820_update_range(u64 start, u64 size, unsigned old_type,
462 unsigned new_type) 474 unsigned new_type)
463{ 475{
464 return e820_update_range_map(&e820, start, size, old_type, new_type); 476 return __e820_update_range(&e820, start, size, old_type, new_type);
465} 477}
466 478
467static u64 __init e820_update_range_saved(u64 start, u64 size, 479static u64 __init e820_update_range_saved(u64 start, u64 size,
468 unsigned old_type, unsigned new_type) 480 unsigned old_type, unsigned new_type)
469{ 481{
470 return e820_update_range_map(&e820_saved, start, size, old_type, 482 return __e820_update_range(&e820_saved, start, size, old_type,
471 new_type); 483 new_type);
472} 484}
473 485
@@ -1020,8 +1032,8 @@ u64 __init find_e820_area_size(u64 start, u64 *sizep, u64 align)
1020 continue; 1032 continue;
1021 return addr; 1033 return addr;
1022 } 1034 }
1023 return -1UL;
1024 1035
1036 return -1ULL;
1025} 1037}
1026 1038
1027/* 1039/*
@@ -1034,13 +1046,22 @@ u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
1034 u64 start; 1046 u64 start;
1035 1047
1036 start = startt; 1048 start = startt;
1037 while (size < sizet) 1049 while (size < sizet && (start + 1))
1038 start = find_e820_area_size(start, &size, align); 1050 start = find_e820_area_size(start, &size, align);
1039 1051
1040 if (size < sizet) 1052 if (size < sizet)
1041 return 0; 1053 return 0;
1042 1054
1055#ifdef CONFIG_X86_32
1056 if (start >= MAXMEM)
1057 return 0;
1058 if (start + size > MAXMEM)
1059 size = MAXMEM - start;
1060#endif
1061
1043 addr = round_down(start + size - sizet, align); 1062 addr = round_down(start + size - sizet, align);
1063 if (addr < start)
1064 return 0;
1044 e820_update_range(addr, sizet, E820_RAM, E820_RESERVED); 1065 e820_update_range(addr, sizet, E820_RAM, E820_RESERVED);
1045 e820_update_range_saved(addr, sizet, E820_RAM, E820_RESERVED); 1066 e820_update_range_saved(addr, sizet, E820_RAM, E820_RESERVED);
1046 printk(KERN_INFO "update e820 for early_reserve_e820\n"); 1067 printk(KERN_INFO "update e820 for early_reserve_e820\n");