]> Pileus Git - ~andy/linux/blobdiff - arch/x86_64/kernel/setup.c
[PATCH] x86_64: Fix the additional_cpus=.. option
[~andy/linux] / arch / x86_64 / kernel / setup.c
index 750e01dcbdf49f364940c87f5ab6b4bc158d460a..5de7eaf5d97cd678025e520cb5d5b2a3041508b5 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/processor.h>
 #include <linux/console.h>
 #include <linux/seq_file.h>
+#include <linux/crash_dump.h>
 #include <linux/root_dev.h>
 #include <linux/pci.h>
 #include <linux/acpi.h>
@@ -42,6 +43,9 @@
 #include <linux/edd.h>
 #include <linux/mmzone.h>
 #include <linux/kexec.h>
+#include <linux/cpufreq.h>
+#include <linux/dmi.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/mtrr.h>
 #include <asm/uaccess.h>
@@ -60,7 +64,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>
 
 /*
  * Machine setup..
@@ -85,15 +91,9 @@ int bootloader_type;
 
 unsigned long saved_video_mode;
 
-#ifdef CONFIG_SWIOTLB
-int swiotlb;
-EXPORT_SYMBOL(swiotlb);
-#endif
-
 /*
  * Setup options
  */
-struct drive_info_struct { char dummy[32]; } drive_info;
 struct screen_info screen_info;
 struct sys_desc_table_struct {
        unsigned short length;
@@ -274,10 +274,7 @@ static __init void parse_cmdline_early (char ** cmdline_p)
 {
        char c = ' ', *to = command_line, *from = COMMAND_LINE;
        int len = 0;
-
-       /* Save unparsed command line copy for /proc/cmdline */
-       memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-       saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+       int userdef = 0;
 
        for (;;) {
                if (c != ' ') 
@@ -345,10 +342,14 @@ static __init void parse_cmdline_early (char ** cmdline_p)
                    !memcmp(from, "disableapic", 11))
                        disable_apic = 1;
 
-               if (!memcmp(from, "noapic", 6)) 
+               /* Don't confuse with noapictimer */
+               if (!memcmp(from, "noapic", 6) &&
+                       (from[6] == ' ' || from[6] == 0))
                        skip_ioapic_setup = 1;
 
-               if (!memcmp(from, "apic", 4)) { 
+               /* Make sure to not confuse with apic= */
+               if (!memcmp(from, "apic", 4) &&
+                       (from[4] == ' ' || from[4] == 0)) {
                        skip_ioapic_setup = 0;
                        ioapic_force = 1;
                }
@@ -356,16 +357,36 @@ static __init void parse_cmdline_early (char ** cmdline_p)
                if (!memcmp(from, "mem=", 4))
                        parse_memopt(from+4, &from); 
 
+               if (!memcmp(from, "memmap=", 7)) {
+                       /* exactmap option is for used defined memory */
+                       if (!memcmp(from+7, "exactmap", 8)) {
+#ifdef CONFIG_CRASH_DUMP
+                               /* If we are doing a crash dump, we
+                                * still need to know the real mem
+                                * size before original memory map is
+                                * reset.
+                                */
+                               saved_max_pfn = e820_end_of_ram();
+#endif
+                               from += 8+7;
+                               end_pfn_map = 0;
+                               e820.nr_map = 0;
+                               userdef = 1;
+                       }
+                       else {
+                               parse_memmapopt(from+7, &from);
+                               userdef = 1;
+                       }
+               }
+
 #ifdef CONFIG_NUMA
                if (!memcmp(from, "numa=", 5))
                        numa_setup(from+5); 
 #endif
 
-#ifdef CONFIG_GART_IOMMU 
                if (!memcmp(from,"iommu=",6)) { 
                        iommu_setup(from+6); 
                }
-#endif
 
                if (!memcmp(from,"oops=panic", 10))
                        panic_on_oops = 1;
@@ -394,6 +415,20 @@ static __init void parse_cmdline_early (char ** cmdline_p)
                }
 #endif
 
+#ifdef CONFIG_PROC_VMCORE
+               /* 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.
+                */
+               else if(!memcmp(from, "elfcorehdr=", 11))
+                       elfcorehdr_addr = memparse(from+11, &from);
+#endif
+
+#ifdef CONFIG_SMP
+               else if (!memcmp(from, "additional_cpus=", 16))
+                       setup_additional_cpus(from+16);
+#endif
+
        next_char:
                c = *(from++);
                if (!c)
@@ -402,6 +437,10 @@ static __init void parse_cmdline_early (char ** cmdline_p)
                        break;
                *(to++) = c;
        }
+       if (userdef) {
+               printk(KERN_INFO "user-defined physical RAM map:\n");
+               e820_print_map("user");
+       }
        *to = '\0';
        *cmdline_p = command_line;
 }
