From bd39fce5dfabb9633e31e96e8e73c552ac0b701a Mon Sep 17 00:00:00 2001
From: Amelia Coutard <eliottulio.coutard@gmail.com>
Date: Sun, 9 Apr 2023 00:15:15 +0200
Subject: [PATCH] Saved all registers required by the system V ABI. (Except for
 the disabled SSE2 one.)

---
 kernel/src/ring3.S   | 42 ++++++++++++++++++++++++++++++++++++++----
 kernel/src/ring3.hpp |  4 ++--
 2 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/kernel/src/ring3.S b/kernel/src/ring3.S
index 6d9b55f..a3a0e76 100644
--- a/kernel/src/ring3.S
+++ b/kernel/src/ring3.S
@@ -37,17 +37,50 @@ load_tss:
 
 .globl syscall_64bit_handler
 syscall_64bit_handler:
-	push %rcx
+	push %rax
+	movq current_pid, %rax
+	shl $17, %rax # * 0x1000 * 32 (i.e. the size of a process)
+	addq process_struct_table, %rax
+	# %rax now contains the address of the current process struct.
+	movq %rcx, 0x10(%rax) # %rip
+	movq %rbx, 0x18(%rax)
+	movq %rsp, 0x20(%rax) # original %rsp
+	addq $8, 0x20(%rax) # here as well
+	movq %rbp, 0x28(%rax)
+	movq %r12, 0x30(%rax)
+	movq %r13, 0x38(%rax)
+	movq %r14, 0x40(%rax)
+	movq %r15, 0x48(%rax)
+	fstcw 0x58(%rax)
+	# Current process registers have now all been updated.
+	pop %rax
+
 	mov %r10, %rcx
 	cmp $syscall_n, %rax
 	jae incorrect_syscall
 	callq *syscalls_call_table(, %rax, 8)
-	pop %rcx
+syscall_end:
+	movq %rax, %rbp
+	movq current_pid, %rax
+	shl $17, %rax # * 0x1000 * 32 (i.e. the size of a process)
+	addq process_struct_table, %rax
+	# %rax now contains the address of the current process struct.
+	movq 0x10(%rax), %rcx # %rip
+	movq 0x18(%rax), %rbx
+	movq 0x20(%rax), %rsp
+	push %rbp # %rax
+	movq 0x28(%rax), %rbp
+	movq 0x30(%rax), %r12
+	movq 0x38(%rax), %r13
+	movq 0x40(%rax), %r14
+	movq 0x48(%rax), %r15
+	fldcw 0x58(%rax)
+	# Current process registers have now all been updated.
+	pop %rax
 	sysretq
 incorrect_syscall:
 	call syscall_rax_error_handler
-	pop %rcx
-	sysretq
+	jmp syscall_end
 
 .section .rodata
 syscalls_call_table:
@@ -55,3 +88,4 @@ syscalls_call_table:
 	.quad syscall_println
 	.quad syscall_print_low_mmap
 .set syscall_n, 3
+process_struct_table: .quad 0xFFFFC00000000000
diff --git a/kernel/src/ring3.hpp b/kernel/src/ring3.hpp
index 1450d04..7d26636 100644
--- a/kernel/src/ring3.hpp
+++ b/kernel/src/ring3.hpp
@@ -71,7 +71,7 @@ struct process {
 	std::uint64_t r13;
 	std::uint64_t r14;
 	std::uint64_t r15;
-	std::uint64_t mxcsr;
+	std::uint64_t mxcsr; // UNUSED for now.
 	std::uint64_t x87cw;
 	port ports[4093];
 };
@@ -88,6 +88,6 @@ inline bool port_exists(std::uint64_t pid, std::uint64_t port) {
 	return port < 4093 && process_exists(pid) && get_process(pid).ports[port].exists;
 }
 
-extern std::uint64_t current_pid;
+extern "C" std::uint64_t current_pid;
 
 } // namespace os
-- 
2.46.0