diff options
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/kernel/process.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 761d4ed47ef3..9d94995e9672 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c | |||
@@ -678,21 +678,26 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas | |||
678 | __unlazy_fpu(prev_p); | 678 | __unlazy_fpu(prev_p); |
679 | 679 | ||
680 | /* | 680 | /* |
681 | * Reload esp0, LDT and the page table pointer: | 681 | * Reload esp0. |
682 | */ | 682 | */ |
683 | load_esp0(tss, next); | 683 | load_esp0(tss, next); |
684 | 684 | ||
685 | /* | 685 | /* |
686 | * Load the per-thread Thread-Local Storage descriptor. | 686 | * Save away %fs and %gs. No need to save %es and %ds, as |
687 | * those are always kernel segments while inside the kernel. | ||
688 | * Doing this before setting the new TLS descriptors avoids | ||
689 | * the situation where we temporarily have non-reloadable | ||
690 | * segments in %fs and %gs. This could be an issue if the | ||
691 | * NMI handler ever used %fs or %gs (it does not today), or | ||
692 | * if the kernel is running inside of a hypervisor layer. | ||
687 | */ | 693 | */ |
688 | load_TLS(next, cpu); | 694 | savesegment(fs, prev->fs); |
695 | savesegment(gs, prev->gs); | ||
689 | 696 | ||
690 | /* | 697 | /* |
691 | * Save away %fs and %gs. No need to save %es and %ds, as | 698 | * Load the per-thread Thread-Local Storage descriptor. |
692 | * those are always kernel segments while inside the kernel. | ||
693 | */ | 699 | */ |
694 | asm volatile("mov %%fs,%0":"=m" (prev->fs)); | 700 | load_TLS(next, cpu); |
695 | asm volatile("mov %%gs,%0":"=m" (prev->gs)); | ||
696 | 701 | ||
697 | /* | 702 | /* |
698 | * Restore %fs and %gs if needed. | 703 | * Restore %fs and %gs if needed. |