[PATCH] [28/40] i386: Fix UP gdt bugs

From: Andi Kleen
Date: Mon Apr 30 2007 - 06:35:38 EST



From: Jeremy Fitzhardinge <jeremy@xxxxxxxx>
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@xxxxxxxxxxxx>
Signed-off-by: Jeremy Fitzhardinge <jeremy@xxxxxxxxxxxxx>
Signed-off-by: Andi Kleen <ak@xxxxxxx>
Cc: Rusty Russell <rusty@xxxxxxxxxxxxxxx>

---
arch/i386/kernel/cpu/common.c | 13 +++++++++++++
arch/i386/kernel/smpboot.c | 12 ------------
include/asm-i386/processor.h | 1 +
include/asm-i386/segment.h | 4 ++++
4 files changed, 18 insertions(+), 12 deletions(-)

===================================================================
Index: linux/arch/i386/kernel/cpu/common.c
===================================================================
--- linux.orig/arch/i386/kernel/cpu/common.c
+++ linux/arch/i386/kernel/cpu/common.c
@@ -638,6 +638,18 @@ struct pt_regs * __devinit idle_regs(str
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
@@ -668,6 +680,7 @@ void __cpuinit cpu_init(void)
}

load_idt(&idt_descr);
+ switch_to_new_gdt();

/*
* Set up and load the per-CPU TSS and LDT
Index: linux/arch/i386/kernel/smpboot.c
===================================================================
--- linux.orig/arch/i386/kernel/smpboot.c
+++ linux/arch/i386/kernel/smpboot.c
@@ -1177,18 +1177,6 @@ void __init native_smp_prepare_cpus(unsi
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)
{
unsigned int cpu = smp_processor_id();
Index: linux/include/asm-i386/processor.h
===================================================================
--- linux.orig/include/asm-i386/processor.h
+++ linux/include/asm-i386/processor.h
@@ -750,6 +750,7 @@ extern void enable_sep_cpu(void);
extern int sysenter_setup(void);

extern void cpu_set_gdt(int);
+extern void switch_to_new_gdt(void);
extern void cpu_init(void);

extern int force_mwait;
Index: linux/include/asm-i386/segment.h
===================================================================
--- linux.orig/include/asm-i386/segment.h
+++ linux/include/asm-i386/segment.h
@@ -75,7 +75,11 @@
#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)

#define GDT_ENTRY_PERCPU (GDT_ENTRY_KERNEL_BASE + 15)
+#ifdef CONFIG_SMP
#define __KERNEL_PERCPU (GDT_ENTRY_PERCPU * 8)
+#else
+#define __KERNEL_PERCPU 0
+#endif

#define GDT_ENTRY_DOUBLEFAULT_TSS 31

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/