Revert to Fedora kernel-2.6.17-1.2187_FC5 patched with vs2.0.2.1; there are too many...
[linux-2.6.git] / arch / x86_64 / kernel / setup.c
index 40a74d4..e8d5f84 100644 (file)
@@ -5,6 +5,8 @@
  *
  *  Nov 2001 Dave Jones <davej@suse.de>
  *  Forked from i386 setup code.
+ *
+ *  $Id$
  */
 
 /*
 #include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
-#include <linux/screen_info.h>
+#include <linux/tty.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/initrd.h>
 #include <linux/highmem.h>
@@ -62,7 +65,9 @@
 #include <asm/setup.h>
 #include <asm/mach_apic.h>
 #include <asm/numa.h>
+#include <asm/swiotlb.h>
 #include <asm/sections.h>
+#include <asm/gart-mapping.h>
 #include <asm/dmi.h>
 
 /*
@@ -70,7 +75,6 @@
  */
 
 struct cpuinfo_x86 boot_cpu_data __read_mostly;
-EXPORT_SYMBOL(boot_cpu_data);
 
 unsigned long mmu_cr4_features;
 
@@ -99,14 +103,12 @@ char dmi_alloc_data[DMI_MAX_DATA];
  * Setup options
  */
 struct screen_info screen_info;
-EXPORT_SYMBOL(screen_info);
 struct sys_desc_table_struct {
        unsigned short length;
        unsigned char table[0];
 };
 
 struct edid_info edid_info;
-EXPORT_SYMBOL_GPL(edid_info);
 struct e820map e820;
 
 extern int root_mountflags;
@@ -471,6 +473,80 @@ contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
 } 
 #endif
 
+/* Use inline assembly to define this because the nops are defined 
+   as inline assembly strings in the include files and we cannot 
+   get them easily into strings. */
+asm("\t.data\nk8nops: " 
+    K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6
+    K8_NOP7 K8_NOP8); 
+    
+extern unsigned char k8nops[];
+static unsigned char *k8_nops[ASM_NOP_MAX+1] = { 
+     NULL,
+     k8nops,
+     k8nops + 1,
+     k8nops + 1 + 2,
+     k8nops + 1 + 2 + 3,
+     k8nops + 1 + 2 + 3 + 4,
+     k8nops + 1 + 2 + 3 + 4 + 5,
+     k8nops + 1 + 2 + 3 + 4 + 5 + 6,
+     k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+}; 
+
+extern char __vsyscall_0;
+
+/* Replace instructions with better alternatives for this CPU type.
+
+   This runs before SMP is initialized to avoid SMP problems with
+   self modifying code. This implies that assymetric systems where
+   APs have less capabilities than the boot processor are not handled. 
+   In this case boot with "noreplacement". */ 
+void apply_alternatives(void *start, void *end) 
+{ 
+       struct alt_instr *a; 
+       int diff, i, k;
+       for (a = start; (void *)a < end; a++) { 
+               u8 *instr;
+
+               if (!boot_cpu_has(a->cpuid))
+                       continue;
+
+               BUG_ON(a->replacementlen > a->instrlen); 
+               instr = a->instr;
+               /* vsyscall code is not mapped yet. resolve it manually. */
+               if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END)
+                       instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0));
+               __inline_memcpy(instr, a->replacement, a->replacementlen);
+               diff = a->instrlen - a->replacementlen; 
+
+               /* Pad the rest with nops */
+               for (i = a->replacementlen; diff > 0; diff -= k, i += k) {
+                       k = diff;
+                       if (k > ASM_NOP_MAX)
+                               k = ASM_NOP_MAX;
+                       __inline_memcpy(instr + i, k8_nops[k], k);
+               } 
+       }
+} 
+
+static int no_replacement __initdata = 0; 
+void __init alternative_instructions(void)
+{
+       extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
+       if (no_replacement) 
+               return;
+       apply_alternatives(__alt_instructions, __alt_instructions_end);
+}
+
+static int __init noreplacement_setup(char *s)
+{ 
+     no_replacement = 1; 
+     return 1;
+} 
+
+__setup("noreplacement", noreplacement_setup); 
+
 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
 struct edd edd;
 #ifdef CONFIG_EDD_MODULE
@@ -521,6 +597,8 @@ static void discover_ebda(void)
 
 void __init setup_arch(char **cmdline_p)
 {
+       unsigned long kernel_end;
+
        ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
        screen_info = SCREEN_INFO;
        edid_info = EDID_INFO;
@@ -594,8 +672,8 @@ void __init setup_arch(char **cmdline_p)
                                (table_end - table_start) << PAGE_SHIFT);
 
        /* reserve kernel */
