sortix-mirror/kernel/x86/syscall.S
2017-06-12 21:26:26 +01:00

109 lines
2.9 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.
*
* x86/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:
/* -- stack is 12 bytes from being 16-byte aligned -- */
cld
movl $0, errno
pushl %ebp
/* -- stack is 8 bytes from being 16-byte aligned -- */
# Grant ourselves kernel permissions to the data segment.
movl %ds, %ebp
pushl %ebp
/* -- stack is 4 bytes from being 16-byte aligned -- */
movw $0x10, %bp
movl %ebp, %ds
movl %ebp, %es
# Make sure the requested system call is valid.
cmp $SYSCALL_MAX_NUM, %eax
jae 3f
1:
# Read a system call function pointer.
xorl %ebp, %ebp
movl syscall_list(%ebp,%eax,4), %eax
# Point the %ebp register to the pushed user-space %ebp above.
movl %esp, %ebp
addl $4, %ebp
# Call the system call.
pushl %esi
/* -- stack is 16-byte aligned -- */
pushl %edi
pushl %edx
pushl %ecx
pushl %ebx
/* -- stack is 16-byte aligned -- */
calll *%eax
addl $20, %esp
# Restore the previous permissions to data segment.
popl %ebp
movl %ebp, %ds
movl %ebp, %es
# Return to user-space, system call result in %eax:%edx, errno in %ecx.
popl %ebp
movl errno, %ecx
# Zero registers to avoid information leaks.
# eax is the return value.
# ecx is errno.
# edx is the return value (MIGHT NOT BE INITIALIZED, CAN LEAK!).
# ebx is set in a moment.
xor %esi, %esi
xor %edi, %edi
# If any signals are pending, fire them now.
movl asm_signal_is_pending, %ebx
testl %ebx, %ebx
jnz 4f
# ebx is zero in this branch.
2:
iretl
3:
# Call the null system call instead.
xorl %eax, %eax
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.
movl %esp, %ebx
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.
xor %ebx, %ebx
jmp 2b
.size syscall_handler, .-syscall_handler