]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/x86/kernel/setup_64.c
x86: add noclflush option
[linux-2.6-omap-h63xx.git] / arch / x86 / kernel / setup_64.c
index ce4d6b52ce36a92e57d47f4a105decce520417a6..cb9b8a90c094bd83da615880939017e64fa44c19 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/crash_dump.h>
 #include <linux/root_dev.h>
 #include <linux/pci.h>
+#include <linux/efi.h>
 #include <linux/acpi.h>
 #include <linux/kallsyms.h>
 #include <linux/edd.h>
 #include <linux/dmi.h>
 #include <linux/dma-mapping.h>
 #include <linux/ctype.h>
+#include <linux/uaccess.h>
 
 #include <asm/mtrr.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
+#include <asm/vsyscall.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/msr.h>
@@ -50,6 +53,7 @@
 #include <video/edid.h>
 #include <asm/e820.h>
 #include <asm/dma.h>
+#include <asm/gart.h>
 #include <asm/mpspec.h>
 #include <asm/mmu_context.h>
 #include <asm/proto.h>
 #include <asm/dmi.h>
 #include <asm/cacheflush.h>
 #include <asm/mce.h>
+#include <asm/ds.h>
+#include <asm/topology.h>
+
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
+#define ARCH_SETUP
+#endif
 
 /*
  * Machine setup..
@@ -68,6 +80,8 @@
 struct cpuinfo_x86 boot_cpu_data __read_mostly;
 EXPORT_SYMBOL(boot_cpu_data);
 
+__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
+
 unsigned long mmu_cr4_features;
 
 /* Boot loader ID as an integer, for the benefit of proc_dointvec */
@@ -233,29 +247,10 @@ static inline void __init reserve_crashkernel(void)
 {}
 #endif
 
-#define EBDA_ADDR_POINTER 0x40E
-
-unsigned __initdata ebda_addr;
-unsigned __initdata ebda_size;
-
-static void discover_ebda(void)
+/* Overridden in paravirt.c if CONFIG_PARAVIRT */
+void __attribute__((weak)) __init memory_setup(void)
 {
-       /*
-        * there is a real-mode segmented pointer pointing to the
-        * 4K EBDA area at 0x40E
-        */
-       ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER);
-       ebda_addr <<= 4;
-
-       ebda_size = *(unsigned short *)__va(ebda_addr);
-
-       /* Round EBDA up to pages */
-       if (ebda_size == 0)
-               ebda_size = 1;
-       ebda_size <<= 10;
-       ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE);
-       if (ebda_size > 64*1024)
-               ebda_size = 64*1024;
+       machine_specific_memory_setup();
 }
 
 void __init setup_arch(char **cmdline_p)
@@ -275,7 +270,15 @@ void __init setup_arch(char **cmdline_p)
        rd_prompt = ((boot_params.hdr.ram_size & RAMDISK_PROMPT_FLAG) != 0);
        rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0);
 #endif
-       setup_memory_region();
+#ifdef CONFIG_EFI
+       if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
+                    "EL64", 4))
+               efi_enabled = 1;
+#endif
+
+       ARCH_SETUP
+
+       memory_setup();
        copy_edd();
 
        if (!boot_params.hdr.root_flags)
@@ -301,27 +304,40 @@ void __init setup_arch(char **cmdline_p)
 
        finish_e820_parsing();
 
+       early_gart_iommu_check();
+
        e820_register_active_regions(0, 0, -1UL);
        /*
         * partially used pages are not usable - thus
         * we are rounding upwards:
         */
        end_pfn = e820_end_of_ram();
+       /* update e820 for memory not covered by WB MTRRs */
+       mtrr_bp_init();
+       if (mtrr_trim_uncached_memory(end_pfn)) {
+               e820_register_active_regions(0, 0, -1UL);
+               end_pfn = e820_end_of_ram();
+       }
+
        num_physpages = end_pfn;
 
        check_efer();
 
-       discover_ebda();
-
        init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
