QEMU handles bits bring written in the (reserved) high bits of SFMASK just fine, but KVM gives a #GP exception.
125 lines
2.3 KiB
ArmAsm
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 (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 (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 (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:
|