-       reserve_bootmem_generic(__pa_symbol(&_text),
-                               __pa_symbol(&_end) - __pa_symbol(&_text));
+       kernel_end = round_up(__pa_symbol(&_end),PAGE_SIZE);
+       reserve_bootmem_generic(HIGH_MEMORY, kernel_end - HIGH_MEMORY);
 
        /*
         * reserve physical page 0 - it's a special BIOS page on many boxes,
@@ -650,7 +728,7 @@ void __init setup_arch(char **cmdline_p)
 #endif
 #ifdef CONFIG_KEXEC
        if (crashk_res.start != crashk_res.end) {
-               reserve_bootmem_generic(crashk_res.start,
+               reserve_bootmem(crashk_res.start,
                        crashk_res.end - crashk_res.start + 1);
        }
 #endif
@@ -689,7 +767,6 @@ void __init setup_arch(char **cmdline_p)
         */
        probe_roms();
        e820_reserve_resources(); 
-       e820_mark_nosave_regions();
 
        request_resource(&iomem_resource, &video_ram_resource);
 
@@ -702,6 +779,10 @@ void __init setup_arch(char **cmdline_p)
 
        e820_setup_gap();
 
+#ifdef CONFIG_GART_IOMMU
+       iommu_hole_init();
+#endif
+
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
        conswitchp = &vga_con;
@@ -786,32 +867,24 @@ static int nearby_node(int apicid)
 static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
+       int cpu = smp_processor_id();
        unsigned bits;
 #ifdef CONFIG_NUMA
-       int cpu = smp_processor_id();
        int node = 0;
        unsigned apicid = hard_smp_processor_id();
 #endif
-       unsigned ecx = cpuid_ecx(0x80000008);
 
-       c->x86_max_cores = (ecx & 0xff) + 1;
-
-       /* CPU telling us the core id bits shift? */
-       bits = (ecx >> 12) & 0xF;
-
-       /* Otherwise recompute */
-       if (bits == 0) {
-               while ((1 << bits) < c->x86_max_cores)
-                       bits++;
-       }
+       bits = 0;
+       while ((1 << bits) < c->x86_max_cores)
+               bits++;
 
        /* Low order bits define the core id (index of core in socket) */
-       c->cpu_core_id = c->phys_proc_id & ((1 << bits)-1);
+       cpu_core_id[cpu] = phys_proc_id[cpu] & ((1 << bits)-1);
        /* Convert the APIC ID into the socket ID */
-       c->phys_proc_id = phys_pkg_id(bits);
+       phys_proc_id[cpu] = phys_pkg_id(bits);
 
 #ifdef CONFIG_NUMA
-       node = c->phys_proc_id;
+       node = phys_proc_id[cpu];
        if (apicid_to_node[apicid] != NUMA_NO_NODE)
                node = apicid_to_node[apicid];
        if (!node_online(node)) {
@@ -824,7 +897,7 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
                   but in the same order as the HT nodeids.
                   If that doesn't result in a usable node fall back to the
                   path for the previous case.  */
-               int ht_nodeid = apicid - (cpu_data[0].phys_proc_id << bits);
+               int ht_nodeid = apicid - (phys_proc_id[0] << bits);
                if (ht_nodeid >= 0 &&
                    apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
                        node = apicid_to_node[ht_nodeid];
@@ -834,13 +907,15 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
        }
        numa_set_node(cpu, node);
 
-       printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
+       printk(KERN_INFO "CPU %d/%x(%d) -> Node %d -> Core %d\n",
+                       cpu, apicid, c->x86_max_cores, node, cpu_core_id[cpu]);
 #endif
 #endif
 }
 
