[PATCH] x86_64: Dont use broadcast shortcut to make it cpu hotplug safe.
[powerpc.git] / arch / x86_64 / kernel / setup.c
index ef74564..ca9a915 100644 (file)
@@ -40,6 +40,8 @@
 #include <linux/acpi.h>
 #include <linux/kallsyms.h>
 #include <linux/edd.h>
+#include <linux/mmzone.h>
+
 #include <asm/mtrr.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -327,6 +329,10 @@ static __init void parse_cmdline_early (char ** cmdline_p)
                else if (!memcmp(from, "acpi=strict", 11)) {
                        acpi_strict = 1;
                }
+#ifdef CONFIG_X86_IO_APIC
+               else if (!memcmp(from, "acpi_skip_timer_override", 24))
+                       acpi_skip_timer_override = 1;
+#endif
 #endif
 
                if (!memcmp(from, "nolapic", 7) ||
@@ -344,7 +350,7 @@ static __init void parse_cmdline_early (char ** cmdline_p)
                if (!memcmp(from, "mem=", 4))
                        parse_memopt(from+4, &from); 
 
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
                if (!memcmp(from, "numa=", 5))
                        numa_setup(from+5); 
 #endif
@@ -373,17 +379,20 @@ static __init void parse_cmdline_early (char ** cmdline_p)
        *cmdline_p = command_line;
 }
 
-#ifndef CONFIG_DISCONTIGMEM
-static void __init contig_initmem_init(void)
+#ifndef CONFIG_NUMA
+static void __init
+contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
 {
-        unsigned long bootmap_size, bootmap; 
-        bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
-        bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size);
-        if (bootmap == -1L) 
-                panic("Cannot find bootmem map of size %ld\n",bootmap_size);
-        bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
-        e820_bootmem_free(&contig_page_data, 0, end_pfn << PAGE_SHIFT); 
-        reserve_bootmem(bootmap, bootmap_size);
+       unsigned long bootmap_size, bootmap;
+
+       memory_present(0, start_pfn, end_pfn);
+       bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
+       bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size);
+       if (bootmap == -1L)
+               panic("Cannot find bootmem map of size %ld\n",bootmap_size);
+       bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
+       e820_bootmem_free(NODE_DATA(0), 0, end_pfn << PAGE_SHIFT);
+       reserve_bootmem(bootmap, bootmap_size);
 } 
 #endif
 
@@ -550,10 +559,10 @@ void __init setup_arch(char **cmdline_p)
        acpi_numa_init();
 #endif
 
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
        numa_initmem_init(0, end_pfn); 
 #else
-       contig_initmem_init(); 
+       contig_initmem_init(0, end_pfn);
 #endif
 
        /* Reserve direct mapping */
@@ -614,6 +623,8 @@ void __init setup_arch(char **cmdline_p)
                }
        }
 #endif
+
+       sparse_init();
        paging_init();
 
        check_ioapic();
@@ -665,11 +676,11 @@ void __init setup_arch(char **cmdline_p)
 #endif
 }
 
-static int __init get_model_name(struct cpuinfo_x86 *c)
+static int __cpuinit get_model_name(struct cpuinfo_x86 *c)
 {
        unsigned int *v;
 
-       if (c->x86_cpuid_level < 0x80000004)
+       if (c->extended_cpuid_level < 0x80000004)
                return 0;
 
        v = (unsigned int *) c->x86_model_id;
@@ -681,11 +692,11 @@ static int __init get_model_name(struct cpuinfo_x86 *c)
 }
 
 
-static void __init display_cacheinfo(struct cpuinfo_x86 *c)
+static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
 {
        unsigned int n, dummy, eax, ebx, ecx, edx;
 
-       n = c->x86_cpuid_level;
+       n = c->extended_cpuid_level;
 
        if (n >= 0x80000005) {
                cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
@@ -715,14 +726,50 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c)
        }
 }
 
