sortix-mirror/kernel/x64/syscall.S

133 lines
3.4 KiB
ArmAsm

/*
* Copyright (c) 2011, 2012, 2013, 2014, 2015 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* x64/syscall.S
* An assembly stub that acts as glue for system calls.
*/
#include <sortix/syscall.h>
.global syscall_handler
.section .text
.type syscall_handler, @function
syscall_handler:
cld
movl $0, errno
pushq %rbp
movq %rsp, %rbp
pushq %rax
sub $8, %rsp
pushf
pop %r10
mov $0x200, %r11
test %r10, %r11
jz 5f
# Make sure the requested system call is valid, if not, then fix it.
mov %rax, %r10
cmp $SYSCALL_MAX_NUM, %rax
jae 3f
1:
# Read a system call function pointer.
xorq %r11, %r11
movq syscall_list(%r11,%rax,8), %rax
# Oh how nice, user-space put the parameters in: rdi, rsi, rdx, rcx, r8, r9
# Call the system call.
callq *%rax
pushf
pop %rsi
mov $0x200, %r8
test %rsi, %r8
jz 6f
addq $16, %rsp
# Return to user-space, system call result in %rax:%rdx, errno in %ecx.
popq %rbp
movl errno, %ecx
# Zero registers to avoid information leaks.
# rax is return value.
# rdi is set in a moment.
xor %rsi, %rsi
# rdx is return value (MIGHT NOT BE INITIALIZED, CAN LEAK!).
# rcx is errno.
xor %r8, %r8
xor %r9, %r9
xor %r10, %r10
xor %r11, %r11
# The rest of the registers are preserved by the ABI and syscall ABI.
# If any signals are pending, fire them now.
movq asm_signal_is_pending, %rdi
testq %rdi, %rdi
jnz 4f
# rdi is zero in this branch.
2:
iretq
3:
# Call the null system call instead.
xorq %rax, %rax
jmp 1b
4:
# We can't return to this location after the signal, since if any system
# call is made this stack will get reused and all our nice temporaries wil
# be garbage. We therefore pass the kernel the state to return to and it'll
# handle it for us when the signal is over.
movq 0(%rsp), %rdi # userspace rip
movq 16(%rsp), %rsi # userspace rflags
movq 24(%rsp), %r8 # userspace rsp, note %rcx is used for errno
int $130 # Deliver pending signals.
# If we end up here, it means that the signal didn't override anything and
# that we should just go ahead and return to userspace ourselves. Zero the
# scratch registers to avoid information leaks.
xor %rdi, %rdi
xor %rsi, %rsi
xor %r8, %r8
jmp 2b
5:
mov $syscall_interrupt_string_before, %rdi
jmp 7f
6:
mov $syscall_interrupt_string_after, %rdi
jmp 7f
7:
add $8, %rsp
pop %rsi
call PanicF
.size syscall_handler, .-syscall_handler
.section .rodata
.type syscall_interrupt_string_before, @object
.size syscall_interrupt_string_before, 56
syscall_interrupt_string_before:
.string "System call %u exited without interrupts enabled before"
.type syscall_interrupt_string_after, @object
.size syscall_interrupt_string_after, 55
syscall_interrupt_string_after:
.string "System call %u exited without interrupts enabled after"