summaryrefslogtreecommitdiffstats
path: root/sys/amd64/amd64
diff options
context:
space:
mode:
Diffstat (limited to 'sys/amd64/amd64')
-rw-r--r--sys/amd64/amd64/exception.S33
1 files changed, 33 insertions, 0 deletions
diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S
index f2339f8..220cf23 100644
--- a/sys/amd64/amd64/exception.S
+++ b/sys/amd64/amd64/exception.S
@@ -339,6 +339,9 @@ IDTVEC(prot)
* and the new privilige level. We are still running on the old user stack
* pointer. We have to juggle a few things around to find our stack etc.
* swapgs gives us access to our PCPU space only.
+ *
+ * We do not support invoking this from a custom %cs or %ss (e.g. using
+ * entries from an LDT).
*/
IDTVEC(fast_syscall)
swapgs
@@ -380,6 +383,36 @@ IDTVEC(fast_syscall)
movq %rsp,%rdi
call syscall
movq PCPU(CURPCB),%rax
+ testq $PCB_FULL_IRET,PCB_FLAGS(%rax)
+ jne 3f
+1: /* Check for and handle AST's on return to userland. */
+ cli
+ movq PCPU(CURTHREAD),%rax
+ testl $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax)
+ je 2f
+ sti
+ movq %rsp, %rdi
+ call ast
+ jmp 1b
+2: /* Restore preserved registers. */
+ MEXITCOUNT
+ movq TF_RDI(%rsp),%rdi /* bonus; preserve arg 1 */
+ movq TF_RSI(%rsp),%rsi /* bonus: preserve arg 2 */
+ movq TF_RDX(%rsp),%rdx /* return value 2 */
+ movq TF_RAX(%rsp),%rax /* return value 1 */
+ movq TF_RBX(%rsp),%rbx /* C preserved */
+ movq TF_RBP(%rsp),%rbp /* C preserved */
+ movq TF_R12(%rsp),%r12 /* C preserved */
+ movq TF_R13(%rsp),%r13 /* C preserved */
+ movq TF_R14(%rsp),%r14 /* C preserved */
+ movq TF_R15(%rsp),%r15 /* C preserved */
+ movq TF_RFLAGS(%rsp),%r11 /* original %rflags */
+ movq TF_RIP(%rsp),%rcx /* original %rip */
+ movq TF_RSP(%rsp),%r9 /* user stack pointer */
+ movq %r9,%rsp /* original %rsp */
+ swapgs
+ sysretq
+3: /* Requested full context restore, use doreti for that. */
MEXITCOUNT
jmp doreti
OpenPOWER on IntegriCloud