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