diff options
Diffstat (limited to 'arch/x86/kernel/e820.c')
| -rw-r--r-- | arch/x86/kernel/e820.c | 79 |
1 files changed, 54 insertions, 25 deletions
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 95b81c18b6bc..fb638d9ce6d2 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c | |||
| @@ -131,6 +131,31 @@ void __init e820_add_region(u64 start, u64 size, int type) | |||
| 131 | __e820_add_region(&e820, start, size, type); | 131 | __e820_add_region(&e820, start, size, type); |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | static void __init e820_print_type(u32 type) | ||
| 135 | { | ||
| 136 | switch (type) { | ||
| 137 | case E820_RAM: | ||
| 138 | case E820_RESERVED_KERN: | ||
| 139 | printk(KERN_CONT "(usable)"); | ||
| 140 | break; | ||
| 141 | case E820_RESERVED: | ||
| 142 | printk(KERN_CONT "(reserved)"); | ||
| 143 | break; | ||
| 144 | case E820_ACPI: | ||
| 145 | printk(KERN_CONT "(ACPI data)"); | ||
| 146 | break; | ||
| 147 | case E820_NVS: | ||
| 148 | printk(KERN_CONT "(ACPI NVS)"); | ||
| 149 | break; | ||
| 150 | case E820_UNUSABLE: | ||
| 151 | printk(KERN_CONT "(unusable)"); | ||
| 152 | break; | ||
| 153 | default: | ||
| 154 | printk(KERN_CONT "type %u", type); | ||
| 155 | break; | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 134 | void __init e820_print_map(char *who) | 159 | void __init e820_print_map(char *who) |
| 135 | { | 160 | { |
| 136 | int i; | 161 | int i; |
| @@ -140,27 +165,8 @@ void __init e820_print_map(char *who) | |||
| 140 | (unsigned long long) e820.map[i].addr, | 165 | (unsigned long long) e820.map[i].addr, |
| 141 | (unsigned long long) | 166 | (unsigned long long) |
| 142 | (e820.map[i].addr + e820.map[i].size)); | 167 | (e820.map[i].addr + e820.map[i].size)); |
| 143 | switch (e820.map[i].type) { | 168 | e820_print_type(e820.map[i].type); |
| 144 | case E820_RAM: | 169 | printk(KERN_CONT "\n"); |
| 145 | case E820_RESERVED_KERN: | ||
| 146 | printk(KERN_CONT "(usable)\n"); | ||
| 147 | break; | ||
| 148 | case E820_RESERVED: | ||
| 149 | printk(KERN_CONT "(reserved)\n"); | ||
| 150 | break; | ||
| 151 | case E820_ACPI: | ||
| 152 | printk(KERN_CONT "(ACPI data)\n"); | ||
| 153 | break; | ||
| 154 | case E820_NVS: | ||
| 155 | printk(KERN_CONT "(ACPI NVS)\n"); | ||
| 156 | break; | ||
| 157 | case E820_UNUSABLE: | ||
| 158 | printk("(unusable)\n"); | ||
| 159 | break; | ||
| 160 | default: | ||
| 161 | printk(KERN_CONT "type %u\n", e820.map[i].type); | ||
| 162 | break; | ||
| 163 | } | ||
| 164 | } | 170 | } |
| 165 | } | 171 | } |
| 166 | 172 | ||
| @@ -427,6 +433,7 @@ static u64 __init __e820_update_range(struct e820map *e820x, u64 start, | |||
| 427 | u64 size, unsigned old_type, | 433 | u64 size, unsigned old_type, |
| 428 | unsigned new_type) | 434 | unsigned new_type) |
| 429 | { | 435 | { |
| 436 | u64 end; | ||
| 430 | unsigned int i; | 437 | unsigned int i; |
| 431 | u64 real_updated_size = 0; | 438 | u64 real_updated_size = 0; |
| 432 | 439 | ||
| @@ -435,21 +442,43 @@ static u64 __init __e820_update_range(struct e820map *e820x, u64 start, | |||
| 435 | if (size > (ULLONG_MAX - start)) | 442 | if (size > (ULLONG_MAX - start)) |
| 436 | size = ULLONG_MAX - start; | 443 | size = ULLONG_MAX - start; |
| 437 | 444 | ||
| 445 | end = start + size; | ||
| 446 | printk(KERN_DEBUG "e820 update range: %016Lx - %016Lx ", | ||
| 447 | (unsigned long long) start, | ||
| 448 | (unsigned long long) end); | ||
| 449 | e820_print_type(old_type); | ||
| 450 | printk(KERN_CONT " ==> "); | ||
| 451 | e820_print_type(new_type); | ||
| 452 | printk(KERN_CONT "\n"); | ||
| 453 | |||
| 438 | for (i = 0; i < e820x->nr_map; i++) { | 454 | for (i = 0; i < e820x->nr_map; i++) { |
| 439 | struct e820entry *ei = &e820x->map[i]; | 455 | struct e820entry *ei = &e820x->map[i]; |
| 440 | u64 final_start, final_end; | 456 | u64 final_start, final_end; |
| 457 | u64 ei_end; | ||
| 458 | |||
| 441 | if (ei->type != old_type) | 459 | if (ei->type != old_type) |
| 442 | continue; | 460 | continue; |
| 443 | /* totally covered? */ | 461 | |
| 444 | if (ei->addr >= start && | 462 | ei_end = ei->addr + ei->size; |
| 445 | (ei->addr + ei->size) <= (start + size)) { | 463 | /* totally covered by new range? */ |
| 464 | if (ei->addr >= start && ei_end <= end) { | ||
| 446 | ei->type = new_type; | 465 | ei->type = new_type; |
| 447 | real_updated_size += ei->size; | 466 | real_updated_size += ei->size; |
| 448 | continue; | 467 | continue; |
| 449 | } | 468 | } |
| 469 | |||
| 470 | /* new range is totally covered? */ | ||
| 471 | if (ei->addr < start && ei_end > end) { | ||
| 472 | __e820_add_region(e820x, start, size, new_type); | ||
| 473 | __e820_add_region(e820x, end, ei_end - end, ei->type); | ||
| 474 | ei->size = start - ei->addr; | ||
| 475 | real_updated_size += size; | ||
| 476 | continue; | ||
| 477 | } | ||
| 478 | |||
| 450 | /* partially covered */ | 479 | /* partially covered */ |
| 451 | final_start = max(start, ei->addr); | 480 | final_start = max(start, ei->addr); |
| 452 | final_end = min(start + size, ei->addr + ei->size); | 481 | final_end = min(end, ei_end); |
| 453 | if (final_start >= final_end) | 482 | if (final_start >= final_end) |
| 454 | continue; | 483 | continue; |
| 455 | 484 | ||
