diff options
Diffstat (limited to 'arch/x86/kernel/e820.c')
-rw-r--r-- | arch/x86/kernel/e820.c | 59 |
1 files changed, 46 insertions, 13 deletions
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index ed46b7a6bc13..544dd12c70f4 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c | |||
@@ -359,6 +359,26 @@ static struct e820entry new_bios[E820_X_MAX] __initdata; | |||
359 | return 0; | 359 | return 0; |
360 | } | 360 | } |
361 | 361 | ||
362 | static int __init __copy_e820_map(struct e820entry *biosmap, int nr_map) | ||
363 | { | ||
364 | while (nr_map) { | ||
365 | u64 start = biosmap->addr; | ||
366 | u64 size = biosmap->size; | ||
367 | u64 end = start + size; | ||
368 | u32 type = biosmap->type; | ||
369 | |||
370 | /* Overflow in 64 bits? Ignore the memory map. */ | ||
371 | if (start > end) | ||
372 | return -1; | ||
373 | |||
374 | e820_add_region(start, size, type); | ||
375 | |||
376 | biosmap++; | ||
377 | nr_map--; | ||
378 | } | ||
379 | return 0; | ||
380 | } | ||
381 | |||
362 | /* | 382 | /* |
363 | * Copy the BIOS e820 map into a safe place. | 383 | * Copy the BIOS e820 map into a safe place. |
364 | * | 384 | * |
@@ -374,19 +394,7 @@ int __init copy_e820_map(struct e820entry *biosmap, int nr_map) | |||
374 | if (nr_map < 2) | 394 | if (nr_map < 2) |
375 | return -1; | 395 | return -1; |
376 | 396 | ||
377 | do { | 397 | return __copy_e820_map(biosmap, nr_map); |
378 | u64 start = biosmap->addr; | ||
379 | u64 size = biosmap->size; | ||
380 | u64 end = start + size; | ||
381 | u32 type = biosmap->type; | ||
382 | |||
383 | /* Overflow in 64 bits? Ignore the memory map. */ | ||
384 | if (start > end) | ||
385 | return -1; | ||
386 | |||
387 | e820_add_region(start, size, type); | ||
388 | } while (biosmap++, --nr_map); | ||
389 | return 0; | ||
390 | } | 398 | } |
391 | 399 | ||
392 | u64 __init e820_update_range(u64 start, u64 size, unsigned old_type, | 400 | u64 __init e820_update_range(u64 start, u64 size, unsigned old_type, |
@@ -496,6 +504,31 @@ __init void e820_setup_gap(void) | |||
496 | pci_mem_start, gapstart, gapsize); | 504 | pci_mem_start, gapstart, gapsize); |
497 | } | 505 | } |
498 | 506 | ||
507 | /** | ||
508 | * Because of the size limitation of struct boot_params, only first | ||
509 | * 128 E820 memory entries are passed to kernel via | ||
510 | * boot_params.e820_map, others are passed via SETUP_E820_EXT node of | ||
511 | * linked list of struct setup_data, which is parsed here. | ||
512 | */ | ||
513 | void __init parse_e820_ext(struct setup_data *sdata, unsigned long pa_data) | ||
514 | { | ||
515 | u32 map_len; | ||
516 | int entries; | ||
517 | struct e820entry *extmap; | ||
518 | |||
519 | entries = sdata->len / sizeof(struct e820entry); | ||
520 | map_len = sdata->len + sizeof(struct setup_data); | ||
521 | if (map_len > PAGE_SIZE) | ||
522 | sdata = early_ioremap(pa_data, map_len); | ||
523 | extmap = (struct e820entry *)(sdata->data); | ||
524 | __copy_e820_map(extmap, entries); | ||
525 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); | ||
526 | if (map_len > PAGE_SIZE) | ||
527 | early_iounmap(sdata, map_len); | ||
528 | printk(KERN_INFO "extended physical RAM map:\n"); | ||
529 | e820_print_map("extended"); | ||
530 | } | ||
531 | |||
499 | #if defined(CONFIG_X86_64) || \ | 532 | #if defined(CONFIG_X86_64) || \ |
500 | (defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION)) | 533 | (defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION)) |
501 | /** | 534 | /** |