Merge branch 'x86/urgent' into x86/mm
[safe/jmp/linux-2.6] / arch / x86 / kernel / setup.c
index 59f07e1..b746deb 100644 (file)
 #include <asm/e820.h>
 #include <asm/mpspec.h>
 #include <asm/setup.h>
-#include <asm/arch_hooks.h>
 #include <asm/efi.h>
+#include <asm/timer.h>
+#include <asm/i8259.h>
 #include <asm/sections.h>
 #include <asm/dmi.h>
 #include <asm/io_apic.h>
 #include <asm/ist.h>
 #include <asm/vmi.h>
-#include <setup_arch.h>
+#include <asm/setup_arch.h>
 #include <asm/bios_ebda.h>
 #include <asm/cacheflush.h>
 #include <asm/processor.h>
 
 #include <asm/system.h>
 #include <asm/vsyscall.h>
-#include <asm/smp.h>
+#include <asm/cpu.h>
 #include <asm/desc.h>
 #include <asm/dma.h>
 #include <asm/iommu.h>
+#include <asm/gart.h>
 #include <asm/mmu_context.h>
 #include <asm/proto.h>
 
-#include <mach_apic.h>
 #include <asm/paravirt.h>
+#include <asm/hypervisor.h>
 
 #include <asm/percpu.h>
 #include <asm/topology.h>
 #define ARCH_SETUP
 #endif
 
+unsigned int boot_cpu_id __read_mostly;
+
+#ifdef CONFIG_X86_64
+int default_cpu_present_to_apicid(int mps_cpu)
+{
+       return __default_cpu_present_to_apicid(mps_cpu);
+}
+
+int default_check_phys_apicid_present(int boot_cpu_physical_apicid)
+{
+       return __default_check_phys_apicid_present(boot_cpu_physical_apicid);
+}
+#endif
+
 #ifndef CONFIG_DEBUG_BOOT_PARAMS
 struct boot_params __initdata boot_params;
 #else
@@ -223,6 +239,9 @@ unsigned long saved_video_mode;
 #define RAMDISK_LOAD_FLAG              0x4000
 
 static char __initdata command_line[COMMAND_LINE_SIZE];
+#ifdef CONFIG_CMDLINE_BOOL
+static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
+#endif
 
 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
 struct edd edd;
@@ -299,7 +318,7 @@ static void __init relocate_initrd(void)
                if (clen > MAX_MAP_CHUNK-slop)
                        clen = MAX_MAP_CHUNK-slop;
                mapaddr = ramdisk_image & PAGE_MASK;
-               p = early_ioremap(mapaddr, clen+slop);
+               p = early_memremap(mapaddr, clen+slop);
                memcpy(q, p+slop, clen);
                early_iounmap(p, clen+slop);
                q += clen;
