Home | History | Annotate | Download | only in sys
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 	.file	"door.s"
     28 
     29 #include "SYS.h"
     30 #include <sys/door.h>
     31 
     32 	/*
     33 	 * weak aliases for public interfaces
     34 	 */
     35 	ANSI_PRAGMA_WEAK2(door_bind,__door_bind,function)
     36 	ANSI_PRAGMA_WEAK2(door_getparam,__door_getparam,function)
     37 	ANSI_PRAGMA_WEAK2(door_info,__door_info,function)
     38 	ANSI_PRAGMA_WEAK2(door_revoke,__door_revoke,function)
     39 	ANSI_PRAGMA_WEAK2(door_setparam,__door_setparam,function)
     40 	ANSI_PRAGMA_WEAK2(door_unbind,__door_unbind,function)
     41 
     42 /*
     43  * Offsets within struct door_results
     44  */
     45 #define	DOOR_COOKIE	_MUL(0, CLONGSIZE)
     46 #define	DOOR_DATA_PTR	_MUL(1, CLONGSIZE)
     47 #define	DOOR_DATA_SIZE	_MUL(2, CLONGSIZE)
     48 #define	DOOR_DESC_PTR	_MUL(3, CLONGSIZE)
     49 #define	DOOR_DESC_SIZE	_MUL(4, CLONGSIZE)
     50 #define	DOOR_PC		_MUL(5, CLONGSIZE)
     51 #define	DOOR_SERVERS	_MUL(6, CLONGSIZE)
     52 #define	DOOR_INFO_PTR	_MUL(7, CLONGSIZE)
     53 
     54 /*
     55  * All of the syscalls except door_return() follow the same pattern.
     56  * The subcode goes in argument 6, which means we have to copy our
     57  * arguments into a new bit of stack, large enough to include the
     58  * subcode.  We fill the unused positions with zeros.
     59  */
     60 #define	DOOR_SYSCALL(name, code, copy_args)				\
     61 	ENTRY(name);							\
     62 	pushl	%ebp;							\
     63 	movl	%esp, %ebp;						\
     64 	pushl	$code;		/* syscall subcode, arg 6 */		\
     65 	pushl	$0;		/* dummy arg 5 */			\
     66 	pushl	$0;		/* dummy arg 4 */			\
     67 	copy_args;		/* args 1, 2, 3 */			\
     68 	pushl	$0;		/* dummy return PC */			\
     69 	SYSTRAP_RVAL1(door);						\
     70 	jae	1f;							\
     71 	addl	$28, %esp;						\
     72 	leave;								\
     73 	jmp	__cerror;						\
     74 1:									\
     75 	addl	$28, %esp;						\
     76 	leave;								\
     77 	ret;								\
     78 	SET_SIZE(name)
     79 
     80 #define	COPY_0								\
     81 	pushl	$0;		/* dummy */				\
     82 	pushl	$0;		/* dummy */				\
     83 	pushl	$0		/* dummy */
     84 
     85 #define	COPY_1								\
     86 	pushl	$0;		/* dummy */				\
     87 	pushl	$0;		/* dummy */				\
     88 	pushl	8(%ebp)		/* 1 */
     89 
     90 #define	COPY_2								\
     91 	pushl	$0;		/* dummy */				\
     92 	pushl	12(%ebp);	/* 2 */					\
     93 	pushl	8(%ebp)		/* 1 */
     94 
     95 #define	COPY_3								\
     96 	pushl	16(%ebp);	/* 3 */					\
     97 	pushl	12(%ebp);	/* 2 */					\
     98 	pushl	8(%ebp)		/* 1 */
     99 
    100 	DOOR_SYSCALL(__door_bind,	DOOR_BIND,	COPY_1)
    101 	DOOR_SYSCALL(__door_call,	DOOR_CALL,	COPY_2)
    102 	DOOR_SYSCALL(__door_create,	DOOR_CREATE,	COPY_3)
    103 	DOOR_SYSCALL(__door_getparam,	DOOR_GETPARAM,	COPY_3)
    104 	DOOR_SYSCALL(__door_info,	DOOR_INFO,	COPY_2)
    105 	DOOR_SYSCALL(__door_revoke,	DOOR_REVOKE,	COPY_1)
    106 	DOOR_SYSCALL(__door_setparam,	DOOR_SETPARAM,	COPY_3)
    107 	DOOR_SYSCALL(__door_ucred,	DOOR_UCRED,	COPY_1)
    108 	DOOR_SYSCALL(__door_unbind,	DOOR_UNBIND,	COPY_0)
    109 	DOOR_SYSCALL(__door_unref,	DOOR_UNREFSYS,	COPY_0)
    110 
    111 /*
    112  * int
    113  * __door_return(
    114  *	void 			*data_ptr,
    115  *	size_t			data_size,	(in bytes)
    116  *	door_return_desc_t	*door_ptr,	(holds returned desc info)
    117  *	caddr_t			stack_base,
    118  *	size_t			stack_size)
    119  */
    120 	ENTRY(__door_return)
    121 	movl	%esp, %edx		/ Save pointer to args
    122 
    123 	pushl	%edi			/ save old %edi and %esi
    124 	pushl	%esi			/ and use them to hold the
    125 	movl	16(%edx), %esi		/ stack pointer and
    126 	movl	20(%edx), %edi		/ size.
    127 
    128 	pushl	$DOOR_RETURN		/ syscall subcode
    129 	pushl	%edi			/ size of user stack
    130 	pushl	%esi			/ base of user stack
    131 	pushl	12(%edx)		/ desc arguments ptr
    132 	pushl	8(%edx)			/ data size
    133 	pushl	4(%edx)			/ data ptr
    134 	pushl	0(%edx)			/ dummy return PC
    135 
    136 door_restart:
    137 	SYSTRAP_RVAL1(door)
    138 	jb	2f			/* errno is set */
    139 	/*
    140 	 * On return, we're serving a door_call.  Our stack looks like this:
    141 	 *
    142 	 *		descriptors (if any)
    143 	 *		data (if any)
    144 	 *	 sp->	struct door_results
    145 	 *
    146 	 * struct door_results has the arguments in place for the server proc,
    147 	 * so we just call it directly.
    148 	 */
    149 	movl	DOOR_SERVERS(%esp), %eax
    150 	andl	%eax, %eax	/* test nservers */
    151 	jg	1f
    152 	/*
    153 	 * this is the last server thread - call creation func for more
    154 	 */
    155 	movl	DOOR_INFO_PTR(%esp), %eax
    156 	_prologue_
    157 	pushl	%eax		/* door_info_t * */
    158 	movl	_daref_(door_server_func), %eax
    159 	movl	0(%eax), %eax
    160 	call	*%eax		/* call create function */
    161 	addl	$4, %esp
    162 	_epilogue_
    163 1:
    164 	/* Call the door server function now */
    165 	movl	DOOR_PC(%esp), %eax
    166 	call	*%eax
    167 	/* Exit the thread if we return here */
    168 	pushl	$0
    169 	call	_thrp_terminate
    170 	/* NOTREACHED */
    171 2:
    172 	/*
    173 	 * Error during door_return call.  Repark the thread in the kernel if
    174 	 * the error code is EINTR (or ERESTART) and this lwp is still part
    175 	 * of the same process.
    176 	 *
    177 	 * If the error code is EINTR or ERESTART, our stack may have been
    178 	 * corrupted by a partial door call, so we refresh the system call
    179 	 * arguments.
    180 	 */
    181 	cmpl	$ERESTART, %eax		/* ERESTART is same as EINTR */
    182 	jne	3f
    183 	movl	$EINTR, %eax
    184 3:
    185 	cmpl	$EINTR, %eax		/* interrupted while waiting? */
    186 	jne	4f			/* if not, return the error */
    187 	_prologue_
    188 	call	getpid
    189 	movl	_daref_(door_create_pid), %edx
    190 	movl	0(%edx), %edx
    191 	_epilogue_
    192 	cmpl	%eax, %edx		/* same process? */
    193 	movl	$EINTR, %eax	/* if no, return EINTR (child of forkall) */
    194 	jne	4f
    195 
    196 	movl	$0, 4(%esp)		/* clear arguments and restart */
    197 	movl	$0, 8(%esp)
    198 	movl	$0, 12(%esp)
    199 	movl	%esi, 16(%esp)		/* refresh sp */
    200 	movl	%edi, 20(%esp)		/* refresh ssize */
    201 	movl	$DOOR_RETURN, 24(%esp)	/* refresh syscall subcode */
    202 	jmp	door_restart
    203 4:
    204 	/* Something bad happened during the door_return */
    205 	addl	$28, %esp
    206 	popl	%esi
    207 	popl	%edi
    208 	jmp	__cerror
    209 	SET_SIZE(__door_return)
    210