Bläddra i källkod

[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>
Jeremy Fitzhardinge 18 år sedan
förälder
incheckning
c5413fbe89

+ 13 - 0
arch/i386/kernel/cpu/common.c

@@ -638,6 +638,18 @@ struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
 	return regs;
 	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
  * cpu_init() initializes state that is per-CPU. Some data is already
  * initialized (naturally) in the bootstrap process, such as the GDT
  * initialized (naturally) in the bootstrap process, such as the GDT
@@ -668,6 +680,7 @@ void __cpuinit cpu_init(void)
 	}
 	}
 
 
 	load_idt(&idt_descr);
 	load_idt(&idt_descr);
+	switch_to_new_gdt();
 
 
 	/*
 	/*
 	 * Set up and load the per-CPU TSS and LDT
 	 * Set up and load the per-CPU TSS and LDT

+ 0 - 12
arch/i386/kernel/smpboot.c

@@ -1177,18 +1177,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
 	smp_boot_cpus(max_cpus);
 	smp_boot_cpus(max_cpus);
 }
 }
 
 
-/* Current gdt points %fs at the "master" per-cpu area: after this,
- * it's on the real one. */
-static inline 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");
-}
-
 void __init native_smp_prepare_boot_cpu(void)
 void __init native_smp_prepare_boot_cpu(void)
 {
 {
 	unsigned int cpu = smp_processor_id();
 	unsigned int cpu = smp_processor_id();

+ 1 - 0
include/asm-i386/processor.h

@@ -750,6 +750,7 @@ extern void enable_sep_cpu(void);
 extern int sysenter_setup(void);
 extern int sysenter_setup(void);
 
 
 extern void cpu_set_gdt(int);
 extern void cpu_set_gdt(int);
+extern void switch_to_new_gdt(void);
 extern void cpu_init(void);
 extern void cpu_init(void);
 
 
 extern int force_mwait;
 extern int force_mwait;

+ 4 - 0
include/asm-i386/segment.h

@@ -75,7 +75,11 @@
 #define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)
 #define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)
 
 
 #define GDT_ENTRY_PERCPU			(GDT_ENTRY_KERNEL_BASE + 15)
 #define GDT_ENTRY_PERCPU			(GDT_ENTRY_KERNEL_BASE + 15)
+#ifdef CONFIG_SMP
 #define __KERNEL_PERCPU (GDT_ENTRY_PERCPU * 8)
 #define __KERNEL_PERCPU (GDT_ENTRY_PERCPU * 8)
+#else
+#define __KERNEL_PERCPU 0
+#endif
 
 
 #define GDT_ENTRY_DOUBLEFAULT_TSS	31
 #define GDT_ENTRY_DOUBLEFAULT_TSS	31