+/*
+ * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
+ * Assumes number of cores is a power of two.
+ */
+static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_SMP
+       int cpu = smp_processor_id();
+       int node = 0;
+       unsigned bits;
+       if (c->x86_num_cores == 1)
+               return;
+
+       bits = 0;
+       while ((1 << bits) < c->x86_num_cores)
+               bits++;
+
+       /* Low order bits define the core id (index of core in socket) */
+       cpu_core_id[cpu] = phys_proc_id[cpu] & ((1 << bits)-1);
+       /* Convert the APIC ID into the socket ID */
+       phys_proc_id[cpu] >>= bits;
+
+#ifdef CONFIG_NUMA
+       /* When an ACPI SRAT table is available use the mappings from SRAT
+          instead. */
+       if (acpi_numa <= 0) {
+               node = phys_proc_id[cpu];
+               if (!node_online(node))
+                       node = first_node(node_online_map);
+               cpu_to_node[cpu] = node;
+       } else {
+               node = cpu_to_node[cpu];
+       }
+#endif
+
+       printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
+                       cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
+#endif
+}
 
 static int __init init_amd(struct cpuinfo_x86 *c)
 {
        int r;
        int level;
-#ifdef CONFIG_NUMA
-       int cpu;
-#endif
 
        /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
           3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
@@ -745,39 +792,25 @@ static int __init init_amd(struct cpuinfo_x86 *c)
        } 
        display_cacheinfo(c);
 
-       if (c->x86_cpuid_level >= 0x80000008) {
+       if (c->extended_cpuid_level >= 0x80000008) {
                c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
                if (c->x86_num_cores & (c->x86_num_cores - 1))
                        c->x86_num_cores = 1;
 
-#ifdef CONFIG_NUMA
-               /* On a dual core setup the lower bits of apic id
-                  distingush the cores. Fix up the CPU<->node mappings
-                  here based on that.
-                  Assumes number of cores is a power of two.
-                  When using SRAT use mapping from SRAT. */
-               cpu = c->x86_apicid;
-               if (acpi_numa <= 0 && c->x86_num_cores > 1) {
-                       cpu_to_node[cpu] = cpu >> hweight32(c->x86_num_cores - 1);
-                       if (!node_online(cpu_to_node[cpu]))
-                               cpu_to_node[cpu] = first_node(node_online_map);
-               }
-               printk(KERN_INFO "CPU %d(%d) -> Node %d\n",
-                               cpu, c->x86_num_cores, cpu_to_node[cpu]);
-#endif
+               amd_detect_cmp(c);
        }
 
        return r;
 }
 
-static void __init detect_ht(struct cpuinfo_x86 *c)
+static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
        u32     eax, ebx, ecx, edx;
        int     index_msb, tmp;
        int     cpu = smp_processor_id();
        
-       if (!cpu_has(c, X86_FEATURE_HT))
+       if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
                return;
 
        cpuid(1, &eax, &ebx, &ecx, &edx);
@@ -828,23 +861,10 @@ static void __init detect_ht(struct cpuinfo_x86 *c)
 #endif
 }
 
-static void __init sched_cmp_hack(struct cpuinfo_x86 *c)
-{
-#ifdef CONFIG_SMP
-       /* AMD dual core looks like HT but isn't really. Hide it from the
-          scheduler. This works around problems with the domain scheduler.
-          Also probably gives slightly better scheduling and disables
-          SMT nice which is harmful on dual core.
-          TBD tune the domain scheduler for dual core. */
-       if (c->x86_vendor == X86_VENDOR_AMD && cpu_has(c, X86_FEATURE_CMP_LEGACY))
-               smp_num_siblings = 1;
-#endif
-}
-
 /*
  * find out the number of processor cores on the die
  */
-static int __init intel_num_cpu_cores(struct cpuinfo_x86 *c)
+static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c)
 {
        unsigned int eax;
 
@@ -862,13 +882,13 @@ static int __init intel_num_cpu_cores(struct cpuinfo_x86 *c)
                return 1;
 }
 
