diff options
Diffstat (limited to 'arch/x86_64/kernel/e820.c')
-rw-r--r-- | arch/x86_64/kernel/e820.c | 118 |
1 files changed, 56 insertions, 62 deletions
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c index 708a3cd9a27e..c0af3828df45 100644 --- a/arch/x86_64/kernel/e820.c +++ b/arch/x86_64/kernel/e820.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include <asm/bootsetup.h> | 25 | #include <asm/bootsetup.h> |
26 | #include <asm/sections.h> | 26 | #include <asm/sections.h> |
27 | 27 | ||
28 | struct e820map e820 __initdata; | ||
29 | |||
28 | /* | 30 | /* |
29 | * PFN of last memory page. | 31 | * PFN of last memory page. |
30 | */ | 32 | */ |
@@ -41,7 +43,7 @@ unsigned long end_pfn_map; | |||
41 | /* | 43 | /* |
42 | * Last pfn which the user wants to use. | 44 | * Last pfn which the user wants to use. |
43 | */ | 45 | */ |
44 | unsigned long end_user_pfn = MAXMEM>>PAGE_SHIFT; | 46 | static unsigned long __initdata end_user_pfn = MAXMEM>>PAGE_SHIFT; |
45 | 47 | ||
46 | extern struct resource code_resource, data_resource; | 48 | extern struct resource code_resource, data_resource; |
47 | 49 | ||
@@ -70,12 +72,7 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size) | |||
70 | return 1; | 72 | return 1; |
71 | } | 73 | } |
72 | #endif | 74 | #endif |
73 | /* kernel code + 640k memory hole (later should not be needed, but | 75 | /* kernel code */ |
74 | be paranoid for now) */ | ||
75 | if (last >= 640*1024 && addr < 1024*1024) { | ||
76 | *addrp = 1024*1024; | ||
77 | return 1; | ||
78 | } | ||
79 | if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) { | 76 | if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) { |
80 | *addrp = __pa_symbol(&_end); | 77 | *addrp = __pa_symbol(&_end); |
81 | return 1; | 78 | return 1; |
@@ -565,13 +562,6 @@ static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map) | |||
565 | * If we're lucky and live on a modern system, the setup code | 562 | * If we're lucky and live on a modern system, the setup code |
566 | * will have given us a memory map that we can use to properly | 563 | * will have given us a memory map that we can use to properly |
567 | * set up memory. If we aren't, we'll fake a memory map. | 564 | * set up memory. If we aren't, we'll fake a memory map. |
568 | * | ||
569 | * We check to see that the memory map contains at least 2 elements | ||
570 | * before we'll use it, because the detection code in setup.S may | ||
571 | * not be perfect and most every PC known to man has two memory | ||
572 | * regions: one from 0 to 640k, and one from 1mb up. (The IBM | ||
573 | * thinkpad 560x, for example, does not cooperate with the memory | ||
574 | * detection code.) | ||
575 | */ | 565 | */ |
576 | static int __init copy_e820_map(struct e820entry * biosmap, int nr_map) | 566 | static int __init copy_e820_map(struct e820entry * biosmap, int nr_map) |
577 | { | 567 | { |
@@ -589,34 +579,19 @@ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map) | |||
589 | if (start > end) | 579 | if (start > end) |
590 | return -1; | 580 | return -1; |
591 | 581 | ||
592 | /* | ||
593 | * Some BIOSes claim RAM in the 640k - 1M region. | ||
594 | * Not right. Fix it up. | ||
595 | * | ||
596 | * This should be removed on Hammer which is supposed to not | ||
597 | * have non e820 covered ISA mappings there, but I had some strange | ||
598 | * problems so it stays for now. -AK | ||
599 | */ | ||
600 | if (type == E820_RAM) { | ||
601 | if (start < 0x100000ULL && end > 0xA0000ULL) { | ||
602 | if (start < 0xA0000ULL) | ||
603 | add_memory_region(start, 0xA0000ULL-start, type); | ||
604 | if (end <= 0x100000ULL) | ||
605 | continue; | ||
606 | start = 0x100000ULL; | ||
607 | size = end - start; | ||
608 | } | ||
609 | } | ||
610 | |||
611 | add_memory_region(start, size, type); | 582 | add_memory_region(start, size, type); |
612 | } while (biosmap++,--nr_map); | 583 | } while (biosmap++,--nr_map); |
613 | return 0; | 584 | return 0; |
614 | } | 585 | } |
615 | 586 | ||
616 | void __init setup_memory_region(void) | 587 | void early_panic(char *msg) |
617 | { | 588 | { |
618 | char *who = "BIOS-e820"; | 589 | early_printk(msg); |
590 | panic(msg); | ||
591 | } | ||
619 | 592 | ||
593 | void __init setup_memory_region(void) | ||
594 | { | ||
620 | /* | 595 | /* |
621 | * Try to copy the BIOS-supplied E820-map. | 596 | * Try to copy the BIOS-supplied E820-map. |
622 | * | 597 | * |
@@ -624,51 +599,70 @@ void __init setup_memory_region(void) | |||
624 | * the next section from 1mb->appropriate_mem_k | 599 | * the next section from 1mb->appropriate_mem_k |
625 | */ | 600 | */ |
626 | sanitize_e820_map(E820_MAP, &E820_MAP_NR); | 601 | sanitize_e820_map(E820_MAP, &E820_MAP_NR); |
627 | if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) { | 602 | if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) |
628 | unsigned long mem_size; | 603 | early_panic("Cannot find a valid memory map"); |
629 | |||
630 | /* compare results from other methods and take the greater */ | ||
631 | if (ALT_MEM_K < EXT_MEM_K) { | ||
632 | mem_size = EXT_MEM_K; | ||
633 | who = "BIOS-88"; | ||
634 | } else { | ||
635 | mem_size = ALT_MEM_K; | ||
636 | who = "BIOS-e801"; | ||
637 | } | ||
638 | |||
639 | e820.nr_map = 0; | ||
640 | add_memory_region(0, LOWMEMSIZE(), E820_RAM); | ||
641 | add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM); | ||
642 | } | ||
643 | printk(KERN_INFO "BIOS-provided physical RAM map:\n"); | 604 | printk(KERN_INFO "BIOS-provided physical RAM map:\n"); |
644 | e820_print_map(who); | 605 | e820_print_map("BIOS-e820"); |
645 | } | 606 | } |
646 | 607 | ||
647 | void __init parse_memopt(char *p, char **from) | 608 | static int __init parse_memopt(char *p) |
648 | { | 609 | { |
649 | end_user_pfn = memparse(p, from); | 610 | if (!p) |
611 | return -EINVAL; | ||
612 | end_user_pfn = memparse(p, &p); | ||
650 | end_user_pfn >>= PAGE_SHIFT; | 613 | end_user_pfn >>= PAGE_SHIFT; |
614 | return 0; | ||
651 | } | 615 | } |
616 | early_param("mem", parse_memopt); | ||
652 | 617 | ||
653 | void __init parse_memmapopt(char *p, char **from) | 618 | static int userdef __initdata; |
619 | |||
620 | static int __init parse_memmap_opt(char *p) | ||
654 | { | 621 | { |
622 | char *oldp; | ||
655 | unsigned long long start_at, mem_size; | 623 | unsigned long long start_at, mem_size; |
656 | 624 | ||
657 | mem_size = memparse(p, from); | 625 | if (!strcmp(p, "exactmap")) { |
658 | p = *from; | 626 | #ifdef CONFIG_CRASH_DUMP |
627 | /* If we are doing a crash dump, we | ||
628 | * still need to know the real mem | ||
629 | * size before original memory map is | ||
630 | * reset. | ||
631 | */ | ||
632 | saved_max_pfn = e820_end_of_ram(); | ||
633 | #endif | ||
634 | end_pfn_map = 0; | ||
635 | e820.nr_map = 0; | ||
636 | userdef = 1; | ||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | oldp = p; | ||
641 | mem_size = memparse(p, &p); | ||
642 | if (p == oldp) | ||
643 | return -EINVAL; | ||
659 | if (*p == '@') { | 644 | if (*p == '@') { |
660 | start_at = memparse(p+1, from); | 645 | start_at = memparse(p+1, &p); |
661 | add_memory_region(start_at, mem_size, E820_RAM); | 646 | add_memory_region(start_at, mem_size, E820_RAM); |
662 | } else if (*p == '#') { | 647 | } else if (*p == '#') { |
663 | start_at = memparse(p+1, from); | 648 | start_at = memparse(p+1, &p); |
664 | add_memory_region(start_at, mem_size, E820_ACPI); | 649 | add_memory_region(start_at, mem_size, E820_ACPI); |
665 | } else if (*p == '$') { | 650 | } else if (*p == '$') { |
666 | start_at = memparse(p+1, from); | 651 | start_at = memparse(p+1, &p); |
667 | add_memory_region(start_at, mem_size, E820_RESERVED); | 652 | add_memory_region(start_at, mem_size, E820_RESERVED); |
668 | } else { | 653 | } else { |
669 | end_user_pfn = (mem_size >> PAGE_SHIFT); | 654 | end_user_pfn = (mem_size >> PAGE_SHIFT); |
670 | } | 655 | } |
671 | p = *from; | 656 | return *p == '\0' ? 0 : -EINVAL; |
657 | } | ||
658 | early_param("memmap", parse_memmap_opt); | ||
659 | |||
660 | void finish_e820_parsing(void) | ||
661 | { | ||
662 | if (userdef) { | ||
663 | printk(KERN_INFO "user-defined physical RAM map:\n"); | ||
664 | e820_print_map("user"); | ||
665 | } | ||
672 | } | 666 | } |
673 | 667 | ||
674 | unsigned long pci_mem_start = 0xaeedbabe; | 668 | unsigned long pci_mem_start = 0xaeedbabe; |