aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/cpu/common.c
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2006-12-06 20:14:02 -0500
committerAndi Kleen <andi@basil.nowhere.org>2006-12-06 20:14:02 -0500
commitf95d47caae5302a63d92be9a0292abc90e2a14e1 (patch)
treecfa963975d104c56aba28df6c941759175ed4b98 /arch/i386/kernel/cpu/common.c
parent62111195800d80c66cdc69063ea3145878c99fbf (diff)
[PATCH] i386: Use %gs as the PDA base-segment in the kernel
This patch is the meat of the PDA change. This patch makes several related changes: 1: Most significantly, %gs is now used in the kernel. This means that on entry, the old value of %gs is saved away, and it is reloaded with __KERNEL_PDA. 2: entry.S constructs the stack in the shape of struct pt_regs, and this is passed around the kernel so that the process's saved register state can be accessed. Unfortunately struct pt_regs doesn't currently have space for %gs (or %fs). This patch extends pt_regs to add space for gs (no space is allocated for %fs, since it won't be used, and it would just complicate the code in entry.S to work around the space). 3: Because %gs is now saved on the stack like %ds, %es and the integer registers, there are a number of places where it no longer needs to be handled specially; namely context switch, and saving/restoring the register state in a signal context. 4: And since kernel threads run in kernel space and call normal kernel code, they need to be created with their %gs == __KERNEL_PDA. Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Signed-off-by: Andi Kleen <ak@suse.de> Cc: Chuck Ebbert <76306.1226@compuserve.com> Cc: Zachary Amsden <zach@vmware.com> Cc: Jan Beulich <jbeulich@novell.com> Cc: Andi Kleen <ak@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org>
Diffstat (limited to 'arch/i386/kernel/cpu/common.c')
-rw-r--r--arch/i386/kernel/cpu/common.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 2534e25ed745..4e63d8ce602b 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -593,6 +593,14 @@ void __init early_cpu_init(void)
593#endif 593#endif
594} 594}
595 595
596/* Make sure %gs is initialized properly in idle threads */
597struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
598{
599 memset(regs, 0, sizeof(struct pt_regs));
600 regs->xgs = __KERNEL_PDA;
601 return regs;
602}
603
596__cpuinit int alloc_gdt(int cpu) 604__cpuinit int alloc_gdt(int cpu)
597{ 605{
598 struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu); 606 struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
@@ -644,6 +652,14 @@ struct i386_pda boot_pda = {
644 ._pda = &boot_pda, 652 ._pda = &boot_pda,
645}; 653};
646 654
655static inline void set_kernel_gs(void)
656{
657 /* Set %gs for this CPU's PDA. Memory clobber is to create a
658 barrier with respect to any PDA operations, so the compiler
659 doesn't move any before here. */
660 asm volatile ("mov %0, %%gs" : : "r" (__KERNEL_PDA) : "memory");
661}
662
647/* Initialize the CPU's GDT and PDA. The boot CPU does this for 663/* Initialize the CPU's GDT and PDA. The boot CPU does this for
648 itself, but secondaries find this done for them. */ 664 itself, but secondaries find this done for them. */
649__cpuinit int init_gdt(int cpu, struct task_struct *idle) 665__cpuinit int init_gdt(int cpu, struct task_struct *idle)
@@ -693,6 +709,7 @@ static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
693 the boot CPU, this will transition from the boot gdt+pda to 709 the boot CPU, this will transition from the boot gdt+pda to
694 the real ones). */ 710 the real ones). */
695 load_gdt(cpu_gdt_descr); 711 load_gdt(cpu_gdt_descr);
712 set_kernel_gs();
696 713
697 if (cpu_test_and_set(cpu, cpu_initialized)) { 714 if (cpu_test_and_set(cpu, cpu_initialized)) {
698 printk(KERN_WARNING "CPU#%d already initialized!\n", cpu); 715 printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
@@ -731,8 +748,8 @@ static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
731 __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss); 748 __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
732#endif 749#endif
733 750
734 /* Clear %fs and %gs. */ 751 /* Clear %fs. */
735 asm volatile ("movl %0, %%fs; movl %0, %%gs" : : "r" (0)); 752 asm volatile ("mov %0, %%fs" : : "r" (0));
736 753
737 /* Clear all 6 debug registers: */ 754 /* Clear all 6 debug registers: */
738 set_debugreg(0, 0); 755 set_debugreg(0, 0);