minix/kernel/arch/i386/usermapped_glo_ipc.S
Ben Gras 2d72cbec41 SYSENTER/SYSCALL support
. add cpufeature detection of both
	. use it for both ipc and kernelcall traps, using a register
	  for call number
	. SYSENTER/SYSCALL does not save any context, therefore userland
	  has to save it
	. to accomodate multiple kernel entry/exit types, the entry
	  type is recorded in the process struct. hitherto all types
	  were interrupt (soft int, exception, hard int); now SYSENTER/SYSCALL
	  is new, with the difference that context is not fully restored
	  from proc struct when running the process again. this can't be
	  done as some information is missing.
	. complication: cases in which the kernel has to fully change
	  process context (i.e. sigreturn). in that case the exit type
	  is changed from SYSENTER/SYSEXIT to soft-int (i.e. iret) and
	  context is fully restored from the proc struct. this does mean
	  the PC and SP must change, as the sysenter/sysexit userland code
	  will otherwise try to restore its own context. this is true in the
	  sigreturn case.
	. override all usage by setting libc_ipc=1
2012-09-24 15:53:43 +02:00

95 lines
2.7 KiB
ArmAsm

#include <minix/ipcconst.h>
#include <machine/asm.h>
/**========================================================================* */
/* IPC assembly routines * */
/**========================================================================* */
/* all message passing routines save ebx, but destroy eax and ecx. */
#define IPCFUNC(name,SETARGS,VEC,POSTTRAP) \
ENTRY(usermapped_ ## name ## _softint) ;\
push %ebp ;\
movl %esp, %ebp ;\
push %ebx ;\
SETARGS ;\
int $VEC /* trap to the kernel */ ;\
mov %ebx, %ecx /* save %ebx */ ;\
POSTTRAP ;\
pop %ebx ;\
pop %ebp ;\
ret ;\
ENTRY(usermapped_ ## name ## _sysenter) ;\
push %ebp ;\
movl %esp, %ebp ;\
push %ebp ;\
push %edx ;\
push %ebx ;\
push %esi ;\
push %edi ;\
movl %esp, %esi /* kernel uses %esi for restored %esp */;\
movl $0f, %edx /* kernel uses %edx for restored %eip */;\
movl $VEC, %edi /* %edi to distinguish ipc/kerncall */ ;\
SETARGS /* call-specific register setup */ ;\
sysenter /* disappear into kernel */ ;\
0: ;\
mov %ebx, %ecx /* return w. state mangled; save %ebx */;\
pop %edi ;\
pop %esi ;\
pop %ebx ;\
pop %edx ;\
pop %ebp ;\
POSTTRAP ;\
pop %ebp ;\
ret ;\
ENTRY(usermapped_ ## name ## _syscall) ;\
push %ebp ;\
movl %esp, %ebp ;\
push %ebp ;\
push %edx ;\
push %ebx ;\
push %esi ;\
push %edi ;\
movl $VEC, %edi /* %edi to distinguish ipc/kerncall */ ;\
SETARGS /* call-specific register setup */ ;\
movl %ecx, %edx /* %ecx is clobbered by SYSCALL */ ;\
syscall /* disappear into kernel */ ;\
mov %ebx, %ecx /* return w. state mangled; save %ebx */;\
pop %edi ;\
pop %esi ;\
pop %ebx ;\
pop %edx ;\
pop %ebp ;\
POSTTRAP ;\
pop %ebp ;\
ret
#define IPCARGS(opcode) \
movl 8(%ebp), %eax /* eax = dest-src */ ;\
movl 12(%ebp), %ebx /* ebx = message pointer */ ;\
movl $opcode, %ecx ;\
#define SENDA_ARGS \
movl 12(%ebp), %eax /* eax = count */ ;\
movl 8(%ebp), %ebx /* ebx = table */ ;\
movl $SENDA, %ecx ;\
#define GETSTATUS \
push %eax ;\
movl 16(%ebp), %eax /* ecx = saved %ebx */ ;\
movl %ecx, (%eax) ;\
pop %eax
#define KERNARGS mov 8(%ebp), %eax
IPCFUNC(send,IPCARGS(SEND),IPCVEC_UM,)
IPCFUNC(receive,IPCARGS(RECEIVE),IPCVEC_UM,GETSTATUS)
IPCFUNC(sendrec,IPCARGS(SENDREC),IPCVEC_UM,)
IPCFUNC(sendnb,IPCARGS(SENDNB),IPCVEC_UM,)
IPCFUNC(notify,IPCARGS(NOTIFY),IPCVEC_UM,)
IPCFUNC(senda,SENDA_ARGS,IPCVEC_UM,)
IPCFUNC(do_kernel_call,KERNARGS,KERVEC_UM,)
.data
LABEL(usermapped_offset)
.space 4