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 2009 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 
     41 /*
     42  * Offsets within struct door_results
     43  */
     44 #define	DOOR_COOKIE	_MUL(0, CLONGSIZE)
     45 #define	DOOR_DATA_PTR	_MUL(1, CLONGSIZE)
     46 #define	DOOR_DATA_SIZE	_MUL(2, CLONGSIZE)
     47 #define	DOOR_DESC_PTR	_MUL(3, CLONGSIZE)
     48 #define	DOOR_DESC_SIZE	_MUL(4, CLONGSIZE)
     49 #define	DOOR_PC		_MUL(5, CLONGSIZE)
     50 #define	DOOR_SERVERS	_MUL(6, CLONGSIZE)
     51 #define	DOOR_INFO_PTR	_MUL(7, CLONGSIZE)
     52 
     53 /*
     54  * All of the syscalls except door_return() follow the same pattern.
     55  * The subcode goes in argument 6, which means we have to copy our
     56  * arguments into a new bit of stack, large enough to include the
     57  * subcode.  We fill the unused positions with zeros.
     58  */
     59 #define	DOOR_SYSCALL(name, code, copy_args)				\
     60 	ENTRY(name);							\
     61 	pushl	%ebp;							\
     62 	movl	%esp, %ebp;						\
     63 	pushl	$code;		/* syscall subcode, arg 6 */		\
     64 	pushl	$0;		/* dummy arg 5 */			\
     65 	pushl	$0;		/* dummy arg 4 */			\
     66 	copy_args;		/* args 1, 2, 3 */			\
     67 	pushl	$0;		/* dummy return PC */			\
     68 	SYSTRAP_RVAL1(door);						\
     69 	jae	1f;							\
     70 	addl	$28, %esp;						\
     71 	leave;								\
     72 	jmp	__cerror;						\
     73 1:									\
     74 	addl	$28, %esp;						\
     75 	leave;								\
     76 	ret;								\
     77 	SET_SIZE(name)
     78 
     79 #define	COPY_0								\
     80 	pushl	$0;		/* dummy */				\
     81 	pushl	$0;		/* dummy */				\
     82 	pushl	$0		/* dummy */
     83 
     84 #define	COPY_1								\
     85 	pushl	$0;		/* dummy */				\
     86 	pushl	$0;		/* dummy */				\
     87 	pushl	8(%ebp)		/* 1 */
     88 
     89 #define	COPY_2								\
     90 	pushl	$0;		/* dummy */				\
     91 	pushl	12(%ebp);	/* 2 */					\
     92 	pushl	8(%ebp)		/* 1 */
     93 
     94 #define	COPY_3								\
     95 	pushl	16(%ebp);	/* 3 */					\
     96 	pushl	12(%ebp);	/* 2 */					\
     97 	pushl	8(%ebp)		/* 1 */
     98 
     99 	DOOR_SYSCALL(__door_bind,	DOOR_BIND,	COPY_1)
    100 	DOOR_SYSCALL(__door_call,	DOOR_CALL,	COPY_2)
    101 	DOOR_SYSCALL(__door_create,	DOOR_CREATE,	COPY_3)
    102 	DOOR_SYSCALL(__door_getparam,	DOOR_GETPARAM,	COPY_3)
    103 	DOOR_SYSCALL(__door_info,	DOOR_INFO,	COPY_2)
    104 	DOOR_SYSCALL(__door_revoke,	DOOR_REVOKE,	COPY_1)
    105 	DOOR_SYSCALL(__door_setparam,	DOOR_SETPARAM,	COPY_3)
    106 	DOOR_SYSCALL(__door_ucred,	DOOR_UCRED,	COPY_1)
    107 	DOOR_SYSCALL(__door_unbind,	DOOR_UNBIND,	COPY_0)
    108 	DOOR_SYSCALL(__door_unref,	DOOR_UNREFSYS,	COPY_0)
    109 
    110 /*
    111  * int
    112  * __door_return(
    113  *	void 			*data_ptr,
    114  *	size_t			data_size,	(in bytes)
    115  *	door_return_desc_t	*door_ptr,	(holds returned desc info)
    116  *	caddr_t			stack_base,
    117  *	size_t			stack_size)
    118  */
    119 	ENTRY(__door_return)
    120 	movl	%esp, %edx		/ Save pointer to args
    121 
    122 	pushl	%edi			/ save old %edi and %esi
    123 	pushl	%esi			/ and use them to hold the
    124 	movl	16(%edx), %esi		/ stack pointer and
    125 	movl	20(%edx), %edi		/ size.
    126 
    127 	pushl	$DOOR_RETURN		/ syscall subcode
    128 	pushl	%edi			/ size of user stack
    129 	pushl	%esi			/ base of user stack
    130 	pushl	12(%edx)		/ desc arguments ptr
    131 	pushl	8(%edx)			/ data size
    132 	pushl	4(%edx)			/ data ptr
    133 	pushl	0(%edx)			/ dummy return PC
    134 
    135 door_restart:
    136 	SYSTRAP_RVAL1(door)
    137 	jb	2f			/* errno is set */
    138 	/*
    139 	 * On return, we're serving a door_call.  Our stack looks like this:
    140 	 *
    141 	 *		descriptors (if any)
    142 	 *		data (if any)
    143 	 *	 sp->	struct door_results
    144 	 *
    145 	 * struct door_results has the arguments in place for the server proc,
    146 	 * so we just call it directly.
    147 	 */
    148 	movl	DOOR_SERVERS(%esp), %eax
    149 	andl	%eax, %eax	/* test nservers */
    150 	jg	1f
    151 	/*
    152 	 * this is the last server thread - call creation func for more
    153 	 */
    154 	movl	DOOR_INFO_PTR(%esp), %eax
    155 	pushl	%eax		/* door_info_t * */
    156 	call	door_depletion_cb@PLT
    157 	addl	$4, %esp
    158 1:
    159 	/* Call the door server function now */
    160 	movl	DOOR_PC(%esp), %eax
    161 	call	*%eax
    162 	/* Exit the thread if we return here */
    163 	pushl	$0
    164 	call	_thrp_terminate
    165 	/* NOTREACHED */
    166 2:
    167 	/*
    168 	 * Error during door_return call.  Repark the thread in the kernel if
    169 	 * the error code is EINTR (or ERESTART) and this lwp is still part
    170 	 * of the same process.
    171 	 *
    172 	 * If the error code is EINTR or ERESTART, our stack may have been
    173 	 * corrupted by a partial door call, so we refresh the system call
    174 	 * arguments.
    175 	 */
    176 	cmpl	$ERESTART, %eax		/* ERESTART is same as EINTR */
    177 	jne	3f
    178 	movl	$EINTR, %eax
    179 3:
    180 	cmpl	$EINTR, %eax		/* interrupted while waiting? */
    181 	jne	4f			/* if not, return the error */
    182 	_prologue_
    183 	call	getpid
    184 	movl	_daref_(door_create_pid), %edx
    185 	movl	0(%edx), %edx
    186 	_epilogue_
    187 	cmpl	%eax, %edx		/* same process? */
    188 	movl	$EINTR, %eax	/* if no, return EINTR (child of forkall) */
    189 	jne	4f
    190 	movl	$0, 4(%esp)		/* clear arguments and restart */
    191 	movl	$0, 8(%esp)
    192 	movl	$0, 12(%esp)
    193 	movl	%esi, 16(%esp)		/* refresh sp */
    194 	movl	%edi, 20(%esp)		/* refresh ssize */
    195 	movl	$DOOR_RETURN, 24(%esp)	/* refresh syscall subcode */
    196 	jmp	door_restart
    197 4:
    198 	/* Something bad happened during the door_return */
    199 	addl	$28, %esp
    200 	popl	%esi
    201 	popl	%edi
    202 	jmp	__cerror
    203 	SET_SIZE(__door_return)
    204