/* Copyright (C) 2005 David Decotigny Copyright (C) 2004 The KOS Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "segment.h" /** * @file swintr_wrappers.S * * The SOS low-level handlers for the software interrupts. Currently * only 1 wrapper: that for the SOS syscalls. */ .file "swintr_wrappers.S" .text /* The address of the real "C" syscall function */ .extern sos_do_syscall /** Update the kernel TSS in case we are switching to a thread in user mode in order to come back into the correct kernel stack */ .extern sos_cpu_context_update_kernel_tss /* The address of the function to call to set back the user thread's MMU configuration upon return to user context */ .extern sos_thread_prepare_syscall_switch_back .p2align 2, 0x90 .globl sos_syscall_wrapper sos_syscall_wrapper: .type sos_syscall_wrapper,@function /* Fake error code */ pushl $0 /* Backup the context */ pushl %ebp movl %esp, %ebp pushl %edi pushl %esi pushl %edx pushl %ecx pushl %ebx pushl %eax subl $2,%esp pushw %ss pushw %ds pushw %es pushw %fs pushw %gs /* Set correct kernel segment descriptors' value */ movw $SOS_BUILD_SEGMENT_REG_VALUE(0, 0, SOS_SEG_KDATA), %di pushw %di ; popw %ds pushw %di ; popw %es pushw %di ; popw %fs pushw %di ; popw %gs /* Prepare the call to do_syscall */ pushl %esp /* user_ctxt */ pushl %eax /* syscall ID */ call sos_do_syscall /* Unallocate the stack used by the do_syscall arguments */ addl $8, %esp /* store the do_syscall return value into interrupted context */ movl %eax, 12(%esp) /* Set the MMU configuration to that of the user thread's process */ pushl %esp /* user_ctxt */ call sos_thread_prepare_syscall_switch_back addl $4, %esp /* Unallocate the stack */ /* Prepare kernel TSS because we are switching back to a user thread: we make sure that we will come back into the kernel at a correct stack location */ pushl %esp /* Pass the location of the context we are restoring to the function */ call sos_cpu_context_update_kernel_tss addl $4, %esp /* Restore the user context */ popw %gs popw %fs popw %es popw %ds popw %ss addl $2,%esp popl %eax /* This is the return value of do_syscall (see above) */ popl %ebx popl %ecx popl %edx popl %esi popl %edi popl %ebp /* Remove fake error code */ addl $4, %esp iret