-static void __init init_intel(struct cpuinfo_x86 *c)
+static void __cpuinit init_intel(struct cpuinfo_x86 *c)
 {
        /* Cache sizes */
        unsigned n;
 
        init_intel_cacheinfo(c);
-       n = c->x86_cpuid_level;
+       n = c->extended_cpuid_level;
        if (n >= 0x80000008) {
                unsigned eax = cpuid_eax(0x80000008);
                c->x86_virt_bits = (eax >> 8) & 0xff;
@@ -882,7 +902,7 @@ static void __init init_intel(struct cpuinfo_x86 *c)
        c->x86_num_cores = intel_num_cpu_cores(c);
 }
 
-void __init get_cpu_vendor(struct cpuinfo_x86 *c)
+void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
 {
        char *v = c->x86_vendor_id;
 
@@ -903,7 +923,7 @@ struct cpu_model_info {
 /* Do some early cpuid on the boot CPU to get some parameter that are
    needed before check_bugs. Everything advanced is in identify_cpu
    below. */
-void __init early_identify_cpu(struct cpuinfo_x86 *c)
+void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
 {
        u32 tfms;
 
@@ -916,8 +936,7 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c)
        c->x86_clflush_size = 64;
        c->x86_cache_alignment = c->x86_clflush_size;
        c->x86_num_cores = 1;
-       c->x86_apicid = c == &boot_cpu_data ? 0 : c - cpu_data;
-       c->x86_cpuid_level = 0;
+       c->extended_cpuid_level = 0;
        memset(&c->x86_capability, 0, sizeof c->x86_capability);
 
        /* Get vendor name */
@@ -945,17 +964,20 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c)
                } 
                if (c->x86_capability[0] & (1<<19)) 
                        c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
-               c->x86_apicid = misc >> 24;
        } else {
                /* Have CPUID level 0 only - unheard of */
                c->x86 = 4;
        }
+
+#ifdef CONFIG_SMP
+       phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
+#endif
 }
 
 /*
  * This does the hard work of actually picking apart the CPU stuff...
  */
-void __init identify_cpu(struct cpuinfo_x86 *c)
+void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
 {
        int i;
        u32 xlvl;
@@ -964,11 +986,11 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
 
        /* AMD-defined flags: level 0x80000001 */
        xlvl = cpuid_eax(0x80000000);
-       c->x86_cpuid_level = xlvl;
+       c->extended_cpuid_level = xlvl;
        if ((xlvl & 0xffff0000) == 0x80000000) {
                if (xlvl >= 0x80000001) {
                        c->x86_capability[1] = cpuid_edx(0x80000001);
-                       c->x86_capability[5] = cpuid_ecx(0x80000001);
+                       c->x86_capability[6] = cpuid_ecx(0x80000001);
                }
                if (xlvl >= 0x80000004)
                        get_model_name(c); /* Default name */
@@ -1009,7 +1031,6 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
 
        select_idle_routine(c);
        detect_ht(c); 
-       sched_cmp_hack(c);
 
        /*
         * On SMP, boot_cpu_data holds the common feature set between
@@ -1033,7 +1054,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
 }
  
 
-void __init print_cpu_info(struct cpuinfo_x86 *c)
+void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
 {
        if (c->x86_model_id[0])
                printk("%s", c->x86_model_id);
@@ -1068,7 +1089,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL,
 
                /* AMD-defined */
-               "pni", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, "nx", NULL, "mmxext", NULL,
                NULL, "fxsr_opt", NULL, NULL, NULL, "lm", "3dnowext", "3dnow",
@@ -1080,7 +1101,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
                /* Other (Linux-defined) */
-               "cxmmx", NULL, "cyrix_arr", "centaur_mcr", "k8c+",
+               "cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL,
                "constant_tsc", NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -1092,11 +1113,17 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
+               /* VIA/Cyrix/Centaur-defined */
+               NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
+               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
                /* AMD-defined (#2) */
                "lahf_lm", "cmp_legacy", NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
        };
        static char *x86_power_flags[] = { 
                "ts",   /* temperature sensor */
@@ -1144,6 +1171,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                seq_printf(m, "physical id\t: %d\n", phys_proc_id[cpu]);
                seq_printf(m, "siblings\t: %d\n",
                                c->x86_num_cores * smp_num_siblings);
+               seq_printf(m, "core id\t\t: %d\n", cpu_core_id[cpu]);
+               seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores);
        }
 #endif 
 
@@ -1187,15 +1216,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                        }
        }
 
-       seq_printf(m, "\n");
+       seq_printf(m, "\n\n");
 
-#ifdef CONFIG_SMP
-       /* Put new fields at the end to lower the probability of
-          breaking user space parsers. */
-       seq_printf(m, "core id\t\t: %d\n", cpu_core_id[c - cpu_data]);
-       seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores);
-#endif
-       seq_printf(m, "\n");
        return 0;
 }