-static void __init init_amd(struct cpuinfo_x86 *c)
+static int __init init_amd(struct cpuinfo_x86 *c)
 {
+       int r;
        unsigned level;
 
 #ifdef CONFIG_SMP
@@ -873,8 +948,8 @@ static void __init init_amd(struct cpuinfo_x86 *c)
        if (c->x86 >= 6)
                set_bit(X86_FEATURE_FXSAVE_LEAK, &c->x86_capability);
 
-       level = get_model_name(c);
-       if (!level) {
+       r = get_model_name(c);
+       if (!r) { 
                switch (c->x86) { 
                case 15:
                        /* Should distinguish Models here, but this is only
@@ -889,12 +964,13 @@ static void __init init_amd(struct cpuinfo_x86 *c)
        if (c->x86_power & (1<<8))
                set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
 
-       /* Multi core CPU? */
-       if (c->extended_cpuid_level >= 0x80000008)
+       if (c->extended_cpuid_level >= 0x80000008) {
+               c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
+
                amd_detect_cmp(c);
+       }
 
-       /* Fix cpuid4 emulation for more */
-       num_cache_leaves = 3;
+       return r;
 }
 
 static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
@@ -902,14 +978,13 @@ static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
 #ifdef CONFIG_SMP
        u32     eax, ebx, ecx, edx;
        int     index_msb, core_bits;
+       int     cpu = smp_processor_id();
 
        cpuid(1, &eax, &ebx, &ecx, &edx);
 
 
-       if (!cpu_has(c, X86_FEATURE_HT))
+       if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
                return;
-       if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
-               goto out;
 
        smp_num_siblings = (ebx & 0xff0000) >> 16;
 
@@ -924,7 +999,10 @@ static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
                }
 
                index_msb = get_count_order(smp_num_siblings);
-               c->phys_proc_id = phys_pkg_id(index_msb);
+               phys_proc_id[cpu] = phys_pkg_id(index_msb);
+
+               printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
+                      phys_proc_id[cpu]);
 
                smp_num_siblings = smp_num_siblings / c->x86_max_cores;
 
@@ -932,15 +1010,13 @@ static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
 
                core_bits = get_count_order(c->x86_max_cores);
 
-               c->cpu_core_id = phys_pkg_id(index_msb) &
+               cpu_core_id[cpu] = phys_pkg_id(index_msb) &
                                               ((1 << core_bits) - 1);
-       }
-out:
-       if ((c->x86_max_cores * smp_num_siblings) > 1) {
-               printk(KERN_INFO  "CPU: Physical Processor ID: %d\n", c->phys_proc_id);
-               printk(KERN_INFO  "CPU: Processor Core ID: %d\n", c->cpu_core_id);
-       }
 
+               if (c->x86_max_cores > 1)
+                       printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
+                              cpu_core_id[cpu]);
+       }
 #endif
 }
 
@@ -949,12 +1025,15 @@ out:
  */
 static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c)
 {
-       unsigned int eax, t;
+       unsigned int eax;
 
        if (c->cpuid_level < 4)
                return 1;
 
-       cpuid_count(4, 0, &eax, &t, &t, &t);
+       __asm__("cpuid"
+               : "=a" (eax)
+               : "0" (4), "c" (0)
+               : "bx", "dx");
 
        if (eax & 0x1f)
                return ((eax >> 26) + 1);
@@ -967,17 +1046,16 @@ static void srat_detect_node(void)
 #ifdef CONFIG_NUMA
        unsigned node;
        int cpu = smp_processor_id();
-       int apicid = hard_smp_processor_id();
 
        /* Don't do the funky fallback heuristics the AMD version employs
           for now. */
-       node = apicid_to_node[apicid];
+       node = apicid_to_node[hard_smp_processor_id()];
        if (node == NUMA_NO_NODE)
                node = first_node(node_online_map);
        numa_set_node(cpu, node);
 
        if (acpi_numa > 0)
-               printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
+               printk(KERN_INFO "CPU %d -> Node %d\n", cpu, node);
 #endif
 }
 
@@ -987,13 +1065,6 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
        unsigned n;
 
        init_intel_cacheinfo(c);
-       if (c->cpuid_level > 9 ) {
-               unsigned eax = cpuid_eax(10);
-               /* Check for version and the number of counters */
-               if ((eax & 0xff) && (((eax>>8) & 0xff) > 1))
-                       set_bit(X86_FEATURE_ARCH_PERFMON, &c->x86_capability);
-       }
-
        n = c->extended_cpuid_level;
        if (n >= 0x80000008) {
                unsigned eax = cpuid_eax(0x80000008);
@@ -1011,10 +1082,7 @@ static void __cpuinit 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);
-       if (c->x86 == 15)
-               set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
-       else
-               clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
+       set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
        c->x86_max_cores = intel_num_cpu_cores(c);
 
        srat_detect_node();
@@ -1088,7 +1156,7 @@ void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
        }
 
 #ifdef CONFIG_SMP
-       c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
+       phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
 #endif
 }
 
@@ -1215,7 +1283,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                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, "rdtscp", NULL, "lm", "3dnowext", "3dnow",
+               NULL, "fxsr_opt", "rdtscp", NULL, NULL, "lm", "3dnowext", "3dnow",
 
                /* Transmeta-defined */
                "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
@@ -1226,7 +1294,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                /* Other (Linux-defined) */
                "cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL,
                "constant_tsc", NULL, NULL,
-               "up", 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,
 
@@ -1296,9 +1364,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 #ifdef CONFIG_SMP
        if (smp_num_siblings * c->x86_max_cores > 1) {
                int cpu = c - cpu_data;
-               seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
+               seq_printf(m, "physical id\t: %d\n", phys_proc_id[cpu]);
                seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[cpu]));
-               seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
+               seq_printf(m, "core id\t\t: %d\n", cpu_core_id[cpu]);
                seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
        }
 #endif