When usermode loaded non-default segment selector into the %gs,

correctly prepare KGSBASE msr to restore the user descriptor base on
the last swapgs during return to usermode.

Reported and tested by:	peterj
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
kib 2014-05-29 16:18:31 +00:00
parent 2bf4c9cd3e
commit 7c98ae3376

View File

@ -721,21 +721,38 @@ ld_fsbase:
pushfq
cli
movl $MSR_GSBASE,%ecx
/* Save current kernel %gs base into %r12d:%r13d */
rdmsr
movl %eax,%r12d
movl %edx,%r13d
.globl ld_gs
ld_gs:
movw %si,%gs
/* Save user %gs base into %r14d:%r15d */
rdmsr
movl %eax,%r14d
movl %edx,%r15d
/* Restore kernel %gs base */
movl %r12d,%eax
movl %r13d,%edx
wrmsr
popfq
/*
* Restore user %gs base, either from PCB if used for TLS, or
* from the previously saved msr read.
*/
movl $MSR_KGSBASE,%ecx
cmpw $KUG32SEL,%si
jne 1f
movl $MSR_KGSBASE,%ecx
movl PCB_GSBASE(%r8),%eax
movl PCB_GSBASE+4(%r8),%edx
jmp ld_gsbase
1:
movl %r14d,%eax
movl %r15d,%edx
.globl ld_gsbase
ld_gsbase:
wrmsr
1:
wrmsr /* May trap if non-canonical, but only for TLS. */
.globl ld_es
ld_es:
movw TF_ES(%rsp),%es