Files
jsix_import/src/kernel/syscall.s
Justin C. Miller 5ea5978ee8 [kernel] Hide kernel symbols by default
Using `-fvisibility=hidden` when building the kernel, and then
`--discard-all` when stripping it, we shave almost 100KiB off of the
resulting ELF file.

Also dropped some unused symbols from the linker script, and rearranged
the sections so that the file is able to be mapped directly into memory
instead of having each section copied.
2023-01-29 20:27:21 -08:00

125 lines
2.3 KiB
ArmAsm

%include "tasking.inc"
%include "syscalls.inc"
; SYSCALL/SYSRET control MSRs
MSR_STAR equ 0xc0000081
MSR_LSTAR equ 0xc0000082
MSR_FMASK equ 0xc0000084
; IA32_STAR - high 32 bits contain k+u CS
; Kernel CS: GDT[1] ring 0 bits[47:32]
; User CS: GDT[3] ring 3 bits[63:48]
STAR_HIGH equ \
(((1 << 3) | 0)) | \
(((3 << 3) | 3) << 16)
; IA32_FMASK - Mask off interrupts in syscalls
FMASK_VAL equ 0x200
extern __counter_syscall_enter
extern __counter_syscall_sysret
extern syscall_registry
extern syscall_invalid
global syscall_handler_prelude: function hidden (syscall_handler_prelude.end - syscall_handler_prelude)
syscall_handler_prelude:
push rbp ; Never executed, fake function prelude
mov rbp, rsp ; to calm down gdb
.real:
swapgs
mov [gs:CPU_DATA.rsp3], rsp
mov rsp, [gs:CPU_DATA.rsp0]
mov [gs:CPU_DATA.rflags3], r11
push rcx
push rbp
mov rbp, rsp
; account for the hole in the sysv abi
; argument list since SYSCALL uses rcx.
; r10 is non-preserved but not part of
; the function call ABI, so the rcx arg
; was stashed there.
mov rcx, r10
push rbx
push r12
push r13
push r14
push r15
; if we've got more than 6 arguments, the rest
; are on the user stack, and pointed to by rbx.
; push rbx so that it's the 7th argument.
push rbx
inc qword [rel __counter_syscall_enter]
cmp rax, NUM_SYSCALLS
jge .bad_syscall
lea r11, [rel syscall_registry]
mov r11, [r11 + rax * 8]
cmp r11, 0
je .bad_syscall
call r11
add rsp, 8 ; account for passing rbx on the stack
inc qword [rel __counter_syscall_sysret]
jmp kernel_to_user_trampoline
.bad_syscall:
mov rdi, rax
call syscall_invalid
.end:
global kernel_to_user_trampoline: function hidden (kernel_to_user_trampoline.end - kernel_to_user_trampoline)
kernel_to_user_trampoline:
pop r15
pop r14
pop r13
pop r12
pop rbx
pop rbp
pop rcx
mov r11, [gs:CPU_DATA.tss]
mov [r11 + TSS.rsp0], rsp
mov [gs:CPU_DATA.rsp0], rsp
mov rsp, [gs:CPU_DATA.rsp3]
mov r11, [gs:CPU_DATA.rflags3]
swapgs
o64 sysret
.end:
global syscall_enable: function hidden (syscall_enable.end - syscall_enable)
syscall_enable:
push rbp
mov rbp, rsp
mov rcx, MSR_STAR
mov rax, 0
mov rdx, STAR_HIGH
wrmsr
mov rcx, MSR_LSTAR
mov rax, syscall_handler_prelude.real
mov rdx, rax
shr rdx, 32
wrmsr
mov rcx, MSR_FMASK
mov rax, FMASK_VAL
mov rdx, 0
wrmsr
pop rbp
ret
.end: