diff options
Diffstat (limited to 'arch/i386/kernel/setup.c')
-rw-r--r-- | arch/i386/kernel/setup.c | 111 |
1 files changed, 92 insertions, 19 deletions
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 2bfbddebdbf8..af4de58cab54 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c | |||
@@ -23,8 +23,10 @@ | |||
23 | * This file handles the architecture-dependent parts of initialization | 23 | * This file handles the architecture-dependent parts of initialization |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/config.h> | ||
26 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
27 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
29 | #include <linux/mmzone.h> | ||
28 | #include <linux/tty.h> | 30 | #include <linux/tty.h> |
29 | #include <linux/ioport.h> | 31 | #include <linux/ioport.h> |
30 | #include <linux/acpi.h> | 32 | #include <linux/acpi.h> |
@@ -41,7 +43,12 @@ | |||
41 | #include <linux/init.h> | 43 | #include <linux/init.h> |
42 | #include <linux/edd.h> | 44 | #include <linux/edd.h> |
43 | #include <linux/nodemask.h> | 45 | #include <linux/nodemask.h> |
46 | #include <linux/kexec.h> | ||
47 | #include <linux/crash_dump.h> | ||
48 | |||
44 | #include <video/edid.h> | 49 | #include <video/edid.h> |
50 | |||
51 | #include <asm/apic.h> | ||
45 | #include <asm/e820.h> | 52 | #include <asm/e820.h> |
46 | #include <asm/mpspec.h> | 53 | #include <asm/mpspec.h> |
47 | #include <asm/setup.h> | 54 | #include <asm/setup.h> |
@@ -53,12 +60,15 @@ | |||
53 | #include "setup_arch_pre.h" | 60 | #include "setup_arch_pre.h" |
54 | #include <bios_ebda.h> | 61 | #include <bios_ebda.h> |
55 | 62 | ||
63 | /* Forward Declaration. */ | ||
64 | void __init find_max_pfn(void); | ||
65 | |||
56 | /* This value is set up by the early boot code to point to the value | 66 | /* This value is set up by the early boot code to point to the value |
57 | immediately after the boot time page tables. It contains a *physical* | 67 | immediately after the boot time page tables. It contains a *physical* |
58 | address, and must not be in the .bss segment! */ | 68 | address, and must not be in the .bss segment! */ |
59 | unsigned long init_pg_tables_end __initdata = ~0UL; | 69 | unsigned long init_pg_tables_end __initdata = ~0UL; |
60 | 70 | ||
61 | int disable_pse __initdata = 0; | 71 | int disable_pse __devinitdata = 0; |
62 | 72 | ||
63 | /* | 73 | /* |
64 | * Machine setup.. | 74 | * Machine setup.. |
@@ -73,6 +83,7 @@ EXPORT_SYMBOL(efi_enabled); | |||
73 | struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 }; | 83 | struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 }; |
74 | /* common cpu data for all cpus */ | 84 | /* common cpu data for all cpus */ |
75 | struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 }; | 85 | struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 }; |
86 | EXPORT_SYMBOL(boot_cpu_data); | ||
76 | 87 | ||
77 | unsigned long mmu_cr4_features; | 88 | unsigned long mmu_cr4_features; |
78 | 89 | ||
@@ -90,12 +101,18 @@ extern acpi_interrupt_flags acpi_sci_flags; | |||
90 | 101 | ||
91 | /* for MCA, but anyone else can use it if they want */ | 102 | /* for MCA, but anyone else can use it if they want */ |
92 | unsigned int machine_id; | 103 | unsigned int machine_id; |
104 | #ifdef CONFIG_MCA | ||
105 | EXPORT_SYMBOL(machine_id); | ||
106 | #endif | ||
93 | unsigned int machine_submodel_id; | 107 | unsigned int machine_submodel_id; |
94 | unsigned int BIOS_revision; | 108 | unsigned int BIOS_revision; |
95 | unsigned int mca_pentium_flag; | 109 | unsigned int mca_pentium_flag; |
96 | 110 | ||
97 | /* For PCI or other memory-mapped resources */ | 111 | /* For PCI or other memory-mapped resources */ |
98 | unsigned long pci_mem_start = 0x10000000; | 112 | unsigned long pci_mem_start = 0x10000000; |
113 | #ifdef CONFIG_PCI | ||
114 | EXPORT_SYMBOL(pci_mem_start); | ||
115 | #endif | ||
99 | 116 | ||
100 | /* Boot loader ID as an integer, for the benefit of proc_dointvec */ | 117 | /* Boot loader ID as an integer, for the benefit of proc_dointvec */ |
101 | int bootloader_type; | 118 | int bootloader_type; |
@@ -107,14 +124,26 @@ static unsigned int highmem_pages = -1; | |||
107 | * Setup options | 124 | * Setup options |
108 | */ | 125 | */ |
109 | struct drive_info_struct { char dummy[32]; } drive_info; | 126 | struct drive_info_struct { char dummy[32]; } drive_info; |
127 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || \ | ||
128 | defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE) | ||
129 | EXPORT_SYMBOL(drive_info); | ||
130 | #endif | ||
110 | struct screen_info screen_info; | 131 | struct screen_info screen_info; |
132 | #ifdef CONFIG_VT | ||
133 | EXPORT_SYMBOL(screen_info); | ||
134 | #endif | ||
111 | struct apm_info apm_info; | 135 | struct apm_info apm_info; |
136 | EXPORT_SYMBOL(apm_info); | ||
112 | struct sys_desc_table_struct { | 137 | struct sys_desc_table_struct { |
113 | unsigned short length; | 138 | unsigned short length; |
114 | unsigned char table[0]; | 139 | unsigned char table[0]; |
115 | }; | 140 | }; |
116 | struct edid_info edid_info; | 141 | struct edid_info edid_info; |
117 | struct ist_info ist_info; | 142 | struct ist_info ist_info; |
143 | #if defined(CONFIG_X86_SPEEDSTEP_SMI) || \ | ||
144 | defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE) | ||
145 | EXPORT_SYMBOL(ist_info); | ||
146 | #endif | ||
118 | struct e820map e820; | 147 | struct e820map e820; |
119 | 148 | ||
120 | extern void early_cpu_init(void); | 149 | extern void early_cpu_init(void); |
@@ -711,6 +740,15 @@ static void __init parse_cmdline_early (char ** cmdline_p) | |||
711 | if (to != command_line) | 740 | if (to != command_line) |
712 | to--; | 741 | to--; |
713 | if (!memcmp(from+7, "exactmap", 8)) { | 742 | if (!memcmp(from+7, "exactmap", 8)) { |
743 | #ifdef CONFIG_CRASH_DUMP | ||
744 | /* If we are doing a crash dump, we | ||
745 | * still need to know the real mem | ||
746 | * size before original memory map is | ||
747 | * reset. | ||
748 | */ | ||
749 | find_max_pfn(); | ||
750 | saved_max_pfn = max_pfn; | ||
751 | #endif | ||
714 | from += 8+7; | 752 | from += 8+7; |
715 | e820.nr_map = 0; | 753 | e820.nr_map = 0; |
716 | userdef = 1; | 754 | userdef = 1; |
@@ -814,6 +852,44 @@ static void __init parse_cmdline_early (char ** cmdline_p) | |||
814 | #endif /* CONFIG_X86_LOCAL_APIC */ | 852 | #endif /* CONFIG_X86_LOCAL_APIC */ |
815 | #endif /* CONFIG_ACPI_BOOT */ | 853 | #endif /* CONFIG_ACPI_BOOT */ |
816 | 854 | ||
855 | #ifdef CONFIG_X86_LOCAL_APIC | ||
856 | /* enable local APIC */ | ||
857 | else if (!memcmp(from, "lapic", 5)) | ||
858 | lapic_enable(); | ||
859 | |||
860 | /* disable local APIC */ | ||
861 | else if (!memcmp(from, "nolapic", 6)) | ||
862 | lapic_disable(); | ||
863 | #endif /* CONFIG_X86_LOCAL_APIC */ | ||
864 | |||
865 | #ifdef CONFIG_KEXEC | ||
866 | /* crashkernel=size@addr specifies the location to reserve for | ||
867 | * a crash kernel. By reserving this memory we guarantee | ||
868 | * that linux never set's it up as a DMA target. | ||
869 | * Useful for holding code to do something appropriate | ||
870 | * after a kernel panic. | ||
871 | */ | ||
872 | else if (!memcmp(from, "crashkernel=", 12)) { | ||
873 | unsigned long size, base; | ||
874 | size = memparse(from+12, &from); | ||
875 | if (*from == '@') { | ||
876 | base = memparse(from+1, &from); | ||
877 | /* FIXME: Do I want a sanity check | ||
878 | * to validate the memory range? | ||
879 | */ | ||
880 | crashk_res.start = base; | ||
881 | crashk_res.end = base + size - 1; | ||
882 | } | ||
883 | } | ||
884 | #endif | ||
885 | #ifdef CONFIG_CRASH_DUMP | ||
886 | /* elfcorehdr= specifies the location of elf core header | ||
887 | * stored by the crashed kernel. | ||
888 | */ | ||
889 | else if (!memcmp(from, "elfcorehdr=", 11)) | ||
890 | elfcorehdr_addr = memparse(from+11, &from); | ||
891 | #endif | ||
892 | |||
817 | /* | 893 | /* |
818 | * highmem=size forces highmem to be exactly 'size' bytes. | 894 | * highmem=size forces highmem to be exactly 'size' bytes. |
819 | * This works even on boxes that have no highmem otherwise. | 895 | * This works even on boxes that have no highmem otherwise. |
@@ -1022,7 +1098,7 @@ static void __init reserve_ebda_region(void) | |||
1022 | reserve_bootmem(addr, PAGE_SIZE); | 1098 | reserve_bootmem(addr, PAGE_SIZE); |
1023 | } | 1099 | } |
1024 | 1100 | ||
1025 | #ifndef CONFIG_DISCONTIGMEM | 1101 | #ifndef CONFIG_NEED_MULTIPLE_NODES |
1026 | void __init setup_bootmem_allocator(void); | 1102 | void __init setup_bootmem_allocator(void); |
1027 | static unsigned long __init setup_memory(void) | 1103 | static unsigned long __init setup_memory(void) |
1028 | { | 1104 | { |
@@ -1072,9 +1148,9 @@ void __init zone_sizes_init(void) | |||
1072 | free_area_init(zones_size); | 1148 | free_area_init(zones_size); |
1073 | } | 1149 | } |
1074 | #else | 1150 | #else |
1075 | extern unsigned long setup_memory(void); | 1151 | extern unsigned long __init setup_memory(void); |
1076 | extern void zone_sizes_init(void); | 1152 | extern void zone_sizes_init(void); |
1077 | #endif /* !CONFIG_DISCONTIGMEM */ | 1153 | #endif /* !CONFIG_NEED_MULTIPLE_NODES */ |
1078 | 1154 | ||
1079 | void __init setup_bootmem_allocator(void) | 1155 | void __init setup_bootmem_allocator(void) |
1080 | { | 1156 | { |
@@ -1092,8 +1168,8 @@ void __init setup_bootmem_allocator(void) | |||
1092 | * the (very unlikely) case of us accidentally initializing the | 1168 | * the (very unlikely) case of us accidentally initializing the |
1093 | * bootmem allocator with an invalid RAM area. | 1169 | * bootmem allocator with an invalid RAM area. |
1094 | */ | 1170 | */ |
1095 | reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(min_low_pfn) + | 1171 | reserve_bootmem(__PHYSICAL_START, (PFN_PHYS(min_low_pfn) + |
1096 | bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY)); | 1172 | bootmap_size + PAGE_SIZE-1) - (__PHYSICAL_START)); |
1097 | 1173 | ||
1098 | /* | 1174 | /* |
1099 | * reserve physical page 0 - it's a special BIOS page on many boxes, | 1175 | * reserve physical page 0 - it's a special BIOS page on many boxes, |
@@ -1149,6 +1225,11 @@ void __init setup_bootmem_allocator(void) | |||
1149 | } | 1225 | } |
1150 | } | 1226 | } |
1151 | #endif | 1227 | #endif |
1228 | #ifdef CONFIG_KEXEC | ||
1229 | if (crashk_res.start != crashk_res.end) | ||
1230 | reserve_bootmem(crashk_res.start, | ||
1231 | crashk_res.end - crashk_res.start + 1); | ||
1232 | #endif | ||
1152 | } | 1233 | } |
1153 | 1234 | ||
1154 | /* | 1235 | /* |
@@ -1202,6 +1283,9 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat | |||
1202 | */ | 1283 | */ |
1203 | request_resource(res, code_resource); | 1284 | request_resource(res, code_resource); |
1204 | request_resource(res, data_resource); | 1285 | request_resource(res, data_resource); |
1286 | #ifdef CONFIG_KEXEC | ||
1287 | request_resource(res, &crashk_res); | ||
1288 | #endif | ||
1205 | } | 1289 | } |
1206 | } | 1290 | } |
1207 | } | 1291 | } |
@@ -1330,7 +1414,7 @@ static struct nop { | |||
1330 | This runs before SMP is initialized to avoid SMP problems with | 1414 | This runs before SMP is initialized to avoid SMP problems with |
1331 | self modifying code. This implies that assymetric systems where | 1415 | self modifying code. This implies that assymetric systems where |
1332 | APs have less capabilities than the boot processor are not handled. | 1416 | APs have less capabilities than the boot processor are not handled. |
1333 | In this case boot with "noreplacement". */ | 1417 | Tough. Make sure you disable such features by hand. */ |
1334 | void apply_alternatives(void *start, void *end) | 1418 | void apply_alternatives(void *start, void *end) |
1335 | { | 1419 | { |
1336 | struct alt_instr *a; | 1420 | struct alt_instr *a; |
@@ -1358,24 +1442,12 @@ void apply_alternatives(void *start, void *end) | |||
1358 | } | 1442 | } |
1359 | } | 1443 | } |
1360 | 1444 | ||
1361 | static int no_replacement __initdata = 0; | ||
1362 | |||
1363 | void __init alternative_instructions(void) | 1445 | void __init alternative_instructions(void) |
1364 | { | 1446 | { |
1365 | extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; | 1447 | extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; |
1366 | if (no_replacement) | ||
1367 | return; | ||
1368 | apply_alternatives(__alt_instructions, __alt_instructions_end); | 1448 | apply_alternatives(__alt_instructions, __alt_instructions_end); |
1369 | } | 1449 | } |
1370 | 1450 | ||
1371 | static int __init noreplacement_setup(char *s) | ||
1372 | { | ||
1373 | no_replacement = 1; | ||
1374 | return 0; | ||
1375 | } | ||
1376 | |||
1377 | __setup("noreplacement", noreplacement_setup); | ||
1378 | |||
1379 | static char * __init machine_specific_memory_setup(void); | 1451 | static char * __init machine_specific_memory_setup(void); |
1380 | 1452 | ||
1381 | #ifdef CONFIG_MCA | 1453 | #ifdef CONFIG_MCA |
@@ -1475,6 +1547,7 @@ void __init setup_arch(char **cmdline_p) | |||
1475 | #endif | 1547 | #endif |
1476 | paging_init(); | 1548 | paging_init(); |
1477 | remapped_pgdat_init(); | 1549 | remapped_pgdat_init(); |
1550 | sparse_init(); | ||
1478 | zone_sizes_init(); | 1551 | zone_sizes_init(); |
1479 | 1552 | ||
1480 | /* | 1553 | /* |