From acf0c1333d620821820b2246e1c7acc0aaf0bd44 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Mon, 22 Jul 2024 19:31:21 +0200 Subject: 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. --- src/kernel/arch/amd64/sysenter.s | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src/kernel/arch') 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 -- cgit v1.2.3