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