diff options
author | dzwdz | 2024-07-22 19:31:21 +0200 |
---|---|---|
committer | dzwdz | 2024-07-22 19:31:21 +0200 |
commit | acf0c1333d620821820b2246e1c7acc0aaf0bd44 (patch) | |
tree | 77b6843892793039f7ca005f1ced6d173e00295b /src/kernel | |
parent | 2a09d77902c5007fb30c40f9c89ecb46aedf4006 (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/kernel')
-rw-r--r-- | src/kernel/arch/amd64/sysenter.s | 21 |
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 |