Fix uninitialized local variable "covered" in i386 acpi-cpufreq driver
[safe/jmp/linux-2.6] / arch / i386 / kernel / cpu / common.c
index 24ac51a..d506201 100644 (file)
 
 #include "cpu.h"
 
-DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
-EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr);
+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(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
-EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
+       [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;
@@ -36,7 +59,7 @@ struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
 
 extern int disable_pse;
 
-static void default_init(struct cpuinfo_x86 * c)
+static void __cpuinit default_init(struct cpuinfo_x86 * c)
 {
        /* Not much we can do here... */
        /* Check if at least it has cpuid */
@@ -49,11 +72,11 @@ static void default_init(struct cpuinfo_x86 * c)
        }
 }
 
-static struct cpu_dev default_cpu = {
+static struct cpu_dev __cpuinitdata default_cpu = {
        .c_init = default_init,
        .c_vendor = "Unknown",
 };
-static struct cpu_dev * this_cpu = &default_cpu;
+static struct cpu_dev * this_cpu __cpuinitdata = &default_cpu;
 
 static int __init cachesize_setup(char *str)
 {
@@ -184,7 +207,16 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
 
 static int __init x86_fxsr_setup(char * s)
 {
+       /* Tell all the other CPU's to not use it... */
        disable_x86_fxsr = 1;
+
+       /*
+        * ... and clear the bits early in the boot_cpu_data
+        * so that the bootup process doesn't try to do this
+        * either.
+        */
+       clear_bit(X86_FEATURE_FXSR, boot_cpu_data.x86_capability);
+       clear_bit(X86_FEATURE_XMM, boot_cpu_data.x86_capability);
        return 1;
 }
 __setup("nofxsr", x86_fxsr_setup);
@@ -226,29 +258,14 @@ static int __cpuinit have_cpuid_p(void)
        return flag_is_changeable_p(X86_EFLAGS_ID);
 }
 
-/* Do minimum CPU detection early.
-   Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
-   The others are not touched to avoid unwanted side effects.
-
-   WARNING: this function is only called on the BP.  Don't add code here
-   that is supposed to run on all CPUs. */
-static void __init early_cpu_detect(void)
+void __init cpu_detect(struct cpuinfo_x86 *c)
 {
-       struct cpuinfo_x86 *c = &boot_cpu_data;
-
-       c->x86_cache_alignment = 32;
-
-       if (!have_cpuid_p())
-               return;
-
        /* Get vendor name */
        cpuid(0x00000000, &c->cpuid_level,
              (int *)&c->x86_vendor_id[0],
              (int *)&c->x86_vendor_id[8],
              (int *)&c->x86_vendor_id[4]);
 
-       get_cpu_vendor(c, 1);
-
        c->x86 = 4;
        if (c->cpuid_level >= 0x00000001) {
                u32 junk, tfms, cap0, misc;
@@ -265,6 +282,26 @@ static void __init early_cpu_detect(void)
        }
 }
 
+/* Do minimum CPU detection early.
+   Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
+   The others are not touched to avoid unwanted side effects.
+
+   WARNING: this function is only called on the BP.  Don't add code here
+   that is supposed to run on all CPUs. */
+static void __init early_cpu_detect(void)
+{
+       struct cpuinfo_x86 *c = &boot_cpu_data;
+
+       c->x86_cache_alignment = 32;
+
+       if (!have_cpuid_p())
+               return;
+
+       cpu_detect(c);
+
+       get_cpu_vendor(c, 1);
+}
+
 static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
 {
        u32 tfms, xlvl;
@@ -299,6 +336,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
 #else
                        c->apicid = (ebx >> 24) & 0xFF;
 #endif
+                       if (c->x86_capability[0] & (1<<19))
+                               c->x86_clflush_size = ((ebx >> 8) & 0xff) * 8;
                } else {
                        /* Have CPUID level 0 only - unheard of */
                        c->x86 = 4;
@@ -314,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);
@@ -351,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;
 
@@ -363,6 +404,7 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
        c->x86_vendor_id[0] = '\0'; /* Unset */
        c->x86_model_id[0] = '\0';  /* Unset */
        c->x86_max_cores = 1;
+       c->x86_clflush_size = 32;
        memset(&c->x86_capability, 0, sizeof c->x86_capability);
 
        if (!have_cpuid_p()) {
@@ -461,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
@@ -557,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);
 
@@ -569,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();
@@ -582,6 +629,27 @@ void __init early_cpu_init(void)
        disable_pse = 1;
 #endif
 }
+
+/* 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_PERCPU;
+       return regs;
+}
+
+/* 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 gdt_descr;
+
+       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");
+}
+
 /*
  * cpu_init() initializes state that is per-CPU. Some data is already
  * initialized (naturally) in the bootstrap process, such as the GDT
@@ -591,16 +659,15 @@ void __init early_cpu_init(void)
 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 = &current->thread;
-       struct desc_struct *gdt;
-       __u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu);
-       struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
+       struct thread_struct *thread = &curr->thread;
 
        if (cpu_test_and_set(cpu, cpu_initialized)) {
                printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
                for (;;) local_irq_enable();
        }
+
        printk(KERN_INFO "Initializing CPU#%d\n", cpu);
 
        if (cpu_has_vme || cpu_has_tsc || cpu_has_de)
@@ -612,57 +679,17 @@ void __cpuinit cpu_init(void)
                set_in_cr4(X86_CR4_TSD);
        }
 
-       /* The CPU hotplug case */
-       if (cpu_gdt_descr->address) {
-               gdt = (struct desc_struct *)cpu_gdt_descr->address;
-               memset(gdt, 0, PAGE_SIZE);
-               goto old_gdt;
-       }
-       /*
-        * This is a horrible hack to allocate the GDT.  The problem
-        * is that cpu_init() is called really early for the boot CPU
-        * (and hence needs bootmem) but much later for the secondary
-        * CPUs, when bootmem will have gone away
-        */
-       if (NODE_DATA(0)->bdata->node_bootmem_map) {
-               gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE);
-               /* alloc_bootmem_pages panics on failure, so no check */
-               memset(gdt, 0, PAGE_SIZE);
-       } else {
-               gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL);
-               if (unlikely(!gdt)) {
-                       printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu);
-                       for (;;)
-                               local_irq_enable();
-               }
-       }
-old_gdt:
-       /*
-        * Initialize the per-CPU GDT with the boot GDT,
-        * and set up the GDT descriptor:
-        */
-       memcpy(gdt, cpu_gdt_table, GDT_SIZE);
-
-       /* Set up GDT entry for 16bit stack */
-       *(__u64 *)(&gdt[GDT_ENTRY_ESPFIX_SS]) |=
-               ((((__u64)stk16_off) << 16) & 0x000000ffffff0000ULL) |
-               ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) |
-               (CPU_16BIT_STACK_SIZE - 1);
-
-       cpu_gdt_descr->size = GDT_SIZE - 1;
-       cpu_gdt_descr->address = (unsigned long)gdt;
-
-       load_gdt(cpu_gdt_descr);
        load_idt(&idt_descr);
+       switch_to_new_gdt();
 
        /*
         * Set up and load the per-CPU TSS and LDT
         */
        atomic_inc(&init_mm.mm_count);
-       current->active_mm = &init_mm;
-       if (current->mm)
+       curr->active_mm = &init_mm;
+       if (curr->mm)
                BUG();
-       enter_lazy_tlb(&init_mm, current);
+       enter_lazy_tlb(&init_mm, curr);
 
        load_esp0(t, thread);
        set_tss_desc(cpu,t);
@@ -674,8 +701,8 @@ old_gdt:
        __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
 #endif
 
-       /* Clear %fs and %gs. */
-       asm volatile ("movl %0, %%fs; movl %0, %%gs" : : "r" (0));
+       /* Clear %gs. */
+       asm volatile ("mov %0, %%gs" : : "r" (0));
 
        /* Clear all 6 debug registers: */
        set_debugreg(0, 0);