@@ -442,6 +481,8 @@ static unsigned char *k8_nops[ASM_NOP_MAX+1] = {
      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
@@ -453,11 +494,17 @@ 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); 
-               __inline_memcpy(a->instr, a->replacement, a->replacementlen); 
+               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 */
@@ -465,7 +512,7 @@ void apply_alternatives(void *start, void *end)
                        k = diff;
                        if (k > ASM_NOP_MAX)
                                k = ASM_NOP_MAX;
-                       __inline_memcpy(a->instr + i, k8_nops[k], k); 
+                       __inline_memcpy(instr + i, k8_nops[k], k);
                } 
        }
 } 
@@ -530,7 +577,6 @@ void __init setup_arch(char **cmdline_p)
        unsigned long kernel_end;
 
        ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
-       drive_info = DRIVE_INFO;
        screen_info = SCREEN_INFO;
        edid_info = EDID_INFO;
        saved_video_mode = SAVED_VIDEO_MODE;
@@ -669,6 +715,8 @@ void __init setup_arch(char **cmdline_p)
        acpi_boot_init();
 #endif
 
+       init_cpu_to_node();
+
 #ifdef CONFIG_X86_LOCAL_APIC
        /*
         * get boot-time SMP configuration:
@@ -697,7 +745,7 @@ void __init setup_arch(char **cmdline_p)
        e820_setup_gap();
 
 #ifdef CONFIG_GART_IOMMU
-       iommu_hole_init();
+       iommu_hole_init();
 #endif
 
 #ifdef CONFIG_VT
@@ -833,7 +881,7 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
 static int __init init_amd(struct cpuinfo_x86 *c)
 {
        int r;
-       int level;
+       unsigned level;
 
 #ifdef CONFIG_SMP
        unsigned long value;
@@ -856,10 +904,10 @@ static int __init init_amd(struct cpuinfo_x86 *c)
           3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
        clear_bit(0*32+31, &c->x86_capability);
        
-       /* C-stepping K8? */
+       /* On C+ stepping K8 rep microcode works well for copy/memset */
        level = cpuid_eax(1);
-       if ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
-               set_bit(X86_FEATURE_K8_C, &c->x86_capability);
+       if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58))
+               set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
 
        r = get_model_name(c);
        if (!r) { 
@@ -873,6 +921,10 @@ static int __init 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_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
+
        if (c->extended_cpuid_level >= 0x80000008) {
                c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
                if (c->x86_max_cores & (c->x86_max_cores - 1))
@@ -991,8 +1043,10 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
 
        if (c->x86 == 15)
                c->x86_cache_alignment = c->x86_clflush_size * 2;
-       if (c->x86 >= 15)
+       if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
+           (c->x86 == 0x6 && c->x86_model >= 0x0e))
                set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
+       set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
        c->x86_max_cores = intel_num_cpu_cores(c);
 
        srat_detect_node();
@@ -1191,7 +1245,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, NULL, NULL, "lm", "3dnowext", "3dnow",
+               NULL, "fxsr_opt", "rdtscp", NULL, NULL, "lm", "3dnowext", "3dnow",
 
                /* Transmeta-defined */
                "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
@@ -1219,7 +1273,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
                /* AMD-defined (#2) */
-               "lahf_lm", "cmp_legacy", NULL, NULL, NULL, NULL, NULL, NULL,
+               "lahf_lm", "cmp_legacy", "svm", NULL, "cr8_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,
@@ -1230,7 +1284,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                "vid",  /* voltage id control */
                "ttp",  /* thermal trip */
                "tm",
-               "stc"
+               "stc",
+               NULL,
+               /* nothing */   /* constant_tsc - moved to flags */
        };
 
 
@@ -1256,8 +1312,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                seq_printf(m, "stepping\t: unknown\n");
        
        if (cpu_has(c,X86_FEATURE_TSC)) {
+               unsigned int freq = cpufreq_quick_get((unsigned)(c-cpu_data));
+               if (!freq)
+                       freq = cpu_khz;
                seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
-                            cpu_khz / 1000, (cpu_khz % 1000));
+                            freq / 1000, (freq % 1000));
        }
 
        /* Cache size */
@@ -1307,8 +1366,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                unsigned i;
                for (i = 0; i < 32; i++) 
                        if (c->x86_power & (1 << i)) {
-                               if (i < ARRAY_SIZE(x86_power_flags))
-                                       seq_printf(m, " %s", x86_power_flags[i]);
+                               if (i < ARRAY_SIZE(x86_power_flags) &&
+                                       x86_power_flags[i])
+                                       seq_printf(m, "%s%s",
+                                               x86_power_flags[i][0]?" ":"",
+                                               x86_power_flags[i]);
                                else
                                        seq_printf(m, " [%d]", i);
                        }
@@ -1340,3 +1402,11 @@ struct seq_operations cpuinfo_op = {
        .stop = c_stop,
        .show = show_cpuinfo,
 };
+
+static int __init run_dmi_scan(void)
+{
+       dmi_scan_machine();
+       return 0;
+}
+core_initcall(run_dmi_scan);
+