+       if (efi_enabled)
+               efi_init();
 
        dmi_scan_machine();
 
        io_delay_init();
 
 #ifdef CONFIG_SMP
-       /* setup to use the static apicid table during kernel startup */
-       x86_cpu_to_apicid_ptr = (void *)&x86_cpu_to_apicid_init;
+       /* setup to use the early static init tables during kernel startup */
+       x86_cpu_to_apicid_early_ptr = (void *)&x86_cpu_to_apicid_init;
+#ifdef CONFIG_NUMA
+       x86_cpu_to_node_map_early_ptr = (void *)&x86_cpu_to_node_map_init;
+#endif
+       x86_bios_cpu_apicid_early_ptr = (void *)&x86_bios_cpu_apicid_init;
 #endif
 
 #ifdef CONFIG_ACPI
@@ -353,33 +369,7 @@ void __init setup_arch(char **cmdline_p)
        contig_initmem_init(0, end_pfn);
 #endif
 
-       /* Reserve direct mapping */
-       reserve_bootmem_generic(table_start << PAGE_SHIFT,
-                               (table_end - table_start) << PAGE_SHIFT);
-
-       /* reserve kernel */
-       reserve_bootmem_generic(__pa_symbol(&_text),
-                               __pa_symbol(&_end) - __pa_symbol(&_text));
-
-       /*
-        * reserve physical page 0 - it's a special BIOS page on many boxes,
-        * enabling clean reboots, SMP operation, laptop functions.
-        */
-       reserve_bootmem_generic(0, PAGE_SIZE);
-
-       /* reserve ebda region */
-       if (ebda_addr)
-               reserve_bootmem_generic(ebda_addr, ebda_size);
-#ifdef CONFIG_NUMA
-       /* reserve nodemap region */
-       if (nodemap_addr)
-               reserve_bootmem_generic(nodemap_addr, nodemap_size);
-#endif
-
-#ifdef CONFIG_SMP
-       /* Reserve SMP trampoline */
-       reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, 2*PAGE_SIZE);
-#endif
+       early_res_to_bootmem();
 
 #ifdef CONFIG_ACPI_SLEEP
        /*
@@ -387,6 +377,12 @@ void __init setup_arch(char **cmdline_p)
         */
        acpi_reserve_bootmem();
 #endif
+
+       if (efi_enabled) {
+               efi_map_memmap();
+               efi_reserve_bootmem();
+       }
+
        /*
        * Find and reserve possible boot-time SMP configuration:
        */
@@ -403,6 +399,8 @@ void __init setup_arch(char **cmdline_p)
                        initrd_start = ramdisk_image + PAGE_OFFSET;
                        initrd_end = initrd_start+ramdisk_size;
                } else {
+                       /* Assumes everything on node 0 */
+                       free_bootmem(ramdisk_image, ramdisk_size);
                        printk(KERN_ERR "initrd extends beyond end of memory "
                               "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
                               ramdisk_end, end_of_mem);
@@ -412,6 +410,7 @@ void __init setup_arch(char **cmdline_p)
 #endif
        reserve_crashkernel();
        paging_init();
+       map_vsyscall();
 
        early_quirks();
 
@@ -452,7 +451,8 @@ void __init setup_arch(char **cmdline_p)
 
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
-       conswitchp = &vga_con;
+       if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
+               conswitchp = &vga_con;
 #elif defined(CONFIG_DUMMY_CONSOLE)
        conswitchp = &dummy_con;
 #endif
@@ -500,9 +500,6 @@ static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
                printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
                c->x86_cache_size, ecx & 0xFF);
        }
-
-       if (n >= 0x80000007)
-               cpuid(0x80000007, &dummy, &dummy, &dummy, &c->x86_power);
        if (n >= 0x80000008) {
                cpuid(0x80000008, &eax, &dummy, &dummy, &dummy);
                c->x86_virt_bits = (eax >> 8) & 0xff;
@@ -580,7 +577,7 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
 #endif
 }
 
-static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
+static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
        unsigned bits, ecx;
