diff options
Diffstat (limited to 'arch/x86/kernel/setup_32.c')
-rw-r--r-- | arch/x86/kernel/setup_32.c | 285 |
1 files changed, 236 insertions, 49 deletions
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c index 9c24b45b513c..62adc5f20be5 100644 --- a/arch/x86/kernel/setup_32.c +++ b/arch/x86/kernel/setup_32.c | |||
@@ -44,9 +44,12 @@ | |||
44 | #include <linux/crash_dump.h> | 44 | #include <linux/crash_dump.h> |
45 | #include <linux/dmi.h> | 45 | #include <linux/dmi.h> |
46 | #include <linux/pfn.h> | 46 | #include <linux/pfn.h> |
47 | #include <linux/pci.h> | ||
48 | #include <linux/init_ohci1394_dma.h> | ||
47 | 49 | ||
48 | #include <video/edid.h> | 50 | #include <video/edid.h> |
49 | 51 | ||
52 | #include <asm/mtrr.h> | ||
50 | #include <asm/apic.h> | 53 | #include <asm/apic.h> |
51 | #include <asm/e820.h> | 54 | #include <asm/e820.h> |
52 | #include <asm/mpspec.h> | 55 | #include <asm/mpspec.h> |
@@ -67,14 +70,83 @@ | |||
67 | address, and must not be in the .bss segment! */ | 70 | address, and must not be in the .bss segment! */ |
68 | unsigned long init_pg_tables_end __initdata = ~0UL; | 71 | unsigned long init_pg_tables_end __initdata = ~0UL; |
69 | 72 | ||
70 | int disable_pse __cpuinitdata = 0; | ||
71 | |||
72 | /* | 73 | /* |
73 | * Machine setup.. | 74 | * Machine setup.. |
74 | */ | 75 | */ |
75 | extern struct resource code_resource; | 76 | static struct resource data_resource = { |
76 | extern struct resource data_resource; | 77 | .name = "Kernel data", |
77 | extern struct resource bss_resource; | 78 | .start = 0, |
79 | .end = 0, | ||
80 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM | ||
81 | }; | ||
82 | |||
83 | static struct resource code_resource = { | ||
84 | .name = "Kernel code", | ||
85 | .start = 0, | ||
86 | .end = 0, | ||
87 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM | ||
88 | }; | ||
89 | |||
90 | static struct resource bss_resource = { | ||
91 | .name = "Kernel bss", | ||
92 | .start = 0, | ||
93 | .end = 0, | ||
94 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM | ||
95 | }; | ||
96 | |||
97 | static struct resource video_ram_resource = { | ||
98 | .name = "Video RAM area", | ||
99 | .start = 0xa0000, | ||
100 | .end = 0xbffff, | ||
101 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM | ||
102 | }; | ||
103 | |||
104 | static struct resource standard_io_resources[] = { { | ||
105 | .name = "dma1", | ||
106 | .start = 0x0000, | ||
107 | .end = 0x001f, | ||
108 | .flags = IORESOURCE_BUSY | IORESOURCE_IO | ||
109 | }, { | ||
110 | .name = "pic1", | ||
111 | .start = 0x0020, | ||
112 | .end = 0x0021, | ||
113 | .flags = IORESOURCE_BUSY | IORESOURCE_IO | ||
114 | }, { | ||
115 | .name = "timer0", | ||
116 | .start = 0x0040, | ||
117 | .end = 0x0043, | ||
118 | .flags = IORESOURCE_BUSY | IORESOURCE_IO | ||
119 | }, { | ||
120 | .name = "timer1", | ||
121 | .start = 0x0050, | ||
122 | .end = 0x0053, | ||
123 | .flags = IORESOURCE_BUSY | IORESOURCE_IO | ||
124 | }, { | ||
125 | .name = "keyboard", | ||
126 | .start = 0x0060, | ||
127 | .end = 0x006f, | ||
128 | .flags = IORESOURCE_BUSY | IORESOURCE_IO | ||
129 | }, { | ||
130 | .name = "dma page reg", | ||
131 | .start = 0x0080, | ||
132 | .end = 0x008f, | ||
133 | .flags = IORESOURCE_BUSY | IORESOURCE_IO | ||
134 | }, { | ||
135 | .name = "pic2", | ||
136 | .start = 0x00a0, | ||
137 | .end = 0x00a1, | ||
138 | .flags = IORESOURCE_BUSY | IORESOURCE_IO | ||
139 | }, { | ||
140 | .name = "dma2", | ||
141 | .start = 0x00c0, | ||
142 | .end = 0x00df, | ||
143 | .flags = IORESOURCE_BUSY | IORESOURCE_IO | ||
144 | }, { | ||
145 | .name = "fpu", | ||
146 | .start = 0x00f0, | ||
147 | .end = 0x00ff, | ||
148 | .flags = IORESOURCE_BUSY | IORESOURCE_IO | ||
149 | } }; | ||
78 | 150 | ||
79 | /* cpu data as detected by the assembly code in head.S */ | 151 | /* cpu data as detected by the assembly code in head.S */ |
80 | struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 }; | 152 | struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 }; |
@@ -116,13 +188,17 @@ extern int root_mountflags; | |||
116 | 188 | ||
117 | unsigned long saved_videomode; | 189 | unsigned long saved_videomode; |
118 | 190 | ||
119 | #define RAMDISK_IMAGE_START_MASK 0x07FF | 191 | #define RAMDISK_IMAGE_START_MASK 0x07FF |
120 | #define RAMDISK_PROMPT_FLAG 0x8000 | 192 | #define RAMDISK_PROMPT_FLAG 0x8000 |
121 | #define RAMDISK_LOAD_FLAG 0x4000 | 193 | #define RAMDISK_LOAD_FLAG 0x4000 |
122 | 194 | ||
123 | static char __initdata command_line[COMMAND_LINE_SIZE]; | 195 | static char __initdata command_line[COMMAND_LINE_SIZE]; |
124 | 196 | ||
197 | #ifndef CONFIG_DEBUG_BOOT_PARAMS | ||
125 | struct boot_params __initdata boot_params; | 198 | struct boot_params __initdata boot_params; |
199 | #else | ||
200 | struct boot_params boot_params; | ||
201 | #endif | ||
126 | 202 | ||
127 | #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) | 203 | #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) |
128 | struct edd edd; | 204 | struct edd edd; |
@@ -166,8 +242,7 @@ static int __init parse_mem(char *arg) | |||
166 | return -EINVAL; | 242 | return -EINVAL; |
167 | 243 | ||
168 | if (strcmp(arg, "nopentium") == 0) { | 244 | if (strcmp(arg, "nopentium") == 0) { |
169 | clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability); | 245 | setup_clear_cpu_cap(X86_FEATURE_PSE); |
170 | disable_pse = 1; | ||
171 | } else { | 246 | } else { |
172 | /* If the user specifies memory size, we | 247 | /* If the user specifies memory size, we |
173 | * limit the BIOS-provided memory map to | 248 | * limit the BIOS-provided memory map to |
@@ -176,7 +251,7 @@ static int __init parse_mem(char *arg) | |||
176 | * trim the existing memory map. | 251 | * trim the existing memory map. |
177 | */ | 252 | */ |
178 | unsigned long long mem_size; | 253 | unsigned long long mem_size; |
179 | 254 | ||
180 | mem_size = memparse(arg, &arg); | 255 | mem_size = memparse(arg, &arg); |
181 | limit_regions(mem_size); | 256 | limit_regions(mem_size); |
182 | user_defined_memmap = 1; | 257 | user_defined_memmap = 1; |
@@ -315,7 +390,7 @@ static void __init reserve_ebda_region(void) | |||
315 | unsigned int addr; | 390 | unsigned int addr; |
316 | addr = get_bios_ebda(); | 391 | addr = get_bios_ebda(); |
317 | if (addr) | 392 | if (addr) |
318 | reserve_bootmem(addr, PAGE_SIZE); | 393 | reserve_bootmem(addr, PAGE_SIZE); |
319 | } | 394 | } |
320 | 395 | ||
321 | #ifndef CONFIG_NEED_MULTIPLE_NODES | 396 | #ifndef CONFIG_NEED_MULTIPLE_NODES |
@@ -420,6 +495,100 @@ static inline void __init reserve_crashkernel(void) | |||
420 | {} | 495 | {} |
421 | #endif | 496 | #endif |
422 | 497 | ||
498 | #ifdef CONFIG_BLK_DEV_INITRD | ||
499 | |||
500 | static bool do_relocate_initrd = false; | ||
501 | |||
502 | static void __init reserve_initrd(void) | ||
503 | { | ||
504 | unsigned long ramdisk_image = boot_params.hdr.ramdisk_image; | ||
505 | unsigned long ramdisk_size = boot_params.hdr.ramdisk_size; | ||
506 | unsigned long ramdisk_end = ramdisk_image + ramdisk_size; | ||
507 | unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT; | ||
508 | unsigned long ramdisk_here; | ||
509 | |||
510 | initrd_start = 0; | ||
511 | |||
512 | if (!boot_params.hdr.type_of_loader || | ||
513 | !ramdisk_image || !ramdisk_size) | ||
514 | return; /* No initrd provided by bootloader */ | ||
515 | |||
516 | if (ramdisk_end < ramdisk_image) { | ||
517 | printk(KERN_ERR "initrd wraps around end of memory, " | ||
518 | "disabling initrd\n"); | ||
519 | return; | ||
520 | } | ||
521 | if (ramdisk_size >= end_of_lowmem/2) { | ||
522 | printk(KERN_ERR "initrd too large to handle, " | ||
523 | "disabling initrd\n"); | ||
524 | return; | ||
525 | } | ||
526 | if (ramdisk_end <= end_of_lowmem) { | ||
527 | /* All in lowmem, easy case */ | ||
528 | reserve_bootmem(ramdisk_image, ramdisk_size); | ||
529 | initrd_start = ramdisk_image + PAGE_OFFSET; | ||
530 | initrd_end = initrd_start+ramdisk_size; | ||
531 | return; | ||
532 | } | ||
533 | |||
534 | /* We need to move the initrd down into lowmem */ | ||
535 | ramdisk_here = (end_of_lowmem - ramdisk_size) & PAGE_MASK; | ||
536 | |||
537 | /* Note: this includes all the lowmem currently occupied by | ||
538 | the initrd, we rely on that fact to keep the data intact. */ | ||
539 | reserve_bootmem(ramdisk_here, ramdisk_size); | ||
540 | initrd_start = ramdisk_here + PAGE_OFFSET; | ||
541 | initrd_end = initrd_start + ramdisk_size; | ||
542 | |||
543 | do_relocate_initrd = true; | ||
544 | } | ||
545 | |||
546 | #define MAX_MAP_CHUNK (NR_FIX_BTMAPS << PAGE_SHIFT) | ||
547 | |||
548 | static void __init relocate_initrd(void) | ||
549 | { | ||
550 | unsigned long ramdisk_image = boot_params.hdr.ramdisk_image; | ||
551 | unsigned long ramdisk_size = boot_params.hdr.ramdisk_size; | ||
552 | unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT; | ||
553 | unsigned long ramdisk_here; | ||
554 | unsigned long slop, clen, mapaddr; | ||
555 | char *p, *q; | ||
556 | |||
557 | if (!do_relocate_initrd) | ||
558 | return; | ||
559 | |||
560 | ramdisk_here = initrd_start - PAGE_OFFSET; | ||
561 | |||
562 | q = (char *)initrd_start; | ||
563 | |||
564 | /* Copy any lowmem portion of the initrd */ | ||
565 | if (ramdisk_image < end_of_lowmem) { | ||
566 | clen = end_of_lowmem - ramdisk_image; | ||
567 | p = (char *)__va(ramdisk_image); | ||
568 | memcpy(q, p, clen); | ||
569 | q += clen; | ||
570 | ramdisk_image += clen; | ||
571 | ramdisk_size -= clen; | ||
572 | } | ||
573 | |||
574 | /* Copy the highmem portion of the initrd */ | ||
575 | while (ramdisk_size) { | ||
576 | slop = ramdisk_image & ~PAGE_MASK; | ||
577 | clen = ramdisk_size; | ||
578 | if (clen > MAX_MAP_CHUNK-slop) | ||
579 | clen = MAX_MAP_CHUNK-slop; | ||
580 | mapaddr = ramdisk_image & PAGE_MASK; | ||
581 | p = early_ioremap(mapaddr, clen+slop); | ||
582 | memcpy(q, p+slop, clen); | ||
583 | early_iounmap(p, clen+slop); | ||
584 | q += clen; | ||
585 | ramdisk_image += clen; | ||
586 | ramdisk_size -= clen; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
591 | |||
423 | void __init setup_bootmem_allocator(void) | 592 | void __init setup_bootmem_allocator(void) |
424 | { | 593 | { |
425 | unsigned long bootmap_size; | 594 | unsigned long bootmap_size; |
@@ -475,26 +644,10 @@ void __init setup_bootmem_allocator(void) | |||
475 | */ | 644 | */ |
476 | find_smp_config(); | 645 | find_smp_config(); |
477 | #endif | 646 | #endif |
478 | numa_kva_reserve(); | ||
479 | #ifdef CONFIG_BLK_DEV_INITRD | 647 | #ifdef CONFIG_BLK_DEV_INITRD |
480 | if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) { | 648 | reserve_initrd(); |
481 | unsigned long ramdisk_image = boot_params.hdr.ramdisk_image; | ||
482 | unsigned long ramdisk_size = boot_params.hdr.ramdisk_size; | ||
483 | unsigned long ramdisk_end = ramdisk_image + ramdisk_size; | ||
484 | unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT; | ||
485 | |||
486 | if (ramdisk_end <= end_of_lowmem) { | ||
487 | reserve_bootmem(ramdisk_image, ramdisk_size); | ||
488 | initrd_start = ramdisk_image + PAGE_OFFSET; | ||
489 | initrd_end = initrd_start+ramdisk_size; | ||
490 | } else { | ||
491 | printk(KERN_ERR "initrd extends beyond end of memory " | ||
492 | "(0x%08lx > 0x%08lx)\ndisabling initrd\n", | ||
493 | ramdisk_end, end_of_lowmem); | ||
494 | initrd_start = 0; | ||
495 | } | ||
496 | } | ||
497 | #endif | 649 | #endif |
650 | numa_kva_reserve(); | ||
498 | reserve_crashkernel(); | 651 | reserve_crashkernel(); |
499 | } | 652 | } |
500 | 653 | ||
@@ -545,17 +698,11 @@ void __init setup_arch(char **cmdline_p) | |||
545 | memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); | 698 | memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); |
546 | pre_setup_arch_hook(); | 699 | pre_setup_arch_hook(); |
547 | early_cpu_init(); | 700 | early_cpu_init(); |
701 | early_ioremap_init(); | ||
548 | 702 | ||
549 | /* | ||
550 | * FIXME: This isn't an official loader_type right | ||
551 | * now but does currently work with elilo. | ||
552 | * If we were configured as an EFI kernel, check to make | ||
553 | * sure that we were loaded correctly from elilo and that | ||
554 | * the system table is valid. If not, then initialize normally. | ||
555 | */ | ||
556 | #ifdef CONFIG_EFI | 703 | #ifdef CONFIG_EFI |
557 | if ((boot_params.hdr.type_of_loader == 0x50) && | 704 | if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, |
558 | boot_params.efi_info.efi_systab) | 705 | "EL32", 4)) |
559 | efi_enabled = 1; | 706 | efi_enabled = 1; |
560 | #endif | 707 | #endif |
561 | 708 | ||
@@ -579,12 +726,9 @@ void __init setup_arch(char **cmdline_p) | |||
579 | rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0); | 726 | rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0); |
580 | #endif | 727 | #endif |
581 | ARCH_SETUP | 728 | ARCH_SETUP |
582 | if (efi_enabled) | 729 | |
583 | efi_init(); | 730 | printk(KERN_INFO "BIOS-provided physical RAM map:\n"); |
584 | else { | 731 | print_memory_map(memory_setup()); |
585 | printk(KERN_INFO "BIOS-provided physical RAM map:\n"); | ||
586 | print_memory_map(memory_setup()); | ||
587 | } | ||
588 | 732 | ||
589 | copy_edd(); | 733 | copy_edd(); |
590 | 734 | ||
@@ -612,8 +756,16 @@ void __init setup_arch(char **cmdline_p) | |||
612 | strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); | 756 | strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); |
613 | *cmdline_p = command_line; | 757 | *cmdline_p = command_line; |
614 | 758 | ||
759 | if (efi_enabled) | ||
760 | efi_init(); | ||
761 | |||
615 | max_low_pfn = setup_memory(); | 762 | max_low_pfn = setup_memory(); |
616 | 763 | ||
764 | /* update e820 for memory not covered by WB MTRRs */ | ||
765 | mtrr_bp_init(); | ||
766 | if (mtrr_trim_uncached_memory(max_pfn)) | ||
767 | max_low_pfn = setup_memory(); | ||
768 | |||
617 | #ifdef CONFIG_VMI | 769 | #ifdef CONFIG_VMI |
618 | /* | 770 | /* |
619 | * Must be after max_low_pfn is determined, and before kernel | 771 | * Must be after max_low_pfn is determined, and before kernel |
@@ -636,6 +788,16 @@ void __init setup_arch(char **cmdline_p) | |||
636 | smp_alloc_memory(); /* AP processor realmode stacks in low memory*/ | 788 | smp_alloc_memory(); /* AP processor realmode stacks in low memory*/ |
637 | #endif | 789 | #endif |
638 | paging_init(); | 790 | paging_init(); |
791 | |||
792 | /* | ||
793 | * NOTE: On x86-32, only from this point on, fixmaps are ready for use. | ||
794 | */ | ||
795 | |||
796 | #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT | ||
797 | if (init_ohci1394_dma_early) | ||
798 | init_ohci1394_dma_on_all_controllers(); | ||
799 | #endif | ||
800 | |||
639 | remapped_pgdat_init(); | 801 | remapped_pgdat_init(); |
640 | sparse_init(); | 802 | sparse_init(); |
641 | zone_sizes_init(); | 803 | zone_sizes_init(); |
@@ -644,15 +806,19 @@ void __init setup_arch(char **cmdline_p) | |||
644 | * NOTE: at this point the bootmem allocator is fully available. | 806 | * NOTE: at this point the bootmem allocator is fully available. |
645 | */ | 807 | */ |
646 | 808 | ||
809 | #ifdef CONFIG_BLK_DEV_INITRD | ||
810 | relocate_initrd(); | ||
811 | #endif | ||
812 | |||
647 | paravirt_post_allocator_init(); | 813 | paravirt_post_allocator_init(); |
648 | 814 | ||
649 | dmi_scan_machine(); | 815 | dmi_scan_machine(); |
650 | 816 | ||
817 | io_delay_init(); | ||
818 | |||
651 | #ifdef CONFIG_X86_GENERICARCH | 819 | #ifdef CONFIG_X86_GENERICARCH |
652 | generic_apic_probe(); | 820 | generic_apic_probe(); |
653 | #endif | 821 | #endif |
654 | if (efi_enabled) | ||
655 | efi_map_memmap(); | ||
656 | 822 | ||
657 | #ifdef CONFIG_ACPI | 823 | #ifdef CONFIG_ACPI |
658 | /* | 824 | /* |
@@ -661,9 +827,7 @@ void __init setup_arch(char **cmdline_p) | |||
661 | acpi_boot_table_init(); | 827 | acpi_boot_table_init(); |
662 | #endif | 828 | #endif |
663 | 829 | ||
664 | #ifdef CONFIG_PCI | ||
665 | early_quirks(); | 830 | early_quirks(); |
666 | #endif | ||
667 | 831 | ||
668 | #ifdef CONFIG_ACPI | 832 | #ifdef CONFIG_ACPI |
669 | acpi_boot_init(); | 833 | acpi_boot_init(); |
@@ -692,3 +856,26 @@ void __init setup_arch(char **cmdline_p) | |||
692 | #endif | 856 | #endif |
693 | #endif | 857 | #endif |
694 | } | 858 | } |
859 | |||
860 | /* | ||
861 | * Request address space for all standard resources | ||
862 | * | ||
863 | * This is called just before pcibios_init(), which is also a | ||
864 | * subsys_initcall, but is linked in later (in arch/i386/pci/common.c). | ||
865 | */ | ||
866 | static int __init request_standard_resources(void) | ||
867 | { | ||
868 | int i; | ||
869 | |||
870 | printk(KERN_INFO "Setting up standard PCI resources\n"); | ||
871 | init_iomem_resources(&code_resource, &data_resource, &bss_resource); | ||
872 | |||
873 | request_resource(&iomem_resource, &video_ram_resource); | ||
874 | |||
875 | /* request I/O space for devices used on all i[345]86 PCs */ | ||
876 | for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++) | ||
877 | request_resource(&ioport_resource, &standard_io_resources[i]); | ||
878 | return 0; | ||
879 | } | ||
880 | |||
881 | subsys_initcall(request_standard_resources); | ||