@@ -376,7 +395,7 @@ static void __init parse_setup_data(void)
                return;
        pa_data = boot_params.hdr.setup_data;
        while (pa_data) {
-               data = early_ioremap(pa_data, PAGE_SIZE);
+               data = early_memremap(pa_data, PAGE_SIZE);
                switch (data->type) {
                case SETUP_E820_EXT:
                        parse_e820_ext(data, pa_data);
@@ -399,7 +418,7 @@ static void __init e820_reserve_setup_data(void)
                return;
        pa_data = boot_params.hdr.setup_data;
        while (pa_data) {
-               data = early_ioremap(pa_data, sizeof(*data));
+               data = early_memremap(pa_data, sizeof(*data));
                e820_update_range(pa_data, sizeof(*data)+data->len,
                         E820_RAM, E820_RESERVED_KERN);
                found = 1;
@@ -425,7 +444,7 @@ static void __init reserve_early_setup_data(void)
                return;
        pa_data = boot_params.hdr.setup_data;
        while (pa_data) {
-               data = early_ioremap(pa_data, sizeof(*data));
+               data = early_memremap(pa_data, sizeof(*data));
                sprintf(buf, "setup data %x", data->type);
                reserve_early(pa_data, pa_data+sizeof(*data)+data->len, buf);
                pa_data = data->next;
@@ -445,7 +464,8 @@ static void __init reserve_early_setup_data(void)
  * @size: Size of the crashkernel memory to reserve.
  * Returns the base address on success, and -1ULL on failure.
  */
-unsigned long long find_and_reserve_crashkernel(unsigned long long size)
+static
+unsigned long long __init find_and_reserve_crashkernel(unsigned long long size)
 {
        const unsigned long long alignment = 16<<20;    /* 16M */
        unsigned long long start = 0LL;
@@ -558,7 +578,13 @@ static void __init reserve_standard_io_resources(void)
 
 }
 
-#ifdef CONFIG_PROC_VMCORE
+/*
+ * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by
+ * is_kdump_kernel() to determine if we are booting after a panic. Hence
+ * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE.
+ */
+
+#ifdef CONFIG_CRASH_DUMP
 /* elfcorehdr= specifies the location of elf core header
  * stored by the crashed kernel. This option will be passed
  * by kexec loader to the capture kernel.
@@ -578,6 +604,41 @@ static struct x86_quirks default_x86_quirks __initdata;
 
 struct x86_quirks *x86_quirks __initdata = &default_x86_quirks;
 
+#ifdef CONFIG_X86_RESERVE_LOW_64K
+static int __init dmi_low_memory_corruption(const struct dmi_system_id *d)
+{
+       printk(KERN_NOTICE
+               "%s detected: BIOS may corrupt low RAM, working around it.\n",
+               d->ident);
+
+       e820_update_range(0, 0x10000, E820_RAM, E820_RESERVED);
+       sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
+
+       return 0;
+}
+#endif
+
+/* List of systems that have known low memory corruption BIOS problems */
+static struct dmi_system_id __initdata bad_bios_dmi_table[] = {
+#ifdef CONFIG_X86_RESERVE_LOW_64K
+       {
+               .callback = dmi_low_memory_corruption,
+               .ident = "AMI BIOS",
+               .matches = {
+                       DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
+               },
+       },
+       {
+               .callback = dmi_low_memory_corruption,
+               .ident = "Phoenix BIOS",
+               .matches = {
+                       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies"),
+               },
+       },
+#endif
+       {}
+};
+
 /*
  * Determine if we were loaded by an EFI loader.  If so, then we have also been
  * passed the efi memmap, systab, etc., so we should use these data structures
@@ -596,22 +657,16 @@ void __init setup_arch(char **cmdline_p)
 #ifdef CONFIG_X86_32
        memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
        visws_early_detect();
-       pre_setup_arch_hook();
 #else
        printk(KERN_INFO "Command line: %s\n", boot_command_line);
 #endif
 
+       /* VMI may relocate the fixmap; do this before touching ioremap area */
+       vmi_init();
+
        early_cpu_init();
        early_ioremap_init();
 
-#if defined(CONFIG_VMI) && defined(CONFIG_X86_32)
-       /*
-        * Must be before kernel pagetables are setup
-        * or fixmap area is touched.
-        */
-       vmi_init();
-#endif
-
        ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev);
        screen_info = boot_params.screen_info;
        edid_info = boot_params.edid_info;
@@ -673,11 +728,31 @@ void __init setup_arch(char **cmdline_p)
        bss_resource.start = virt_to_phys(&__bss_start);
        bss_resource.end = virt_to_phys(&__bss_stop)-1;
 
+#ifdef CONFIG_CMDLINE_BOOL
+#ifdef CONFIG_CMDLINE_OVERRIDE
+       strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
+#else
+       if (builtin_cmdline[0]) {
+               /* append boot loader cmdline to builtin */
+               strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE);
+               strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE);
+               strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
+       }
+#endif
+#endif
+
        strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
        *cmdline_p = command_line;
 
        parse_early_param();
 
+#ifdef CONFIG_X86_64
+       check_efer();
+#endif
+
+       /* Must be before kernel pagetables are setup */
+       vmi_activate();
+
        /* after early param, so could get panic from serial */
        reserve_early_setup_data();
 
@@ -695,6 +770,19 @@ void __init setup_arch(char **cmdline_p)
 
        finish_e820_parsing();
 
+       if (efi_enabled)
+               efi_init();
+
+       dmi_scan_machine();
+
+       dmi_check_system(bad_bios_dmi_table);
+
+       /*
+        * VMware detection requires dmi to be available, so this
+        * needs to be done after dmi_scan_machine, for the BP.
+        */
+       init_hypervisor(&boot_cpu_data);
+
 #ifdef CONFIG_X86_32
        probe_roms();
 #endif
@@ -704,8 +792,6 @@ void __init setup_arch(char **cmdline_p)
        insert_resource(&iomem_resource, &data_resource);
        insert_resource(&iomem_resource, &bss_resource);
 
-       if (efi_enabled)
-               efi_init();
 
 #ifdef CONFIG_X86_32
        if (ppro_with_ram_bug()) {
@@ -738,9 +824,7 @@ void __init setup_arch(char **cmdline_p)
 #else
        num_physpages = max_pfn;
 
-       check_efer();
-       if (cpu_has_x2apic)
-               check_x2apic();
+       check_x2apic();
 
        /* How many end-of-memory variables you have, grandma! */
        /* need this before calling reserve_initrd */
@@ -752,6 +836,10 @@ void __init setup_arch(char **cmdline_p)
        high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
 #endif
 
+#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
+       setup_bios_corruption_check();
+#endif
+
        /* max_pfn_mapped is updated here */
        max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT);
        max_pfn_mapped = max_low_pfn_mapped;
@@ -776,11 +864,7 @@ void __init setup_arch(char **cmdline_p)
 
        reserve_initrd();
 
-#ifdef CONFIG_X86_64
        vsmp_init();
-#endif
-
-       dmi_scan_machine();
 
        io_delay_init();
 
@@ -789,6 +873,8 @@ void __init setup_arch(char **cmdline_p)
         */
        acpi_boot_table_init();
 
+       early_acpi_boot_init();
+
 #ifdef CONFIG_ACPI_NUMA
        /*
         * Parse SRAT to discover nodes.
@@ -804,12 +890,11 @@ void __init setup_arch(char **cmdline_p)
         */
        acpi_reserve_bootmem();
 #endif
-#ifdef CONFIG_X86_FIND_SMP_CONFIG
        /*
         * Find and reserve possible boot-time SMP configuration:
         */
        find_smp_config();
-#endif
+
        reserve_crashkernel();
 
 #ifdef CONFIG_X86_64
@@ -836,9 +921,7 @@ void __init setup_arch(char **cmdline_p)
        map_vsyscall();
 #endif
 
-#ifdef CONFIG_X86_GENERICARCH
        generic_apic_probe();
-#endif
 
        early_quirks();
 
@@ -856,6 +939,7 @@ void __init setup_arch(char **cmdline_p)
 #endif
 
        prefill_possible_map();
+
 #ifdef CONFIG_X86_64
        init_cpu_to_node();
 #endif
@@ -863,6 +947,9 @@ void __init setup_arch(char **cmdline_p)
        init_apic_mappings();
        ioapic_init_mappings();
 
+       /* need to wait for io_apic is mapped */
+       probe_nr_irqs_gsi();
+
        kvm_guest_init();
 
        e820_reserve_resources();
@@ -884,3 +971,96 @@ void __init setup_arch(char **cmdline_p)
 #endif
 #endif
 }