@@ -638,6 +635,15 @@ static __cpuinit int amd_apic_timer_broken(void)
        return 0;
 }
 
+static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
+{
+       early_init_amd_mc(c);
+
+       /* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */
+       if (c->x86_power & (1<<8))
+               set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+}
+
 static void __cpuinit init_amd(struct cpuinfo_x86 *c)
 {
        unsigned level;
@@ -687,10 +693,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
        }
        display_cacheinfo(c);
 
-       /* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */
-       if (c->x86_power & (1<<8))
-               set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
-
        /* Multi core CPU? */
        if (c->extended_cpuid_level >= 0x80000008)
                amd_detect_cmp(c);
@@ -704,18 +706,14 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
        if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x11)
                set_cpu_cap(c, X86_FEATURE_K8);
 
-       /* RDTSC can be speculated around */
-       clear_cpu_cap(c, X86_FEATURE_SYNC_RDTSC);
-
-       /* Family 10 doesn't support C states in MWAIT so don't use it */
-       if (c->x86 == 0x10 && !force_mwait)
-               clear_cpu_cap(c, X86_FEATURE_MWAIT);
+       /* MFENCE stops RDTSC speculation */
+       set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
 
        if (amd_apic_timer_broken())
                disable_apic_timer = 1;
 }
 
-static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+void __cpuinit detect_ht(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
        u32 eax, ebx, ecx, edx;
@@ -801,6 +799,13 @@ static void srat_detect_node(void)
 #endif
 }
 
+static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
+{
+       if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
+           (c->x86 == 0x6 && c->x86_model >= 0x0e))
+               set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
+}
+
 static void __cpuinit init_intel(struct cpuinfo_x86 *c)
 {
        /* Cache sizes */
@@ -823,6 +828,10 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
                        set_cpu_cap(c, X86_FEATURE_PEBS);
        }
 
+
+       if (cpu_has_bts)
+               ds_init_intel(c);
+
        n = c->extended_cpuid_level;
        if (n >= 0x80000008) {
                unsigned eax = cpuid_eax(0x80000008);
@@ -842,10 +851,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
                set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
        if (c->x86 == 6)
                set_cpu_cap(c, X86_FEATURE_REP_GOOD);
-       if (c->x86 == 15)
-               set_cpu_cap(c, X86_FEATURE_SYNC_RDTSC);
-       else
-               clear_cpu_cap(c, X86_FEATURE_SYNC_RDTSC);
+       set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
        c->x86_max_cores = intel_num_cpu_cores(c);
 
        srat_detect_node();
@@ -942,10 +948,17 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
                        c->x86_capability[2] = cpuid_edx(0x80860001);
        }
 
+       c->extended_cpuid_level = cpuid_eax(0x80000000);
+       if (c->extended_cpuid_level >= 0x80000007)
+               c->x86_power = cpuid_edx(0x80000007);
+
        switch (c->x86_vendor) {
        case X86_VENDOR_AMD:
                early_init_amd(c);
                break;
+       case X86_VENDOR_INTEL:
+               early_init_intel(c);
+               break;
        }
 
 }
@@ -988,7 +1001,6 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
                break;
        }
 
-       select_idle_routine(c);
        detect_ht(c);
 
        /*
@@ -1003,15 +1015,29 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
                        boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
        }
 
+       /* Clear all flags overriden by options */
+       for (i = 0; i < NCAPINTS; i++)
+               c->x86_capability[i] ^= cleared_cpu_caps[i];
+
 #ifdef CONFIG_X86_MCE
        mcheck_init(c);
 #endif
+       select_idle_routine(c);
+
        if (c != &boot_cpu_data)
                mtrr_ap_init();
 #ifdef CONFIG_NUMA
        numa_add_cpu(smp_processor_id());
 #endif
+
+}
+
+static __init int setup_noclflush(char *arg)
+{
+       setup_clear_cpu_cap(X86_FEATURE_CLFLSH);
+       return 1;
 }
+__setup("noclflush", setup_noclflush);
 
 void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
 {