The iret instruction may generate #np and #ss fault, besides #gp.

When returning to usermode, the handler for that exceptions is also
executed with wrong gs base.  Handle all three possible faults in the
same way, checking for iret fault, and performing full iret.

Sponsored by:	The FreeBSD Foundation
MFC after:	3 days
This commit is contained in:
Konstantin Belousov 2014-12-16 18:28:33 +00:00
parent 6b8c8dee3c
commit 2d45c2d52d

View File

@ -153,9 +153,13 @@ IDTVEC(xmm)
IDTVEC(tss) IDTVEC(tss)
TRAP_ERR(T_TSSFLT) TRAP_ERR(T_TSSFLT)
IDTVEC(missing) IDTVEC(missing)
TRAP_ERR(T_SEGNPFLT) subq $TF_ERR,%rsp
movl $T_SEGNPFLT,TF_TRAPNO(%rsp)
jmp prot_addrf
IDTVEC(stk) IDTVEC(stk)
TRAP_ERR(T_STKFLT) subq $TF_ERR,%rsp
movl $T_STKFLT,TF_TRAPNO(%rsp)
jmp prot_addrf
IDTVEC(align) IDTVEC(align)
TRAP_ERR(T_ALIGNFLT) TRAP_ERR(T_ALIGNFLT)
@ -318,6 +322,7 @@ IDTVEC(page)
IDTVEC(prot) IDTVEC(prot)
subq $TF_ERR,%rsp subq $TF_ERR,%rsp
movl $T_PROTFLT,TF_TRAPNO(%rsp) movl $T_PROTFLT,TF_TRAPNO(%rsp)
prot_addrf:
movq $0,TF_ADDR(%rsp) movq $0,TF_ADDR(%rsp)
movq %rdi,TF_RDI(%rsp) /* free up a GP register */ movq %rdi,TF_RDI(%rsp) /* free up a GP register */
leaq doreti_iret(%rip),%rdi leaq doreti_iret(%rip),%rdi