diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2006-09-26 04:52:32 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-09-26 04:52:32 -0400 |
commit | 1a3f239ddf9208f2e52d36fef1c1c4518cbbbabe (patch) | |
tree | f2ad21f766102540e15ea61145e94be65901e272 /arch/i386 | |
parent | 33df0d19ea425d28bd5afb48898af32237fe81af (diff) |
[PATCH] i386: Replace i386 open-coded cmdline parsing with
This patch replaces the open-coded early commandline parsing
throughout the i386 boot code with the generic mechanism (already used
by ppc, powerpc, ia64 and s390). The code was inconsistent with
whether it deletes the option from the cmdline or not, meaning some of
these will get passed through the environment into init.
This transformation is mainly mechanical, but there are some notable
parts:
1) Grammar: s/linux never set's it up/linux never sets it up/
2) Remove hacked-in earlyprintk= option scanning. When someone
actually implements CONFIG_EARLY_PRINTK, then they can use
early_param().
[AK: actually it is implemented, but I'm adding the early_param it in the next
x86-64 patch]
3) Move declaration of generic_apic_probe() from setup.c into asm/apic.h
4) Various parameters now moved into their appropriate files (thanks Andi).
5) All parse functions which examine arg need to check for NULL,
except one where it has subtle humor value.
AK: readded acpi_sci handling which was completely dropped
AK: moved some more variables into acpi/boot.c
Cc: len.brown@intel.com
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/kernel/acpi/boot.c | 76 | ||||
-rw-r--r-- | arch/i386/kernel/apic.c | 15 | ||||
-rw-r--r-- | arch/i386/kernel/io_apic.c | 24 | ||||
-rw-r--r-- | arch/i386/kernel/machine_kexec.c | 23 | ||||
-rw-r--r-- | arch/i386/kernel/setup.c | 350 | ||||
-rw-r--r-- | arch/i386/kernel/smpboot.c | 13 | ||||
-rw-r--r-- | arch/i386/mach-generic/probe.c | 58 | ||||
-rw-r--r-- | arch/i386/mm/init.c | 18 |
8 files changed, 306 insertions, 271 deletions
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index ee003bc0e8b1..87e2ab50b694 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c | |||
@@ -36,6 +36,8 @@ | |||
36 | #include <asm/io.h> | 36 | #include <asm/io.h> |
37 | #include <asm/mpspec.h> | 37 | #include <asm/mpspec.h> |
38 | 38 | ||
39 | int __initdata acpi_force = 0; | ||
40 | |||
39 | #ifdef CONFIG_X86_64 | 41 | #ifdef CONFIG_X86_64 |
40 | 42 | ||
41 | extern void __init clustered_apic_check(void); | 43 | extern void __init clustered_apic_check(void); |
@@ -860,8 +862,6 @@ static void __init acpi_process_madt(void) | |||
860 | return; | 862 | return; |
861 | } | 863 | } |
862 | 864 | ||
863 | extern int acpi_force; | ||
864 | |||
865 | #ifdef __i386__ | 865 | #ifdef __i386__ |
866 | 866 | ||
867 | static int __init disable_acpi_irq(struct dmi_system_id *d) | 867 | static int __init disable_acpi_irq(struct dmi_system_id *d) |
@@ -1163,3 +1163,75 @@ int __init acpi_boot_init(void) | |||
1163 | 1163 | ||
1164 | return 0; | 1164 | return 0; |
1165 | } | 1165 | } |
1166 | |||
1167 | static int __init parse_acpi(char *arg) | ||
1168 | { | ||
1169 | if (!arg) | ||
1170 | return -EINVAL; | ||
1171 | |||
1172 | /* "acpi=off" disables both ACPI table parsing and interpreter */ | ||
1173 | if (strcmp(arg, "off") == 0) { | ||
1174 | disable_acpi(); | ||
1175 | } | ||
1176 | /* acpi=force to over-ride black-list */ | ||
1177 | else if (strcmp(arg, "force") == 0) { | ||
1178 | acpi_force = 1; | ||
1179 | acpi_ht = 1; | ||
1180 | acpi_disabled = 0; | ||
1181 | } | ||
1182 | /* acpi=strict disables out-of-spec workarounds */ | ||
1183 | else if (strcmp(arg, "strict") == 0) { | ||
1184 | acpi_strict = 1; | ||
1185 | } | ||
1186 | /* Limit ACPI just to boot-time to enable HT */ | ||
1187 | else if (strcmp(arg, "ht") == 0) { | ||
1188 | if (!acpi_force) | ||
1189 | disable_acpi(); | ||
1190 | acpi_ht = 1; | ||
1191 | } | ||
1192 | /* "acpi=noirq" disables ACPI interrupt routing */ | ||
1193 | else if (strcmp(arg, "noirq") == 0) { | ||
1194 | acpi_noirq_set(); | ||
1195 | } else { | ||
1196 | /* Core will printk when we return error. */ | ||
1197 | return -EINVAL; | ||
1198 | } | ||
1199 | return 0; | ||
1200 | } | ||
1201 | early_param("acpi", parse_acpi); | ||
1202 | |||
1203 | /* FIXME: Using pci= for an ACPI parameter is a travesty. */ | ||
1204 | static int __init parse_pci(char *arg) | ||
1205 | { | ||
1206 | if (arg && strcmp(arg, "noacpi") == 0) | ||
1207 | acpi_disable_pci(); | ||
1208 | return 0; | ||
1209 | } | ||
1210 | early_param("pci", parse_pci); | ||
1211 | |||
1212 | #ifdef CONFIG_X86_IO_APIC | ||
1213 | static int __init parse_acpi_skip_timer_override(char *arg) | ||
1214 | { | ||
1215 | acpi_skip_timer_override = 1; | ||
1216 | return 0; | ||
1217 | } | ||
1218 | early_param("acpi_skip_timer_override", parse_acpi_skip_timer_override); | ||
1219 | #endif /* CONFIG_X86_IO_APIC */ | ||
1220 | |||
1221 | static int __init setup_acpi_sci(char *s) | ||
1222 | { | ||
1223 | if (!s) | ||
1224 | return -EINVAL; | ||
1225 | if (!strcmp(s, "edge")) | ||
1226 | acpi_sci_flags.trigger = 1; | ||
1227 | else if (!strcmp(s, "level")) | ||
1228 | acpi_sci_flags.trigger = 3; | ||
1229 | else if (!strcmp(s, "high")) | ||
1230 | acpi_sci_flags.polarity = 1; | ||
1231 | else if (!strcmp(s, "low")) | ||
1232 | acpi_sci_flags.polarity = 3; | ||
1233 | else | ||
1234 | return -EINVAL; | ||
1235 | return 0; | ||
1236 | } | ||
1237 | early_param("acpi_sci", setup_acpi_sci); | ||
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 1a34fc57800b..ce75e71b694f 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c | |||
@@ -1372,3 +1372,18 @@ int __init APIC_init_uniprocessor (void) | |||
1372 | 1372 | ||
1373 | return 0; | 1373 | return 0; |
1374 | } | 1374 | } |
1375 | |||
1376 | static int __init parse_lapic(char *arg) | ||
1377 | { | ||
1378 | lapic_enable(); | ||
1379 | return 0; | ||
1380 | } | ||
1381 | early_param("lapic", parse_lapic); | ||
1382 | |||
1383 | static int __init parse_nolapic(char *arg) | ||
1384 | { | ||
1385 | lapic_disable(); | ||
1386 | return 0; | ||
1387 | } | ||
1388 | early_param("nolapic", parse_nolapic); | ||
1389 | |||
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index b713f27d7e86..fd0df75cfbda 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c | |||
@@ -66,7 +66,7 @@ int sis_apic_bug = -1; | |||
66 | */ | 66 | */ |
67 | int nr_ioapic_registers[MAX_IO_APICS]; | 67 | int nr_ioapic_registers[MAX_IO_APICS]; |
68 | 68 | ||
69 | int disable_timer_pin_1 __initdata; | 69 | static int disable_timer_pin_1 __initdata; |
70 | 70 | ||
71 | /* | 71 | /* |
72 | * Rough estimation of how many shared IRQs there are, can | 72 | * Rough estimation of how many shared IRQs there are, can |
@@ -2691,3 +2691,25 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a | |||
2691 | } | 2691 | } |
2692 | 2692 | ||
2693 | #endif /* CONFIG_ACPI */ | 2693 | #endif /* CONFIG_ACPI */ |
2694 | |||
2695 | static int __init parse_disable_timer_pin_1(char *arg) | ||
2696 | { | ||
2697 | disable_timer_pin_1 = 1; | ||
2698 | return 0; | ||
2699 | } | ||
2700 | early_param("disable_timer_pin_1", parse_disable_timer_pin_1); | ||
2701 | |||
2702 | static int __init parse_enable_timer_pin_1(char *arg) | ||
2703 | { | ||
2704 | disable_timer_pin_1 = -1; | ||
2705 | return 0; | ||
2706 | } | ||
2707 | early_param("enable_timer_pin_1", parse_enable_timer_pin_1); | ||
2708 | |||
2709 | static int __init parse_noapic(char *arg) | ||
2710 | { | ||
2711 | /* disable IO-APIC */ | ||
2712 | disable_ioapic_setup(); | ||
2713 | return 0; | ||
2714 | } | ||
2715 | early_param("noapic", parse_noapic); | ||
diff --git a/arch/i386/kernel/machine_kexec.c b/arch/i386/kernel/machine_kexec.c index 6b1ae6ba76f0..66c3dc99a655 100644 --- a/arch/i386/kernel/machine_kexec.c +++ b/arch/i386/kernel/machine_kexec.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/mm.h> | 9 | #include <linux/mm.h> |
10 | #include <linux/kexec.h> | 10 | #include <linux/kexec.h> |
11 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
12 | #include <linux/init.h> | ||
12 | #include <asm/pgtable.h> | 13 | #include <asm/pgtable.h> |
13 | #include <asm/pgalloc.h> | 14 | #include <asm/pgalloc.h> |
14 | #include <asm/tlbflush.h> | 15 | #include <asm/tlbflush.h> |
@@ -209,3 +210,25 @@ NORET_TYPE void machine_kexec(struct kimage *image) | |||
209 | rnk = (relocate_new_kernel_t) reboot_code_buffer; | 210 | rnk = (relocate_new_kernel_t) reboot_code_buffer; |
210 | (*rnk)(page_list, reboot_code_buffer, image->start, cpu_has_pae); | 211 | (*rnk)(page_list, reboot_code_buffer, image->start, cpu_has_pae); |
211 | } | 212 | } |
213 | |||
214 | /* crashkernel=size@addr specifies the location to reserve for | ||
215 | * a crash kernel. By reserving this memory we guarantee | ||
216 | * that linux never sets it up as a DMA target. | ||
217 | * Useful for holding code to do something appropriate | ||
218 | * after a kernel panic. | ||
219 | */ | ||
220 | static int __init parse_crashkernel(char *arg) | ||
221 | { | ||
222 | unsigned long size, base; | ||
223 | size = memparse(arg, &arg); | ||
224 | if (*arg == '@') { | ||
225 | base = memparse(arg+1, &arg); | ||
226 | /* FIXME: Do I want a sanity check | ||
227 | * to validate the memory range? | ||
228 | */ | ||
229 | crashk_res.start = base; | ||
230 | crashk_res.end = base + size - 1; | ||
231 | } | ||
232 | return 0; | ||
233 | } | ||
234 | early_param("crashkernel", parse_crashkernel); | ||
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(); |
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 9367af76ce37..517eb3874550 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c | |||
@@ -1491,3 +1491,16 @@ void __init smp_intr_init(void) | |||
1491 | /* IPI for generic function call */ | 1491 | /* IPI for generic function call */ |
1492 | set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); | 1492 | set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); |
1493 | } | 1493 | } |
1494 | |||
1495 | /* | ||
1496 | * If the BIOS enumerates physical processors before logical, | ||
1497 | * maxcpus=N at enumeration-time can be used to disable HT. | ||
1498 | */ | ||
1499 | static int __init parse_maxcpus(char *arg) | ||
1500 | { | ||
1501 | extern unsigned int maxcpus; | ||
1502 | |||
1503 | maxcpus = simple_strtoul(arg, NULL, 0); | ||
1504 | return 0; | ||
1505 | } | ||
1506 | early_param("maxcpus", parse_maxcpus); | ||
diff --git a/arch/i386/mach-generic/probe.c b/arch/i386/mach-generic/probe.c index 793d1b473251..94b1fd9cbe3c 100644 --- a/arch/i386/mach-generic/probe.c +++ b/arch/i386/mach-generic/probe.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/ctype.h> | 10 | #include <linux/ctype.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/errno.h> | ||
12 | #include <asm/fixmap.h> | 13 | #include <asm/fixmap.h> |
13 | #include <asm/mpspec.h> | 14 | #include <asm/mpspec.h> |
14 | #include <asm/apicdef.h> | 15 | #include <asm/apicdef.h> |
@@ -29,7 +30,24 @@ struct genapic *apic_probe[] __initdata = { | |||
29 | NULL, | 30 | NULL, |
30 | }; | 31 | }; |
31 | 32 | ||
32 | static int cmdline_apic; | 33 | static int cmdline_apic __initdata; |
34 | static int __init parse_apic(char *arg) | ||
35 | { | ||
36 | int i; | ||
37 | |||
38 | if (!arg) | ||
39 | return -EINVAL; | ||
40 | |||
41 | for (i = 0; apic_probe[i]; i++) { | ||
42 | if (!strcmp(apic_probe[i]->name, arg)) { | ||
43 | genapic = apic_probe[i]; | ||
44 | cmdline_apic = 1; | ||
45 | return 0; | ||
46 | } | ||
47 | } | ||
48 | return -ENOENT; | ||
49 | } | ||
50 | early_param("apic", parse_apic); | ||
33 | 51 | ||
34 | void __init generic_bigsmp_probe(void) | 52 | void __init generic_bigsmp_probe(void) |
35 | { | 53 | { |
@@ -48,40 +66,20 @@ void __init generic_bigsmp_probe(void) | |||
48 | } | 66 | } |
49 | } | 67 | } |
50 | 68 | ||
51 | void __init generic_apic_probe(char *command_line) | 69 | void __init generic_apic_probe(void) |
52 | { | 70 | { |
53 | char *s; | 71 | if (!cmdline_apic) { |
54 | int i; | 72 | int i; |
55 | int changed = 0; | 73 | for (i = 0; apic_probe[i]; i++) { |
56 | 74 | if (apic_probe[i]->probe()) { | |
57 | s = strstr(command_line, "apic="); | ||
58 | if (s && (s == command_line || isspace(s[-1]))) { | ||
59 | char *p = strchr(s, ' '), old; | ||
60 | if (!p) | ||
61 | p = strchr(s, '\0'); | ||
62 | old = *p; | ||
63 | *p = 0; | ||
64 | for (i = 0; !changed && apic_probe[i]; i++) { | ||
65 | if (!strcmp(apic_probe[i]->name, s+5)) { | ||
66 | changed = 1; | ||
67 | genapic = apic_probe[i]; | 75 | genapic = apic_probe[i]; |
76 | break; | ||
68 | } | 77 | } |
69 | } | 78 | } |
70 | if (!changed) | 79 | /* Not visible without early console */ |
71 | printk(KERN_ERR "Unknown genapic `%s' specified.\n", s); | 80 | if (!apic_probe[i]) |
72 | *p = old; | 81 | panic("Didn't find an APIC driver"); |
73 | cmdline_apic = changed; | ||
74 | } | ||
75 | for (i = 0; !changed && apic_probe[i]; i++) { | ||
76 | if (apic_probe[i]->probe()) { | ||
77 | changed = 1; | ||
78 | genapic = apic_probe[i]; | ||
79 | } | ||
80 | } | 82 | } |
81 | /* Not visible without early console */ | ||
82 | if (!changed) | ||
83 | panic("Didn't find an APIC driver"); | ||
84 | |||
85 | printk(KERN_INFO "Using APIC driver %s\n", genapic->name); | 83 | printk(KERN_INFO "Using APIC driver %s\n", genapic->name); |
86 | } | 84 | } |
87 | 85 | ||
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index d0c2fdf6a4d7..951386606d09 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c | |||
@@ -435,16 +435,22 @@ u64 __supported_pte_mask __read_mostly = ~_PAGE_NX; | |||
435 | * on Enable | 435 | * on Enable |
436 | * off Disable | 436 | * off Disable |
437 | */ | 437 | */ |
438 | void __init noexec_setup(const char *str) | 438 | static int __init noexec_setup(char *str) |
439 | { | 439 | { |
440 | if (!strncmp(str, "on",2) && cpu_has_nx) { | 440 | if (!str || !strcmp(str, "on")) { |
441 | __supported_pte_mask |= _PAGE_NX; | 441 | if (cpu_has_nx) { |
442 | disable_nx = 0; | 442 | __supported_pte_mask |= _PAGE_NX; |
443 | } else if (!strncmp(str,"off",3)) { | 443 | disable_nx = 0; |
444 | } | ||
445 | } else if (!strcmp(str,"off")) { | ||
444 | disable_nx = 1; | 446 | disable_nx = 1; |
445 | __supported_pte_mask &= ~_PAGE_NX; | 447 | __supported_pte_mask &= ~_PAGE_NX; |
446 | } | 448 | } else |
449 | return -EINVAL; | ||
450 | |||
451 | return 0; | ||
447 | } | 452 | } |
453 | early_param("noexec", noexec_setup); | ||
448 | 454 | ||
449 | int nx_enabled = 0; | 455 | int nx_enabled = 0; |
450 | #ifdef CONFIG_X86_PAE | 456 | #ifdef CONFIG_X86_PAE |