]> Pileus Git - ~andy/linux/blobdiff - arch/x86/kernel/setup_64.c
x86: move x86_64 gdt closer to i386
[~andy/linux] / arch / x86 / kernel / setup_64.c
index c4e6a0b6c30394b73e83caf2a4ba01cc754d622d..a93300de4da96411a1dbbc046189008e0b96dd1a 100644 (file)
@@ -56,6 +56,7 @@
 #include <asm/desc.h>
 #include <video/edid.h>
 #include <asm/e820.h>
+#include <asm/mpspec.h>
 #include <asm/dma.h>
 #include <asm/gart.h>
 #include <asm/mpspec.h>
@@ -117,7 +118,7 @@ EXPORT_SYMBOL_GPL(edid_info);
 
 extern int root_mountflags;
 
-char __initdata command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
 
 static struct resource standard_io_resources[] = {
        { .name = "dma1", .start = 0x00, .end = 0x1f,
@@ -163,6 +164,7 @@ static struct resource bss_resource = {
        .flags = IORESOURCE_RAM,
 };
 
+static void __init early_cpu_init(void);
 static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c);
 
 #ifdef CONFIG_PROC_VMCORE
@@ -224,72 +226,21 @@ static inline void copy_edd(void)
 }
 #endif
 
-#ifdef CONFIG_KEXEC
-static void __init reserve_crashkernel(void)
-{
-       unsigned long long total_mem;
-       unsigned long long crash_size, crash_base;
-       int ret;
-
-       total_mem = ((unsigned long long)max_low_pfn - min_low_pfn) << PAGE_SHIFT;
-
-       ret = parse_crashkernel(boot_command_line, total_mem,
-                       &crash_size, &crash_base);
-       if (ret == 0 && crash_size) {
-               if (crash_base <= 0) {
-                       printk(KERN_INFO "crashkernel reservation failed - "
-                                       "you have to specify a base address\n");
-                       return;
-               }
-
-               if (reserve_bootmem(crash_base, crash_size,
-                                       BOOTMEM_EXCLUSIVE) < 0) {
-                       printk(KERN_INFO "crashkernel reservation failed - "
-                                       "memory is in use\n");
-                       return;
-               }
-
-               printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
-                               "for crashkernel (System RAM: %ldMB)\n",
-                               (unsigned long)(crash_size >> 20),
-                               (unsigned long)(crash_base >> 20),
-                               (unsigned long)(total_mem >> 20));
-               crashk_res.start = crash_base;
-               crashk_res.end   = crash_base + crash_size - 1;
-               insert_resource(&iomem_resource, &crashk_res);
-       }
-}
-#else
-static inline void __init reserve_crashkernel(void)
-{}
-#endif
-
 /* Overridden in paravirt.c if CONFIG_PARAVIRT */
 void __attribute__((weak)) __init memory_setup(void)
 {
        machine_specific_memory_setup();
 }
 
-static void __init parse_setup_data(void)
+/* Current gdt points %fs at the "master" per-cpu area: after this,
+ * it's on the real one. */
+void switch_to_new_gdt(void)
 {
-       struct setup_data *data;
-       unsigned long pa_data;
+       struct desc_ptr gdt_descr;
 
-       if (boot_params.hdr.version < 0x0209)
-               return;
-       pa_data = boot_params.hdr.setup_data;
-       while (pa_data) {
-               data = early_ioremap(pa_data, PAGE_SIZE);
-               switch (data->type) {
-               default:
-                       break;
-               }
-#ifndef CONFIG_DEBUG_BOOT_PARAMS
-               free_early(pa_data, pa_data+sizeof(*data)+data->len);
-#endif
-               pa_data = data->next;
-               early_iounmap(data, PAGE_SIZE);
-       }
+       gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
+       gdt_descr.size = GDT_SIZE - 1;
+       load_gdt(&gdt_descr);
 }
 
 /*
@@ -316,13 +267,15 @@ void __init setup_arch(char **cmdline_p)
 #endif
 #ifdef CONFIG_EFI
        if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
-                    "EL64", 4))
+                    "EL64", 4)) {
                efi_enabled = 1;
+               efi_reserve_early();
+       }
 #endif
 
        ARCH_SETUP
 
-       memory_setup();
+       setup_memory_map();
        copy_edd();
 
        if (!boot_params.hdr.root_flags)
@@ -339,6 +292,7 @@ void __init setup_arch(char **cmdline_p)
        bss_resource.start = virt_to_phys(&__bss_start);
        bss_resource.end = virt_to_phys(&__bss_stop)-1;
 
+       early_cpu_init();
        early_identify_cpu(&boot_cpu_data);
 
        strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
@@ -368,9 +322,13 @@ void __init setup_arch(char **cmdline_p)
         * we are rounding upwards:
         */
        end_pfn = e820_end_of_ram();
