diff options
Diffstat (limited to 'arch/i386/kernel/cpu/common.c')
| -rw-r--r-- | arch/i386/kernel/cpu/common.c | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 7eb9213734a3..4ecd4b326ded 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #include <linux/smp.h> | 4 | #include <linux/smp.h> |
| 5 | #include <linux/module.h> | 5 | #include <linux/module.h> |
| 6 | #include <linux/percpu.h> | 6 | #include <linux/percpu.h> |
| 7 | #include <linux/bootmem.h> | ||
| 7 | #include <asm/semaphore.h> | 8 | #include <asm/semaphore.h> |
| 8 | #include <asm/processor.h> | 9 | #include <asm/processor.h> |
| 9 | #include <asm/i387.h> | 10 | #include <asm/i387.h> |
| @@ -18,6 +19,9 @@ | |||
| 18 | 19 | ||
| 19 | #include "cpu.h" | 20 | #include "cpu.h" |
| 20 | 21 | ||
| 22 | DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr); | ||
| 23 | EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr); | ||
| 24 | |||
| 21 | DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]); | 25 | DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]); |
| 22 | EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack); | 26 | EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack); |
| 23 | 27 | ||
| @@ -571,8 +575,9 @@ void __devinit cpu_init(void) | |||
| 571 | int cpu = smp_processor_id(); | 575 | int cpu = smp_processor_id(); |
| 572 | struct tss_struct * t = &per_cpu(init_tss, cpu); | 576 | struct tss_struct * t = &per_cpu(init_tss, cpu); |
| 573 | struct thread_struct *thread = ¤t->thread; | 577 | struct thread_struct *thread = ¤t->thread; |
| 574 | struct desc_struct *gdt = get_cpu_gdt_table(cpu); | 578 | struct desc_struct *gdt; |
| 575 | __u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu); | 579 | __u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu); |
| 580 | struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu); | ||
| 576 | 581 | ||
| 577 | if (cpu_test_and_set(cpu, cpu_initialized)) { | 582 | if (cpu_test_and_set(cpu, cpu_initialized)) { |
| 578 | printk(KERN_WARNING "CPU#%d already initialized!\n", cpu); | 583 | printk(KERN_WARNING "CPU#%d already initialized!\n", cpu); |
| @@ -590,6 +595,25 @@ void __devinit cpu_init(void) | |||
| 590 | } | 595 | } |
| 591 | 596 | ||
| 592 | /* | 597 | /* |
| 598 | * This is a horrible hack to allocate the GDT. The problem | ||
| 599 | * is that cpu_init() is called really early for the boot CPU | ||
| 600 | * (and hence needs bootmem) but much later for the secondary | ||
| 601 | * CPUs, when bootmem will have gone away | ||
| 602 | */ | ||
| 603 | if (NODE_DATA(0)->bdata->node_bootmem_map) { | ||
| 604 | gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE); | ||
| 605 | /* alloc_bootmem_pages panics on failure, so no check */ | ||
| 606 | memset(gdt, 0, PAGE_SIZE); | ||
| 607 | } else { | ||
| 608 | gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL); | ||
| 609 | if (unlikely(!gdt)) { | ||
| 610 | printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu); | ||
| 611 | for (;;) | ||
| 612 | local_irq_enable(); | ||
| 613 | } | ||
| 614 | } | ||
| 615 | |||
| 616 | /* | ||
| 593 | * Initialize the per-CPU GDT with the boot GDT, | 617 | * Initialize the per-CPU GDT with the boot GDT, |
| 594 | * and set up the GDT descriptor: | 618 | * and set up the GDT descriptor: |
| 595 | */ | 619 | */ |
| @@ -601,10 +625,10 @@ void __devinit cpu_init(void) | |||
| 601 | ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) | | 625 | ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) | |
| 602 | (CPU_16BIT_STACK_SIZE - 1); | 626 | (CPU_16BIT_STACK_SIZE - 1); |
| 603 | 627 | ||
| 604 | cpu_gdt_descr[cpu].size = GDT_SIZE - 1; | 628 | cpu_gdt_descr->size = GDT_SIZE - 1; |
| 605 | cpu_gdt_descr[cpu].address = (unsigned long)gdt; | 629 | cpu_gdt_descr->address = (unsigned long)gdt; |
| 606 | 630 | ||
| 607 | load_gdt(&cpu_gdt_descr[cpu]); | 631 | load_gdt(cpu_gdt_descr); |
| 608 | load_idt(&idt_descr); | 632 | load_idt(&idt_descr); |
| 609 | 633 | ||
| 610 | /* | 634 | /* |
