]> err.no Git - linux-2.6/blobdiff - arch/i386/kernel/cpu/common.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[linux-2.6] / arch / i386 / kernel / cpu / common.c
index 2335f4464eada9460f41ae1485e5090c16d2d6d1..d506201d397c5fb2e13b364189a37d058876dd46 100644 (file)
 #include <asm/apic.h>
 #include <mach_apic.h>
 #endif
-#include <asm/pda.h>
 
 #include "cpu.h"
 
-DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
-EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr);
-
-DEFINE_PER_CPU(struct desc_struct, cpu_gdt[GDT_ENTRIES]);
+DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = {
+       [GDT_ENTRY_KERNEL_CS] = { 0x0000ffff, 0x00cf9a00 },
+       [GDT_ENTRY_KERNEL_DS] = { 0x0000ffff, 0x00cf9200 },
+       [GDT_ENTRY_DEFAULT_USER_CS] = { 0x0000ffff, 0x00cffa00 },
+       [GDT_ENTRY_DEFAULT_USER_DS] = { 0x0000ffff, 0x00cff200 },
+       /*
+        * Segments used for calling PnP BIOS have byte granularity.
+        * They code segments and data segments have fixed 64k limits,
+        * the transfer segment sizes are set at run time.
+        */
+       [GDT_ENTRY_PNPBIOS_CS32] = { 0x0000ffff, 0x00409a00 },/* 32-bit code */
+       [GDT_ENTRY_PNPBIOS_CS16] = { 0x0000ffff, 0x00009a00 },/* 16-bit code */
+       [GDT_ENTRY_PNPBIOS_DS] = { 0x0000ffff, 0x00009200 }, /* 16-bit data */
+       [GDT_ENTRY_PNPBIOS_TS1] = { 0x00000000, 0x00009200 },/* 16-bit data */
+       [GDT_ENTRY_PNPBIOS_TS2] = { 0x00000000, 0x00009200 },/* 16-bit data */
+       /*
+        * The APM segments have byte granularity and their bases
+        * are set at run time.  All have 64k limits.
+        */
+       [GDT_ENTRY_APMBIOS_BASE] = { 0x0000ffff, 0x00409a00 },/* 32-bit code */
+       /* 16-bit code */
+       [GDT_ENTRY_APMBIOS_BASE+1] = { 0x0000ffff, 0x00009a00 },
+       [GDT_ENTRY_APMBIOS_BASE+2] = { 0x0000ffff, 0x00409200 }, /* data */
 
-DEFINE_PER_CPU(struct i386_pda, _cpu_pda);
-EXPORT_PER_CPU_SYMBOL(_cpu_pda);
+       [GDT_ENTRY_ESPFIX_SS] = { 0x00000000, 0x00c09200 },
+       [GDT_ENTRY_PERCPU] = { 0x00000000, 0x00000000 },
+} };
+EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
 
 static int cachesize_override __cpuinitdata = -1;
 static int disable_x86_fxsr __cpuinitdata;
@@ -333,6 +353,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
                        if ( xlvl >= 0x80000004 )
                                get_model_name(c); /* Default name */
                }
+
+               init_scattered_cpuid_features(c);
        }
 
        early_intel_workaround(c);
@@ -370,7 +392,7 @@ __setup("serialnumber", x86_serial_nr_setup);
 /*
  * This does the hard work of actually picking apart the CPU stuff...
  */
-void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
 {
        int i;
 
@@ -481,15 +503,22 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
 
        /* Init Machine Check Exception if available. */
        mcheck_init(c);
+}
 
-       if (c == &boot_cpu_data)
-               sysenter_setup();
+void __init identify_boot_cpu(void)
+{
+       identify_cpu(&boot_cpu_data);
+       sysenter_setup();
        enable_sep_cpu();
+       mtrr_bp_init();
+}
 
-       if (c == &boot_cpu_data)
-               mtrr_bp_init();
-       else
-               mtrr_ap_init();
+void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
+{
+       BUG_ON(c == &boot_cpu_data);
+       identify_cpu(c);
+       enable_sep_cpu();
+       mtrr_ap_init();
 }
 
 #ifdef CONFIG_X86_HT
@@ -577,7 +606,6 @@ extern int nsc_init_cpu(void);
 extern int amd_init_cpu(void);
 extern int centaur_init_cpu(void);
 extern int transmeta_init_cpu(void);
-extern int rise_init_cpu(void);
 extern int nexgen_init_cpu(void);
 extern int umc_init_cpu(void);
 