+
+       /* pre allocte 4k for mptable mpc */
+       early_reserve_e820_mpc_new();
        /* update e820 for memory not covered by WB MTRRs */
        mtrr_bp_init();
        if (mtrr_trim_uncached_memory(end_pfn)) {
+               remove_all_active_ranges();
                e820_register_active_regions(0, 0, -1UL);
                end_pfn = e820_end_of_ram();
        }
@@ -379,7 +337,7 @@ void __init setup_arch(char **cmdline_p)
 
        check_efer();
 
-       max_pfn_mapped = init_memory_mapping(0, (max_pfn_mapped << PAGE_SHIFT));
+       max_pfn_mapped = init_memory_mapping(0, (end_pfn << PAGE_SHIFT));
        if (efi_enabled)
                efi_init();
 
@@ -393,15 +351,6 @@ void __init setup_arch(char **cmdline_p)
        kvmclock_init();
 #endif
 
-#ifdef CONFIG_SMP
-       /* setup to use the early static init tables during kernel startup */
-       x86_cpu_to_apicid_early_ptr = (void *)x86_cpu_to_apicid_init;
-       x86_bios_cpu_apicid_early_ptr = (void *)x86_bios_cpu_apicid_init;
-#ifdef CONFIG_NUMA
-       x86_cpu_to_node_map_early_ptr = (void *)x86_cpu_to_node_map_init;
-#endif
-#endif
-
 #ifdef CONFIG_ACPI
        /*
         * Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
@@ -440,13 +389,12 @@ void __init setup_arch(char **cmdline_p)
        acpi_reserve_bootmem();
 #endif
 
-       if (efi_enabled)
-               efi_reserve_bootmem();
-
+#ifdef CONFIG_X86_MPPARSE
        /*
        * Find and reserve possible boot-time SMP configuration:
        */
        find_smp_config();
+#endif
 #ifdef CONFIG_BLK_DEV_INITRD
        if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
                unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
@@ -489,11 +437,13 @@ void __init setup_arch(char **cmdline_p)
 
        init_cpu_to_node();
 
+#ifdef CONFIG_X86_MPPARSE
        /*
         * get boot-time SMP configuration:
         */
        if (smp_found_config)
                get_smp_config();
+#endif
        init_apic_mappings();
        ioapic_init_mappings();
 
@@ -503,7 +453,7 @@ void __init setup_arch(char **cmdline_p)
         * We trust e820 completely. No explicit ROM probing in memory.
         */
        e820_reserve_resources();
-       e820_mark_nosave_regions();
+       e820_mark_nosave_regions(end_pfn);
 
        /* request I/O space for devices used on all i[345]86 PCs */
        for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
@@ -524,6 +474,19 @@ void __init setup_arch(char **cmdline_p)
        check_enable_amd_mmconf_dmi();
 }
 
+struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
+
+static void __cpuinit default_init(struct cpuinfo_x86 *c)
+{
+       display_cacheinfo(c);
+}
+
+static struct cpu_dev __cpuinitdata default_cpu = {
+       .c_init = default_init,
+       .c_vendor = "Unknown",
+};
+static struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
+
 int __cpuinit get_model_name(struct cpuinfo_x86 *c)
 {
        unsigned int *v;
@@ -622,52 +585,61 @@ out:
 #endif
 }
 
