diff options
author | 2011-07-04 15:54:24 +0000 | |
---|---|---|
committer | 2011-07-04 15:54:24 +0000 | |
commit | 1396572dbc2406b717937a7e52f80e062def9901 (patch) | |
tree | df4f5f493913e516e716015583120451cfcd62a7 | |
parent | - Take into account padding for the IEEE extended shape types. It (diff) | |
download | wireguard-openbsd-1396572dbc2406b717937a7e52f80e062def9901.tar.xz wireguard-openbsd-1396572dbc2406b717937a7e52f80e062def9901.zip |
Force the sigreturn syscall to return to userspace via iretq by setting
the MDP_IRET flag in md_proc, then switch sigcode to enter the kernel
via syscall instead of int$80. Rearrange the return paths in both the
sysretq and iretq paths to reduce how long interrupts are blocked and
shave instructions.
ok kettenis@, extra testing krw@
-rw-r--r-- | sys/arch/amd64/amd64/locore.S | 70 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/machdep.c | 12 | ||||
-rw-r--r-- | sys/arch/amd64/include/frameasm.h | 20 |
3 files changed, 59 insertions, 43 deletions
diff --git a/sys/arch/amd64/amd64/locore.S b/sys/arch/amd64/amd64/locore.S index 9ab0e28127f..b23921787bb 100644 --- a/sys/arch/amd64/amd64/locore.S +++ b/sys/arch/amd64/amd64/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.47 2011/04/13 02:49:12 guenther Exp $ */ +/* $OpenBSD: locore.S,v 1.48 2011/07/04 15:54:24 guenther Exp $ */ /* $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $ */ /* @@ -637,12 +637,6 @@ longmode_hi: /* * Signal trampoline; copied to top of user stack. - * - * Note, the "system call" to sigreturn() needs to be an 'int $0x80' one - * so that the kernel returns using 'iretq' method. This way if a process - * was interrupted (by tick) as opposed to in the kernel when a signal was - * being delivered, the process will be completely restored, including the - * userland %rcx register, which the 'sysret' instruction can not restore. */ NENTRY(sigcode) call *%rax @@ -650,7 +644,7 @@ NENTRY(sigcode) movq %rsp,%rdi pushq %rdi /* fake return address */ movq $SYS_sigreturn,%rax - int $0x80 + syscall movq $SYS_exit,%rax syscall .globl _C_LABEL(esigcode) @@ -958,17 +952,28 @@ syscall_return: #ifdef DIAGNOSTIC cmpl $IPL_NONE,CPUVAR(ILEVEL) jne 3f -#endif - /* - * XXX interrupts off longer than they should be here. - */ +#endif /* DIAGNOSTIC */ + + movq TF_RDI(%rsp),%rdi + movq TF_RSI(%rsp),%rsi + movq TF_R8(%rsp),%r8 + movq TF_R9(%rsp),%r9 + movq TF_R10(%rsp),%r10 + movq TF_R12(%rsp),%r12 + movq TF_R13(%rsp),%r13 + movq TF_R14(%rsp),%r14 + movq TF_R15(%rsp),%r15 + movq TF_RBP(%rsp),%rbp + movq TF_RBX(%rsp),%rbx + INTR_RESTORE_SELECTORS - INTR_RESTORE_GPRS - addq $48,%rsp - popq %rcx /* return rip */ - addq $8,%rsp - popq %r11 /* flags as set by sysret insn */ - movq %ss:(%rsp),%rsp + + movq TF_RDX(%rsp),%rdx + movq TF_RAX(%rsp),%rax + + movq TF_RIP(%rsp),%rcx + movq TF_RFLAGS(%rsp),%r11 + movq TF_RSP(%rsp),%rsp sysretq #ifdef DIAGNOSTIC @@ -1007,11 +1012,9 @@ NENTRY(child_trampoline) call *%r12 jmp syscall_return - .globl _C_LABEL(osyscall_return) - /* - * Trap gate entry for int $80 syscall, also used by sigreturn. + * Trap gate entry for old int $80 syscall (used to be used by sigreturn) */ IDTVEC(osyscall) pushq $2 # size of instruction for restart @@ -1035,6 +1038,9 @@ _C_LABEL(osyscall_return): call _C_LABEL(trap) jmp 2b +/* + * Return via iretq, for real interrupts and signal returns + */ iret_return: 1: #ifdef DIAGNOSTIC @@ -1043,11 +1049,29 @@ iret_return: #endif /* DIAGNOSTIC */ .globl intr_fast_exit intr_fast_exit: + movq TF_RDI(%rsp),%rdi + movq TF_RSI(%rsp),%rsi + movq TF_R8(%rsp),%r8 + movq TF_R9(%rsp),%r9 + movq TF_R10(%rsp),%r10 + movq TF_R12(%rsp),%r12 + movq TF_R13(%rsp),%r13 + movq TF_R14(%rsp),%r14 + movq TF_R15(%rsp),%r15 + movq TF_RBP(%rsp),%rbp + movq TF_RBX(%rsp),%rbx + testq $SEL_UPL,TF_CS(%rsp) je 5f + INTR_RESTORE_SELECTORS -5: INTR_RESTORE_GPRS - addq $48,%rsp + +5: movq TF_RDX(%rsp),%rdx + movq TF_RCX(%rsp),%rcx + movq TF_R11(%rsp),%r11 + movq TF_RAX(%rsp),%rax + addq $TF_RIP,%rsp + .globl _C_LABEL(doreti_iret) _C_LABEL(doreti_iret): iretq diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index 321859c3889..d18fd2ed792 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.146 2011/07/04 06:05:56 guenther Exp $ */ +/* $OpenBSD: machdep.c,v 1.147 2011/07/04 15:54:24 guenther Exp $ */ /* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */ /*- @@ -670,6 +670,16 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval) p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; p->p_sigmask = ksc.sc_mask & ~sigcantmask; + /* + * sigreturn() needs to return to userspace via the 'iretq' + * method, so that if the process was interrupted (by tick, + * an IPI, whatever) as opposed to already being in the kernel + * when a signal was being delivered, the process will be + * completely restored, including the userland %rcx and %r11 + * registers which the 'sysretq' instruction cannot restore. + */ + p->p_md.md_flags |= MDP_IRET; + return (EJUSTRETURN); } diff --git a/sys/arch/amd64/include/frameasm.h b/sys/arch/amd64/include/frameasm.h index 57fb5bff2c8..83388ab874d 100644 --- a/sys/arch/amd64/include/frameasm.h +++ b/sys/arch/amd64/include/frameasm.h @@ -1,4 +1,4 @@ -/* $OpenBSD: frameasm.h,v 1.5 2011/04/13 02:49:12 guenther Exp $ */ +/* $OpenBSD: frameasm.h,v 1.6 2011/07/04 15:54:24 guenther Exp $ */ /* $NetBSD: frameasm.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */ #ifndef _AMD64_MACHINE_FRAMEASM_H @@ -30,24 +30,6 @@ movq %rcx,TF_RCX(%rsp) ; \ movq %rax,TF_RAX(%rsp) -#define INTR_RESTORE_GPRS \ - movq TF_R15(%rsp),%r15 ; \ - movq TF_R14(%rsp),%r14 ; \ - movq TF_R13(%rsp),%r13 ; \ - movq TF_R12(%rsp),%r12 ; \ - movq TF_R11(%rsp),%r11 ; \ - movq TF_R10(%rsp),%r10 ; \ - movq TF_R9(%rsp),%r9 ; \ - movq TF_R8(%rsp),%r8 ; \ - movq TF_RDI(%rsp),%rdi ; \ - movq TF_RSI(%rsp),%rsi ; \ - movq TF_RBP(%rsp),%rbp ; \ - movq TF_RBX(%rsp),%rbx ; \ - movq TF_RDX(%rsp),%rdx ; \ - movq TF_RCX(%rsp),%rcx ; \ - movq TF_RAX(%rsp),%rax ; \ - addq $120,%rsp - #define INTRENTRY \ subq $32,%rsp ; \ testq $SEL_UPL,56(%rsp) ; \ |