@@ -589,7 +617,6 @@ void __init early_cpu_init(void)
        amd_init_cpu();
        centaur_init_cpu();
        transmeta_init_cpu();
-       rise_init_cpu();
        nexgen_init_cpu();
        umc_init_cpu();
        early_cpu_detect();
@@ -603,64 +630,36 @@ void __init early_cpu_init(void)
 #endif
 }
 
-/* Make sure %gs is initialized properly in idle threads */
+/* Make sure %fs is initialized properly in idle threads */
 struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
 {
        memset(regs, 0, sizeof(struct pt_regs));
-       regs->xfs = __KERNEL_PDA;
+       regs->xfs = __KERNEL_PERCPU;
        return regs;
 }
 
-/* Initial PDA used by boot CPU */
-struct i386_pda boot_pda = {
-       ._pda = &boot_pda,
-       .cpu_number = 0,
-       .pcurrent = &init_task,
-};
-
-static inline void set_kernel_fs(void)
-{
-       /* Set %fs for this CPU's PDA.  Memory clobber is to create a
-          barrier with respect to any PDA operations, so the compiler
-          doesn't move any before here. */
-       asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_PDA) : "memory");
-}
-
-/* Initialize the CPU's GDT and PDA.  This is either the boot CPU doing itself
-   (still using cpu_gdt_table), or a CPU doing it for a secondary which
-   will soon come up. */
-__cpuinit void init_gdt(int cpu, struct task_struct *idle)
-{
-       struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
-       struct desc_struct *gdt = per_cpu(cpu_gdt, cpu);
-       struct i386_pda *pda = &per_cpu(_cpu_pda, cpu);
-
-       memcpy(gdt, cpu_gdt_table, GDT_SIZE);
-       cpu_gdt_descr->address = (unsigned long)gdt;
-       cpu_gdt_descr->size = GDT_SIZE - 1;
-
-       pack_descriptor((u32 *)&gdt[GDT_ENTRY_PDA].a,
-                       (u32 *)&gdt[GDT_ENTRY_PDA].b,
-                       (unsigned long)pda, sizeof(*pda) - 1,
-                       0x80 | DESCTYPE_S | 0x2, 0); /* present read-write data segment */
-
-       memset(pda, 0, sizeof(*pda));
-       pda->_pda = pda;
-       pda->cpu_number = cpu;
-       pda->pcurrent = idle;
-}
-
-void __cpuinit cpu_set_gdt(int cpu)
+/* 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 Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
+       struct Xgt_desc_struct gdt_descr;
 
-       load_gdt(cpu_gdt_descr);
-       set_kernel_fs();
+       gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
+       gdt_descr.size = GDT_SIZE - 1;
+       load_gdt(&gdt_descr);
+       asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory");
 }
 
-/* Common CPU init for both boot and secondary CPUs */
-static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
+/*
+ * cpu_init() initializes state that is per-CPU. Some data is already
+ * initialized (naturally) in the bootstrap process, such as the GDT
+ * and IDT. We reload them nevertheless, this function acts as a
+ * 'CPU state barrier', nothing should get across.
+ */
+void __cpuinit cpu_init(void)
 {
+       int cpu = smp_processor_id();
+       struct task_struct *curr = current;
        struct tss_struct * t = &per_cpu(init_tss, cpu);
        struct thread_struct *thread = &curr->thread;
 
@@ -681,6 +680,7 @@ static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
        }
 
        load_idt(&idt_descr);
+       switch_to_new_gdt();
 
        /*
         * Set up and load the per-CPU TSS and LDT
@@ -720,33 +720,6 @@ static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
        mxcsr_feature_mask_init();
 }
 
-/* Entrypoint to initialize secondary CPU */
-void __cpuinit secondary_cpu_init(void)
-{
-       int cpu = smp_processor_id();
-       struct task_struct *curr = current;
-
-       _cpu_init(cpu, curr);
-}
-
-/*
- * cpu_init() initializes state that is per-CPU. Some data is already
- * initialized (naturally) in the bootstrap process, such as the GDT
- * and IDT. We reload them nevertheless, this function acts as a
- * 'CPU state barrier', nothing should get across.
- */
-void __cpuinit cpu_init(void)
-{
-       int cpu = smp_processor_id();
-       struct task_struct *curr = current;
-
-       /* Set up the real GDT and PDA, so we can transition from the
-          boot_gdt_table & boot_pda. */
-       init_gdt(cpu, curr);
-       cpu_set_gdt(cpu);
-       _cpu_init(cpu, curr);
-}
-
 #ifdef CONFIG_HOTPLUG_CPU
 void __cpuinit cpu_uninit(void)
 {