-static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c)
+static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
 {
-       if (c->x86 == 0x6 && c->x86_model >= 0xf)
-               set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+       char *v = c->x86_vendor_id;
+       int i;
+       static int printed;
+
+       for (i = 0; i < X86_VENDOR_NUM; i++) {
+               if (cpu_devs[i]) {
+                       if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
+                           (cpu_devs[i]->c_ident[1] &&
+                           !strcmp(v, cpu_devs[i]->c_ident[1]))) {
+                               c->x86_vendor = i;
+                               this_cpu = cpu_devs[i];
+                               return;
+                       }
+               }
+       }
+       if (!printed) {
+               printed++;
+               printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n");
+               printk(KERN_ERR "CPU: Your system may be unstable.\n");
+       }
+       c->x86_vendor = X86_VENDOR_UNKNOWN;
 }
 
-static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
+static void __init early_cpu_support_print(void)
 {
-       /* Cache sizes */
-       unsigned n;
-
-       n = c->extended_cpuid_level;
-       if (n >= 0x80000008) {
-               unsigned eax = cpuid_eax(0x80000008);
-               c->x86_virt_bits = (eax >> 8) & 0xff;
-               c->x86_phys_bits = eax & 0xff;
-       }
-
-       if (c->x86 == 0x6 && c->x86_model >= 0xf) {
-               c->x86_cache_alignment = c->x86_clflush_size * 2;
-               set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
-               set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+       int i,j;
+       struct cpu_dev *cpu_devx;
+
+       printk("KERNEL supported cpus:\n");
+       for (i = 0; i < X86_VENDOR_NUM; i++) {
+               cpu_devx = cpu_devs[i];
+               if (!cpu_devx)
+                       continue;
+               for (j = 0; j < 2; j++) {
+                       if (!cpu_devx->c_ident[j])
+                               continue;
+                       printk("  %s %s\n", cpu_devx->c_vendor,
+                               cpu_devx->c_ident[j]);
+               }
        }
-       set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
 }
 
-static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
+static void __init early_cpu_init(void)
 {
-       char *v = c->x86_vendor_id;
+        struct cpu_vendor_dev *cvdev;
 
-       if (!strcmp(v, "AuthenticAMD"))
-               c->x86_vendor = X86_VENDOR_AMD;
-       else if (!strcmp(v, "GenuineIntel"))
-               c->x86_vendor = X86_VENDOR_INTEL;
-       else if (!strcmp(v, "CentaurHauls"))
-               c->x86_vendor = X86_VENDOR_CENTAUR;
-       else
-               c->x86_vendor = X86_VENDOR_UNKNOWN;
+        for (cvdev = __x86cpuvendor_start ;
+             cvdev < __x86cpuvendor_end   ;
+             cvdev++)
+                cpu_devs[cvdev->vendor] = cvdev->cpu_dev;
+       early_cpu_support_print();
 }
 
-// FIXME: Needs to use cpu_vendor_dev_register
-extern void __cpuinit early_init_amd(struct cpuinfo_x86 *c);
-extern void __cpuinit init_amd(struct cpuinfo_x86 *c);
-extern void __cpuinit early_init_intel(struct cpuinfo_x86 *c);
-extern void __cpuinit init_intel(struct cpuinfo_x86 *c);
-
 /* 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. */
@@ -746,17 +718,9 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
        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;
-       case X86_VENDOR_CENTAUR:
-               early_init_centaur(c);
-               break;
-       }
+       if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
+           cpu_devs[c->x86_vendor]->c_early_init)
+               cpu_devs[c->x86_vendor]->c_early_init(c);
 
        validate_pat_support(c);
 }
@@ -784,24 +748,8 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
         * At the end of this section, c->x86_capability better
         * indicate the features this CPU genuinely supports!
         */
-       switch (c->x86_vendor) {
-       case X86_VENDOR_AMD:
-               init_amd(c);
-               break;
-
-       case X86_VENDOR_INTEL:
-               init_intel(c);
-               break;
-
-       case X86_VENDOR_CENTAUR:
-               init_centaur(c);
-               break;
-
-       case X86_VENDOR_UNKNOWN:
-       default:
-               display_cacheinfo(c);
-               break;
-       }
+       if (this_cpu->c_init)
+               this_cpu->c_init(c);
 
        detect_ht(c);