From 2be2236e99e5aed779b820b540d72dffb47da406 Mon Sep 17 00:00:00 2001
From: dzwdz
Date: Mon, 22 Jul 2024 20:49:58 +0200
Subject: kernel: explicitly store process RIP and RFLAGS

Once again, needed for the interrupt return syscall.
Seems to have made the kernel slower in timebench?
---
 src/kernel/arch/amd64/registers.h |  2 +-
 src/kernel/arch/amd64/sysenter.s  | 46 ++++++++++++++++++++++-----------------
 src/kernel/execbuf.c              |  2 +-
 src/kernel/proc.c                 |  6 ++---
 4 files changed, 31 insertions(+), 25 deletions(-)

(limited to 'src/kernel')

diff --git a/src/kernel/arch/amd64/registers.h b/src/kernel/arch/amd64/registers.h
index 5fd09c9..cfbfa54 100644
--- a/src/kernel/arch/amd64/registers.h
+++ b/src/kernel/arch/amd64/registers.h
@@ -7,7 +7,7 @@ struct CpuRegs {
 	uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
 	uint64_t rdi, rsi;
 	userptr_t rbp, rsp;
-	uint64_t rbx, rdx, rcx, rax;
+	uint64_t rbx, rdx, rcx, rax, rip, flags;
 	uint8_t _sse[512];
 } __attribute__((__packed__));
 
diff --git a/src/kernel/arch/amd64/sysenter.s b/src/kernel/arch/amd64/sysenter.s
index 8d91c4a..8e07dbb 100644
--- a/src/kernel/arch/amd64/sysenter.s
+++ b/src/kernel/arch/amd64/sysenter.s
@@ -41,13 +41,19 @@ stored_rsp:
 pagedir_current:
 	.skip 8
 
-// temporarily used for IRET
+/* fake stack used for IRET */
+.align 8
+iret_stack:
+iret_ip:
 	.skip 8
+iret_cs:
+	.quad SEG_r3code << 3 | 3
+iret_flags:
 	.skip 8
+iret_sp:
 	.skip 8
-	.skip 8
-	.skip 8
-dumb_stack:
+iret_ss:
+	.quad SEG_r3data << 3 | 3
 
 .global _sysexit_real
 .type _sysexit_real, @function
@@ -58,12 +64,6 @@ _sysexit_real:
 	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
-	 * as required [...] will result in an incorrect state restoration. */
-	// TODO will probably end up fucking something up in a hard to debug way
-	// sorry, future me. hopefully you have learned something from this
-	fxrstor (_sysexit_regs + 128)
 	mov $_sysexit_regs, %rsp
 	pop %r15
 	pop %r14
@@ -78,23 +78,25 @@ _sysexit_real:
 	pop %rdi
 	pop %rsi
 	pop %rbp
-	pop (stored_rsp)
+	pop (iret_sp)
 
 	pop %rbx
 	pop %rdx
 	pop %rcx
 	pop %rax
 
-	// enable paging
+	pop (iret_ip)
+	pop (iret_flags)
+
+	/* The state image referenced with an FXRSTOR instruction must have
+	 * been saved using an  FXSAVE instruction or be in the same format
+	 * as required [...] will result in an incorrect state restoration. */
+	fxrstor (%rsp)
+
 	mov (pagedir_current), %rsp
 	mov %rsp, %cr3
 
-	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 */
+	mov $iret_stack, %rsp
 	iretq
 
 sysenter_stage1:
@@ -105,8 +107,12 @@ sysenter_stage1:
 	mov $pml4_identity, %rsp
 	mov %rsp, %cr3
 
-	fxsave (_sysexit_regs + 128)
-	mov $(_sysexit_regs + 128), %rsp
+	mov $(_sysexit_regs + 144), %rsp
+	fxsave (%rsp)
+
+	push %r11 /* flags */
+	push %rcx /* ip */
+
 	push %rax
 	push %rcx
 	push %rdx
diff --git a/src/kernel/execbuf.c b/src/kernel/execbuf.c
index fe9e159..71fc662 100644
--- a/src/kernel/execbuf.c
+++ b/src/kernel/execbuf.c
@@ -36,7 +36,7 @@ _Noreturn void execbuf_run(Proc *proc) {
 
 			case EXECBUF_JMP:
 				try_fetch(proc, buf, 1);
-				proc->regs.rcx = buf[0];
+				proc->regs.rip = buf[0];
 				break;
 
 			default:
diff --git a/src/kernel/proc.c b/src/kernel/proc.c
index 6cc1679..a22f632 100644
--- a/src/kernel/proc.c
+++ b/src/kernel/proc.c
@@ -40,7 +40,7 @@ Proc *proc_seed(void *data, size_t datalen) {
 	for (uintptr_t off = 0; off < datalen; off += PAGE_SIZE)
 		pagedir_map(proc_first->pages, init_base + off, data + off, true, true);
 
-	proc_first->regs.rcx = (uintptr_t)init_base; // SYSRET jumps to %rcx
+	proc_first->regs.rip = (uintptr_t)init_base;
 	// proc_first->regs.r11 |= 1<<9; /* enable interrupts */
 
 	return proc_first;
@@ -372,12 +372,12 @@ void proc_intr(Proc *p, const char *buf, size_t len) {
 	/* save old rsp,rip */
 	struct intr_data d;
 	void __user *sp = p->regs.rsp - 128 - sizeof(d);
-	d.ip = (void __user *)p->regs.rcx;
+	d.ip = (void __user *)p->regs.rip;
 	d.sp = p->regs.rsp;
 	pcpy_to(p, sp, &d, sizeof(d));
 
 	/* switch to intr handler */
-	p->regs.rcx = (uint64_t)p->intr_fn;
+	p->regs.rip = (uint64_t)p->intr_fn;
 	p->regs.rsp = sp;
 }
 
-- 
cgit v1.2.3