diff options
Diffstat (limited to 'arch/x86_64/kernel/process.c')
-rw-r--r-- | arch/x86_64/kernel/process.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 70dd8e5c6889..fb903e65e079 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c | |||
@@ -575,8 +575,10 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
575 | prev->userrsp = read_pda(oldrsp); | 575 | prev->userrsp = read_pda(oldrsp); |
576 | write_pda(oldrsp, next->userrsp); | 576 | write_pda(oldrsp, next->userrsp); |
577 | write_pda(pcurrent, next_p); | 577 | write_pda(pcurrent, next_p); |
578 | |||
578 | /* This must be here to ensure both math_state_restore() and | 579 | /* This must be here to ensure both math_state_restore() and |
579 | kernel_fpu_begin() work consistently. */ | 580 | kernel_fpu_begin() work consistently. |
581 | And the AMD workaround requires it to be after DS reload. */ | ||
580 | unlazy_fpu(prev_p); | 582 | unlazy_fpu(prev_p); |
581 | write_pda(kernelstack, | 583 | write_pda(kernelstack, |
582 | task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET); | 584 | task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET); |
@@ -781,10 +783,16 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) | |||
781 | } | 783 | } |
782 | case ARCH_GET_GS: { | 784 | case ARCH_GET_GS: { |
783 | unsigned long base; | 785 | unsigned long base; |
786 | unsigned gsindex; | ||
784 | if (task->thread.gsindex == GS_TLS_SEL) | 787 | if (task->thread.gsindex == GS_TLS_SEL) |
785 | base = read_32bit_tls(task, GS_TLS); | 788 | base = read_32bit_tls(task, GS_TLS); |
786 | else if (doit) | 789 | else if (doit) { |
787 | rdmsrl(MSR_KERNEL_GS_BASE, base); | 790 | asm("movl %%gs,%0" : "=r" (gsindex)); |
791 | if (gsindex) | ||
792 | rdmsrl(MSR_KERNEL_GS_BASE, base); | ||
793 | else | ||
794 | base = task->thread.gs; | ||
795 | } | ||
788 | else | 796 | else |
789 | base = task->thread.gs; | 797 | base = task->thread.gs; |
790 | ret = put_user(base, (unsigned long __user *)addr); | 798 | ret = put_user(base, (unsigned long __user *)addr); |