73 lines
2.1 KiB
C
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
|
|
);
|
|
}
|