summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordzwdz2024-07-22 19:31:21 +0200
committerdzwdz2024-07-22 19:31:21 +0200
commitacf0c1333d620821820b2246e1c7acc0aaf0bd44 (patch)
tree77b6843892793039f7ca005f1ced6d173e00295b /src
parent2a09d77902c5007fb30c40f9c89ecb46aedf4006 (diff)
kernel: use IRET instead of SYSRET for switching into usermode
I want to implement a new syscall for returning from "interrupts" (my crappy take on Plan 9's notes / UNIX signals), and I've realized that I can't use SYSRET for that, as it clobbers RCX and R11. This hasn't been an issue so far, as I've only been switching into usermode to return from syscalls, but now I might be switching into it at arbitrary moments (right after an interrupt handler recovers from a page fault, etc). I could make it so I switch between IRET and SYSRET depending on the context, but I don't think it's worth it.
Diffstat (limited to 'src')
-rw-r--r--src/kernel/arch/amd64/sysenter.s21
1 files changed, 17 insertions, 4 deletions
diff --git a/src/kernel/arch/amd64/sysenter.s b/src/kernel/arch/amd64/sysenter.s
index c1af69f..8d91c4a 100644
--- a/src/kernel/arch/amd64/sysenter.s
+++ b/src/kernel/arch/amd64/sysenter.s
@@ -2,6 +2,7 @@
.set SEG_r0code, 1
.set SEG_r3code32, 3
.set SEG_r3data, 4
+.set SEG_r3code, 5
.set IA32_STAR, 0xC0000081
.set IA32_LSTAR, 0xC0000082
@@ -40,16 +41,22 @@ stored_rsp:
pagedir_current:
.skip 8
+// temporarily used for IRET
+ .skip 8
+ .skip 8
+ .skip 8
+ .skip 8
+ .skip 8
+dumb_stack:
+
.global _sysexit_real
.type _sysexit_real, @function
_sysexit_real:
- /* TODO check if SYSRET correctly sets segments
mov $(SEG_r3data << 3 | 3), %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
- */
/* The state image referenced with an FXRSTOR instruction must have
* been saved using an FXSAVE instruction or be in the same format
@@ -81,8 +88,14 @@ _sysexit_real:
// enable paging
mov (pagedir_current), %rsp
mov %rsp, %cr3
- mov (stored_rsp), %rsp
- sysretq
+
+ mov $dumb_stack, %rsp
+ push $(SEG_r3data << 3 | 3) /* SS */
+ push (stored_rsp) /* SP */
+ push %r11 /* FLAGS */
+ push $(SEG_r3code << 3 | 3) /* CS */
+ push %rcx /* IP */
+ iretq
sysenter_stage1:
cli