+
+#ifdef CONFIG_X86_32
+
+/**
+ * x86_quirk_pre_intr_init - initialisation prior to setting up interrupt vectors
+ *
+ * Description:
+ *     Perform any necessary interrupt initialisation prior to setting up
+ *     the "ordinary" interrupt call gates.  For legacy reasons, the ISA
+ *     interrupts should be initialised here if the machine emulates a PC
+ *     in any way.
+ **/
+void __init x86_quirk_pre_intr_init(void)
+{
+       if (x86_quirks->arch_pre_intr_init) {
+               if (x86_quirks->arch_pre_intr_init())
+                       return;
+       }
+       init_ISA_irqs();
+}
+
+/**
+ * x86_quirk_intr_init - post gate setup interrupt initialisation
+ *
+ * Description:
+ *     Fill in any interrupts that may have been left out by the general
+ *     init_IRQ() routine.  interrupts having to do with the machine rather
+ *     than the devices on the I/O bus (like APIC interrupts in intel MP
+ *     systems) are started here.
+ **/
+void __init x86_quirk_intr_init(void)
+{
+       if (x86_quirks->arch_intr_init) {
+               if (x86_quirks->arch_intr_init())
+                       return;
+       }
+}
+
+/**
+ * x86_quirk_trap_init - initialise system specific traps
+ *
+ * Description:
+ *     Called as the final act of trap_init().  Used in VISWS to initialise
+ *     the various board specific APIC traps.
+ **/
+void __init x86_quirk_trap_init(void)
+{
+       if (x86_quirks->arch_trap_init) {
+               if (x86_quirks->arch_trap_init())
+                       return;
+       }
+}
+
+static struct irqaction irq0  = {
+       .handler = timer_interrupt,
+       .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,
+       .mask = CPU_MASK_NONE,
+       .name = "timer"
+};
+
+/**
+ * x86_quirk_pre_time_init - do any specific initialisations before.
+ *
+ **/
+void __init x86_quirk_pre_time_init(void)
+{
+       if (x86_quirks->arch_pre_time_init)
+               x86_quirks->arch_pre_time_init();
+}
+
+/**
+ * x86_quirk_time_init - do any specific initialisations for the system timer.
+ *
+ * Description:
+ *     Must plug the system timer interrupt source at HZ into the IRQ listed
+ *     in irq_vectors.h:TIMER_IRQ
+ **/
+void __init x86_quirk_time_init(void)
+{
+       if (x86_quirks->arch_time_init) {
+               /*
+                * A nonzero return code does not mean failure, it means
+                * that the architecture quirk does not want any
+                * generic (timer) setup to be performed after this:
+                */
+               if (x86_quirks->arch_time_init())
+                       return;
+       }
+
+       irq0.mask = cpumask_of_cpu(0);
+       setup_irq(0, &irq0);
+}
+#endif /* CONFIG_X86_32 */