diff options
Diffstat (limited to 'arch/x86/kernel/setup.c')
-rw-r--r-- | arch/x86/kernel/setup.c | 186 |
1 files changed, 103 insertions, 83 deletions
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 2a34f9c5be21..c4851eff57b3 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -55,7 +55,6 @@ | |||
55 | #include <linux/stddef.h> | 55 | #include <linux/stddef.h> |
56 | #include <linux/unistd.h> | 56 | #include <linux/unistd.h> |
57 | #include <linux/ptrace.h> | 57 | #include <linux/ptrace.h> |
58 | #include <linux/slab.h> | ||
59 | #include <linux/user.h> | 58 | #include <linux/user.h> |
60 | #include <linux/delay.h> | 59 | #include <linux/delay.h> |
61 | 60 | ||
@@ -73,6 +72,7 @@ | |||
73 | 72 | ||
74 | #include <asm/mtrr.h> | 73 | #include <asm/mtrr.h> |
75 | #include <asm/apic.h> | 74 | #include <asm/apic.h> |
75 | #include <asm/trampoline.h> | ||
76 | #include <asm/e820.h> | 76 | #include <asm/e820.h> |
77 | #include <asm/mpspec.h> | 77 | #include <asm/mpspec.h> |
78 | #include <asm/setup.h> | 78 | #include <asm/setup.h> |
@@ -106,9 +106,11 @@ | |||
106 | #include <asm/percpu.h> | 106 | #include <asm/percpu.h> |
107 | #include <asm/topology.h> | 107 | #include <asm/topology.h> |
108 | #include <asm/apicdef.h> | 108 | #include <asm/apicdef.h> |
109 | #include <asm/k8.h> | ||
109 | #ifdef CONFIG_X86_64 | 110 | #ifdef CONFIG_X86_64 |
110 | #include <asm/numa_64.h> | 111 | #include <asm/numa_64.h> |
111 | #endif | 112 | #endif |
113 | #include <asm/mce.h> | ||
112 | 114 | ||
113 | /* | 115 | /* |
114 | * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries. | 116 | * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries. |
@@ -118,7 +120,9 @@ | |||
118 | unsigned long max_low_pfn_mapped; | 120 | unsigned long max_low_pfn_mapped; |
119 | unsigned long max_pfn_mapped; | 121 | unsigned long max_pfn_mapped; |
120 | 122 | ||
123 | #ifdef CONFIG_DMI | ||
121 | RESERVE_BRK(dmi_alloc, 65536); | 124 | RESERVE_BRK(dmi_alloc, 65536); |
125 | #endif | ||
122 | 126 | ||
123 | unsigned int boot_cpu_id __read_mostly; | 127 | unsigned int boot_cpu_id __read_mostly; |
124 | 128 | ||
@@ -247,7 +251,7 @@ EXPORT_SYMBOL(edd); | |||
247 | * from boot_params into a safe place. | 251 | * from boot_params into a safe place. |
248 | * | 252 | * |
249 | */ | 253 | */ |
250 | static inline void copy_edd(void) | 254 | static inline void __init copy_edd(void) |
251 | { | 255 | { |
252 | memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer, | 256 | memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer, |
253 | sizeof(edd.mbr_signature)); | 257 | sizeof(edd.mbr_signature)); |
@@ -256,7 +260,7 @@ static inline void copy_edd(void) | |||
256 | edd.edd_info_nr = boot_params.eddbuf_entries; | 260 | edd.edd_info_nr = boot_params.eddbuf_entries; |
257 | } | 261 | } |
258 | #else | 262 | #else |
259 | static inline void copy_edd(void) | 263 | static inline void __init copy_edd(void) |
260 | { | 264 | { |
261 | } | 265 | } |
262 | #endif | 266 | #endif |
@@ -309,16 +313,17 @@ static void __init reserve_brk(void) | |||
309 | #define MAX_MAP_CHUNK (NR_FIX_BTMAPS << PAGE_SHIFT) | 313 | #define MAX_MAP_CHUNK (NR_FIX_BTMAPS << PAGE_SHIFT) |
310 | static void __init relocate_initrd(void) | 314 | static void __init relocate_initrd(void) |
311 | { | 315 | { |
312 | 316 | /* Assume only end is not page aligned */ | |
313 | u64 ramdisk_image = boot_params.hdr.ramdisk_image; | 317 | u64 ramdisk_image = boot_params.hdr.ramdisk_image; |
314 | u64 ramdisk_size = boot_params.hdr.ramdisk_size; | 318 | u64 ramdisk_size = boot_params.hdr.ramdisk_size; |
319 | u64 area_size = PAGE_ALIGN(ramdisk_size); | ||
315 | u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT; | 320 | u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT; |
316 | u64 ramdisk_here; | 321 | u64 ramdisk_here; |
317 | unsigned long slop, clen, mapaddr; | 322 | unsigned long slop, clen, mapaddr; |
318 | char *p, *q; | 323 | char *p, *q; |
319 | 324 | ||
320 | /* We need to move the initrd down into lowmem */ | 325 | /* We need to move the initrd down into lowmem */ |
321 | ramdisk_here = find_e820_area(0, end_of_lowmem, ramdisk_size, | 326 | ramdisk_here = find_e820_area(0, end_of_lowmem, area_size, |
322 | PAGE_SIZE); | 327 | PAGE_SIZE); |
323 | 328 | ||
324 | if (ramdisk_here == -1ULL) | 329 | if (ramdisk_here == -1ULL) |
@@ -327,7 +332,7 @@ static void __init relocate_initrd(void) | |||
327 | 332 | ||
328 | /* Note: this includes all the lowmem currently occupied by | 333 | /* Note: this includes all the lowmem currently occupied by |
329 | the initrd, we rely on that fact to keep the data intact. */ | 334 | the initrd, we rely on that fact to keep the data intact. */ |
330 | reserve_early(ramdisk_here, ramdisk_here + ramdisk_size, | 335 | reserve_early(ramdisk_here, ramdisk_here + area_size, |
331 | "NEW RAMDISK"); | 336 | "NEW RAMDISK"); |
332 | initrd_start = ramdisk_here + PAGE_OFFSET; | 337 | initrd_start = ramdisk_here + PAGE_OFFSET; |
333 | initrd_end = initrd_start + ramdisk_size; | 338 | initrd_end = initrd_start + ramdisk_size; |
@@ -371,9 +376,10 @@ static void __init relocate_initrd(void) | |||
371 | 376 | ||
372 | static void __init reserve_initrd(void) | 377 | static void __init reserve_initrd(void) |
373 | { | 378 | { |
379 | /* Assume only end is not page aligned */ | ||
374 | u64 ramdisk_image = boot_params.hdr.ramdisk_image; | 380 | u64 ramdisk_image = boot_params.hdr.ramdisk_image; |
375 | u64 ramdisk_size = boot_params.hdr.ramdisk_size; | 381 | u64 ramdisk_size = boot_params.hdr.ramdisk_size; |
376 | u64 ramdisk_end = ramdisk_image + ramdisk_size; | 382 | u64 ramdisk_end = PAGE_ALIGN(ramdisk_image + ramdisk_size); |
377 | u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT; | 383 | u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT; |
378 | 384 | ||
379 | if (!boot_params.hdr.type_of_loader || | 385 | if (!boot_params.hdr.type_of_loader || |
@@ -486,42 +492,11 @@ static void __init reserve_early_setup_data(void) | |||
486 | 492 | ||
487 | #ifdef CONFIG_KEXEC | 493 | #ifdef CONFIG_KEXEC |
488 | 494 | ||
489 | /** | ||
490 | * Reserve @size bytes of crashkernel memory at any suitable offset. | ||
491 | * | ||
492 | * @size: Size of the crashkernel memory to reserve. | ||
493 | * Returns the base address on success, and -1ULL on failure. | ||
494 | */ | ||
495 | static | ||
496 | unsigned long long __init find_and_reserve_crashkernel(unsigned long long size) | ||
497 | { | ||
498 | const unsigned long long alignment = 16<<20; /* 16M */ | ||
499 | unsigned long long start = 0LL; | ||
500 | |||
501 | while (1) { | ||
502 | int ret; | ||
503 | |||
504 | start = find_e820_area(start, ULONG_MAX, size, alignment); | ||
505 | if (start == -1ULL) | ||
506 | return start; | ||
507 | |||
508 | /* try to reserve it */ | ||
509 | ret = reserve_bootmem_generic(start, size, BOOTMEM_EXCLUSIVE); | ||
510 | if (ret >= 0) | ||
511 | return start; | ||
512 | |||
513 | start += alignment; | ||
514 | } | ||
515 | } | ||
516 | |||
517 | static inline unsigned long long get_total_mem(void) | 495 | static inline unsigned long long get_total_mem(void) |
518 | { | 496 | { |
519 | unsigned long long total; | 497 | unsigned long long total; |
520 | 498 | ||
521 | total = max_low_pfn - min_low_pfn; | 499 | total = max_pfn - min_low_pfn; |
522 | #ifdef CONFIG_HIGHMEM | ||
523 | total += highend_pfn - highstart_pfn; | ||
524 | #endif | ||
525 | 500 | ||
526 | return total << PAGE_SHIFT; | 501 | return total << PAGE_SHIFT; |
527 | } | 502 | } |
@@ -541,21 +516,25 @@ static void __init reserve_crashkernel(void) | |||
541 | 516 | ||
542 | /* 0 means: find the address automatically */ | 517 | /* 0 means: find the address automatically */ |
543 | if (crash_base <= 0) { | 518 | if (crash_base <= 0) { |
544 | crash_base = find_and_reserve_crashkernel(crash_size); | 519 | const unsigned long long alignment = 16<<20; /* 16M */ |
520 | |||
521 | crash_base = find_e820_area(alignment, ULONG_MAX, crash_size, | ||
522 | alignment); | ||
545 | if (crash_base == -1ULL) { | 523 | if (crash_base == -1ULL) { |
546 | pr_info("crashkernel reservation failed. " | 524 | pr_info("crashkernel reservation failed - No suitable area found.\n"); |
547 | "No suitable area found.\n"); | ||
548 | return; | 525 | return; |
549 | } | 526 | } |
550 | } else { | 527 | } else { |
551 | ret = reserve_bootmem_generic(crash_base, crash_size, | 528 | unsigned long long start; |
552 | BOOTMEM_EXCLUSIVE); | 529 | |
553 | if (ret < 0) { | 530 | start = find_e820_area(crash_base, ULONG_MAX, crash_size, |
554 | pr_info("crashkernel reservation failed - " | 531 | 1<<20); |
555 | "memory is in use\n"); | 532 | if (start != crash_base) { |
533 | pr_info("crashkernel reservation failed - memory is in use.\n"); | ||
556 | return; | 534 | return; |
557 | } | 535 | } |
558 | } | 536 | } |
537 | reserve_early(crash_base, crash_base + crash_size, "CRASH KERNEL"); | ||
559 | 538 | ||
560 | printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " | 539 | printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " |
561 | "for crashkernel (System RAM: %ldMB)\n", | 540 | "for crashkernel (System RAM: %ldMB)\n", |
@@ -628,6 +607,16 @@ static int __init setup_elfcorehdr(char *arg) | |||
628 | early_param("elfcorehdr", setup_elfcorehdr); | 607 | early_param("elfcorehdr", setup_elfcorehdr); |
629 | #endif | 608 | #endif |
630 | 609 | ||
610 | static __init void reserve_ibft_region(void) | ||
611 | { | ||
612 | unsigned long addr, size = 0; | ||
613 | |||
614 | addr = find_ibft_region(&size); | ||
615 | |||
616 | if (size) | ||
617 | reserve_early_overlap_ok(addr, addr + size, "ibft"); | ||
618 | } | ||
619 | |||
631 | #ifdef CONFIG_X86_RESERVE_LOW_64K | 620 | #ifdef CONFIG_X86_RESERVE_LOW_64K |
632 | static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) | 621 | static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) |
633 | { | 622 | { |
@@ -666,23 +655,48 @@ static struct dmi_system_id __initdata bad_bios_dmi_table[] = { | |||
666 | DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix/MSC"), | 655 | DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix/MSC"), |
667 | }, | 656 | }, |
668 | }, | 657 | }, |
669 | { | ||
670 | /* | 658 | /* |
671 | * AMI BIOS with low memory corruption was found on Intel DG45ID board. | 659 | * AMI BIOS with low memory corruption was found on Intel DG45ID and |
672 | * It hase different DMI_BIOS_VENDOR = "Intel Corp.", for now we will | 660 | * DG45FC boards. |
661 | * It has a different DMI_BIOS_VENDOR = "Intel Corp.", for now we will | ||
673 | * match only DMI_BOARD_NAME and see if there is more bad products | 662 | * match only DMI_BOARD_NAME and see if there is more bad products |
674 | * with this vendor. | 663 | * with this vendor. |
675 | */ | 664 | */ |
665 | { | ||
676 | .callback = dmi_low_memory_corruption, | 666 | .callback = dmi_low_memory_corruption, |
677 | .ident = "AMI BIOS", | 667 | .ident = "AMI BIOS", |
678 | .matches = { | 668 | .matches = { |
679 | DMI_MATCH(DMI_BOARD_NAME, "DG45ID"), | 669 | DMI_MATCH(DMI_BOARD_NAME, "DG45ID"), |
680 | }, | 670 | }, |
681 | }, | 671 | }, |
672 | { | ||
673 | .callback = dmi_low_memory_corruption, | ||
674 | .ident = "AMI BIOS", | ||
675 | .matches = { | ||
676 | DMI_MATCH(DMI_BOARD_NAME, "DG45FC"), | ||
677 | }, | ||
678 | }, | ||
682 | #endif | 679 | #endif |
683 | {} | 680 | {} |
684 | }; | 681 | }; |
685 | 682 | ||
683 | static void __init trim_bios_range(void) | ||
684 | { | ||
685 | /* | ||
686 | * A special case is the first 4Kb of memory; | ||
687 | * This is a BIOS owned area, not kernel ram, but generally | ||
688 | * not listed as such in the E820 table. | ||
689 | */ | ||
690 | e820_update_range(0, PAGE_SIZE, E820_RAM, E820_RESERVED); | ||
691 | /* | ||
692 | * special case: Some BIOSen report the PC BIOS | ||
693 | * area (640->1Mb) as ram even though it is not. | ||
694 | * take them out. | ||
695 | */ | ||
696 | e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1); | ||
697 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); | ||
698 | } | ||
699 | |||
686 | /* | 700 | /* |
687 | * Determine if we were loaded by an EFI loader. If so, then we have also been | 701 | * Determine if we were loaded by an EFI loader. If so, then we have also been |
688 | * passed the efi memmap, systab, etc., so we should use these data structures | 702 | * passed the efi memmap, systab, etc., so we should use these data structures |
@@ -698,6 +712,9 @@ static struct dmi_system_id __initdata bad_bios_dmi_table[] = { | |||
698 | 712 | ||
699 | void __init setup_arch(char **cmdline_p) | 713 | void __init setup_arch(char **cmdline_p) |
700 | { | 714 | { |
715 | int acpi = 0; | ||
716 | int k8 = 0; | ||
717 | |||
701 | #ifdef CONFIG_X86_32 | 718 | #ifdef CONFIG_X86_32 |
702 | memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); | 719 | memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); |
703 | visws_early_detect(); | 720 | visws_early_detect(); |
@@ -790,21 +807,18 @@ void __init setup_arch(char **cmdline_p) | |||
790 | strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); | 807 | strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); |
791 | *cmdline_p = command_line; | 808 | *cmdline_p = command_line; |
792 | 809 | ||
793 | #ifdef CONFIG_X86_64 | ||
794 | /* | 810 | /* |
795 | * Must call this twice: Once just to detect whether hardware doesn't | 811 | * x86_configure_nx() is called before parse_early_param() to detect |
796 | * support NX (so that the early EHCI debug console setup can safely | 812 | * whether hardware doesn't support NX (so that the early EHCI debug |
797 | * call set_fixmap(), and then again after parsing early parameters to | 813 | * console setup can safely call set_fixmap()). It may then be called |
798 | * honor the respective command line option. | 814 | * again from within noexec_setup() during parsing early parameters |
815 | * to honor the respective command line option. | ||
799 | */ | 816 | */ |
800 | check_efer(); | 817 | x86_configure_nx(); |
801 | #endif | ||
802 | 818 | ||
803 | parse_early_param(); | 819 | parse_early_param(); |
804 | 820 | ||
805 | #ifdef CONFIG_X86_64 | 821 | x86_report_nx(); |
806 | check_efer(); | ||
807 | #endif | ||
808 | 822 | ||
809 | /* Must be before kernel pagetables are setup */ | 823 | /* Must be before kernel pagetables are setup */ |
810 | vmi_activate(); | 824 | vmi_activate(); |
@@ -846,7 +860,7 @@ void __init setup_arch(char **cmdline_p) | |||
846 | insert_resource(&iomem_resource, &data_resource); | 860 | insert_resource(&iomem_resource, &data_resource); |
847 | insert_resource(&iomem_resource, &bss_resource); | 861 | insert_resource(&iomem_resource, &bss_resource); |
848 | 862 | ||
849 | 863 | trim_bios_range(); | |
850 | #ifdef CONFIG_X86_32 | 864 | #ifdef CONFIG_X86_32 |
851 | if (ppro_with_ram_bug()) { | 865 | if (ppro_with_ram_bug()) { |
852 | e820_update_range(0x70000000ULL, 0x40000ULL, E820_RAM, | 866 | e820_update_range(0x70000000ULL, 0x40000ULL, E820_RAM, |
@@ -900,6 +914,22 @@ void __init setup_arch(char **cmdline_p) | |||
900 | 914 | ||
901 | reserve_brk(); | 915 | reserve_brk(); |
902 | 916 | ||
917 | /* | ||
918 | * Find and reserve possible boot-time SMP configuration: | ||
919 | */ | ||
920 | find_smp_config(); | ||
921 | |||
922 | reserve_ibft_region(); | ||
923 | |||
924 | reserve_trampoline_memory(); | ||
925 | |||
926 | #ifdef CONFIG_ACPI_SLEEP | ||
927 | /* | ||
928 | * Reserve low memory region for sleep support. | ||
929 | * even before init_memory_mapping | ||
930 | */ | ||
931 | acpi_reserve_wakeup_memory(); | ||
932 | #endif | ||
903 | init_gbpages(); | 933 | init_gbpages(); |
904 | 934 | ||
905 | /* max_pfn_mapped is updated here */ | 935 | /* max_pfn_mapped is updated here */ |
@@ -926,6 +956,8 @@ void __init setup_arch(char **cmdline_p) | |||
926 | 956 | ||
927 | reserve_initrd(); | 957 | reserve_initrd(); |
928 | 958 | ||
959 | reserve_crashkernel(); | ||
960 | |||
929 | vsmp_init(); | 961 | vsmp_init(); |
930 | 962 | ||
931 | io_delay_init(); | 963 | io_delay_init(); |
@@ -941,34 +973,20 @@ void __init setup_arch(char **cmdline_p) | |||
941 | /* | 973 | /* |
942 | * Parse SRAT to discover nodes. | 974 | * Parse SRAT to discover nodes. |
943 | */ | 975 | */ |
944 | acpi_numa_init(); | 976 | acpi = acpi_numa_init(); |
945 | #endif | 977 | #endif |
946 | 978 | ||
947 | initmem_init(0, max_pfn); | 979 | #ifdef CONFIG_K8_NUMA |
948 | 980 | if (!acpi) | |
949 | #ifdef CONFIG_ACPI_SLEEP | 981 | k8 = !k8_numa_init(0, max_pfn); |
950 | /* | ||
951 | * Reserve low memory region for sleep support. | ||
952 | */ | ||
953 | acpi_reserve_bootmem(); | ||
954 | #endif | 982 | #endif |
955 | /* | ||
956 | * Find and reserve possible boot-time SMP configuration: | ||
957 | */ | ||
958 | find_smp_config(); | ||
959 | 983 | ||
960 | reserve_crashkernel(); | 984 | initmem_init(0, max_pfn, acpi, k8); |
961 | 985 | #ifndef CONFIG_NO_BOOTMEM | |
962 | #ifdef CONFIG_X86_64 | 986 | early_res_to_bootmem(0, max_low_pfn<<PAGE_SHIFT); |
963 | /* | ||
964 | * dma32_reserve_bootmem() allocates bootmem which may conflict | ||
965 | * with the crashkernel command line, so do that after | ||
966 | * reserve_crashkernel() | ||
967 | */ | ||
968 | dma32_reserve_bootmem(); | ||
969 | #endif | 987 | #endif |
970 | 988 | ||
971 | reserve_ibft_region(); | 989 | dma32_reserve_bootmem(); |
972 | 990 | ||
973 | #ifdef CONFIG_KVM_CLOCK | 991 | #ifdef CONFIG_KVM_CLOCK |
974 | kvmclock_init(); | 992 | kvmclock_init(); |
@@ -1031,6 +1049,8 @@ void __init setup_arch(char **cmdline_p) | |||
1031 | #endif | 1049 | #endif |
1032 | #endif | 1050 | #endif |
1033 | x86_init.oem.banner(); | 1051 | x86_init.oem.banner(); |
1052 | |||
1053 | mcheck_init(); | ||
1034 | } | 1054 | } |
1035 | 1055 | ||
1036 | #ifdef CONFIG_X86_32 | 1056 | #ifdef CONFIG_X86_32 |