diff options
Diffstat (limited to 'arch/x86/kernel/e820.c')
-rw-r--r-- | arch/x86/kernel/e820.c | 53 |
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 | */ |
113 | void __init e820_add_region(u64 start, u64 size, int type) | 113 | static 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 | |||
129 | void __init e820_add_region(u64 start, u64 size, int type) | ||
130 | { | ||
131 | __e820_add_region(&e820, start, size, type); | ||
126 | } | 132 | } |
127 | 133 | ||
128 | void __init e820_print_map(char *who) | 134 | void __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 | ||
420 | static u64 __init e820_update_range_map(struct e820map *e820x, u64 start, | 426 | static 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, | |||
461 | u64 __init e820_update_range(u64 start, u64 size, unsigned old_type, | 473 | u64 __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 | ||
467 | static u64 __init e820_update_range_saved(u64 start, u64 size, | 479 | static 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"); |