diff options
Diffstat (limited to 'arch/i386/kernel/setup.c')
-rw-r--r-- | arch/i386/kernel/setup.c | 350 |
1 files changed, 118 insertions, 232 deletions
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 71a540362b78..c6e31ed386f5 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c | |||
@@ -96,11 +96,6 @@ unsigned long mmu_cr4_features; | |||
96 | #endif | 96 | #endif |
97 | EXPORT_SYMBOL(acpi_disabled); | 97 | EXPORT_SYMBOL(acpi_disabled); |
98 | 98 | ||
99 | #ifdef CONFIG_ACPI | ||
100 | int __initdata acpi_force = 0; | ||
101 | extern acpi_interrupt_flags acpi_sci_flags; | ||
102 | #endif | ||
103 | |||
104 | /* for MCA, but anyone else can use it if they want */ | 99 | /* for MCA, but anyone else can use it if they want */ |
105 | unsigned int machine_id; | 100 | unsigned int machine_id; |
106 | #ifdef CONFIG_MCA | 101 | #ifdef CONFIG_MCA |
@@ -148,7 +143,6 @@ EXPORT_SYMBOL(ist_info); | |||
148 | struct e820map e820; | 143 | struct e820map e820; |
149 | 144 | ||
150 | extern void early_cpu_init(void); | 145 | extern void early_cpu_init(void); |
151 | extern void generic_apic_probe(char *); | ||
152 | extern int root_mountflags; | 146 | extern int root_mountflags; |
153 | 147 | ||
154 | unsigned long saved_videomode; | 148 | unsigned long saved_videomode; |
@@ -700,238 +694,132 @@ static inline void copy_edd(void) | |||
700 | } | 694 | } |
701 | #endif | 695 | #endif |
702 | 696 | ||
703 | static void __init parse_cmdline_early (char ** cmdline_p) | 697 | static int __initdata user_defined_memmap = 0; |
704 | { | ||
705 | char c = ' ', *to = command_line, *from = saved_command_line; | ||
706 | int len = 0; | ||
707 | int userdef = 0; | ||
708 | 698 | ||
709 | /* Save unparsed command line copy for /proc/cmdline */ | 699 | /* |
710 | saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; | 700 | * "mem=nopentium" disables the 4MB page tables. |
701 | * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM | ||
702 | * to <mem>, overriding the bios size. | ||
703 | * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from | ||
704 | * <start> to <start>+<mem>, overriding the bios size. | ||
705 | * | ||
706 | * HPA tells me bootloaders need to parse mem=, so no new | ||
707 | * option should be mem= [also see Documentation/i386/boot.txt] | ||
708 | */ | ||
709 | static int __init parse_mem(char *arg) | ||
710 | { | ||
711 | if (!arg) | ||
712 | return -EINVAL; | ||
711 | 713 | ||
712 | for (;;) { | 714 | if (strcmp(arg, "nopentium") == 0) { |
713 | if (c != ' ') | 715 | clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability); |
714 | goto next_char; | 716 | disable_pse = 1; |
715 | /* | 717 | } else { |
716 | * "mem=nopentium" disables the 4MB page tables. | 718 | /* If the user specifies memory size, we |
717 | * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM | 719 | * limit the BIOS-provided memory map to |
718 | * to <mem>, overriding the bios size. | 720 | * that size. exactmap can be used to specify |
719 | * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from | 721 | * the exact map. mem=number can be used to |
720 | * <start> to <start>+<mem>, overriding the bios size. | 722 | * trim the existing memory map. |
721 | * | ||
722 | * HPA tells me bootloaders need to parse mem=, so no new | ||
723 | * option should be mem= [also see Documentation/i386/boot.txt] | ||
724 | */ | 723 | */ |
725 | if (!memcmp(from, "mem=", 4)) { | 724 | unsigned long long mem_size; |
726 | if (to != command_line) | ||
727 | to--; | ||
728 | if (!memcmp(from+4, "nopentium", 9)) { | ||
729 | from += 9+4; | ||
730 | clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability); | ||
731 | disable_pse = 1; | ||
732 | } else { | ||
733 | /* If the user specifies memory size, we | ||
734 | * limit the BIOS-provided memory map to | ||
735 | * that size. exactmap can be used to specify | ||
736 | * the exact map. mem=number can be used to | ||
737 | * trim the existing memory map. | ||
738 | */ | ||
739 | unsigned long long mem_size; | ||
740 | 725 | ||
741 | mem_size = memparse(from+4, &from); | 726 | mem_size = memparse(arg, &arg); |
742 | limit_regions(mem_size); | 727 | limit_regions(mem_size); |
743 | userdef=1; | 728 | user_defined_memmap = 1; |
744 | } | 729 | } |
745 | } | 730 | return 0; |
746 | 731 | } | |
747 | else if (!memcmp(from, "memmap=", 7)) { | 732 | early_param("mem", parse_mem); |
748 | if (to != command_line) | ||
749 | to--; | ||
750 | if (!memcmp(from+7, "exactmap", 8)) { | ||
751 | #ifdef CONFIG_CRASH_DUMP | ||
752 | /* If we are doing a crash dump, we | ||
753 | * still need to know the real mem | ||
754 | * size before original memory map is | ||
755 | * reset. | ||
756 | */ | ||
757 | find_max_pfn(); | ||
758 | saved_max_pfn = max_pfn; | ||
759 | #endif | ||
760 | from += 8+7; | ||
761 | e820.nr_map = 0; | ||
762 | userdef = 1; | ||
763 | } else { | ||
764 | /* If the user specifies memory size, we | ||
765 | * limit the BIOS-provided memory map to | ||
766 | * that size. exactmap can be used to specify | ||
767 | * the exact map. mem=number can be used to | ||
768 | * trim the existing memory map. | ||
769 | */ | ||
770 | unsigned long long start_at, mem_size; | ||
771 | |||
772 | mem_size = memparse(from+7, &from); | ||
773 | if (*from == '@') { | ||
774 | start_at = memparse(from+1, &from); | ||
775 | add_memory_region(start_at, mem_size, E820_RAM); | ||
776 | } else if (*from == '#') { | ||
777 | start_at = memparse(from+1, &from); | ||
778 | add_memory_region(start_at, mem_size, E820_ACPI); | ||
779 | } else if (*from == '$') { | ||
780 | start_at = memparse(from+1, &from); | ||
781 | add_memory_region(start_at, mem_size, E820_RESERVED); | ||
782 | } else { | ||
783 | limit_regions(mem_size); | ||
784 | userdef=1; | ||
785 | } | ||
786 | } | ||
787 | } | ||
788 | |||
789 | else if (!memcmp(from, "noexec=", 7)) | ||
790 | noexec_setup(from + 7); | ||
791 | 733 | ||
734 | static int __init parse_memmap(char *arg) | ||
735 | { | ||
736 | if (!arg) | ||
737 | return -EINVAL; | ||
792 | 738 | ||
793 | #ifdef CONFIG_X86_SMP | 739 | if (strcmp(arg, "exactmap") == 0) { |
794 | /* | 740 | #ifdef CONFIG_CRASH_DUMP |
795 | * If the BIOS enumerates physical processors before logical, | 741 | /* If we are doing a crash dump, we |
796 | * maxcpus=N at enumeration-time can be used to disable HT. | 742 | * still need to know the real mem |
743 | * size before original memory map is | ||
744 | * reset. | ||
797 | */ | 745 | */ |
798 | else if (!memcmp(from, "maxcpus=", 8)) { | 746 | find_max_pfn(); |
799 | extern unsigned int maxcpus; | 747 | saved_max_pfn = max_pfn; |
800 | |||
801 | maxcpus = simple_strtoul(from + 8, NULL, 0); | ||
802 | } | ||
803 | #endif | 748 | #endif |
804 | 749 | e820.nr_map = 0; | |
805 | #ifdef CONFIG_ACPI | 750 | user_defined_memmap = 1; |
806 | /* "acpi=off" disables both ACPI table parsing and interpreter */ | 751 | } else { |
807 | else if (!memcmp(from, "acpi=off", 8)) { | 752 | /* If the user specifies memory size, we |
808 | disable_acpi(); | 753 | * limit the BIOS-provided memory map to |
809 | } | 754 | * that size. exactmap can be used to specify |
810 | 755 | * the exact map. mem=number can be used to | |
811 | /* acpi=force to over-ride black-list */ | 756 | * trim the existing memory map. |
812 | else if (!memcmp(from, "acpi=force", 10)) { | 757 | */ |
813 | acpi_force = 1; | 758 | unsigned long long start_at, mem_size; |
814 | acpi_ht = 1; | 759 | |
815 | acpi_disabled = 0; | 760 | mem_size = memparse(arg, &arg); |
816 | } | 761 | if (*arg == '@') { |
817 | 762 | start_at = memparse(arg+1, &arg); | |
818 | /* acpi=strict disables out-of-spec workarounds */ | 763 | add_memory_region(start_at, mem_size, E820_RAM); |
819 | else if (!memcmp(from, "acpi=strict", 11)) { | 764 | } else if (*arg == '#') { |
820 | acpi_strict = 1; | 765 | start_at = memparse(arg+1, &arg); |
821 | } | 766 | add_memory_region(start_at, mem_size, E820_ACPI); |
822 | 767 | } else if (*arg == '$') { | |
823 | /* Limit ACPI just to boot-time to enable HT */ | 768 | start_at = memparse(arg+1, &arg); |
824 | else if (!memcmp(from, "acpi=ht", 7)) { | 769 | add_memory_region(start_at, mem_size, E820_RESERVED); |
825 | if (!acpi_force) | 770 | } else { |
826 | disable_acpi(); | 771 | limit_regions(mem_size); |
827 | acpi_ht = 1; | 772 | user_defined_memmap = 1; |
828 | } | ||
829 | |||
830 | /* "pci=noacpi" disable ACPI IRQ routing and PCI scan */ | ||
831 | else if (!memcmp(from, "pci=noacpi", 10)) { | ||
832 | acpi_disable_pci(); | ||
833 | } | ||
834 | /* "acpi=noirq" disables ACPI interrupt routing */ | ||
835 | else if (!memcmp(from, "acpi=noirq", 10)) { | ||
836 | acpi_noirq_set(); | ||
837 | } | 773 | } |
774 | } | ||
775 | return 0; | ||
776 | } | ||
777 | early_param("memmap", parse_memmap); | ||
838 | 778 | ||
839 | else if (!memcmp(from, "acpi_sci=edge", 13)) | 779 | #ifdef CONFIG_PROC_VMCORE |
840 | acpi_sci_flags.trigger = 1; | 780 | /* elfcorehdr= specifies the location of elf core header |
841 | 781 | * stored by the crashed kernel. | |
842 | else if (!memcmp(from, "acpi_sci=level", 14)) | 782 | */ |
843 | acpi_sci_flags.trigger = 3; | 783 | static int __init parse_elfcorehdr(char *arg) |
844 | 784 | { | |
845 | else if (!memcmp(from, "acpi_sci=high", 13)) | 785 | if (!arg) |
846 | acpi_sci_flags.polarity = 1; | 786 | return -EINVAL; |
847 | |||
848 | else if (!memcmp(from, "acpi_sci=low", 12)) | ||
849 | acpi_sci_flags.polarity = 3; | ||
850 | |||
851 | #ifdef CONFIG_X86_IO_APIC | ||
852 | else if (!memcmp(from, "acpi_skip_timer_override", 24)) | ||
853 | acpi_skip_timer_override = 1; | ||
854 | |||
855 | if (!memcmp(from, "disable_timer_pin_1", 19)) | ||
856 | disable_timer_pin_1 = 1; | ||
857 | if (!memcmp(from, "enable_timer_pin_1", 18)) | ||
858 | disable_timer_pin_1 = -1; | ||
859 | 787 | ||
860 | /* disable IO-APIC */ | 788 | elfcorehdr_addr = memparse(arg, &arg); |
861 | else if (!memcmp(from, "noapic", 6)) | 789 | return 0; |
862 | disable_ioapic_setup(); | 790 | } |
863 | #endif /* CONFIG_X86_IO_APIC */ | 791 | early_param("elfcorehdr", parse_elfcorehdr); |
864 | #endif /* CONFIG_ACPI */ | 792 | #endif /* CONFIG_PROC_VMCORE */ |
865 | 793 | ||
866 | #ifdef CONFIG_X86_LOCAL_APIC | 794 | /* |
867 | /* enable local APIC */ | 795 | * highmem=size forces highmem to be exactly 'size' bytes. |
868 | else if (!memcmp(from, "lapic", 5)) | 796 | * This works even on boxes that have no highmem otherwise. |
869 | lapic_enable(); | 797 | * This also works to reduce highmem size on bigger boxes. |
798 | */ | ||
799 | static int __init parse_highmem(char *arg) | ||
800 | { | ||
801 | if (!arg) | ||
802 | return -EINVAL; | ||
870 | 803 | ||
871 | /* disable local APIC */ | 804 | highmem_pages = memparse(arg, &arg) >> PAGE_SHIFT; |
872 | else if (!memcmp(from, "nolapic", 6)) | 805 | return 0; |
873 | lapic_disable(); | 806 | } |
874 | #endif /* CONFIG_X86_LOCAL_APIC */ | 807 | early_param("highmem", parse_highmem); |
875 | 808 | ||
876 | #ifdef CONFIG_KEXEC | 809 | /* |
877 | /* crashkernel=size@addr specifies the location to reserve for | 810 | * vmalloc=size forces the vmalloc area to be exactly 'size' |
878 | * a crash kernel. By reserving this memory we guarantee | 811 | * bytes. This can be used to increase (or decrease) the |
879 | * that linux never set's it up as a DMA target. | 812 | * vmalloc area - the default is 128m. |
880 | * Useful for holding code to do something appropriate | 813 | */ |
881 | * after a kernel panic. | 814 | static int __init parse_vmalloc(char *arg) |
882 | */ | 815 | { |
883 | else if (!memcmp(from, "crashkernel=", 12)) { | 816 | if (!arg) |
884 | unsigned long size, base; | 817 | return -EINVAL; |
885 | size = memparse(from+12, &from); | ||
886 | if (*from == '@') { | ||
887 | base = memparse(from+1, &from); | ||
888 | /* FIXME: Do I want a sanity check | ||
889 | * to validate the memory range? | ||
890 | */ | ||
891 | crashk_res.start = base; | ||
892 | crashk_res.end = base + size - 1; | ||
893 | } | ||
894 | } | ||
895 | #endif | ||
896 | #ifdef CONFIG_PROC_VMCORE | ||
897 | /* elfcorehdr= specifies the location of elf core header | ||
898 | * stored by the crashed kernel. | ||
899 | */ | ||
900 | else if (!memcmp(from, "elfcorehdr=", 11)) | ||
901 | elfcorehdr_addr = memparse(from+11, &from); | ||
902 | #endif | ||
903 | 818 | ||
904 | /* | 819 | __VMALLOC_RESERVE = memparse(arg, &arg); |
905 | * highmem=size forces highmem to be exactly 'size' bytes. | 820 | return 0; |
906 | * This works even on boxes that have no highmem otherwise. | ||
907 | * This also works to reduce highmem size on bigger boxes. | ||
908 | */ | ||
909 | else if (!memcmp(from, "highmem=", 8)) | ||
910 | highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT; | ||
911 | |||
912 | /* | ||
913 | * vmalloc=size forces the vmalloc area to be exactly 'size' | ||
914 | * bytes. This can be used to increase (or decrease) the | ||
915 | * vmalloc area - the default is 128m. | ||
916 | */ | ||
917 | else if (!memcmp(from, "vmalloc=", 8)) | ||
918 | __VMALLOC_RESERVE = memparse(from+8, &from); | ||
919 | |||
920 | next_char: | ||
921 | c = *(from++); | ||
922 | if (!c) | ||
923 | break; | ||
924 | if (COMMAND_LINE_SIZE <= ++len) | ||
925 | break; | ||
926 | *(to++) = c; | ||
927 | } | ||
928 | *to = '\0'; | ||
929 | *cmdline_p = command_line; | ||
930 | if (userdef) { | ||
931 | printk(KERN_INFO "user-defined physical RAM map:\n"); | ||
932 | print_memory_map("user"); | ||
933 | } | ||
934 | } | 821 | } |
822 | early_param("vmalloc", parse_vmalloc); | ||
935 | 823 | ||
936 | /* | 824 | /* |
937 | * Callback for efi_memory_walk. | 825 | * Callback for efi_memory_walk. |
@@ -1507,17 +1395,15 @@ void __init setup_arch(char **cmdline_p) | |||
1507 | data_resource.start = virt_to_phys(_etext); | 1395 | data_resource.start = virt_to_phys(_etext); |
1508 | data_resource.end = virt_to_phys(_edata)-1; | 1396 | data_resource.end = virt_to_phys(_edata)-1; |
1509 | 1397 | ||
1510 | parse_cmdline_early(cmdline_p); | 1398 | parse_early_param(); |
1511 | 1399 | ||
1512 | #ifdef CONFIG_EARLY_PRINTK | 1400 | if (user_defined_memmap) { |
1513 | { | 1401 | printk(KERN_INFO "user-defined physical RAM map:\n"); |
1514 | char *s = strstr(*cmdline_p, "earlyprintk="); | 1402 | print_memory_map("user"); |
1515 | if (s) { | ||
1516 | setup_early_printk(strchr(s, '=') + 1); | ||
1517 | printk("early console enabled\n"); | ||
1518 | } | ||
1519 | } | 1403 | } |
1520 | #endif | 1404 | |
1405 | strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE); | ||
1406 | *cmdline_p = command_line; | ||
1521 | 1407 | ||
1522 | max_low_pfn = setup_memory(); | 1408 | max_low_pfn = setup_memory(); |
1523 | 1409 | ||
@@ -1546,7 +1432,7 @@ void __init setup_arch(char **cmdline_p) | |||
1546 | dmi_scan_machine(); | 1432 | dmi_scan_machine(); |
1547 | 1433 | ||
1548 | #ifdef CONFIG_X86_GENERICARCH | 1434 | #ifdef CONFIG_X86_GENERICARCH |
1549 | generic_apic_probe(*cmdline_p); | 1435 | generic_apic_probe(); |
1550 | #endif | 1436 | #endif |
1551 | if (efi_enabled) | 1437 | if (efi_enabled) |
1552 | efi_map_memmap(); | 1438 | efi_map_memmap(); |