Files
zinnia/arch/x86_64/syscall.c
T
2026-09-25 15:39:16 +02:00

73 lines
2.1 KiB
C

#include <zinnia/compiler.h>
#include <zinnia/percpu.h>
#include <zinnia/syscall.h>
#include <bits/sched.h>
#include <stddef.h>
#include <x86_64/defs.h>
#include <x86_64/gdt.h>
// TODO: Refactor to only push callee-saved registers.
[[__naked]]
void arch_syscall_stub() {
asm volatile(
" swapgs\n"
" mov gs:%c0, rsp\n" // user_stack
" mov rsp, gs:%c1\n" // kernel_stack
" cld\n"
"1:\n"
" push %c3\n" // ss
" push gs:%c0\n"
" push r11\n" // rflags
" push %c2\n" // cs
" push rcx\n" // rip
" push 0x00\n" // arch_context::error
" push 0x00\n" // arch_context::isr
" push rax\n"
" push rbx\n"
" push rcx\n"
" push rdx\n"
" push rbp\n"
" push rdi\n"
" push rsi\n"
" push r8\n"
" push r9\n"
" push r10\n"
" push r11\n"
" push r12\n"
" push r13\n"
" push r14\n"
" push r15\n"
" xor rbp, rbp\n"
" mov rdi, rsp\n" // SysV ABI first argument.
" call %4\n" // Call syscall handler.
" cli\n"
" pop r15\n"
" pop r14\n"
" pop r13\n"
" pop r12\n"
" pop r11\n"
" pop r10\n"
" pop r9\n"
" pop r8\n"
" pop rsi\n"
" pop rdi\n"
" pop rbp\n"
" pop rdx\n"
" pop rcx\n"
" pop rbx\n"
" pop rax\n"
" add rsp, 0x10\n" // Skip .error and .isr fields
"2:\n"
" mov rsp, gs:%c0\n" // user_stack
" swapgs\n"
" sysretq\n"
:
: "i"(offsetof(struct percpu, user_stack)), // 0
"i"(offsetof(struct percpu, kernel_stack)), // 1
"i"(offsetof(struct gdt, user_code64) | CPL_USER), // 2
"i"(offsetof(struct gdt, user_data) | CPL_USER), // 3
"r"(syscall_dispatch) // 4
);
}