diff options
Diffstat (limited to 'arch/i386/kernel/cpu/common.c')
-rw-r--r-- | arch/i386/kernel/cpu/common.c | 249 |
1 files changed, 179 insertions, 70 deletions
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index d9f3e3c31f05..1b34c56f8123 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c | |||
@@ -18,14 +18,15 @@ | |||
18 | #include <asm/apic.h> | 18 | #include <asm/apic.h> |
19 | #include <mach_apic.h> | 19 | #include <mach_apic.h> |
20 | #endif | 20 | #endif |
21 | #include <asm/pda.h> | ||
21 | 22 | ||
22 | #include "cpu.h" | 23 | #include "cpu.h" |
23 | 24 | ||
24 | DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr); | 25 | DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr); |
25 | EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr); | 26 | EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr); |
26 | 27 | ||
27 | DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]); | 28 | struct i386_pda *_cpu_pda[NR_CPUS] __read_mostly; |
28 | EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack); | 29 | EXPORT_SYMBOL(_cpu_pda); |
29 | 30 | ||
30 | static int cachesize_override __cpuinitdata = -1; | 31 | static int cachesize_override __cpuinitdata = -1; |
31 | static int disable_x86_fxsr __cpuinitdata; | 32 | static int disable_x86_fxsr __cpuinitdata; |
@@ -235,29 +236,14 @@ static int __cpuinit have_cpuid_p(void) | |||
235 | return flag_is_changeable_p(X86_EFLAGS_ID); | 236 | return flag_is_changeable_p(X86_EFLAGS_ID); |
236 | } | 237 | } |
237 | 238 | ||
238 | /* Do minimum CPU detection early. | 239 | void __init cpu_detect(struct cpuinfo_x86 *c) |
239 | Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment. | ||
240 | The others are not touched to avoid unwanted side effects. | ||
241 | |||
242 | WARNING: this function is only called on the BP. Don't add code here | ||
243 | that is supposed to run on all CPUs. */ | ||
244 | static void __init early_cpu_detect(void) | ||
245 | { | 240 | { |
246 | struct cpuinfo_x86 *c = &boot_cpu_data; | ||
247 | |||
248 | c->x86_cache_alignment = 32; | ||
249 | |||
250 | if (!have_cpuid_p()) | ||
251 | return; | ||
252 | |||
253 | /* Get vendor name */ | 241 | /* Get vendor name */ |
254 | cpuid(0x00000000, &c->cpuid_level, | 242 | cpuid(0x00000000, &c->cpuid_level, |
255 | (int *)&c->x86_vendor_id[0], | 243 | (int *)&c->x86_vendor_id[0], |
256 | (int *)&c->x86_vendor_id[8], | 244 | (int *)&c->x86_vendor_id[8], |
257 | (int *)&c->x86_vendor_id[4]); | 245 | (int *)&c->x86_vendor_id[4]); |
258 | 246 | ||
259 | get_cpu_vendor(c, 1); | ||
260 | |||
261 | c->x86 = 4; | 247 | c->x86 = 4; |
262 | if (c->cpuid_level >= 0x00000001) { | 248 | if (c->cpuid_level >= 0x00000001) { |
263 | u32 junk, tfms, cap0, misc; | 249 | u32 junk, tfms, cap0, misc; |
@@ -274,6 +260,26 @@ static void __init early_cpu_detect(void) | |||
274 | } | 260 | } |
275 | } | 261 | } |
276 | 262 | ||
263 | /* Do minimum CPU detection early. | ||
264 | Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment. | ||
265 | The others are not touched to avoid unwanted side effects. | ||
266 | |||
267 | WARNING: this function is only called on the BP. Don't add code here | ||
268 | that is supposed to run on all CPUs. */ | ||
269 | static void __init early_cpu_detect(void) | ||
270 | { | ||
271 | struct cpuinfo_x86 *c = &boot_cpu_data; | ||
272 | |||
273 | c->x86_cache_alignment = 32; | ||
274 | |||
275 | if (!have_cpuid_p()) | ||
276 | return; | ||
277 | |||
278 | cpu_detect(c); | ||
279 | |||
280 | get_cpu_vendor(c, 1); | ||
281 | } | ||
282 | |||
277 | static void __cpuinit generic_identify(struct cpuinfo_x86 * c) | 283 | static void __cpuinit generic_identify(struct cpuinfo_x86 * c) |
278 | { | 284 | { |
279 | u32 tfms, xlvl; | 285 | u32 tfms, xlvl; |
@@ -308,6 +314,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 * c) | |||
308 | #else | 314 | #else |
309 | c->apicid = (ebx >> 24) & 0xFF; | 315 | c->apicid = (ebx >> 24) & 0xFF; |
310 | #endif | 316 | #endif |
317 | if (c->x86_capability[0] & (1<<19)) | ||
318 | c->x86_clflush_size = ((ebx >> 8) & 0xff) * 8; | ||
311 | } else { | 319 | } else { |
312 | /* Have CPUID level 0 only - unheard of */ | 320 | /* Have CPUID level 0 only - unheard of */ |
313 | c->x86 = 4; | 321 | c->x86 = 4; |
@@ -372,6 +380,7 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c) | |||
372 | c->x86_vendor_id[0] = '\0'; /* Unset */ | 380 | c->x86_vendor_id[0] = '\0'; /* Unset */ |
373 | c->x86_model_id[0] = '\0'; /* Unset */ | 381 | c->x86_model_id[0] = '\0'; /* Unset */ |
374 | c->x86_max_cores = 1; | 382 | c->x86_max_cores = 1; |
383 | c->x86_clflush_size = 32; | ||
375 | memset(&c->x86_capability, 0, sizeof c->x86_capability); | 384 | memset(&c->x86_capability, 0, sizeof c->x86_capability); |
376 | 385 | ||
377 | if (!have_cpuid_p()) { | 386 | if (!have_cpuid_p()) { |
@@ -591,42 +600,24 @@ void __init early_cpu_init(void) | |||
591 | disable_pse = 1; | 600 | disable_pse = 1; |
592 | #endif | 601 | #endif |
593 | } | 602 | } |
594 | /* | 603 | |
595 | * cpu_init() initializes state that is per-CPU. Some data is already | 604 | /* Make sure %gs is initialized properly in idle threads */ |
596 | * initialized (naturally) in the bootstrap process, such as the GDT | 605 | struct pt_regs * __devinit idle_regs(struct pt_regs *regs) |
597 | * and IDT. We reload them nevertheless, this function acts as a | ||
598 | * 'CPU state barrier', nothing should get across. | ||
599 | */ | ||
600 | void __cpuinit cpu_init(void) | ||
601 | { | 606 | { |
602 | int cpu = smp_processor_id(); | 607 | memset(regs, 0, sizeof(struct pt_regs)); |
603 | struct tss_struct * t = &per_cpu(init_tss, cpu); | 608 | regs->xgs = __KERNEL_PDA; |
604 | struct thread_struct *thread = ¤t->thread; | 609 | return regs; |
605 | struct desc_struct *gdt; | 610 | } |
606 | __u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu); | ||
607 | struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu); | ||
608 | 611 | ||
609 | if (cpu_test_and_set(cpu, cpu_initialized)) { | 612 | static __cpuinit int alloc_gdt(int cpu) |
610 | printk(KERN_WARNING "CPU#%d already initialized!\n", cpu); | 613 | { |
611 | for (;;) local_irq_enable(); | 614 | struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu); |
612 | } | 615 | struct desc_struct *gdt; |
613 | printk(KERN_INFO "Initializing CPU#%d\n", cpu); | 616 | struct i386_pda *pda; |
614 | 617 | ||
615 | if (cpu_has_vme || cpu_has_tsc || cpu_has_de) | 618 | gdt = (struct desc_struct *)cpu_gdt_descr->address; |
616 | clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); | 619 | pda = cpu_pda(cpu); |
617 | if (tsc_disable && cpu_has_tsc) { | ||
618 | printk(KERN_NOTICE "Disabling TSC...\n"); | ||
619 | /**** FIX-HPA: DOES THIS REALLY BELONG HERE? ****/ | ||
620 | clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability); | ||
621 | set_in_cr4(X86_CR4_TSD); | ||
622 | } | ||
623 | 620 | ||
624 | /* The CPU hotplug case */ | ||
625 | if (cpu_gdt_descr->address) { | ||
626 | gdt = (struct desc_struct *)cpu_gdt_descr->address; | ||
627 | memset(gdt, 0, PAGE_SIZE); | ||
628 | goto old_gdt; | ||
629 | } | ||
630 | /* | 621 | /* |
631 | * This is a horrible hack to allocate the GDT. The problem | 622 | * This is a horrible hack to allocate the GDT. The problem |
632 | * is that cpu_init() is called really early for the boot CPU | 623 | * is that cpu_init() is called really early for the boot CPU |
@@ -634,43 +625,130 @@ void __cpuinit cpu_init(void) | |||
634 | * CPUs, when bootmem will have gone away | 625 | * CPUs, when bootmem will have gone away |
635 | */ | 626 | */ |
636 | if (NODE_DATA(0)->bdata->node_bootmem_map) { | 627 | if (NODE_DATA(0)->bdata->node_bootmem_map) { |
637 | gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE); | 628 | BUG_ON(gdt != NULL || pda != NULL); |
638 | /* alloc_bootmem_pages panics on failure, so no check */ | 629 | |
630 | gdt = alloc_bootmem_pages(PAGE_SIZE); | ||
631 | pda = alloc_bootmem(sizeof(*pda)); | ||
632 | /* alloc_bootmem(_pages) panics on failure, so no check */ | ||
633 | |||
639 | memset(gdt, 0, PAGE_SIZE); | 634 | memset(gdt, 0, PAGE_SIZE); |
635 | memset(pda, 0, sizeof(*pda)); | ||
640 | } else { | 636 | } else { |
641 | gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL); | 637 | /* GDT and PDA might already have been allocated if |
642 | if (unlikely(!gdt)) { | 638 | this is a CPU hotplug re-insertion. */ |
643 | printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu); | 639 | if (gdt == NULL) |
644 | for (;;) | 640 | gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL); |
645 | local_irq_enable(); | 641 | |
642 | if (pda == NULL) | ||
643 | pda = kmalloc_node(sizeof(*pda), GFP_KERNEL, cpu_to_node(cpu)); | ||
644 | |||
645 | if (unlikely(!gdt || !pda)) { | ||
646 | free_pages((unsigned long)gdt, 0); | ||
647 | kfree(pda); | ||
648 | return 0; | ||
646 | } | 649 | } |
647 | } | 650 | } |
648 | old_gdt: | 651 | |
652 | cpu_gdt_descr->address = (unsigned long)gdt; | ||
653 | cpu_pda(cpu) = pda; | ||
654 | |||
655 | return 1; | ||
656 | } | ||
657 | |||
658 | /* Initial PDA used by boot CPU */ | ||
659 | struct i386_pda boot_pda = { | ||
660 | ._pda = &boot_pda, | ||
661 | .cpu_number = 0, | ||
662 | .pcurrent = &init_task, | ||
663 | }; | ||
664 | |||
665 | static inline void set_kernel_gs(void) | ||
666 | { | ||
667 | /* Set %gs for this CPU's PDA. Memory clobber is to create a | ||
668 | barrier with respect to any PDA operations, so the compiler | ||
669 | doesn't move any before here. */ | ||
670 | asm volatile ("mov %0, %%gs" : : "r" (__KERNEL_PDA) : "memory"); | ||
671 | } | ||
672 | |||
673 | /* Initialize the CPU's GDT and PDA. The boot CPU does this for | ||
674 | itself, but secondaries find this done for them. */ | ||
675 | __cpuinit int init_gdt(int cpu, struct task_struct *idle) | ||
676 | { | ||
677 | struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu); | ||
678 | struct desc_struct *gdt; | ||
679 | struct i386_pda *pda; | ||
680 | |||
681 | /* For non-boot CPUs, the GDT and PDA should already have been | ||
682 | allocated. */ | ||
683 | if (!alloc_gdt(cpu)) { | ||
684 | printk(KERN_CRIT "CPU%d failed to allocate GDT or PDA\n", cpu); | ||
685 | return 0; | ||
686 | } | ||
687 | |||
688 | gdt = (struct desc_struct *)cpu_gdt_descr->address; | ||
689 | pda = cpu_pda(cpu); | ||
690 | |||
691 | BUG_ON(gdt == NULL || pda == NULL); | ||
692 | |||
649 | /* | 693 | /* |
650 | * Initialize the per-CPU GDT with the boot GDT, | 694 | * Initialize the per-CPU GDT with the boot GDT, |
651 | * and set up the GDT descriptor: | 695 | * and set up the GDT descriptor: |
652 | */ | 696 | */ |
653 | memcpy(gdt, cpu_gdt_table, GDT_SIZE); | 697 | memcpy(gdt, cpu_gdt_table, GDT_SIZE); |
698 | cpu_gdt_descr->size = GDT_SIZE - 1; | ||
654 | 699 | ||
655 | /* Set up GDT entry for 16bit stack */ | 700 | pack_descriptor((u32 *)&gdt[GDT_ENTRY_PDA].a, |
656 | *(__u64 *)(&gdt[GDT_ENTRY_ESPFIX_SS]) |= | 701 | (u32 *)&gdt[GDT_ENTRY_PDA].b, |
657 | ((((__u64)stk16_off) << 16) & 0x000000ffffff0000ULL) | | 702 | (unsigned long)pda, sizeof(*pda) - 1, |
658 | ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) | | 703 | 0x80 | DESCTYPE_S | 0x2, 0); /* present read-write data segment */ |
659 | (CPU_16BIT_STACK_SIZE - 1); | ||
660 | 704 | ||
661 | cpu_gdt_descr->size = GDT_SIZE - 1; | 705 | memset(pda, 0, sizeof(*pda)); |
662 | cpu_gdt_descr->address = (unsigned long)gdt; | 706 | pda->_pda = pda; |
707 | pda->cpu_number = cpu; | ||
708 | pda->pcurrent = idle; | ||
709 | |||
710 | return 1; | ||
711 | } | ||
712 | |||
713 | /* Common CPU init for both boot and secondary CPUs */ | ||
714 | static void __cpuinit _cpu_init(int cpu, struct task_struct *curr) | ||
715 | { | ||
716 | struct tss_struct * t = &per_cpu(init_tss, cpu); | ||
717 | struct thread_struct *thread = &curr->thread; | ||
718 | struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu); | ||
663 | 719 | ||
720 | /* Reinit these anyway, even if they've already been done (on | ||
721 | the boot CPU, this will transition from the boot gdt+pda to | ||
722 | the real ones). */ | ||
664 | load_gdt(cpu_gdt_descr); | 723 | load_gdt(cpu_gdt_descr); |
724 | set_kernel_gs(); | ||
725 | |||
726 | if (cpu_test_and_set(cpu, cpu_initialized)) { | ||
727 | printk(KERN_WARNING "CPU#%d already initialized!\n", cpu); | ||
728 | for (;;) local_irq_enable(); | ||
729 | } | ||
730 | |||
731 | printk(KERN_INFO "Initializing CPU#%d\n", cpu); | ||
732 | |||
733 | if (cpu_has_vme || cpu_has_tsc || cpu_has_de) | ||
734 | clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); | ||
735 | if (tsc_disable && cpu_has_tsc) { | ||
736 | printk(KERN_NOTICE "Disabling TSC...\n"); | ||
737 | /**** FIX-HPA: DOES THIS REALLY BELONG HERE? ****/ | ||
738 | clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability); | ||
739 | set_in_cr4(X86_CR4_TSD); | ||
740 | } | ||
741 | |||
665 | load_idt(&idt_descr); | 742 | load_idt(&idt_descr); |
666 | 743 | ||
667 | /* | 744 | /* |
668 | * Set up and load the per-CPU TSS and LDT | 745 | * Set up and load the per-CPU TSS and LDT |
669 | */ | 746 | */ |
670 | atomic_inc(&init_mm.mm_count); | 747 | atomic_inc(&init_mm.mm_count); |
671 | current->active_mm = &init_mm; | 748 | curr->active_mm = &init_mm; |
672 | BUG_ON(current->mm); | 749 | if (curr->mm) |
673 | enter_lazy_tlb(&init_mm, current); | 750 | BUG(); |
751 | enter_lazy_tlb(&init_mm, curr); | ||
674 | 752 | ||
675 | load_esp0(t, thread); | 753 | load_esp0(t, thread); |
676 | set_tss_desc(cpu,t); | 754 | set_tss_desc(cpu,t); |
@@ -682,8 +760,8 @@ old_gdt: | |||
682 | __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss); | 760 | __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss); |
683 | #endif | 761 | #endif |
684 | 762 | ||
685 | /* Clear %fs and %gs. */ | 763 | /* Clear %fs. */ |
686 | asm volatile ("movl %0, %%fs; movl %0, %%gs" : : "r" (0)); | 764 | asm volatile ("mov %0, %%fs" : : "r" (0)); |
687 | 765 | ||
688 | /* Clear all 6 debug registers: */ | 766 | /* Clear all 6 debug registers: */ |
689 | set_debugreg(0, 0); | 767 | set_debugreg(0, 0); |
@@ -701,6 +779,37 @@ old_gdt: | |||
701 | mxcsr_feature_mask_init(); | 779 | mxcsr_feature_mask_init(); |
702 | } | 780 | } |
703 | 781 | ||
782 | /* Entrypoint to initialize secondary CPU */ | ||
783 | void __cpuinit secondary_cpu_init(void) | ||
784 | { | ||
785 | int cpu = smp_processor_id(); | ||
786 | struct task_struct *curr = current; | ||
787 | |||
788 | _cpu_init(cpu, curr); | ||
789 | } | ||
790 | |||
791 | /* | ||
792 | * cpu_init() initializes state that is per-CPU. Some data is already | ||
793 | * initialized (naturally) in the bootstrap process, such as the GDT | ||
794 | * and IDT. We reload them nevertheless, this function acts as a | ||
795 | * 'CPU state barrier', nothing should get across. | ||
796 | */ | ||
797 | void __cpuinit cpu_init(void) | ||
798 | { | ||
799 | int cpu = smp_processor_id(); | ||
800 | struct task_struct *curr = current; | ||
801 | |||
802 | /* Set up the real GDT and PDA, so we can transition from the | ||
803 | boot versions. */ | ||
804 | if (!init_gdt(cpu, curr)) { | ||
805 | /* failed to allocate something; not much we can do... */ | ||
806 | for (;;) | ||
807 | local_irq_enable(); | ||
808 | } | ||
809 | |||
810 | _cpu_init(cpu, curr); | ||
811 | } | ||
812 | |||
704 | #ifdef CONFIG_HOTPLUG_CPU | 813 | #ifdef CONFIG_HOTPLUG_CPU |
705 | void __cpuinit cpu_uninit(void) | 814 | void __cpuinit cpu_uninit(void) |
706 | { | 815 | { |