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.c79
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
134static 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
134void __init e820_print_map(char *who) 159void __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