aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2007-05-02 13:27:16 -0400
committerAndi Kleen <andi@basil.nowhere.org>2007-05-02 13:27:16 -0400
commitc5413fbe894924ddb8aa474a4d4da52e7a6c7e0b (patch)
tree8f317bf2494b6b4bceb5e6d1ee35fabc0eeb9971
parent1956c73bb5bf81ee577ed7d3c64e3cad876ad2a5 (diff)
[PATCH] i386: Fix UP gdt bugs
Fixes two problems with the GDT when compiling for uniprocessor: - There's no percpu segment, so trying to load its selector into %fs fails. Use a null selector instead. - The real gdt needs to be loaded at some point. Do it in cpu_init(). Signed-off-by: Chris Wright <chrisw@sous-sol.org> Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Signed-off-by: Andi Kleen <ak@suse.de> Cc: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--arch/i386/kernel/cpu/common.c13
-rw-r--r--arch/i386/kernel/smpboot.c12
-rw-r--r--include/asm-i386/processor.h1
-rw-r--r--include/asm-i386/segment.h4
4 files changed, 18 insertions, 12 deletions
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 27e00565f5e4..794d593c47eb 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -638,6 +638,18 @@ struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
638 return regs; 638 return regs;
639} 639}
640 640
641/* Current gdt points %fs at the "master" per-cpu area: after this,
642 * it's on the real one. */
643void switch_to_new_gdt(void)
644{
645 struct Xgt_desc_struct gdt_descr;
646
647 gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
648 gdt_descr.size = GDT_SIZE - 1;
649 load_gdt(&gdt_descr);
650 asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory");
651}
652
641/* 653/*
642 * cpu_init() initializes state that is per-CPU. Some data is already 654 * cpu_init() initializes state that is per-CPU. Some data is already
643 * initialized (naturally) in the bootstrap process, such as the GDT 655 * initialized (naturally) in the bootstrap process, such as the GDT
@@ -668,6 +680,7 @@ void __cpuinit cpu_init(void)
668 } 680 }
669 681
670 load_idt(&idt_descr); 682 load_idt(&idt_descr);
683 switch_to_new_gdt();
671 684
672 /* 685 /*
673 * Set up and load the per-CPU TSS and LDT 686 * Set up and load the per-CPU TSS and LDT
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index f79b6233db78..7c1dbef399cd 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -1177,18 +1177,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
1177 smp_boot_cpus(max_cpus); 1177 smp_boot_cpus(max_cpus);
1178} 1178}
1179 1179
1180/* Current gdt points %fs at the "master" per-cpu area: after this,
1181 * it's on the real one. */
1182static inline void switch_to_new_gdt(void)
1183{
1184 struct Xgt_desc_struct gdt_descr;
1185
1186 gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
1187 gdt_descr.size = GDT_SIZE - 1;
1188 load_gdt(&gdt_descr);
1189 asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory");
1190}
1191
1192void __init native_smp_prepare_boot_cpu(void) 1180void __init native_smp_prepare_boot_cpu(void)
1193{ 1181{
1194 unsigned int cpu = smp_processor_id(); 1182 unsigned int cpu = smp_processor_id();
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index ced2da8a0d65..70f3515c3db0 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -750,6 +750,7 @@ extern void enable_sep_cpu(void);
750extern int sysenter_setup(void); 750extern int sysenter_setup(void);
751 751
752extern void cpu_set_gdt(int); 752extern void cpu_set_gdt(int);
753extern void switch_to_new_gdt(void);
753extern void cpu_init(void); 754extern void cpu_init(void);
754 755
755extern int force_mwait; 756extern int force_mwait;
diff --git a/include/asm-i386/segment.h b/include/asm-i386/segment.h
index 07e70624d87c..597a47c2515f 100644
--- a/include/asm-i386/segment.h
+++ b/include/asm-i386/segment.h
@@ -75,7 +75,11 @@
75#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8) 75#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)
76 76
77#define GDT_ENTRY_PERCPU (GDT_ENTRY_KERNEL_BASE + 15) 77#define GDT_ENTRY_PERCPU (GDT_ENTRY_KERNEL_BASE + 15)
78#ifdef CONFIG_SMP
78#define __KERNEL_PERCPU (GDT_ENTRY_PERCPU * 8) 79#define __KERNEL_PERCPU (GDT_ENTRY_PERCPU * 8)
80#else
81#define __KERNEL_PERCPU 0
82#endif
79 83
80#define GDT_ENTRY_DOUBLEFAULT_TSS 31 84#define GDT_ENTRY_DOUBLEFAULT_TSS 31
81 85