1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
.file "door.s"
#include "SYS.h"
#include <sys/door.h>
/*
* weak aliases for public interfaces
*/
ANSI_PRAGMA_WEAK2(door_bind,__door_bind,function)
ANSI_PRAGMA_WEAK2(door_getparam,__door_getparam,function)
ANSI_PRAGMA_WEAK2(door_info,__door_info,function)
ANSI_PRAGMA_WEAK2(door_revoke,__door_revoke,function)
ANSI_PRAGMA_WEAK2(door_setparam,__door_setparam,function)
/*
* Offsets within struct door_results
*/
#define DOOR_COOKIE _MUL(0, CLONGSIZE)
#define DOOR_DATA_PTR _MUL(1, CLONGSIZE)
#define DOOR_DATA_SIZE _MUL(2, CLONGSIZE)
#define DOOR_DESC_PTR _MUL(3, CLONGSIZE)
#define DOOR_DESC_SIZE _MUL(4, CLONGSIZE)
#define DOOR_PC _MUL(5, CLONGSIZE)
#define DOOR_SERVERS _MUL(6, CLONGSIZE)
#define DOOR_INFO_PTR _MUL(7, CLONGSIZE)
/*
* All of the syscalls except door_return() follow the same pattern. The
* subcode goes in %r9, after all of the other arguments.
*/
#define DOOR_SYSCALL(name, code) \
ENTRY(name); \
movq $code, %r9; /* subcode */ \
SYSTRAP_RVAL1(door); \
SYSCERROR; \
RET; \
SET_SIZE(name)
DOOR_SYSCALL(__door_bind, DOOR_BIND)
DOOR_SYSCALL(__door_call, DOOR_CALL)
DOOR_SYSCALL(__door_create, DOOR_CREATE)
DOOR_SYSCALL(__door_getparam, DOOR_GETPARAM)
DOOR_SYSCALL(__door_info, DOOR_INFO)
DOOR_SYSCALL(__door_revoke, DOOR_REVOKE)
DOOR_SYSCALL(__door_setparam, DOOR_SETPARAM)
DOOR_SYSCALL(__door_ucred, DOOR_UCRED)
DOOR_SYSCALL(__door_unbind, DOOR_UNBIND)
DOOR_SYSCALL(__door_unref, DOOR_UNREFSYS)
/*
* int
* __door_return(
* void *data_ptr,
* size_t data_size, (in bytes)
* door_return_desc_t *door_ptr, (holds returned desc info)
* caddr_t stack_base,
* size_t stack_size)
*/
ENTRY(__door_return)
pushq %rbp
movq %rsp, %rbp
subq $0x8, %rsp
/*
* Save stack_base (arg4), since %rcx will be trashed if the syscall
* returns via sysret
*/
movq %rcx, -0x8(%rbp)
door_restart:
movq $DOOR_RETURN, %r9 /* subcode */
SYSTRAP_RVAL1(door)
jb 2f /* errno is set */
/*
* On return, we're serving a door_call. Our stack looks like this:
*
* descriptors (if any)
* data (if any)
* sp-> struct door_results
*/
movl DOOR_SERVERS(%rsp), %eax
andl %eax, %eax /* test nservers */
jg 1f
/*
* this is the last server thread - call creation func for more
*/
movq DOOR_INFO_PTR(%rsp), %rdi
call door_depletion_cb@PLT
1:
/* Call the door server function now */
movq DOOR_COOKIE(%rsp), %rdi
movq DOOR_DATA_PTR(%rsp), %rsi
movq DOOR_DATA_SIZE(%rsp), %rdx
movq DOOR_DESC_PTR(%rsp), %rcx
movq DOOR_DESC_SIZE(%rsp), %r8
movq DOOR_PC(%rsp), %rax
call *%rax
/* Exit the thread if we return here */
movq $0, %rdi
call _thrp_terminate
/* NOTREACHED */
2:
/*
* Error during door_return call. Repark the thread in the kernel if
* the error code is EINTR (or ERESTART) and this lwp is still part
* of the same process.
*/
cmpl $ERESTART, %eax /* ERESTART is same as EINTR */
jne 3f
movl $EINTR, %eax
3:
cmpl $EINTR, %eax /* interrupted while waiting? */
jne 4f /* if not, return the error */
call getpid /* get current process id */
movq _daref_(door_create_pid), %rdx
movl 0(%rdx), %edx
cmpl %eax, %edx /* same process? */
movl $EINTR, %eax /* if no, return EINTR (child of forkall) */
jne 4f
movq $0, %rdi /* clear arguments and restart */
movq $0, %rsi
movq $0, %rdx
movq -0x8(%rbp), %rcx /* Restore arg4 (stack_base) */
jmp door_restart
4:
leave
jmp __cerror
SET_SIZE(__door_return)
|