Home | History | Annotate | Download | only in doorfs
      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 /*
     28  * System call I/F to doors (outside of vnodes I/F) and misc support
     29  * routines
     30  */
     31 #include <sys/types.h>
     32 #include <sys/systm.h>
     33 #include <sys/door.h>
     34 #include <sys/door_data.h>
     35 #include <sys/proc.h>
     36 #include <sys/thread.h>
     37 #include <sys/prsystm.h>
     38 #include <sys/procfs.h>
     39 #include <sys/class.h>
     40 #include <sys/cred.h>
     41 #include <sys/kmem.h>
     42 #include <sys/cmn_err.h>
     43 #include <sys/stack.h>
     44 #include <sys/debug.h>
     45 #include <sys/cpuvar.h>
     46 #include <sys/file.h>
     47 #include <sys/fcntl.h>
     48 #include <sys/vnode.h>
     49 #include <sys/vfs.h>
     50 #include <sys/vfs_opreg.h>
     51 #include <sys/sobject.h>
     52 #include <sys/schedctl.h>
     53 #include <sys/callb.h>
     54 #include <sys/ucred.h>
     55 
     56 #include <sys/mman.h>
     57 #include <sys/sysmacros.h>
     58 #include <sys/vmsystm.h>
     59 #include <vm/as.h>
     60 #include <vm/hat.h>
     61 #include <vm/page.h>
     62 #include <vm/seg.h>
     63 #include <vm/seg_vn.h>
     64 #include <vm/seg_vn.h>
     65 
     66 #include <sys/modctl.h>
     67 #include <sys/syscall.h>
     68 #include <sys/pathname.h>
     69 #include <sys/rctl.h>
     70 
     71 /*
     72  * The maximum amount of data (in bytes) that will be transferred using
     73  * an intermediate kernel buffer.  For sizes greater than this we map
     74  * in the destination pages and perform a 1-copy transfer.
     75  */
     76 size_t	door_max_arg = 16 * 1024;
     77 
     78 /*
     79  * Maximum amount of data that will be transferred in a reply to a
     80  * door_upcall.  Need to guard against a process returning huge amounts
     81  * of data and getting the kernel stuck in kmem_alloc.
     82  */
     83 size_t	door_max_upcall_reply = 1024 * 1024;
     84 
     85 /*
     86  * Maximum number of descriptors allowed to be passed in a single
     87  * door_call or door_return.  We need to allocate kernel memory
     88  * for all of them at once, so we can't let it scale without limit.
     89  */
     90 uint_t door_max_desc = 1024;
     91 
     92 /*
     93  * Definition of a door handle, used by other kernel subsystems when
     94  * calling door functions.  This is really a file structure but we
     95  * want to hide that fact.
     96  */
     97 struct __door_handle {
     98 	file_t dh_file;
     99 };
    100 
    101 #define	DHTOF(dh) ((file_t *)(dh))
    102 #define	FTODH(fp) ((door_handle_t)(fp))
    103 
    104 static int doorfs(long, long, long, long, long, long);
    105 
    106 static struct sysent door_sysent = {
    107 	6,
    108 	SE_ARGC | SE_NOUNLOAD,
    109 	(int (*)())doorfs,
    110 };
    111 
    112 static struct modlsys modlsys = {
    113 	&mod_syscallops, "doors", &door_sysent
    114 };
    115 
    116 #ifdef _SYSCALL32_IMPL
    117 
    118 static int
    119 doorfs32(int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4,
    120     int32_t arg5, int32_t subcode);
    121 
    122 static struct sysent door_sysent32 = {
    123 	6,
    124 	SE_ARGC | SE_NOUNLOAD,
    125 	(int (*)())doorfs32,
    126 };
    127 
    128 static struct modlsys modlsys32 = {
    129 	&mod_syscallops32,
    130 	"32-bit door syscalls",
    131 	&door_sysent32
    132 };
    133 #endif
    134 
    135 static struct modlinkage modlinkage = {
    136 	MODREV_1,
    137 	&modlsys,
    138 #ifdef _SYSCALL32_IMPL
    139 	&modlsys32,
    140 #endif
    141 	NULL
    142 };
    143 
    144 dev_t	doordev;
    145 
    146 extern	struct vfs door_vfs;
    147 extern	struct vnodeops *door_vnodeops;
    148 
    149 int
    150 _init(void)
    151 {
    152 	static const fs_operation_def_t door_vfsops_template[] = {
    153 		NULL, NULL
    154 	};
    155 	extern const fs_operation_def_t door_vnodeops_template[];
    156 	vfsops_t *door_vfsops;
    157 	major_t major;
    158 	int error;
    159 
    160 	mutex_init(&door_knob, NULL, MUTEX_DEFAULT, NULL);
    161 	if ((major = getudev()) == (major_t)-1)
    162 		return (ENXIO);
    163 	doordev = makedevice(major, 0);
    164 
    165 	/* Create a dummy vfs */
    166 	error = vfs_makefsops(door_vfsops_template, &door_vfsops);
    167 	if (error != 0) {
    168 		cmn_err(CE_WARN, "door init: bad vfs ops");
    169 		return (error);
    170 	}
    171 	VFS_INIT(&door_vfs, door_vfsops, NULL);
    172 	door_vfs.vfs_flag = VFS_RDONLY;
    173 	door_vfs.vfs_dev = doordev;
    174 	vfs_make_fsid(&(door_vfs.vfs_fsid), doordev, 0);
    175 
    176 	error = vn_make_ops("doorfs", door_vnodeops_template, &door_vnodeops);
    177 	if (error != 0) {
    178 		vfs_freevfsops(door_vfsops);
    179 		cmn_err(CE_WARN, "door init: bad vnode ops");
    180 		return (error);
    181 	}
    182 	return (mod_install(&modlinkage));
    183 }
    184 
    185 int
    186 _info(struct modinfo *modinfop)
    187 {
    188 	return (mod_info(&modlinkage, modinfop));
    189 }
    190 
    191 /* system call functions */
    192 static int door_call(int, void *);
    193 static int door_return(caddr_t, size_t, door_desc_t *, uint_t, caddr_t, size_t);
    194 static int door_create(void (*pc_cookie)(void *, char *, size_t, door_desc_t *,
    195     uint_t), void *data_cookie, uint_t);
    196 static int door_revoke(int);
    197 static int door_info(int, struct door_info *);
    198 static int door_ucred(struct ucred_s *);
    199 static int door_bind(int);
    200 static int door_unbind(void);
    201 static int door_unref(void);
    202 static int door_getparam(int, int, size_t *);
    203 static int door_setparam(int, int, size_t);
    204 
    205 #define	DOOR_RETURN_OLD	4		/* historic value, for s10 */
    206 
    207 /*
    208  * System call wrapper for all door related system calls
    209  */
    210 static int
    211 doorfs(long arg1, long arg2, long arg3, long arg4, long arg5, long subcode)
    212 {
    213 	switch (subcode) {
    214 	case DOOR_CALL:
    215 		return (door_call(arg1, (void *)arg2));
    216 	case DOOR_RETURN: {
    217 		door_return_desc_t *drdp = (door_return_desc_t *)arg3;
    218 
    219 		if (drdp != NULL) {
    220 			door_return_desc_t drd;
    221 			if (copyin(drdp, &drd, sizeof (drd)))
    222 				return (EFAULT);
    223 			return (door_return((caddr_t)arg1, arg2, drd.desc_ptr,
    224 			    drd.desc_num, (caddr_t)arg4, arg5));
    225 		}
    226 		return (door_return((caddr_t)arg1, arg2, NULL,
    227 		    0, (caddr_t)arg4, arg5));
    228 	}
    229 	case DOOR_RETURN_OLD:
    230 		/*
    231 		 * In order to support the S10 runtime environment, we
    232 		 * still respond to the old syscall subcode for door_return.
    233 		 * We treat it as having no stack limits.  This code should
    234 		 * be removed when such support is no longer needed.
    235 		 */
    236 		return (door_return((caddr_t)arg1, arg2, (door_desc_t *)arg3,
    237 		    arg4, (caddr_t)arg5, 0));
    238 	case DOOR_CREATE:
    239 		return (door_create((void (*)())arg1, (void *)arg2, arg3));
    240 	case DOOR_REVOKE:
    241 		return (door_revoke(arg1));
    242 	case DOOR_INFO:
    243 		return (door_info(arg1, (struct door_info *)arg2));
    244 	case DOOR_BIND:
    245 		return (door_bind(arg1));
    246 	case DOOR_UNBIND:
    247 		return (door_unbind());
    248 	case DOOR_UNREFSYS:
    249 		return (door_unref());
    250 	case DOOR_UCRED:
    251 		return (door_ucred((struct ucred_s *)arg1));
    252 	case DOOR_GETPARAM:
    253 		return (door_getparam(arg1, arg2, (size_t *)arg3));
    254 	case DOOR_SETPARAM:
    255 		return (door_setparam(arg1, arg2, arg3));
    256 	default:
    257 		return (set_errno(EINVAL));
    258 	}
    259 }
    260 
    261 #ifdef _SYSCALL32_IMPL
    262 /*
    263  * System call wrapper for all door related system calls from 32-bit programs.
    264  * Needed at the moment because of the casts - they undo some damage
    265  * that truss causes (sign-extending the stack pointer) when truss'ing
    266  * a 32-bit program using doors.
    267  */
    268 static int
    269 doorfs32(int32_t arg1, int32_t arg2, int32_t arg3,
    270     int32_t arg4, int32_t arg5, int32_t subcode)
    271 {
    272 	switch (subcode) {
    273 	case DOOR_CALL:
    274 		return (door_call(arg1, (void *)(uintptr_t)(caddr32_t)arg2));
    275 	case DOOR_RETURN: {
    276 		door_return_desc32_t *drdp =
    277 		    (door_return_desc32_t *)(uintptr_t)(caddr32_t)arg3;
    278 		if (drdp != NULL) {
    279 			door_return_desc32_t drd;
    280 			if (copyin(drdp, &drd, sizeof (drd)))
    281 				return (EFAULT);
    282 			return (door_return(
    283 			    (caddr_t)(uintptr_t)(caddr32_t)arg1, arg2,
    284 			    (door_desc_t *)(uintptr_t)drd.desc_ptr,
    285 			    drd.desc_num, (caddr_t)(uintptr_t)(caddr32_t)arg4,
    286 			    (size_t)(uintptr_t)(size32_t)arg5));
    287 		}
    288 		return (door_return((caddr_t)(uintptr_t)(caddr32_t)arg1,
    289 		    arg2, NULL, 0, (caddr_t)(uintptr_t)(caddr32_t)arg4,
    290 		    (size_t)(uintptr_t)(size32_t)arg5));
    291 	}
    292 	case DOOR_RETURN_OLD:
    293 		/*
    294 		 * In order to support the S10 runtime environment, we
    295 		 * still respond to the old syscall subcode for door_return.
    296 		 * We treat it as having no stack limits.  This code should
    297 		 * be removed when such support is no longer needed.
    298 		 */
    299 		return (door_return((caddr_t)(uintptr_t)(caddr32_t)arg1, arg2,
    300 		    (door_desc_t *)(uintptr_t)(caddr32_t)arg3, arg4,
    301 		    (caddr_t)(uintptr_t)(caddr32_t)arg5, 0));
    302 	case DOOR_CREATE:
    303 		return (door_create((void (*)())(uintptr_t)(caddr32_t)arg1,
    304 		    (void *)(uintptr_t)(caddr32_t)arg2, arg3));
    305 	case DOOR_REVOKE:
    306 		return (door_revoke(arg1));
    307 	case DOOR_INFO:
    308 		return (door_info(arg1,
    309 		    (struct door_info *)(uintptr_t)(caddr32_t)arg2));
    310 	case DOOR_BIND:
    311 		return (door_bind(arg1));
    312 	case DOOR_UNBIND:
    313 		return (door_unbind());
    314 	case DOOR_UNREFSYS:
    315 		return (door_unref());
    316 	case DOOR_UCRED:
    317 		return (door_ucred(
    318 		    (struct ucred_s *)(uintptr_t)(caddr32_t)arg1));
    319 	case DOOR_GETPARAM:
    320 		return (door_getparam(arg1, arg2,
    321 		    (size_t *)(uintptr_t)(caddr32_t)arg3));
    322 	case DOOR_SETPARAM:
    323 		return (door_setparam(arg1, arg2, (size_t)(size32_t)arg3));
    324 
    325 	default:
    326 		return (set_errno(EINVAL));
    327 	}
    328 }
    329 #endif
    330 
    331 void shuttle_resume(kthread_t *, kmutex_t *);
    332 void shuttle_swtch(kmutex_t *);
    333 void shuttle_sleep(kthread_t *);
    334 
    335 /*
    336  * Support routines
    337  */
    338 static int door_create_common(void (*)(), void *, uint_t, int, int *,
    339     file_t **);
    340 static int door_overflow(kthread_t *, caddr_t, size_t, door_desc_t *, uint_t);
    341 static int door_args(kthread_t *, int);
    342 static int door_results(kthread_t *, caddr_t, size_t, door_desc_t *, uint_t);
    343 static int door_copy(struct as *, caddr_t, caddr_t, uint_t);
    344 static void	door_server_exit(proc_t *, kthread_t *);
    345 static void	door_release_server(door_node_t *, kthread_t *);
    346 static kthread_t	*door_get_server(door_node_t *);
    347 static door_node_t	*door_lookup(int, file_t **);
    348 static int	door_translate_in(void);
    349 static int	door_translate_out(void);
    350 static void	door_fd_rele(door_desc_t *, uint_t, int);
    351 static void	door_list_insert(door_node_t *);
    352 static void	door_info_common(door_node_t *, door_info_t *, file_t *);
    353 static int	door_release_fds(door_desc_t *, uint_t);
    354 static void	door_fd_close(door_desc_t *, uint_t);
    355 static void	door_fp_close(struct file **, uint_t);
    356 
    357 static door_data_t *
    358 door_my_data(int create_if_missing)
    359 {
    360 	door_data_t *ddp;
    361 
    362 	ddp = curthread->t_door;
    363 	if (create_if_missing && ddp == NULL)
    364 		ddp = curthread->t_door = kmem_zalloc(sizeof (*ddp), KM_SLEEP);
    365 
    366 	return (ddp);
    367 }
    368 
    369 static door_server_t *
    370 door_my_server(int create_if_missing)
    371 {
    372 	door_data_t *ddp = door_my_data(create_if_missing);
    373 
    374 	return ((ddp != NULL)? DOOR_SERVER(ddp) : NULL);
    375 }
    376 
    377 static door_client_t *
    378 door_my_client(int create_if_missing)
    379 {
    380 	door_data_t *ddp = door_my_data(create_if_missing);
    381 
    382 	return ((ddp != NULL)? DOOR_CLIENT(ddp) : NULL);
    383 }
    384 
    385 /*
    386  * System call to create a door
    387  */
    388 int
    389 door_create(void (*pc_cookie)(), void *data_cookie, uint_t attributes)
    390 {
    391 	int fd;
    392 	int err;
    393 
    394 	if ((attributes & ~DOOR_CREATE_MASK) ||
    395 	    ((attributes & (DOOR_UNREF | DOOR_UNREF_MULTI)) ==
    396 	    (DOOR_UNREF | DOOR_UNREF_MULTI)))
    397 		return (set_errno(EINVAL));
    398 
    399 	if ((err = door_create_common(pc_cookie, data_cookie, attributes, 0,
    400 	    &fd, NULL)) != 0)
    401 		return (set_errno(err));
    402 
    403 	f_setfd(fd, FD_CLOEXEC);
    404 	return (fd);
    405 }
    406 
    407 /*
    408  * Common code for creating user and kernel doors.  If a door was
    409  * created, stores a file structure pointer in the location pointed
    410  * to by fpp (if fpp is non-NULL) and returns 0.  Also, if a non-NULL
    411  * pointer to a file descriptor is passed in as fdp, allocates a file
    412  * descriptor representing the door.  If a door could not be created,
    413  * returns an error.
    414  */
    415 static int
    416 door_create_common(void (*pc_cookie)(), void *data_cookie, uint_t attributes,
    417     int from_kernel, int *fdp, file_t **fpp)
    418 {
    419 	door_node_t	*dp;
    420 	vnode_t		*vp;
    421 	struct file	*fp;
    422 	static door_id_t index = 0;
    423 	proc_t		*p = (from_kernel)? &p0 : curproc;
    424 
    425 	dp = kmem_zalloc(sizeof (door_node_t), KM_SLEEP);
    426 
    427 	dp->door_vnode = vn_alloc(KM_SLEEP);
    428 	dp->door_target = p;
    429 	dp->door_data = data_cookie;
    430 	dp->door_pc = pc_cookie;
    431 	dp->door_flags = attributes;
    432 #ifdef _SYSCALL32_IMPL
    433 	if (!from_kernel && get_udatamodel() != DATAMODEL_NATIVE)
    434 		dp->door_data_max = UINT32_MAX;
    435 	else
    436 #endif
    437 		dp->door_data_max = SIZE_MAX;
    438 	dp->door_data_min = 0UL;
    439 	dp->door_desc_max = (attributes & DOOR_REFUSE_DESC)? 0 : INT_MAX;
    440 
    441 	vp = DTOV(dp);
    442 	vn_setops(vp, door_vnodeops);
    443 	vp->v_type = VDOOR;
    444 	vp->v_vfsp = &door_vfs;
    445 	vp->v_data = (caddr_t)dp;
    446 	mutex_enter(&door_knob);
    447 	dp->door_index = index++;
    448 	/* add to per-process door list */
    449 	door_list_insert(dp);
    450 	mutex_exit(&door_knob);
    451 
    452 	if (falloc(vp, FREAD | FWRITE, &fp, fdp)) {
    453 		/*
    454 		 * If the file table is full, remove the door from the
    455 		 * per-process list, free the door, and return NULL.
    456 		 */
    457 		mutex_enter(&door_knob);
    458 		door_list_delete(dp);
    459 		mutex_exit(&door_knob);
    460 		vn_free(vp);
    461 		kmem_free(dp, sizeof (door_node_t));
    462 		return (EMFILE);
    463 	}
    464 	vn_exists(vp);
    465 	if (fdp != NULL)
    466 		setf(*fdp, fp);
    467 	mutex_exit(&fp->f_tlock);
    468 
    469 	if (fpp != NULL)
    470 		*fpp = fp;
    471 	return (0);
    472 }
    473 
    474 static int
    475 door_check_limits(door_node_t *dp, door_arg_t *da, int upcall)
    476 {
    477 	ASSERT(MUTEX_HELD(&door_knob));
    478 
    479 	/* we allow unref upcalls through, despite any minimum */
    480 	if (da->data_size < dp->door_data_min &&
    481 	    !(upcall && da->data_ptr == DOOR_UNREF_DATA))
    482 		return (ENOBUFS);
    483 
    484 	if (da->data_size > dp->door_data_max)
    485 		return (ENOBUFS);
    486 
    487 	if (da->desc_num > 0 && (dp->door_flags & DOOR_REFUSE_DESC))
    488 		return (ENOTSUP);
    489 
    490 	if (da->desc_num > dp->door_desc_max)
    491 		return (ENFILE);
    492 
    493 	return (0);
    494 }
    495 
    496 /*
    497  * Door invocation.
    498  */
    499 int
    500 door_call(int did, void *args)
    501 {
    502 	/* Locals */
    503 	door_node_t	*dp;
    504 	kthread_t	*server_thread;
    505 	int		error = 0;
    506 	klwp_t		*lwp;
    507 	door_client_t	*ct;		/* curthread door_data */
    508 	door_server_t	*st;		/* server thread door_data */
    509 	door_desc_t	*start = NULL;
    510 	uint_t		ncopied = 0;
    511 	size_t		dsize;
    512 	/* destructor for data returned by a kernel server */
    513 	void		(*destfn)() = NULL;
    514 	void		*destarg;
    515 	model_t		datamodel;
    516 	int		gotresults = 0;
    517 	int		needcleanup = 0;
    518 	int		cancel_pending;
    519 
    520 	lwp = ttolwp(curthread);
    521 	datamodel = lwp_getdatamodel(lwp);
    522 
    523 	ct = door_my_client(1);
    524 
    525 	/*
    526 	 * Get the arguments
    527 	 */
    528 	if (args) {
    529 		if (datamodel == DATAMODEL_NATIVE) {
    530 			if (copyin(args, &ct->d_args, sizeof (door_arg_t)) != 0)
    531 				return (set_errno(EFAULT));
    532 		} else {
    533 			door_arg32_t    da32;
    534 
    535 			if (copyin(args, &da32, sizeof (door_arg32_t)) != 0)
    536 				return (set_errno(EFAULT));
    537 			ct->d_args.data_ptr =
    538 			    (char *)(uintptr_t)da32.data_ptr;
    539 			ct->d_args.data_size = da32.data_size;
    540 			ct->d_args.desc_ptr =
    541 			    (door_desc_t *)(uintptr_t)da32.desc_ptr;
    542 			ct->d_args.desc_num = da32.desc_num;
    543 			ct->d_args.rbuf =
    544 			    (char *)(uintptr_t)da32.rbuf;
    545 			ct->d_args.rsize = da32.rsize;
    546 		}
    547 	} else {
    548 		/* No arguments, and no results allowed */
    549 		ct->d_noresults = 1;
    550 		ct->d_args.data_size = 0;
    551 		ct->d_args.desc_num = 0;
    552 		ct->d_args.rsize = 0;
    553 	}
    554 
    555 	if ((dp = door_lookup(did, NULL)) == NULL)
    556 		return (set_errno(EBADF));
    557 
    558 	/*
    559 	 * We don't want to hold the door FD over the entire operation;
    560 	 * instead, we put a hold on the door vnode and release the FD
    561 	 * immediately
    562 	 */
    563 	VN_HOLD(DTOV(dp));
    564 	releasef(did);
    565 
    566 	/*
    567 	 * This should be done in shuttle_resume(), just before going to
    568 	 * sleep, but we want to avoid overhead while holding door_knob.
    569 	 * prstop() is just a no-op if we don't really go to sleep.
    570 	 * We test not-kernel-address-space for the sake of clustering code.
    571 	 */
    572 	if (lwp && lwp->lwp_nostop == 0 && curproc->p_as != &kas)
    573 		prstop(PR_REQUESTED, 0);
    574 
    575 	mutex_enter(&door_knob);
    576 	if (DOOR_INVALID(dp)) {
    577 		mutex_exit(&door_knob);
    578 		error = EBADF;
    579 		goto out;
    580 	}
    581 
    582 	/*
    583 	 * before we do anything, check that we are not overflowing the
    584 	 * required limits.
    585 	 */
    586 	error = door_check_limits(dp, &ct->d_args, 0);
    587 	if (error != 0) {
    588 		mutex_exit(&door_knob);
    589 		goto out;
    590 	}
    591 
    592 	/*
    593 	 * Check for in-kernel door server.
    594 	 */
    595 	if (dp->door_target == &p0) {
    596 		caddr_t rbuf = ct->d_args.rbuf;
    597 		size_t rsize = ct->d_args.rsize;
    598 
    599 		dp->door_active++;
    600 		ct->d_kernel = 1;
    601 		ct->d_error = DOOR_WAIT;
    602 		mutex_exit(&door_knob);
    603 		/* translate file descriptors to vnodes */
    604 		if (ct->d_args.desc_num) {
    605 			error = door_translate_in();
    606 			if (error)
    607 				goto out;
    608 		}
    609 		/*
    610 		 * Call kernel door server.  Arguments are passed and
    611 		 * returned as a door_arg pointer.  When called, data_ptr
    612 		 * points to user data and desc_ptr points to a kernel list
    613 		 * of door descriptors that have been converted to file
    614 		 * structure pointers.  It's the server function's
    615 		 * responsibility to copyin the data pointed to by data_ptr
    616 		 * (this avoids extra copying in some cases).  On return,
    617 		 * data_ptr points to a user buffer of data, and desc_ptr
    618 		 * points to a kernel list of door descriptors representing
    619 		 * files.  When a reference is passed to a kernel server,
    620 		 * it is the server's responsibility to release the reference
    621 		 * (by calling closef).  When the server includes a
    622 		 * reference in its reply, it is released as part of the
    623 		 * the call (the server must duplicate the reference if
    624 		 * it wants to retain a copy).  The destfn, if set to
    625 		 * non-NULL, is a destructor to be called when the returned
    626 		 * kernel data (if any) is no longer needed (has all been
    627 		 * translated and copied to user level).
    628 		 */
    629 		(*(dp->door_pc))(dp->door_data, &ct->d_args,
    630 		    &destfn, &destarg, &error);
    631 		mutex_enter(&door_knob);
    632 		/* not implemented yet */
    633 		if (--dp->door_active == 0 && (dp->door_flags & DOOR_DELAY))
    634 			door_deliver_unref(dp);
    635 		mutex_exit(&door_knob);
    636 		if (error)
    637 			goto out;
    638 
    639 		/* translate vnodes to files */
    640 		if (ct->d_args.desc_num) {
    641 			error = door_translate_out();
    642 			if (error)
    643 				goto out;
    644 		}
    645 		ct->d_buf = ct->d_args.rbuf;
    646 		ct->d_bufsize = ct->d_args.rsize;
    647 		if (rsize < (ct->d_args.data_size +
    648 		    (ct->d_args.desc_num * sizeof (door_desc_t)))) {
    649 			/* handle overflow */
    650 			error = door_overflow(curthread, ct->d_args.data_ptr,
    651 			    ct->d_args.data_size, ct->d_args.desc_ptr,
    652 			    ct->d_args.desc_num);
    653 			if (error)
    654 				goto out;
    655 			/* door_overflow sets d_args rbuf and rsize */
    656 		} else {
    657 			ct->d_args.rbuf = rbuf;
    658 			ct->d_args.rsize = rsize;
    659 		}
    660 		goto results;
    661 	}
    662 
    663 	/*
    664 	 * Get a server thread from the target domain
    665 	 */
    666 	if ((server_thread = door_get_server(dp)) == NULL) {
    667 		if (DOOR_INVALID(dp))
    668 			error = EBADF;
    669 		else
    670 			error = EAGAIN;
    671 		mutex_exit(&door_knob);
    672 		goto out;
    673 	}
    674 
    675 	st = DOOR_SERVER(server_thread->t_door);
    676 	if (ct->d_args.desc_num || ct->d_args.data_size) {
    677 		int is_private = (dp->door_flags & DOOR_PRIVATE);
    678 		/*
    679 		 * Move data from client to server
    680 		 */
    681 		DOOR_T_HOLD(st);
    682 		mutex_exit(&door_knob);
    683 		error = door_args(server_thread, is_private);
    684 		mutex_enter(&door_knob);
    685 		DOOR_T_RELEASE(st);
    686 		if (error) {
    687 			/*
    688 			 * We're not going to resume this thread after all
    689 			 */
    690 			door_release_server(dp, server_thread);
    691 			shuttle_sleep(server_thread);
    692 			mutex_exit(&door_knob);
    693 			goto out;
    694 		}
    695 	}
    696 
    697 	dp->door_active++;
    698 	ct->d_error = DOOR_WAIT;
    699 	ct->d_args_done = 0;
    700 	st->d_caller = curthread;
    701 	st->d_active = dp;
    702 
    703 	shuttle_resume(server_thread, &door_knob);
    704 
    705 	mutex_enter(&door_knob);
    706 shuttle_return:
    707 	if ((error = ct->d_error) < 0) {	/* DOOR_WAIT or DOOR_EXIT */
    708 		/*
    709 		 * Premature wakeup. Find out why (stop, forkall, sig, exit ...)
    710 		 */
    711 		mutex_exit(&door_knob);		/* May block in ISSIG */
    712 		cancel_pending = 0;
    713 		if (ISSIG(curthread, FORREAL) || lwp->lwp_sysabort ||
    714 		    MUSTRETURN(curproc, curthread) ||
    715 		    (cancel_pending = schedctl_cancel_pending()) != 0) {
    716 			/* Signal, forkall, ... */
    717 			lwp->lwp_sysabort = 0;
    718 			if (cancel_pending)
    719 				schedctl_cancel_eintr();
    720 			mutex_enter(&door_knob);
    721 			error = EINTR;
    722 			/*
    723 			 * If the server has finished processing our call,
    724 			 * or exited (calling door_slam()), then d_error
    725 			 * will have changed.  If the server hasn't finished
    726 			 * yet, d_error will still be DOOR_WAIT, and we
    727 			 * let it know we are not interested in any
    728 			 * results by sending a SIGCANCEL, unless the door
    729 			 * is marked with DOOR_NO_CANCEL.
    730 			 */
    731 			if (ct->d_error == DOOR_WAIT &&
    732 			    st->d_caller == curthread) {
    733 				proc_t	*p = ttoproc(server_thread);
    734 
    735 				st->d_active = NULL;
    736 				st->d_caller = NULL;
    737 
    738 				if (!(dp->door_flags & DOOR_NO_CANCEL)) {
    739 					DOOR_T_HOLD(st);
    740 					mutex_exit(&door_knob);
    741 
    742 					mutex_enter(&p->p_lock);
    743 					sigtoproc(p, server_thread, SIGCANCEL);
    744 					mutex_exit(&p->p_lock);
    745 
    746 					mutex_enter(&door_knob);
    747 					DOOR_T_RELEASE(st);
    748 				}
    749 			}
    750 		} else {
    751 			/*
    752 			 * Return from stop(), server exit...
    753 			 *
    754 			 * Note that the server could have done a
    755 			 * door_return while the client was in stop state
    756 			 * (ISSIG), in which case the error condition
    757 			 * is updated by the server.
    758 			 */
    759 			mutex_enter(&door_knob);
    760 			if (ct->d_error == DOOR_WAIT) {
    761 				/* Still waiting for a reply */
    762 				shuttle_swtch(&door_knob);
    763 				mutex_enter(&door_knob);
    764 				lwp->lwp_asleep = 0;
    765 				goto	shuttle_return;
    766 			} else if (ct->d_error == DOOR_EXIT) {
    767 				/* Server exit */
    768 				error = EINTR;
    769 			} else {
    770 				/* Server did a door_return during ISSIG */
    771 				error = ct->d_error;
    772 			}
    773 		}
    774 		/*
    775 		 * Can't exit if the server is currently copying
    776 		 * results for me.
    777 		 */
    778 		while (DOOR_T_HELD(ct))
    779 			cv_wait(&ct->d_cv, &door_knob);
    780 
    781 		/*
    782 		 * If the server has not processed our message, free the
    783 		 * descriptors.
    784 		 */
    785 		if (!ct->d_args_done) {
    786 			needcleanup = 1;
    787 			ct->d_args_done = 1;
    788 		}
    789 
    790 		/*
    791 		 * Find out if results were successfully copied.
    792 		 */
    793 		if (ct->d_error == 0)
    794 			gotresults = 1;
    795 	}
    796 	ASSERT(ct->d_args_done);
    797 	lwp->lwp_asleep = 0;		/* /proc */
    798 	lwp->lwp_sysabort = 0;		/* /proc */
    799 	if (--dp->door_active == 0 && (dp->door_flags & DOOR_DELAY))
    800 		door_deliver_unref(dp);
    801 	mutex_exit(&door_knob);
    802 
    803 	if (needcleanup)
    804 		door_fp_close(ct->d_fpp, ct->d_args.desc_num);
    805 
    806 results:
    807 	/*
    808 	 * Move the results to userland (if any)
    809 	 */
    810 
    811 	if (ct->d_noresults)
    812 		goto out;
    813 
    814 	if (error) {
    815 		/*
    816 		 * If server returned results successfully, then we've
    817 		 * been interrupted and may need to clean up.
    818 		 */
    819 		if (gotresults) {
    820 			ASSERT(error == EINTR);
    821 			door_fp_close(ct->d_fpp, ct->d_args.desc_num);
    822 		}
    823 		goto out;
    824 	}
    825 
    826 	/*
    827 	 * Copy back data if we haven't caused an overflow (already
    828 	 * handled) and we are using a 2 copy transfer, or we are
    829 	 * returning data from a kernel server.
    830 	 */
    831 	if (ct->d_args.data_size) {
    832 		ct->d_args.data_ptr = ct->d_args.rbuf;
    833 		if (ct->d_kernel || (!ct->d_overflow &&
    834 		    ct->d_args.data_size <= door_max_arg)) {
    835 			if (copyout_nowatch(ct->d_buf, ct->d_args.rbuf,
    836 			    ct->d_args.data_size)) {
    837 				door_fp_close(ct->d_fpp, ct->d_args.desc_num);
    838 				error = EFAULT;
    839 				goto out;
    840 			}
    841 		}
    842 	}
    843 
    844 	/*
    845 	 * stuff returned doors into our proc, copyout the descriptors
    846 	 */
    847 	if (ct->d_args.desc_num) {
    848 		struct file	**fpp;
    849 		door_desc_t	*didpp;
    850 		uint_t		n = ct->d_args.desc_num;
    851 
    852 		dsize = n * sizeof (door_desc_t);
    853 		start = didpp = kmem_alloc(dsize, KM_SLEEP);
    854 		fpp = ct->d_fpp;
    855 
    856 		while (n--) {
    857 			if (door_insert(*fpp, didpp) == -1) {
    858 				/* Close remaining files */
    859 				door_fp_close(fpp, n + 1);
    860 				error = EMFILE;
    861 				goto out;
    862 			}
    863 			fpp++; didpp++; ncopied++;
    864 		}
    865 
    866 		ct->d_args.desc_ptr = (door_desc_t *)(ct->d_args.rbuf +
    867 		    roundup(ct->d_args.data_size, sizeof (door_desc_t)));
    868 
    869 		if (copyout_nowatch(start, ct->d_args.desc_ptr, dsize)) {
    870 			error = EFAULT;
    871 			goto out;
    872 		}
    873 	}
    874 
    875 	/*
    876 	 * Return the results
    877 	 */
    878 	if (datamodel == DATAMODEL_NATIVE) {
    879 		if (copyout_nowatch(&ct->d_args, args,
    880 		    sizeof (door_arg_t)) != 0)
    881 			error = EFAULT;
    882 	} else {
    883 		door_arg32_t    da32;
    884 
    885 		da32.data_ptr = (caddr32_t)(uintptr_t)ct->d_args.data_ptr;
    886 		da32.data_size = ct->d_args.data_size;
    887 		da32.desc_ptr = (caddr32_t)(uintptr_t)ct->d_args.desc_ptr;
    888 		da32.desc_num = ct->d_args.desc_num;
    889 		da32.rbuf = (caddr32_t)(uintptr_t)ct->d_args.rbuf;
    890 		da32.rsize = ct->d_args.rsize;
    891 		if (copyout_nowatch(&da32, args, sizeof (door_arg32_t)) != 0) {
    892 			error = EFAULT;
    893 		}
    894 	}
    895 
    896 out:
    897 	ct->d_noresults = 0;
    898 
    899 	/* clean up the overflow buffer if an error occurred */
    900 	if (error != 0 && ct->d_overflow) {
    901 		(void) as_unmap(curproc->p_as, ct->d_args.rbuf,
    902 		    ct->d_args.rsize);
    903 	}
    904 	ct->d_overflow = 0;
    905 
    906 	/* call destructor */
    907 	if (destfn) {
    908 		ASSERT(ct->d_kernel);
    909 		(*destfn)(dp->door_data, destarg);
    910 		ct->d_buf = NULL;
    911 		ct->d_bufsize = 0;
    912 	}
    913 
    914 	if (dp)
    915 		VN_RELE(DTOV(dp));
    916 
    917 	if (ct->d_buf) {
    918 		ASSERT(!ct->d_kernel);
    919 		kmem_free(ct->d_buf, ct->d_bufsize);
    920 		ct->d_buf = NULL;
    921 		ct->d_bufsize = 0;
    922 	}
    923 	ct->d_kernel = 0;
    924 
    925 	/* clean up the descriptor copyout buffer */
    926 	if (start != NULL) {
    927 		if (error != 0)
    928 			door_fd_close(start, ncopied);
    929 		kmem_free(start, dsize);
    930 	}
    931 
    932 	if (ct->d_fpp) {
    933 		kmem_free(ct->d_fpp, ct->d_fpp_size);
    934 		ct->d_fpp = NULL;
    935 		ct->d_fpp_size = 0;
    936 	}
    937 
    938 	if (error)
    939 		return (set_errno(error));
    940 
    941 	return (0);
    942 }
    943 
    944 static int
    945 door_setparam_common(door_node_t *dp, int from_kernel, int type, size_t val)
    946 {
    947 	int error = 0;
    948 
    949 	mutex_enter(&door_knob);
    950 
    951 	if (DOOR_INVALID(dp)) {
    952 		mutex_exit(&door_knob);
    953 		return (EBADF);
    954 	}
    955 
    956 	/*
    957 	 * door_ki_setparam() can only affect kernel doors.
    958 	 * door_setparam() can only affect doors attached to the current
    959 	 * process.
    960 	 */
    961 	if ((from_kernel && dp->door_target != &p0) ||
    962 	    (!from_kernel && dp->door_target != curproc)) {
    963 		mutex_exit(&door_knob);
    964 		return (EPERM);
    965 	}
    966 
    967 	switch (type) {
    968 	case DOOR_PARAM_DESC_MAX:
    969 		if (val > INT_MAX)
    970 			error = ERANGE;
    971 		else if ((dp->door_flags & DOOR_REFUSE_DESC) && val != 0)
    972 			error = ENOTSUP;
    973 		else
    974 			dp->door_desc_max = (uint_t)val;
    975 		break;
    976 
    977 	case DOOR_PARAM_DATA_MIN:
    978 		if (val > dp->door_data_max)
    979 			error = EINVAL;
    980 		else
    981 			dp->door_data_min = val;
    982 		break;
    983 
    984 	case DOOR_PARAM_DATA_MAX:
    985 		if (val < dp->door_data_min)
    986 			error = EINVAL;
    987 		else
    988 			dp->door_data_max = val;
    989 		break;
    990 
    991 	default:
    992 		error = EINVAL;
    993 		break;
    994 	}
    995 
    996 	mutex_exit(&door_knob);
    997 	return (error);
    998 }
    999 
   1000 static int
   1001 door_getparam_common(door_node_t *dp, int type, size_t *out)
   1002 {
   1003 	int error = 0;
   1004 
   1005 	mutex_enter(&door_knob);
   1006 	switch (type) {
   1007 	case DOOR_PARAM_DESC_MAX:
   1008 		*out = (size_t)dp->door_desc_max;
   1009 		break;
   1010 	case DOOR_PARAM_DATA_MIN:
   1011 		*out = dp->door_data_min;
   1012 		break;
   1013 	case DOOR_PARAM_DATA_MAX:
   1014 		*out = dp->door_data_max;
   1015 		break;
   1016 	default:
   1017 		error = EINVAL;
   1018 		break;
   1019 	}
   1020 	mutex_exit(&door_knob);
   1021 	return (error);
   1022 }
   1023 
   1024 int
   1025 door_setparam(int did, int type, size_t val)
   1026 {
   1027 	door_node_t *dp;
   1028 	int error = 0;
   1029 
   1030 	if ((dp = door_lookup(did, NULL)) == NULL)
   1031 		return (set_errno(EBADF));
   1032 
   1033 	error = door_setparam_common(dp, 0, type, val);
   1034 
   1035 	releasef(did);
   1036 
   1037 	if (error)
   1038 		return (set_errno(error));
   1039 
   1040 	return (0);
   1041 }
   1042 
   1043 int
   1044 door_getparam(int did, int type, size_t *out)
   1045 {
   1046 	door_node_t *dp;
   1047 	size_t val = 0;
   1048 	int error = 0;
   1049 
   1050 	if ((dp = door_lookup(did, NULL)) == NULL)
   1051 		return (set_errno(EBADF));
   1052 
   1053 	error = door_getparam_common(dp, type, &val);
   1054 
   1055 	releasef(did);
   1056 
   1057 	if (error)
   1058 		return (set_errno(error));
   1059 
   1060 	if (get_udatamodel() == DATAMODEL_NATIVE) {
   1061 		if (copyout(&val, out, sizeof (val)))
   1062 			return (set_errno(EFAULT));
   1063 #ifdef _SYSCALL32_IMPL
   1064 	} else {
   1065 		size32_t val32 = (size32_t)val;
   1066 
   1067 		if (val != val32)
   1068 			return (set_errno(EOVERFLOW));
   1069 
   1070 		if (copyout(&val32, out, sizeof (val32)))
   1071 			return (set_errno(EFAULT));
   1072 #endif /* _SYSCALL32_IMPL */
   1073 	}
   1074 
   1075 	return (0);
   1076 }
   1077 
   1078 /*
   1079  * A copyout() which proceeds from high addresses to low addresses.  This way,
   1080  * stack guard pages are effective.
   1081  *
   1082  * Note that we use copyout_nowatch();  this is called while the client is
   1083  * held.
   1084  */
   1085 static int
   1086 door_stack_copyout(const void *kaddr, void *uaddr, size_t count)
   1087 {
   1088 	const char *kbase = (const char *)kaddr;
   1089 	uintptr_t ubase = (uintptr_t)uaddr;
   1090 	size_t pgsize = PAGESIZE;
   1091 
   1092 	if (count <= pgsize)
   1093 		return (copyout_nowatch(kaddr, uaddr, count));
   1094 
   1095 	while (count > 0) {
   1096 		uintptr_t start, end, offset, amount;
   1097 
   1098 		end = ubase + count;
   1099 		start = P2ALIGN(end - 1, pgsize);
   1100 		if (P2ALIGN(ubase, pgsize) == start)
   1101 			start = ubase;
   1102 
   1103 		offset = start - ubase;
   1104 		amount = end - start;
   1105 
   1106 		ASSERT(amount > 0 && amount <= count && amount <= pgsize);
   1107 
   1108 		if (copyout_nowatch(kbase + offset, (void *)start, amount))
   1109 			return (1);
   1110 		count -= amount;
   1111 	}
   1112 	return (0);
   1113 }
   1114 
   1115 /*
   1116  * Writes the stack layout for door_return() into the door_server_t of the
   1117  * server thread.
   1118  */
   1119 static int
   1120 door_layout(kthread_t *tp, size_t data_size, uint_t ndesc, int info_needed)
   1121 {
   1122 	door_server_t *st = DOOR_SERVER(tp->t_door);
   1123 	door_layout_t *out = &st->d_layout;
   1124 	uintptr_t base_sp = (uintptr_t)st->d_sp;
   1125 	size_t ssize = st->d_ssize;
   1126 	size_t descsz;
   1127 	uintptr_t descp, datap, infop, resultsp, finalsp;
   1128 	size_t align = STACK_ALIGN;
   1129 	size_t results_sz = sizeof (struct door_results);
   1130 	model_t datamodel = lwp_getdatamodel(ttolwp(tp));
   1131 
   1132 	ASSERT(!st->d_layout_done);
   1133 
   1134 #ifndef _STACK_GROWS_DOWNWARD
   1135 #error stack does not grow downward, door_layout() must change
   1136 #endif
   1137 
   1138 #ifdef _SYSCALL32_IMPL
   1139 	if (datamodel != DATAMODEL_NATIVE) {
   1140 		align = STACK_ALIGN32;
   1141 		results_sz = sizeof (struct door_results32);
   1142 	}
   1143 #endif
   1144 
   1145 	descsz = ndesc * sizeof (door_desc_t);
   1146 
   1147 	/*
   1148 	 * To speed up the overflow checking, we do an initial check
   1149 	 * that the passed in data size won't cause us to wrap past
   1150 	 * base_sp.  Since door_max_desc limits descsz, we can
   1151 	 * safely use it here.  65535 is an arbitrary 'bigger than
   1152 	 * we need, small enough to not cause trouble' constant;
   1153 	 * the only constraint is that it must be > than:
   1154 	 *
   1155 	 *	5 * STACK_ALIGN +
   1156 	 *	    sizeof (door_info_t) +
   1157 	 *	    sizeof (door_results_t) +
   1158 	 *	    (max adjustment from door_final_sp())
   1159 	 *
   1160 	 * After we compute the layout, we can safely do a "did we wrap
   1161 	 * around" check, followed by a check against the recorded
   1162 	 * stack size.
   1163 	 */
   1164 	if (data_size >= SIZE_MAX - (size_t)65535UL - descsz)
   1165 		return (E2BIG);		/* overflow */
   1166 
   1167 	descp = P2ALIGN(base_sp - descsz, align);
   1168 	datap = P2ALIGN(descp - data_size, align);
   1169 
   1170 	if (info_needed)
   1171 		infop = P2ALIGN(datap - sizeof (door_info_t), align);
   1172 	else
   1173 		infop = datap;
   1174 
   1175 	resultsp = P2ALIGN(infop - results_sz, align);
   1176 	finalsp = door_final_sp(resultsp, align, datamodel);
   1177 
   1178 	if (finalsp > base_sp)
   1179 		return (E2BIG);		/* overflow */
   1180 
   1181 	if (ssize != 0 && (base_sp - finalsp) > ssize)
   1182 		return (E2BIG);		/* doesn't fit in stack */
   1183 
   1184 	out->dl_descp = (ndesc != 0)? (caddr_t)descp : 0;
   1185 	out->dl_datap = (data_size != 0)? (caddr_t)datap : 0;
   1186 	out->dl_infop = info_needed? (caddr_t)infop : 0;
   1187 	out->dl_resultsp = (caddr_t)resultsp;
   1188 	out->dl_sp = (caddr_t)finalsp;
   1189 
   1190 	st->d_layout_done = 1;
   1191 	return (0);
   1192 }
   1193 
   1194 static int
   1195 door_server_dispatch(door_client_t *ct, door_node_t *dp)
   1196 {
   1197 	door_server_t *st = DOOR_SERVER(curthread->t_door);
   1198 	door_layout_t *layout = &st->d_layout;
   1199 	int error = 0;
   1200 
   1201 	int is_private = (dp->door_flags & DOOR_PRIVATE);
   1202 
   1203 	door_pool_t *pool = (is_private)? &dp->door_servers :
   1204 	    &curproc->p_server_threads;
   1205 
   1206 	int empty_pool = (pool->dp_threads == NULL);
   1207 
   1208 	caddr_t infop = NULL;
   1209 	char *datap = NULL;
   1210 	size_t datasize = 0;
   1211 	size_t descsize;
   1212 
   1213 	file_t **fpp = ct->d_fpp;
   1214 	door_desc_t *start = NULL;
   1215 	uint_t ndesc = 0;
   1216 	uint_t ncopied = 0;
   1217 
   1218 	if (ct != NULL) {
   1219 		datap = ct->d_args.data_ptr;
   1220 		datasize = ct->d_args.data_size;
   1221 		ndesc = ct->d_args.desc_num;
   1222 	}
   1223 
   1224 	descsize = ndesc * sizeof (door_desc_t);
   1225 
   1226 	/*
   1227 	 * Reset datap to NULL if we aren't passing any data.  Be careful
   1228 	 * to let unref notifications through, though.
   1229 	 */
   1230 	if (datap == DOOR_UNREF_DATA) {
   1231 		if (ct->d_upcall != NULL)
   1232 			datasize = 0;
   1233 		else
   1234 			datap = NULL;
   1235 	} else if (datasize == 0) {
   1236 		datap = NULL;
   1237 	}
   1238 
   1239 	/*
   1240 	 * Get the stack layout, if it hasn't already been done.
   1241 	 */
   1242 	if (!st->d_layout_done) {
   1243 		error = door_layout(curthread, datasize, ndesc,
   1244 		    (is_private && empty_pool));
   1245 		if (error != 0)
   1246 			goto fail;
   1247 	}
   1248 
   1249 	/*
   1250 	 * fill out the stack, starting from the top.  Layout was already
   1251 	 * filled in by door_args() or door_translate_out().
   1252 	 */
   1253 	if (layout->dl_descp != NULL) {
   1254 		ASSERT(ndesc != 0);
   1255 		start = kmem_alloc(descsize, KM_SLEEP);
   1256 
   1257 		while (ndesc > 0) {
   1258 			if (door_insert(*fpp, &start[ncopied]) == -1) {
   1259 				error = EMFILE;
   1260 				goto fail;
   1261 			}
   1262 			ndesc--;
   1263 			ncopied++;
   1264 			fpp++;
   1265 		}
   1266 		if (door_stack_copyout(start, layout->dl_descp, descsize)) {
   1267 			error = E2BIG;
   1268 			goto fail;
   1269 		}
   1270 	}
   1271 	fpp = NULL;			/* finished processing */
   1272 
   1273 	if (layout->dl_datap != NULL) {
   1274 		ASSERT(datasize != 0);
   1275 		datap = layout->dl_datap;
   1276 		if (ct->d_upcall != NULL || datasize <= door_max_arg) {
   1277 			if (door_stack_copyout(ct->d_buf, datap, datasize)) {
   1278 				error = E2BIG;
   1279 				goto fail;
   1280 			}
   1281 		}
   1282 	}
   1283 
   1284 	if (is_private && empty_pool) {
   1285 		door_info_t di;
   1286 
   1287 		infop = layout->dl_infop;
   1288 		ASSERT(infop != NULL);
   1289 
   1290 		di.di_target = curproc->p_pid;
   1291 		di.di_proc = (door_ptr_t)(uintptr_t)dp->door_pc;
   1292 		di.di_data = (door_ptr_t)(uintptr_t)dp->door_data;
   1293 		di.di_uniquifier = dp->door_index;
   1294 		di.di_attributes = (dp->door_flags & DOOR_ATTR_MASK) |
   1295 		    DOOR_LOCAL;
   1296 
   1297 		if (door_stack_copyout(&di, infop, sizeof (di))) {
   1298 			error = E2BIG;
   1299 			goto fail;
   1300 		}
   1301 	}
   1302 
   1303 	if (get_udatamodel() == DATAMODEL_NATIVE) {
   1304 		struct door_results dr;
   1305 
   1306 		dr.cookie = dp->door_data;
   1307 		dr.data_ptr = datap;
   1308 		dr.data_size = datasize;
   1309 		dr.desc_ptr = (door_desc_t *)layout->dl_descp;
   1310 		dr.desc_num = ncopied;
   1311 		dr.pc = dp->door_pc;
   1312 		dr.nservers = !empty_pool;
   1313 		dr.door_info = (door_info_t *)infop;
   1314 
   1315 		if (door_stack_copyout(&dr, layout->dl_resultsp, sizeof (dr))) {
   1316 			error = E2BIG;
   1317 			goto fail;
   1318 		}
   1319 #ifdef _SYSCALL32_IMPL
   1320 	} else {
   1321 		struct door_results32 dr32;
   1322 
   1323 		dr32.cookie = (caddr32_t)(uintptr_t)dp->door_data;
   1324 		dr32.data_ptr = (caddr32_t)(uintptr_t)datap;
   1325 		dr32.data_size = (size32_t)datasize;
   1326 		dr32.desc_ptr = (caddr32_t)(uintptr_t)layout->dl_descp;
   1327 		dr32.desc_num = ncopied;
   1328 		dr32.pc = (caddr32_t)(uintptr_t)dp->door_pc;
   1329 		dr32.nservers = !empty_pool;
   1330 		dr32.door_info = (caddr32_t)(uintptr_t)infop;
   1331 
   1332 		if (door_stack_copyout(&dr32, layout->dl_resultsp,
   1333 		    sizeof (dr32))) {
   1334 			error = E2BIG;
   1335 			goto fail;
   1336 		}
   1337 #endif
   1338 	}
   1339 
   1340 	error = door_finish_dispatch(layout->dl_sp);
   1341 fail:
   1342 	if (start != NULL) {
   1343 		if (error != 0)
   1344 			door_fd_close(start, ncopied);
   1345 		kmem_free(start, descsize);
   1346 	}
   1347 	if (fpp != NULL)
   1348 		door_fp_close(fpp, ndesc);
   1349 
   1350 	return (error);
   1351 }
   1352 
   1353 /*
   1354  * Return the results (if any) to the caller (if any) and wait for the
   1355  * next invocation on a door.
   1356  */
   1357 int
   1358 door_return(caddr_t data_ptr, size_t data_size,
   1359     door_desc_t *desc_ptr, uint_t desc_num, caddr_t sp, size_t ssize)
   1360 {
   1361 	kthread_t	*caller;
   1362 	klwp_t		*lwp;
   1363 	int		error = 0;
   1364 	door_node_t	*dp;
   1365 	door_server_t	*st;		/* curthread door_data */
   1366 	door_client_t	*ct;		/* caller door_data */
   1367 	int		cancel_pending;
   1368 
   1369 	st = door_my_server(1);
   1370 
   1371 	/*
   1372 	 * If thread was bound to a door that no longer exists, return
   1373 	 * an error.  This can happen if a thread is bound to a door
   1374 	 * before the process calls forkall(); in the child, the door
   1375 	 * doesn't exist and door_fork() sets the d_invbound flag.
   1376 	 */
   1377 	if (st->d_invbound)
   1378 		return (set_errno(EINVAL));
   1379 
   1380 	st->d_sp = sp;			/* Save base of stack. */
   1381 	st->d_ssize = ssize;		/* and its size */
   1382 
   1383 	/*
   1384 	 * This should be done in shuttle_resume(), just before going to
   1385 	 * sleep, but we want to avoid overhead while holding door_knob.
   1386 	 * prstop() is just a no-op if we don't really go to sleep.
   1387 	 * We test not-kernel-address-space for the sake of clustering code.
   1388 	 */
   1389 	lwp = ttolwp(curthread);
   1390 	if (lwp && lwp->lwp_nostop == 0 && curproc->p_as != &kas)
   1391 		prstop(PR_REQUESTED, 0);
   1392 
   1393 	/* Make sure the caller hasn't gone away */
   1394 	mutex_enter(&door_knob);
   1395 	if ((caller = st->d_caller) == NULL || caller->t_door == NULL) {
   1396 		if (desc_num != 0) {
   1397 			/* close any DOOR_RELEASE descriptors */
   1398 			mutex_exit(&door_knob);
   1399 			error = door_release_fds(desc_ptr, desc_num);
   1400 			if (error)
   1401 				return (set_errno(error));
   1402 			mutex_enter(&door_knob);
   1403 		}
   1404 		goto out;
   1405 	}
   1406 	ct = DOOR_CLIENT(caller->t_door);
   1407 
   1408 	ct->d_args.data_size = data_size;
   1409 	ct->d_args.desc_num = desc_num;
   1410 	/*
   1411 	 * Transfer results, if any, to the client
   1412 	 */
   1413 	if (data_size != 0 || desc_num != 0) {
   1414 		/*
   1415 		 * Prevent the client from exiting until we have finished
   1416 		 * moving results.
   1417 		 */
   1418 		DOOR_T_HOLD(ct);
   1419 		mutex_exit(&door_knob);
   1420 		error = door_results(caller, data_ptr, data_size,
   1421 		    desc_ptr, desc_num);
   1422 		mutex_enter(&door_knob);
   1423 		DOOR_T_RELEASE(ct);
   1424 		/*
   1425 		 * Pass EOVERFLOW errors back to the client
   1426 		 */
   1427 		if (error && error != EOVERFLOW) {
   1428 			mutex_exit(&door_knob);
   1429 			return (set_errno(error));
   1430 		}
   1431 	}
   1432 out:
   1433 	/* Put ourselves on the available server thread list */
   1434 	door_release_server(st->d_pool, curthread);
   1435 
   1436 	/*
   1437 	 * Make sure the caller is still waiting to be resumed
   1438 	 */
   1439 	if (caller) {
   1440 		disp_lock_t *tlp;
   1441 
   1442 		thread_lock(caller);
   1443 		ct->d_error = error;		/* Return any errors */
   1444 		if (caller->t_state == TS_SLEEP &&
   1445 		    SOBJ_TYPE(caller->t_sobj_ops) == SOBJ_SHUTTLE) {
   1446 			cpu_t *cp = CPU;
   1447 
   1448 			tlp = caller->t_lockp;
   1449 			/*
   1450 			 * Setting t_disp_queue prevents erroneous preemptions
   1451 			 * if this thread is still in execution on another
   1452 			 * processor
   1453 			 */
   1454 			caller->t_disp_queue = cp->cpu_disp;
   1455 			CL_ACTIVE(caller);
   1456 			/*
   1457 			 * We are calling thread_onproc() instead of
   1458 			 * THREAD_ONPROC() because compiler can reorder
   1459 			 * the two stores of t_state and t_lockp in
   1460 			 * THREAD_ONPROC().
   1461 			 */
   1462 			thread_onproc(caller, cp);
   1463 			disp_lock_exit_high(tlp);
   1464 			shuttle_resume(caller, &door_knob);
   1465 		} else {
   1466 			/* May have been setrun or in stop state */
   1467 			thread_unlock(caller);
   1468 			shuttle_swtch(&door_knob);
   1469 		}
   1470 	} else {
   1471 		shuttle_swtch(&door_knob);
   1472 	}
   1473 
   1474 	/*
   1475 	 * We've sprung to life. Determine if we are part of a door
   1476 	 * invocation, or just interrupted
   1477 	 */
   1478 	mutex_enter(&door_knob);
   1479 	if ((dp = st->d_active) != NULL) {
   1480 		/*
   1481 		 * Normal door invocation. Return any error condition
   1482 		 * encountered while trying to pass args to the server
   1483 		 * thread.
   1484 		 */
   1485 		lwp->lwp_asleep = 0;
   1486 		/*
   1487 		 * Prevent the caller from leaving us while we
   1488 		 * are copying out the arguments from it's buffer.
   1489 		 */
   1490 		ASSERT(st->d_caller != NULL);
   1491 		ct = DOOR_CLIENT(st->d_caller->t_door);
   1492 
   1493 		DOOR_T_HOLD(ct);
   1494 		mutex_exit(&door_knob);
   1495 		error = door_server_dispatch(ct, dp);
   1496 		mutex_enter(&door_knob);
   1497 		DOOR_T_RELEASE(ct);
   1498 
   1499 		/* let the client know we have processed his message */
   1500 		ct->d_args_done = 1;
   1501 
   1502 		if (error) {
   1503 			caller = st->d_caller;
   1504 			if (caller)
   1505 				ct = DOOR_CLIENT(caller->t_door);
   1506 			else
   1507 				ct = NULL;
   1508 			goto out;
   1509 		}
   1510 		mutex_exit(&door_knob);
   1511 		return (0);
   1512 	} else {
   1513 		/*
   1514 		 * We are not involved in a door_invocation.
   1515 		 * Check for /proc related activity...
   1516 		 */
   1517 		st->d_caller = NULL;
   1518 		door_server_exit(curproc, curthread);
   1519 		mutex_exit(&door_knob);
   1520 		cancel_pending = 0;
   1521 		if (ISSIG(curthread, FORREAL) || lwp->lwp_sysabort ||
   1522 		    MUSTRETURN(curproc, curthread) ||
   1523 		    (cancel_pending = schedctl_cancel_pending()) != 0) {
   1524 			if (cancel_pending)
   1525 				schedctl_cancel_eintr();
   1526 			lwp->lwp_asleep = 0;
   1527 			lwp->lwp_sysabort = 0;
   1528 			return (set_errno(EINTR));
   1529 		}
   1530 		/* Go back and wait for another request */
   1531 		lwp->lwp_asleep = 0;
   1532 		mutex_enter(&door_knob);
   1533 		caller = NULL;
   1534 		goto out;
   1535 	}
   1536 }
   1537 
   1538 /*
   1539  * Revoke any future invocations on this door
   1540  */
   1541 int
   1542 door_revoke(int did)
   1543 {
   1544 	door_node_t	*d;
   1545 	int		error;
   1546 
   1547 	if ((d = door_lookup(did, NULL)) == NULL)
   1548 		return (set_errno(EBADF));
   1549 
   1550 	mutex_enter(&door_knob);
   1551 	if (d->door_target != curproc) {
   1552 		mutex_exit(&door_knob);
   1553 		releasef(did);
   1554 		return (set_errno(EPERM));
   1555 	}
   1556 	d->door_flags |= DOOR_REVOKED;
   1557 	if (d->door_flags & DOOR_PRIVATE)
   1558 		cv_broadcast(&d->door_servers.dp_cv);
   1559 	else
   1560 		cv_broadcast(&curproc->p_server_threads.dp_cv);
   1561 	mutex_exit(&door_knob);
   1562 	releasef(did);
   1563 	/* Invalidate the descriptor */
   1564 	if ((error = closeandsetf(did, NULL)) != 0)
   1565 		return (set_errno(error));
   1566 	return (0);
   1567 }
   1568 
   1569 int
   1570 door_info(int did, struct door_info *d_info)
   1571 {
   1572 	door_node_t	*dp;
   1573 	door_info_t	di;
   1574 	door_server_t	*st;
   1575 	file_t		*fp = NULL;
   1576 
   1577 	if (did == DOOR_QUERY) {
   1578 		/* Get information on door current thread is bound to */
   1579 		if ((st = door_my_server(0)) == NULL ||
   1580 		    (dp = st->d_pool) == NULL)
   1581 			/* Thread isn't bound to a door */
   1582 			return (set_errno(EBADF));
   1583 	} else if ((dp = door_lookup(did, &fp)) == NULL) {
   1584 		/* Not a door */
   1585 		return (set_errno(EBADF));
   1586 	}
   1587 
   1588 	door_info_common(dp, &di, fp);
   1589 
   1590 	if (did != DOOR_QUERY)
   1591 		releasef(did);
   1592 
   1593 	if (copyout(&di, d_info, sizeof (struct door_info)))
   1594 		return (set_errno(EFAULT));
   1595 	return (0);
   1596 }
   1597 
   1598 /*
   1599  * Common code for getting information about a door either via the
   1600  * door_info system call or the door_ki_info kernel call.
   1601  */
   1602 void
   1603 door_info_common(door_node_t *dp, struct door_info *dip, file_t *fp)
   1604 {
   1605 	int unref_count;
   1606 
   1607 	bzero(dip, sizeof (door_info_t));
   1608 
   1609 	mutex_enter(&door_knob);
   1610 	if (dp->door_target == NULL)
   1611 		dip->di_target = -1;
   1612 	else
   1613 		dip->di_target = dp->door_target->p_pid;
   1614 
   1615 	dip->di_attributes = dp->door_flags & DOOR_ATTR_MASK;
   1616 	if (dp->door_target == curproc)
   1617 		dip->di_attributes |= DOOR_LOCAL;
   1618 	dip->di_proc = (door_ptr_t)(uintptr_t)dp->door_pc;
   1619 	dip->di_data = (door_ptr_t)(uintptr_t)dp->door_data;
   1620 	dip->di_uniquifier = dp->door_index;
   1621 	/*
   1622 	 * If this door is in the middle of having an unreferenced
   1623 	 * notification delivered, don't count the VN_HOLD by
   1624 	 * door_deliver_unref in determining if it is unreferenced.
   1625 	 * This handles the case where door_info is called from the
   1626 	 * thread delivering the unref notification.
   1627 	 */
   1628 	if (dp->door_flags & DOOR_UNREF_ACTIVE)
   1629 		unref_count = 2;
   1630 	else
   1631 		unref_count = 1;
   1632 	mutex_exit(&door_knob);
   1633 
   1634 	if (fp == NULL) {
   1635 		/*
   1636 		 * If this thread is bound to the door, then we can just
   1637 		 * check the vnode; a ref count of 1 (or 2 if this is
   1638 		 * handling an unref notification) means that the hold
   1639 		 * from the door_bind is the only reference to the door
   1640 		 * (no file descriptor refers to it).
   1641 		 */
   1642 		if (DTOV(dp)->v_count == unref_count)
   1643 			dip->di_attributes |= DOOR_IS_UNREF;
   1644 	} else {
   1645 		/*
   1646 		 * If we're working from a file descriptor or door handle
   1647 		 * we need to look at the file structure count.  We don't
   1648 		 * need to hold the vnode lock since this is just a snapshot.
   1649 		 */
   1650 		mutex_enter(&fp->f_tlock);
   1651 		if (fp->f_count == 1 && DTOV(dp)->v_count == unref_count)
   1652 			dip->di_attributes |= DOOR_IS_UNREF;
   1653 		mutex_exit(&fp->f_tlock);
   1654 	}
   1655 }
   1656 
   1657 /*
   1658  * Return credentials of the door caller (if any) for this invocation
   1659  */
   1660 int
   1661 door_ucred(struct ucred_s *uch)
   1662 {
   1663 	kthread_t	*caller;
   1664 	door_server_t	*st;
   1665 	door_client_t	*ct;
   1666 	door_upcall_t	*dup;
   1667 	struct proc	*p;
   1668 	struct ucred_s	*res;
   1669 	int		err;
   1670 
   1671 	mutex_enter(&door_knob);
   1672 	if ((st = door_my_server(0)) == NULL ||
   1673 	    (caller = st->d_caller) == NULL) {
   1674 		mutex_exit(&door_knob);
   1675 		return (set_errno(EINVAL));
   1676 	}
   1677 
   1678 	ASSERT(caller->t_door != NULL);
   1679 	ct = DOOR_CLIENT(caller->t_door);
   1680 
   1681 	/* Prevent caller from exiting while we examine the cred */
   1682 	DOOR_T_HOLD(ct);
   1683 	mutex_exit(&door_knob);
   1684 
   1685 	p = ttoproc(caller);
   1686 
   1687 	/*
   1688 	 * If the credentials are not specified by the client, get the one
   1689 	 * associated with the calling process.
   1690 	 */
   1691 	if ((dup = ct->d_upcall) != NULL)
   1692 		res = cred2ucred(dup->du_cred, p0.p_pid, NULL, CRED());
   1693 	else
   1694 		res = cred2ucred(caller->t_cred, p->p_pid, NULL, CRED());
   1695 
   1696 	mutex_enter(&door_knob);
   1697 	DOOR_T_RELEASE(ct);
   1698 	mutex_exit(&door_knob);
   1699 
   1700 	err = copyout(res, uch, res->uc_size);
   1701 
   1702 	kmem_free(res, res->uc_size);
   1703 
   1704 	if (err != 0)
   1705 		return (set_errno(EFAULT));
   1706 
   1707 	return (0);
   1708 }
   1709 
   1710 /*
   1711  * Bind the current lwp to the server thread pool associated with 'did'
   1712  */
   1713 int
   1714 door_bind(int did)
   1715 {
   1716 	door_node_t	*dp;
   1717 	door_server_t	*st;
   1718 
   1719 	if ((dp = door_lookup(did, NULL)) == NULL) {
   1720 		/* Not a door */
   1721 		return (set_errno(EBADF));
   1722 	}
   1723 
   1724 	/*
   1725 	 * Can't bind to a non-private door, and can't bind to a door
   1726 	 * served by another process.
   1727 	 */
   1728 	if ((dp->door_flags & DOOR_PRIVATE) == 0 ||
   1729 	    dp->door_target != curproc) {
   1730 		releasef(did);
   1731 		return (set_errno(EINVAL));
   1732 	}
   1733 
   1734 	st = door_my_server(1);
   1735 	if (st->d_pool)
   1736 		door_unbind_thread(st->d_pool);
   1737 	st->d_pool = dp;
   1738 	st->d_invbound = 0;
   1739 	door_bind_thread(dp);
   1740 	releasef(did);
   1741 
   1742 	return (0);
   1743 }
   1744 
   1745 /*
   1746  * Unbind the current lwp from it's server thread pool
   1747  */
   1748 int
   1749 door_unbind(void)
   1750 {
   1751 	door_server_t *st;
   1752 
   1753 	if ((st = door_my_server(0)) == NULL)
   1754 		return (set_errno(EBADF));
   1755 
   1756 	if (st->d_invbound) {
   1757 		ASSERT(st->d_pool == NULL);
   1758 		st->d_invbound = 0;
   1759 		return (0);
   1760 	}
   1761 	if (st->d_pool == NULL)
   1762 		return (set_errno(EBADF));
   1763 	door_unbind_thread(st->d_pool);
   1764 	st->d_pool = NULL;
   1765 	return (0);
   1766 }
   1767 
   1768 /*
   1769  * Create a descriptor for the associated file and fill in the
   1770  * attributes associated with it.
   1771  *
   1772  * Return 0 for success, -1 otherwise;
   1773  */
   1774 int
   1775 door_insert(struct file *fp, door_desc_t *dp)
   1776 {
   1777 	struct vnode *vp;
   1778 	int	fd;
   1779 	door_attr_t attributes = DOOR_DESCRIPTOR;
   1780 
   1781 	ASSERT(MUTEX_NOT_HELD(&door_knob));
   1782 	if ((fd = ufalloc(0)) == -1)
   1783 		return (-1);
   1784 	setf(fd, fp);
   1785 	dp->d_data.d_desc.d_descriptor = fd;
   1786 
   1787 	/* Fill in the attributes */
   1788 	if (VOP_REALVP(fp->f_vnode, &vp, NULL))
   1789 		vp = fp->f_vnode;
   1790 	if (vp && vp->v_type == VDOOR) {
   1791 		if (VTOD(vp)->door_target == curproc)
   1792 			attributes |= DOOR_LOCAL;
   1793 		attributes |= VTOD(vp)->door_flags & DOOR_ATTR_MASK;
   1794 		dp->d_data.d_desc.d_id = VTOD(vp)->door_index;
   1795 	}
   1796 	dp->d_attributes = attributes;
   1797 	return (0);
   1798 }
   1799 
   1800 /*
   1801  * Return an available thread for this server.  A NULL return value indicates
   1802  * that either:
   1803  *	The door has been revoked, or
   1804  *	a signal was received.
   1805  * The two conditions can be differentiated using DOOR_INVALID(dp).
   1806  */
   1807 static kthread_t *
   1808 door_get_server(door_node_t *dp)
   1809 {
   1810 	kthread_t **ktp;
   1811 	kthread_t *server_t;
   1812 	door_pool_t *pool;
   1813 	door_server_t *st;
   1814 	int signalled;
   1815 
   1816 	disp_lock_t *tlp;
   1817 	cpu_t *cp;
   1818 
   1819 	ASSERT(MUTEX_HELD(&door_knob));
   1820 
   1821 	if (dp->door_flags & DOOR_PRIVATE)
   1822 		pool = &dp->door_servers;
   1823 	else
   1824 		pool = &dp->door_target->p_server_threads;
   1825 
   1826 	for (;;) {
   1827 		/*
   1828 		 * We search the thread pool, looking for a server thread
   1829 		 * ready to take an invocation (i.e. one which is still
   1830 		 * sleeping on a shuttle object).  If none are available,
   1831 		 * we sleep on the pool's CV, and will be signaled when a
   1832 		 * thread is added to the pool.
   1833 		 *
   1834 		 * This relies on the fact that once a thread in the thread
   1835 		 * pool wakes up, it *must* remove and add itself to the pool
   1836 		 * before it can receive door calls.
   1837 		 */
   1838 		if (DOOR_INVALID(dp))
   1839 			return (NULL);	/* Target has become invalid */
   1840 
   1841 		for (ktp = &pool->dp_threads;
   1842 		    (server_t = *ktp) != NULL;
   1843 		    ktp = &st->d_servers) {
   1844 			st = DOOR_SERVER(server_t->t_door);
   1845 
   1846 			thread_lock(server_t);
   1847 			if (server_t->t_state == TS_SLEEP &&
   1848 			    SOBJ_TYPE(server_t->t_sobj_ops) == SOBJ_SHUTTLE)
   1849 				break;
   1850 			thread_unlock(server_t);
   1851 		}
   1852 		if (server_t != NULL)
   1853 			break;		/* we've got a live one! */
   1854 
   1855 		if (!cv_wait_sig_swap_core(&pool->dp_cv, &door_knob,
   1856 		    &signalled)) {
   1857 			/*
   1858 			 * If we were signaled and the door is still
   1859 			 * valid, pass the signal on to another waiter.
   1860 			 */
   1861 			if (signalled && !DOOR_INVALID(dp))
   1862 				cv_signal(&pool->dp_cv);
   1863 			return (NULL);	/* Got a signal */
   1864 		}
   1865 	}
   1866 
   1867 	/*
   1868 	 * We've got a thread_lock()ed thread which is still on the
   1869 	 * shuttle.  Take it off the list of available server threads
   1870 	 * and mark it as ONPROC.  We are committed to resuming this
   1871 	 * thread now.
   1872 	 */
   1873 	tlp = server_t->t_lockp;
   1874 	cp = CPU;
   1875 
   1876 	*ktp = st->d_servers;
   1877 	st->d_servers = NULL;
   1878 	/*
   1879 	 * Setting t_disp_queue prevents erroneous preemptions
   1880 	 * if this thread is still in execution on another processor
   1881 	 */
   1882 	server_t->t_disp_queue = cp->cpu_disp;
   1883 	CL_ACTIVE(server_t);
   1884 	/*
   1885 	 * We are calling thread_onproc() instead of
   1886 	 * THREAD_ONPROC() because compiler can reorder
   1887 	 * the two stores of t_state and t_lockp in
   1888 	 * THREAD_ONPROC().
   1889 	 */
   1890 	thread_onproc(server_t, cp);
   1891 	disp_lock_exit(tlp);
   1892 	return (server_t);
   1893 }
   1894 
   1895 /*
   1896  * Put a server thread back in the pool.
   1897  */
   1898 static void
   1899 door_release_server(door_node_t *dp, kthread_t *t)
   1900 {
   1901 	door_server_t *st = DOOR_SERVER(t->t_door);
   1902 	door_pool_t *pool;
   1903 
   1904 	ASSERT(MUTEX_HELD(&door_knob));
   1905 	st->d_active = NULL;
   1906 	st->d_caller = NULL;
   1907 	st->d_layout_done = 0;
   1908 	if (dp && (dp->door_flags & DOOR_PRIVATE)) {
   1909 		ASSERT(dp->door_target == NULL ||
   1910 		    dp->door_target == ttoproc(t));
   1911 		pool = &dp->door_servers;
   1912 	} else {
   1913 		pool = &ttoproc(t)->p_server_threads;
   1914 	}
   1915 
   1916 	st->d_servers = pool->dp_threads;
   1917 	pool->dp_threads = t;
   1918 
   1919 	/* If someone is waiting for a server thread, wake him up */
   1920 	cv_signal(&pool->dp_cv);
   1921 }
   1922 
   1923 /*
   1924  * Remove a server thread from the pool if present.
   1925  */
   1926 static void
   1927 door_server_exit(proc_t *p, kthread_t *t)
   1928 {
   1929 	door_pool_t *pool;
   1930 	kthread_t **next;
   1931 	door_server_t *st = DOOR_SERVER(t->t_door);
   1932 
   1933 	ASSERT(MUTEX_HELD(&door_knob));
   1934 	if (st->d_pool != NULL) {
   1935 		ASSERT(st->d_pool->door_flags & DOOR_PRIVATE);
   1936 		pool = &st->d_pool->door_servers;
   1937 	} else {
   1938 		pool = &p->p_server_threads;
   1939 	}
   1940 
   1941 	next = &pool->dp_threads;
   1942 	while (*next != NULL) {
   1943 		if (*next == t) {
   1944 			*next = DOOR_SERVER(t->t_door)->d_servers;
   1945 			return;
   1946 		}
   1947 		next = &(DOOR_SERVER((*next)->t_door)->d_servers);
   1948 	}
   1949 }
   1950 
   1951 /*
   1952  * Lookup the door descriptor. Caller must call releasef when finished
   1953  * with associated door.
   1954  */
   1955 static door_node_t *
   1956 door_lookup(int did, file_t **fpp)
   1957 {
   1958 	vnode_t	*vp;
   1959 	file_t *fp;
   1960 
   1961 	ASSERT(MUTEX_NOT_HELD(&door_knob));
   1962 	if ((fp = getf(did)) == NULL)
   1963 		return (NULL);
   1964 	/*
   1965 	 * Use the underlying vnode (we may be namefs mounted)
   1966 	 */
   1967 	if (VOP_REALVP(fp->f_vnode, &vp, NULL))
   1968 		vp = fp->f_vnode;
   1969 
   1970 	if (vp == NULL || vp->v_type != VDOOR) {
   1971 		releasef(did);
   1972 		return (NULL);
   1973 	}
   1974 
   1975 	if (fpp)
   1976 		*fpp = fp;
   1977 
   1978 	return (VTOD(vp));
   1979 }
   1980 
   1981 /*
   1982  * The current thread is exiting, so clean up any pending
   1983  * invocation details
   1984  */
   1985 void
   1986 door_slam(void)
   1987 {
   1988 	door_node_t *dp;
   1989 	door_data_t *dt;
   1990 	door_client_t *ct;
   1991 	door_server_t *st;
   1992 
   1993 	/*
   1994 	 * If we are an active door server, notify our
   1995 	 * client that we are exiting and revoke our door.
   1996 	 */
   1997 	if ((dt = door_my_data(0)) == NULL)
   1998 		return;
   1999 	ct = DOOR_CLIENT(dt);
   2000 	st = DOOR_SERVER(dt);
   2001 
   2002 	mutex_enter(&door_knob);
   2003 	for (;;) {
   2004 		if (DOOR_T_HELD(ct))
   2005 			cv_wait(&ct->d_cv, &door_knob);
   2006 		else if (DOOR_T_HELD(st))
   2007 			cv_wait(&st->d_cv, &door_knob);
   2008 		else
   2009 			break;			/* neither flag is set */
   2010 	}
   2011 	curthread->t_door = NULL;
   2012 	if ((dp = st->d_active) != NULL) {
   2013 		kthread_t *t = st->d_caller;
   2014 		proc_t *p = curproc;
   2015 
   2016 		/* Revoke our door if the process is exiting */
   2017 		if (dp->door_target == p && (p->p_flag & SEXITING)) {
   2018 			door_list_delete(dp);
   2019 			dp->door_target = NULL;
   2020 			dp->door_flags |= DOOR_REVOKED;
   2021 			if (dp->door_flags & DOOR_PRIVATE)
   2022 				cv_broadcast(&dp->door_servers.dp_cv);
   2023 			else
   2024 				cv_broadcast(&p->p_server_threads.dp_cv);
   2025 		}
   2026 
   2027 		if (t != NULL) {
   2028 			/*
   2029 			 * Let the caller know we are gone
   2030 			 */
   2031 			DOOR_CLIENT(t->t_door)->d_error = DOOR_EXIT;
   2032 			thread_lock(t);
   2033 			if (t->t_state == TS_SLEEP &&
   2034 			    SOBJ_TYPE(t->t_sobj_ops) == SOBJ_SHUTTLE)
   2035 				setrun_locked(t);
   2036 			thread_unlock(t);
   2037 		}
   2038 	}
   2039 	mutex_exit(&door_knob);
   2040 	if (st->d_pool)
   2041 		door_unbind_thread(st->d_pool);	/* Implicit door_unbind */
   2042 	kmem_free(dt, sizeof (door_data_t));
   2043 }
   2044 
   2045 /*
   2046  * Set DOOR_REVOKED for all doors of the current process. This is called
   2047  * on exit before all lwp's are being terminated so that door calls will
   2048  * return with an error.
   2049  */
   2050 void
   2051 door_revoke_all()
   2052 {
   2053 	door_node_t *dp;
   2054 	proc_t *p = ttoproc(curthread);
   2055 
   2056 	mutex_enter(&door_knob);
   2057 	for (dp = p->p_door_list; dp != NULL; dp = dp->door_list) {
   2058 		ASSERT(dp->door_target == p);
   2059 		dp->door_flags |= DOOR_REVOKED;
   2060 		if (dp->door_flags & DOOR_PRIVATE)
   2061 			cv_broadcast(&dp->door_servers.dp_cv);
   2062 	}
   2063 	cv_broadcast(&p->p_server_threads.dp_cv);
   2064 	mutex_exit(&door_knob);
   2065 }
   2066 
   2067 /*
   2068  * The process is exiting, and all doors it created need to be revoked.
   2069  */
   2070 void
   2071 door_exit(void)
   2072 {
   2073 	door_node_t *dp;
   2074 	proc_t *p = ttoproc(curthread);
   2075 
   2076 	ASSERT(p->p_lwpcnt == 1);
   2077 	/*
   2078 	 * Walk the list of active doors created by this process and
   2079 	 * revoke them all.
   2080 	 */
   2081 	mutex_enter(&door_knob);
   2082 	for (dp = p->p_door_list; dp != NULL; dp = dp->door_list) {
   2083 		dp->door_target = NULL;
   2084 		dp->door_flags |= DOOR_REVOKED;
   2085 		if (dp->door_flags & DOOR_PRIVATE)
   2086 			cv_broadcast(&dp->door_servers.dp_cv);
   2087 	}
   2088 	cv_broadcast(&p->p_server_threads.dp_cv);
   2089 	/* Clear the list */
   2090 	p->p_door_list = NULL;
   2091 
   2092 	/* Clean up the unref list */
   2093 	while ((dp = p->p_unref_list) != NULL) {
   2094 		p->p_unref_list = dp->door_ulist;
   2095 		dp->door_ulist = NULL;
   2096 		mutex_exit(&door_knob);
   2097 		VN_RELE(DTOV(dp));
   2098 		mutex_enter(&door_knob);
   2099 	}
   2100 	mutex_exit(&door_knob);
   2101 }
   2102 
   2103 
   2104 /*
   2105  * The process is executing forkall(), and we need to flag threads that
   2106  * are bound to a door in the child.  This will make the child threads
   2107  * return an error to door_return unless they call door_unbind first.
   2108  */
   2109 void
   2110 door_fork(kthread_t *parent, kthread_t *child)
   2111 {
   2112 	door_data_t *pt = parent->t_door;
   2113 	door_server_t *st = DOOR_SERVER(pt);
   2114 	door_data_t *dt;
   2115 
   2116 	ASSERT(MUTEX_NOT_HELD(&door_knob));
   2117 	if (pt != NULL && (st->d_pool != NULL || st->d_invbound)) {
   2118 		/* parent thread is bound to a door */
   2119 		dt = child->t_door =
   2120 		    kmem_zalloc(sizeof (door_data_t), KM_SLEEP);
   2121 		DOOR_SERVER(dt)->d_invbound = 1;
   2122 	}
   2123 }
   2124 
   2125 /*
   2126  * Deliver queued unrefs to appropriate door server.
   2127  */
   2128 static int
   2129 door_unref(void)
   2130 {
   2131 	door_node_t	*dp;
   2132 	static door_arg_t unref_args = { DOOR_UNREF_DATA, 0, 0, 0, 0, 0 };
   2133 	proc_t *p = ttoproc(curthread);
   2134 
   2135 	/* make sure there's only one unref thread per process */
   2136 	mutex_enter(&door_knob);
   2137 	if (p->p_unref_thread) {
   2138 		mutex_exit(&door_knob);
   2139 		return (set_errno(EALREADY));
   2140 	}
   2141 	p->p_unref_thread = 1;
   2142 	mutex_exit(&door_knob);
   2143 
   2144 	(void) door_my_data(1);			/* create info, if necessary */
   2145 
   2146 	for (;;) {
   2147 		mutex_enter(&door_knob);
   2148 
   2149 		/* Grab a queued request */
   2150 		while ((dp = p->p_unref_list) == NULL) {
   2151 			if (!cv_wait_sig(&p->p_unref_cv, &door_knob)) {
   2152 				/*
   2153 				 * Interrupted.
   2154 				 * Return so we can finish forkall() or exit().
   2155 				 */
   2156 				p->p_unref_thread = 0;
   2157 				mutex_exit(&door_knob);
   2158 				return (set_errno(EINTR));
   2159 			}
   2160 		}
   2161 		p->p_unref_list = dp->door_ulist;
   2162 		dp->door_ulist = NULL;
   2163 		dp->door_flags |= DOOR_UNREF_ACTIVE;
   2164 		mutex_exit(&door_knob);
   2165 
   2166 		(void) door_upcall(DTOV(dp), &unref_args, NULL, SIZE_MAX, 0);
   2167 
   2168 		if (unref_args.rbuf != 0) {
   2169 			kmem_free(unref_args.rbuf, unref_args.rsize);
   2170 			unref_args.rbuf = NULL;
   2171 			unref_args.rsize = 0;
   2172 		}
   2173 
   2174 		mutex_enter(&door_knob);
   2175 		ASSERT(dp->door_flags & DOOR_UNREF_ACTIVE);
   2176 		dp->door_flags &= ~DOOR_UNREF_ACTIVE;
   2177 		mutex_exit(&door_knob);
   2178 		VN_RELE(DTOV(dp));
   2179 	}
   2180 }
   2181 
   2182 
   2183 /*
   2184  * Deliver queued unrefs to kernel door server.
   2185  */
   2186 /* ARGSUSED */
   2187 static void
   2188 door_unref_kernel(caddr_t arg)
   2189 {
   2190 	door_node_t	*dp;
   2191 	static door_arg_t unref_args = { DOOR_UNREF_DATA, 0, 0, 0, 0, 0 };
   2192 	proc_t *p = ttoproc(curthread);
   2193 	callb_cpr_t cprinfo;
   2194 
   2195 	/* should only be one of these */
   2196 	mutex_enter(&door_knob);
   2197 	if (p->p_unref_thread) {
   2198 		mutex_exit(&door_knob);
   2199 		return;
   2200 	}
   2201 	p->p_unref_thread = 1;
   2202 	mutex_exit(&door_knob);
   2203 
   2204 	(void) door_my_data(1);		/* make sure we have a door_data_t */
   2205 
   2206 	CALLB_CPR_INIT(&cprinfo, &door_knob, callb_generic_cpr, "door_unref");
   2207 	for (;;) {
   2208 		mutex_enter(&door_knob);
   2209 		/* Grab a queued request */
   2210 		while ((dp = p->p_unref_list) == NULL) {
   2211 			CALLB_CPR_SAFE_BEGIN(&cprinfo);
   2212 			cv_wait(&p->p_unref_cv, &door_knob);
   2213 			CALLB_CPR_SAFE_END(&cprinfo, &door_knob);
   2214 		}
   2215 		p->p_unref_list = dp->door_ulist;
   2216 		dp->door_ulist = NULL;
   2217 		dp->door_flags |= DOOR_UNREF_ACTIVE;
   2218 		mutex_exit(&door_knob);
   2219 
   2220 		(*(dp->door_pc))(dp->door_data, &unref_args, NULL, NULL, NULL);
   2221 
   2222 		mutex_enter(&door_knob);
   2223 		ASSERT(dp->door_flags & DOOR_UNREF_ACTIVE);
   2224 		dp->door_flags &= ~DOOR_UNREF_ACTIVE;
   2225 		mutex_exit(&door_knob);
   2226 		VN_RELE(DTOV(dp));
   2227 	}
   2228 }
   2229 
   2230 
   2231 /*
   2232  * Queue an unref invocation for processing for the current process
   2233  * The door may or may not be revoked at this point.
   2234  */
   2235 void
   2236 door_deliver_unref(door_node_t *d)
   2237 {
   2238 	struct proc *server = d->door_target;
   2239 
   2240 	ASSERT(MUTEX_HELD(&door_knob));
   2241 	ASSERT(d->door_active == 0);
   2242 
   2243 	if (server == NULL)
   2244 		return;
   2245 	/*
   2246 	 * Create a lwp to deliver unref calls if one isn't already running.
   2247 	 *
   2248 	 * A separate thread is used to deliver unrefs since the current
   2249 	 * thread may be holding resources (e.g. locks) in user land that
   2250 	 * may be needed by the unref processing. This would cause a
   2251 	 * deadlock.
   2252 	 */
   2253 	if (d->door_flags & DOOR_UNREF_MULTI) {
   2254 		/* multiple unrefs */
   2255 		d->door_flags &= ~DOOR_DELAY;
   2256 	} else {
   2257 		/* Only 1 unref per door */
   2258 		d->door_flags &= ~(DOOR_UNREF|DOOR_DELAY);
   2259 	}
   2260 	mutex_exit(&door_knob);
   2261 
   2262 	/*
   2263 	 * Need to bump the vnode count before putting the door on the
   2264 	 * list so it doesn't get prematurely released by door_unref.
   2265 	 */
   2266 	VN_HOLD(DTOV(d));
   2267 
   2268 	mutex_enter(&door_knob);
   2269 	/* is this door already on the unref list? */
   2270 	if (d->door_flags & DOOR_UNREF_MULTI) {
   2271 		door_node_t *dp;
   2272 		for (dp = server->p_unref_list; dp != NULL;
   2273 		    dp = dp->door_ulist) {
   2274 			if (d == dp) {
   2275 				/* already there, don't need to add another */
   2276 				mutex_exit(&door_knob);
   2277 				VN_RELE(DTOV(d));
   2278 				mutex_enter(&door_knob);
   2279 				return;
   2280 			}
   2281 		}
   2282 	}
   2283 	ASSERT(d->door_ulist == NULL);
   2284 	d->door_ulist = server->p_unref_list;
   2285 	server->p_unref_list = d;
   2286 	cv_broadcast(&server->p_unref_cv);
   2287 }
   2288 
   2289 /*
   2290  * The callers buffer isn't big enough for all of the data/fd's. Allocate
   2291  * space in the callers address space for the results and copy the data
   2292  * there.
   2293  *
   2294  * For EOVERFLOW, we must clean up the server's door descriptors.
   2295  */
   2296 static int
   2297 door_overflow(
   2298 	kthread_t	*caller,
   2299 	caddr_t		data_ptr,	/* data location */
   2300 	size_t		data_size,	/* data size */
   2301 	door_desc_t	*desc_ptr,	/* descriptor location */
   2302 	uint_t		desc_num)	/* descriptor size */
   2303 {
   2304 	proc_t *callerp = ttoproc(caller);
   2305 	struct as *as = callerp->p_as;
   2306 	door_client_t *ct = DOOR_CLIENT(caller->t_door);
   2307 	caddr_t	addr;			/* Resulting address in target */
   2308 	size_t	rlen;			/* Rounded len */
   2309 	size_t	len;
   2310 	uint_t	i;
   2311 	size_t	ds = desc_num * sizeof (door_desc_t);
   2312 
   2313 	ASSERT(MUTEX_NOT_HELD(&door_knob));
   2314 	ASSERT(DOOR_T_HELD(ct) || ct->d_kernel);
   2315 
   2316 	/* Do initial overflow check */
   2317 	if (!ufcanalloc(callerp, desc_num))
   2318 		return (EMFILE);
   2319 
   2320 	/*
   2321 	 * Allocate space for this stuff in the callers address space
   2322 	 */
   2323 	rlen = roundup(data_size + ds, PAGESIZE);
   2324 	as_rangelock(as);
   2325 	map_addr_proc(&addr, rlen, 0, 1, as->a_userlimit, ttoproc(caller), 0);
   2326 	if (addr == NULL ||
   2327 	    as_map(as, addr, rlen, segvn_create, zfod_argsp) != 0) {
   2328 		/* No virtual memory available, or anon mapping failed */
   2329 		as_rangeunlock(as);
   2330 		if (!ct->d_kernel && desc_num > 0) {
   2331 			int error = door_release_fds(desc_ptr, desc_num);
   2332 			if (error)
   2333 				return (error);
   2334 		}
   2335 		return (EOVERFLOW);
   2336 	}
   2337 	as_rangeunlock(as);
   2338 
   2339 	if (ct->d_kernel)
   2340 		goto out;
   2341 
   2342 	if (data_size != 0) {
   2343 		caddr_t	src = data_ptr;
   2344 		caddr_t saddr = addr;
   2345 
   2346 		/* Copy any data */
   2347 		len = data_size;
   2348 		while (len != 0) {
   2349 			int	amount;
   2350 			int	error;
   2351 
   2352 			amount = len > PAGESIZE ? PAGESIZE : len;
   2353 			if ((error = door_copy(as, src, saddr, amount)) != 0) {
   2354 				(void) as_unmap(as, addr, rlen);
   2355 				return (error);
   2356 			}
   2357 			saddr += amount;
   2358 			src += amount;
   2359 			len -= amount;
   2360 		}
   2361 	}
   2362 	/* Copy any fd's */
   2363 	if (desc_num != 0) {
   2364 		door_desc_t	*didpp, *start;
   2365 		struct file	**fpp;
   2366 		int		fpp_size;
   2367 
   2368 		start = didpp = kmem_alloc(ds, KM_SLEEP);
   2369 		if (copyin_nowatch(desc_ptr, didpp, ds)) {
   2370 			kmem_free(start, ds);
   2371 			(void) as_unmap(as, addr, rlen);
   2372 			return (EFAULT);
   2373 		}
   2374 
   2375 		fpp_size = desc_num * sizeof (struct file *);
   2376 		if (fpp_size > ct->d_fpp_size) {
   2377 			/* make more space */
   2378 			if (ct->d_fpp_size)
   2379 				kmem_free(ct->d_fpp, ct->d_fpp_size);
   2380 			ct->d_fpp_size = fpp_size;
   2381 			ct->d_fpp = kmem_alloc(ct->d_fpp_size, KM_SLEEP);
   2382 		}
   2383 		fpp = ct->d_fpp;
   2384 
   2385 		for (i = 0; i < desc_num; i++) {
   2386 			struct file *fp;
   2387 			int fd = didpp->d_data.d_desc.d_descriptor;
   2388 
   2389 			if (!(didpp->d_attributes & DOOR_DESCRIPTOR) ||
   2390 			    (fp = getf(fd)) == NULL) {
   2391 				/* close translated references */
   2392 				door_fp_close(ct->d_fpp, fpp - ct->d_fpp);
   2393 				/* close untranslated references */
   2394 				door_fd_rele(didpp, desc_num - i, 0);
   2395 				kmem_free(start, ds);
   2396 				(void) as_unmap(as, addr, rlen);
   2397 				return (EINVAL);
   2398 			}
   2399 			mutex_enter(&fp->f_tlock);
   2400 			fp->f_count++;
   2401 			mutex_exit(&fp->f_tlock);
   2402 
   2403 			*fpp = fp;
   2404 			releasef(fd);
   2405 
   2406 			if (didpp->d_attributes & DOOR_RELEASE) {
   2407 				/* release passed reference */
   2408 				(void) closeandsetf(fd, NULL);
   2409 			}
   2410 
   2411 			fpp++; didpp++;
   2412 		}
   2413 		kmem_free(start, ds);
   2414 	}
   2415 
   2416 out:
   2417 	ct->d_overflow = 1;
   2418 	ct->d_args.rbuf = addr;
   2419 	ct->d_args.rsize = rlen;
   2420 	return (0);
   2421 }
   2422 
   2423 /*
   2424  * Transfer arguments from the client to the server.
   2425  */
   2426 static int
   2427 door_args(kthread_t *server, int is_private)
   2428 {
   2429 	door_server_t *st = DOOR_SERVER(server->t_door);
   2430 	door_client_t *ct = DOOR_CLIENT(curthread->t_door);
   2431 	uint_t	ndid;
   2432 	size_t	dsize;
   2433 	int	error;
   2434 
   2435 	ASSERT(DOOR_T_HELD(st));
   2436 	ASSERT(MUTEX_NOT_HELD(&door_knob));
   2437 
   2438 	ndid = ct->d_args.desc_num;
   2439 	if (ndid > door_max_desc)
   2440 		return (E2BIG);
   2441 
   2442 	/*
   2443 	 * Get the stack layout, and fail now if it won't fit.
   2444 	 */
   2445 	error = door_layout(server, ct->d_args.data_size, ndid, is_private);
   2446 	if (error != 0)
   2447 		return (error);
   2448 
   2449 	dsize = ndid * sizeof (door_desc_t);
   2450 	if (ct->d_args.data_size != 0) {
   2451 		if (ct->d_args.data_size <= door_max_arg) {
   2452 			/*
   2453 			 * Use a 2 copy method for small amounts of data
   2454 			 *
   2455 			 * Allocate a little more than we need for the
   2456 			 * args, in the hope that the results will fit
   2457 			 * without having to reallocate a buffer
   2458 			 */
   2459 			ASSERT(ct->d_buf == NULL);
   2460 			ct->d_bufsize = roundup(ct->d_args.data_size,
   2461 			    DOOR_ROUND);
   2462 			ct->d_buf = kmem_alloc(ct->d_bufsize, KM_SLEEP);
   2463 			if (copyin_nowatch(ct->d_args.data_ptr,
   2464 			    ct->d_buf, ct->d_args.data_size) != 0) {
   2465 				kmem_free(ct->d_buf, ct->d_bufsize);
   2466 				ct->d_buf = NULL;
   2467 				ct->d_bufsize = 0;
   2468 				return (EFAULT);
   2469 			}
   2470 		} else {
   2471 			struct as	*as;
   2472 			caddr_t		src;
   2473 			caddr_t		dest;
   2474 			size_t		len = ct->d_args.data_size;
   2475 			uintptr_t	base;
   2476 
   2477 			/*
   2478 			 * Use a 1 copy method
   2479 			 */
   2480 			as = ttoproc(server)->p_as;
   2481 			src = ct->d_args.data_ptr;
   2482 
   2483 			dest = st->d_layout.dl_datap;
   2484 			base = (uintptr_t)dest;
   2485 
   2486 			/*
   2487 			 * Copy data directly into server.  We proceed
   2488 			 * downward from the top of the stack, to mimic
   2489 			 * normal stack usage. This allows the guard page
   2490 			 * to stop us before we corrupt anything.
   2491 			 */
   2492 			while (len != 0) {
   2493 				uintptr_t start;
   2494 				uintptr_t end;
   2495 				uintptr_t offset;
   2496 				size_t	amount;
   2497 
   2498 				/*
   2499 				 * Locate the next part to copy.
   2500 				 */
   2501 				end = base + len;
   2502 				start = P2ALIGN(end - 1, PAGESIZE);
   2503 
   2504 				/*
   2505 				 * if we are on the final (first) page, fix
   2506 				 * up the start position.
   2507 				 */
   2508 				if (P2ALIGN(base, PAGESIZE) == start)
   2509 					start = base;
   2510 
   2511 				offset = start - base;	/* the copy offset */
   2512 				amount = end - start;	/* # bytes to copy */
   2513 
   2514 				ASSERT(amount > 0 && amount <= len &&
   2515 				    amount <= PAGESIZE);
   2516 
   2517 				error = door_copy(as, src + offset,
   2518 				    dest + offset, amount);
   2519 				if (error != 0)
   2520 					return (error);
   2521 				len -= amount;
   2522 			}
   2523 		}
   2524 	}
   2525 	/*
   2526 	 * Copyin the door args and translate them into files
   2527 	 */
   2528 	if (ndid != 0) {
   2529 		door_desc_t	*didpp;
   2530 		door_desc_t	*start;
   2531 		struct file	**fpp;
   2532 
   2533 		start = didpp = kmem_alloc(dsize, KM_SLEEP);
   2534 
   2535 		if (copyin_nowatch(ct->d_args.desc_ptr, didpp, dsize)) {
   2536 			kmem_free(start, dsize);
   2537 			return (EFAULT);
   2538 		}
   2539 		ct->d_fpp_size = ndid * sizeof (struct file *);
   2540 		ct->d_fpp = kmem_alloc(ct->d_fpp_size, KM_SLEEP);
   2541 		fpp = ct->d_fpp;
   2542 		while (ndid--) {
   2543 			struct file *fp;
   2544 			int fd = didpp->d_data.d_desc.d_descriptor;
   2545 
   2546 			/* We only understand file descriptors as passed objs */
   2547 			if (!(didpp->d_attributes & DOOR_DESCRIPTOR) ||
   2548 			    (fp = getf(fd)) == NULL) {
   2549 				/* close translated references */
   2550 				door_fp_close(ct->d_fpp, fpp - ct->d_fpp);
   2551 				/* close untranslated references */
   2552 				door_fd_rele(didpp, ndid + 1, 0);
   2553 				kmem_free(start, dsize);
   2554 				kmem_free(ct->d_fpp, ct->d_fpp_size);
   2555 				ct->d_fpp = NULL;
   2556 				ct->d_fpp_size = 0;
   2557 				return (EINVAL);
   2558 			}
   2559 			/* Hold the fp */
   2560 			mutex_enter(&fp->f_tlock);
   2561 			fp->f_count++;
   2562 			mutex_exit(&fp->f_tlock);
   2563 
   2564 			*fpp = fp;
   2565 			releasef(fd);
   2566 
   2567 			if (didpp->d_attributes & DOOR_RELEASE) {
   2568 				/* release passed reference */
   2569 				(void) closeandsetf(fd, NULL);
   2570 			}
   2571 
   2572 			fpp++; didpp++;
   2573 		}
   2574 		kmem_free(start, dsize);
   2575 	}
   2576 	return (0);
   2577 }
   2578 
   2579 /*
   2580  * Transfer arguments from a user client to a kernel server.  This copies in
   2581  * descriptors and translates them into door handles.  It doesn't touch the
   2582  * other data, letting the kernel server deal with that (to avoid needing
   2583  * to copy the data twice).
   2584  */
   2585 static int
   2586 door_translate_in(void)
   2587 {
   2588 	door_client_t *ct = DOOR_CLIENT(curthread->t_door);
   2589 	uint_t	ndid;
   2590 
   2591 	ASSERT(MUTEX_NOT_HELD(&door_knob));
   2592 	ndid = ct->d_args.desc_num;
   2593 	if (ndid > door_max_desc)
   2594 		return (E2BIG);
   2595 	/*
   2596 	 * Copyin the door args and translate them into door handles.
   2597 	 */
   2598 	if (ndid != 0) {
   2599 		door_desc_t	*didpp;
   2600 		door_desc_t	*start;
   2601 		size_t		dsize = ndid * sizeof (door_desc_t);
   2602 		struct file	*fp;
   2603 
   2604 		start = didpp = kmem_alloc(dsize, KM_SLEEP);
   2605 
   2606 		if (copyin_nowatch(ct->d_args.desc_ptr, didpp, dsize)) {
   2607 			kmem_free(start, dsize);
   2608 			return (EFAULT);
   2609 		}
   2610 		while (ndid--) {
   2611 			vnode_t	*vp;
   2612 			int fd = didpp->d_data.d_desc.d_descriptor;
   2613 
   2614 			/*
   2615 			 * We only understand file descriptors as passed objs
   2616 			 */
   2617 			if ((didpp->d_attributes & DOOR_DESCRIPTOR) &&
   2618 			    (fp = getf(fd)) != NULL) {
   2619 				didpp->d_data.d_handle = FTODH(fp);
   2620 				/* Hold the door */
   2621 				door_ki_hold(didpp->d_data.d_handle);
   2622 
   2623 				releasef(fd);
   2624 
   2625 				if (didpp->d_attributes & DOOR_RELEASE) {
   2626 					/* release passed reference */
   2627 					(void) closeandsetf(fd, NULL);
   2628 				}
   2629 
   2630 				if (VOP_REALVP(fp->f_vnode, &vp, NULL))
   2631 					vp = fp->f_vnode;
   2632 
   2633 				/* Set attributes */
   2634 				didpp->d_attributes = DOOR_HANDLE |
   2635 				    (VTOD(vp)->door_flags & DOOR_ATTR_MASK);
   2636 			} else {
   2637 				/* close translated references */
   2638 				door_fd_close(start, didpp - start);
   2639 				/* close untranslated references */
   2640 				door_fd_rele(didpp, ndid + 1, 0);
   2641 				kmem_free(start, dsize);
   2642 				return (EINVAL);
   2643 			}
   2644 			didpp++;
   2645 		}
   2646 		ct->d_args.desc_ptr = start;
   2647 	}
   2648 	return (0);
   2649 }
   2650 
   2651 /*
   2652  * Translate door arguments from kernel to user.  This copies the passed
   2653  * door handles.  It doesn't touch other data.  It is used by door_upcall,
   2654  * and for data returned by a door_call to a kernel server.
   2655  */
   2656 static int
   2657 door_translate_out(void)
   2658 {
   2659 	door_client_t *ct = DOOR_CLIENT(curthread->t_door);
   2660 	uint_t	ndid;
   2661 
   2662 	ASSERT(MUTEX_NOT_HELD(&door_knob));
   2663 	ndid = ct->d_args.desc_num;
   2664 	if (ndid > door_max_desc) {
   2665 		door_fd_rele(ct->d_args.desc_ptr, ndid, 1);
   2666 		return (E2BIG);
   2667 	}
   2668 	/*
   2669 	 * Translate the door args into files
   2670 	 */
   2671 	if (ndid != 0) {
   2672 		door_desc_t	*didpp = ct->d_args.desc_ptr;
   2673 		struct file	**fpp;
   2674 
   2675 		ct->d_fpp_size = ndid * sizeof (struct file *);
   2676 		fpp = ct->d_fpp = kmem_alloc(ct->d_fpp_size, KM_SLEEP);
   2677 		while (ndid--) {
   2678 			struct file *fp = NULL;
   2679 			int fd = -1;
   2680 
   2681 			/*
   2682 			 * We understand file descriptors and door
   2683 			 * handles as passed objs.
   2684 			 */
   2685 			if (didpp->d_attributes & DOOR_DESCRIPTOR) {
   2686 				fd = didpp->d_data.d_desc.d_descriptor;
   2687 				fp = getf(fd);
   2688 			} else if (didpp->d_attributes & DOOR_HANDLE)
   2689 				fp = DHTOF(didpp->d_data.d_handle);
   2690 			if (fp != NULL) {
   2691 				/* Hold the fp */
   2692 				mutex_enter(&fp->f_tlock);
   2693 				fp->f_count++;
   2694 				mutex_exit(&fp->f_tlock);
   2695 
   2696 				*fpp = fp;
   2697 				if (didpp->d_attributes & DOOR_DESCRIPTOR)
   2698 					releasef(fd);
   2699 				if (didpp->d_attributes & DOOR_RELEASE) {
   2700 					/* release passed reference */
   2701 					if (fd >= 0)
   2702 						(void) closeandsetf(fd, NULL);
   2703 					else
   2704 						(void) closef(fp);
   2705 				}
   2706 			} else {
   2707 				/* close translated references */
   2708 				door_fp_close(ct->d_fpp, fpp - ct->d_fpp);
   2709 				/* close untranslated references */
   2710 				door_fd_rele(didpp, ndid + 1, 1);
   2711 				kmem_free(ct->d_fpp, ct->d_fpp_size);
   2712 				ct->d_fpp = NULL;
   2713 				ct->d_fpp_size = 0;
   2714 				return (EINVAL);
   2715 			}
   2716 			fpp++; didpp++;
   2717 		}
   2718 	}
   2719 	return (0);
   2720 }
   2721 
   2722 /*
   2723  * Move the results from the server to the client
   2724  */
   2725 static int
   2726 door_results(kthread_t *caller, caddr_t data_ptr, size_t data_size,
   2727 		door_desc_t *desc_ptr, uint_t desc_num)
   2728 {
   2729 	door_client_t	*ct = DOOR_CLIENT(caller->t_door);
   2730 	door_upcall_t	*dup = ct->d_upcall;
   2731 	size_t		dsize;
   2732 	size_t		rlen;
   2733 	size_t		result_size;
   2734 
   2735 	ASSERT(DOOR_T_HELD(ct));
   2736 	ASSERT(MUTEX_NOT_HELD(&door_knob));
   2737 
   2738 	if (ct->d_noresults)
   2739 		return (E2BIG);		/* No results expected */
   2740 
   2741 	if (desc_num > door_max_desc)
   2742 		return (E2BIG);		/* Too many descriptors */
   2743 
   2744 	dsize = desc_num * sizeof (door_desc_t);
   2745 	/*
   2746 	 * Check if the results are bigger than the clients buffer
   2747 	 */
   2748 	if (dsize)
   2749 		rlen = roundup(data_size, sizeof (door_desc_t));
   2750 	else
   2751 		rlen = data_size;
   2752 	if ((result_size = rlen + dsize) == 0)
   2753 		return (0);
   2754 
   2755 	if (dup != NULL) {
   2756 		if (desc_num > dup->du_max_descs)
   2757 			return (EMFILE);
   2758 
   2759 		if (data_size > dup->du_max_data)
   2760 			return (E2BIG);
   2761 
   2762 		/*
   2763 		 * Handle upcalls
   2764 		 */
   2765 		if (ct->d_args.rbuf == NULL || ct->d_args.rsize < result_size) {
   2766 			/*
   2767 			 * If there's no return buffer or the buffer is too
   2768 			 * small, allocate a new one.  The old buffer (if it
   2769 			 * exists) will be freed by the upcall client.
   2770 			 */
   2771 			if (result_size > door_max_upcall_reply)
   2772 				return (E2BIG);
   2773 			ct->d_args.rsize = result_size;
   2774 			ct->d_args.rbuf = kmem_alloc(result_size, KM_SLEEP);
   2775 		}
   2776 		ct->d_args.data_ptr = ct->d_args.rbuf;
   2777 		if (data_size != 0 &&
   2778 		    copyin_nowatch(data_ptr, ct->d_args.data_ptr,
   2779 		    data_size) != 0)
   2780 			return (EFAULT);
   2781 	} else if (result_size > ct->d_args.rsize) {
   2782 		return (door_overflow(caller, data_ptr, data_size,
   2783 		    desc_ptr, desc_num));
   2784 	} else if (data_size != 0) {
   2785 		if (data_size <= door_max_arg) {
   2786 			/*
   2787 			 * Use a 2 copy method for small amounts of data
   2788 			 */
   2789 			if (ct->d_buf == NULL) {
   2790 				ct->d_bufsize = data_size;
   2791 				ct->d_buf = kmem_alloc(ct->d_bufsize, KM_SLEEP);
   2792 			} else if (ct->d_bufsize < data_size) {
   2793 				kmem_free(ct->d_buf, ct->d_bufsize);
   2794 				ct->d_bufsize = data_size;
   2795 				ct->d_buf = kmem_alloc(ct->d_bufsize, KM_SLEEP);
   2796 			}
   2797 			if (copyin_nowatch(data_ptr, ct->d_buf, data_size) != 0)
   2798 				return (EFAULT);
   2799 		} else {
   2800 			struct as *as = ttoproc(caller)->p_as;
   2801 			caddr_t	dest = ct->d_args.rbuf;
   2802 			caddr_t	src = data_ptr;
   2803 			size_t	len = data_size;
   2804 
   2805 			/* Copy data directly into client */
   2806 			while (len != 0) {
   2807 				uint_t	amount;
   2808 				uint_t	max;
   2809 				uint_t	off;
   2810 				int	error;
   2811 
   2812 				off = (uintptr_t)dest & PAGEOFFSET;
   2813 				if (off)
   2814 					max = PAGESIZE - off;
   2815 				else
   2816 					max = PAGESIZE;
   2817 				amount = len > max ? max : len;
   2818 				error = door_copy(as, src, dest, amount);
   2819 				if (error != 0)
   2820 					return (error);
   2821 				dest += amount;
   2822 				src += amount;
   2823 				len -= amount;
   2824 			}
   2825 		}
   2826 	}
   2827 
   2828 	/*
   2829 	 * Copyin the returned door ids and translate them into door_node_t
   2830 	 */
   2831 	if (desc_num != 0) {
   2832 		door_desc_t *start;
   2833 		door_desc_t *didpp;
   2834 		struct file **fpp;
   2835 		size_t	fpp_size;
   2836 		uint_t	i;
   2837 
   2838 		/* First, check if we would overflow client */
   2839 		if (!ufcanalloc(ttoproc(caller), desc_num))
   2840 			return (EMFILE);
   2841 
   2842 		start = didpp = kmem_alloc(dsize, KM_SLEEP);
   2843 		if (copyin_nowatch(desc_ptr, didpp, dsize)) {
   2844 			kmem_free(start, dsize);
   2845 			return (EFAULT);
   2846 		}
   2847 		fpp_size = desc_num * sizeof (struct file *);
   2848 		if (fpp_size > ct->d_fpp_size) {
   2849 			/* make more space */
   2850 			if (ct->d_fpp_size)
   2851 				kmem_free(ct->d_fpp, ct->d_fpp_size);
   2852 			ct->d_fpp_size = fpp_size;
   2853 			ct->d_fpp = kmem_alloc(fpp_size, KM_SLEEP);
   2854 		}
   2855 		fpp = ct->d_fpp;
   2856 
   2857 		for (i = 0; i < desc_num; i++) {
   2858 			struct file *fp;
   2859 			int fd = didpp->d_data.d_desc.d_descriptor;
   2860 
   2861 			/* Only understand file descriptor results */
   2862 			if (!(didpp->d_attributes & DOOR_DESCRIPTOR) ||
   2863 			    (fp = getf(fd)) == NULL) {
   2864 				/* close translated references */
   2865 				door_fp_close(ct->d_fpp, fpp - ct->d_fpp);
   2866 				/* close untranslated references */
   2867 				door_fd_rele(didpp, desc_num - i, 0);
   2868 				kmem_free(start, dsize);
   2869 				return (EINVAL);
   2870 			}
   2871 
   2872 			mutex_enter(&fp->f_tlock);
   2873 			fp->f_count++;
   2874 			mutex_exit(&fp->f_tlock);
   2875 
   2876 			*fpp = fp;
   2877 			releasef(fd);
   2878 
   2879 			if (didpp->d_attributes & DOOR_RELEASE) {
   2880 				/* release passed reference */
   2881 				(void) closeandsetf(fd, NULL);
   2882 			}
   2883 
   2884 			fpp++; didpp++;
   2885 		}
   2886 		kmem_free(start, dsize);
   2887 	}
   2888 	return (0);
   2889 }
   2890 
   2891 /*
   2892  * Close all the descriptors.
   2893  */
   2894 static void
   2895 door_fd_close(door_desc_t *d, uint_t n)
   2896 {
   2897 	uint_t	i;
   2898 
   2899 	ASSERT(MUTEX_NOT_HELD(&door_knob));
   2900 	for (i = 0; i < n; i++) {
   2901 		if (d->d_attributes & DOOR_DESCRIPTOR) {
   2902 			(void) closeandsetf(
   2903 			    d->d_data.d_desc.d_descriptor, NULL);
   2904 		} else if (d->d_attributes & DOOR_HANDLE) {
   2905 			door_ki_rele(d->d_data.d_handle);
   2906 		}
   2907 		d++;
   2908 	}
   2909 }
   2910 
   2911 /*
   2912  * Close descriptors that have the DOOR_RELEASE attribute set.
   2913  */
   2914 void
   2915 door_fd_rele(door_desc_t *d, uint_t n, int from_kernel)
   2916 {
   2917 	uint_t	i;
   2918 
   2919 	ASSERT(MUTEX_NOT_HELD(&door_knob));
   2920 	for (i = 0; i < n; i++) {
   2921 		if (d->d_attributes & DOOR_RELEASE) {
   2922 			if (d->d_attributes & DOOR_DESCRIPTOR) {
   2923 				(void) closeandsetf(
   2924 				    d->d_data.d_desc.d_descriptor, NULL);
   2925 			} else if (from_kernel &&
   2926 			    (d->d_attributes & DOOR_HANDLE)) {
   2927 				door_ki_rele(d->d_data.d_handle);
   2928 			}
   2929 		}
   2930 		d++;
   2931 	}
   2932 }
   2933 
   2934 /*
   2935  * Copy descriptors into the kernel so we can release any marked
   2936  * DOOR_RELEASE.
   2937  */
   2938 int
   2939 door_release_fds(door_desc_t *desc_ptr, uint_t ndesc)
   2940 {
   2941 	size_t dsize;
   2942 	door_desc_t *didpp;
   2943 	uint_t desc_num;
   2944 
   2945 	ASSERT(MUTEX_NOT_HELD(&door_knob));
   2946 	ASSERT(ndesc != 0);
   2947 
   2948 	desc_num = MIN(ndesc, door_max_desc);
   2949 
   2950 	dsize = desc_num * sizeof (door_desc_t);
   2951 	didpp = kmem_alloc(dsize, KM_SLEEP);
   2952 
   2953 	while (ndesc > 0) {
   2954 		uint_t count = MIN(ndesc, desc_num);
   2955 
   2956 		if (copyin_nowatch(desc_ptr, didpp,
   2957 		    count * sizeof (door_desc_t))) {
   2958 			kmem_free(didpp, dsize);
   2959 			return (EFAULT);
   2960 		}
   2961 		door_fd_rele(didpp, count, 0);
   2962 
   2963 		ndesc -= count;
   2964 		desc_ptr += count;
   2965 	}
   2966 	kmem_free(didpp, dsize);
   2967 	return (0);
   2968 }
   2969 
   2970 /*
   2971  * Decrement ref count on all the files passed
   2972  */
   2973 static void
   2974 door_fp_close(struct file **fp, uint_t n)
   2975 {
   2976 	uint_t	i;
   2977 
   2978 	ASSERT(MUTEX_NOT_HELD(&door_knob));
   2979 
   2980 	for (i = 0; i < n; i++)
   2981 		(void) closef(fp[i]);
   2982 }
   2983 
   2984 /*
   2985  * Copy data from 'src' in current address space to 'dest' in 'as' for 'len'
   2986  * bytes.
   2987  *
   2988  * Performs this using 1 mapin and 1 copy operation.
   2989  *
   2990  * We really should do more than 1 page at a time to improve
   2991  * performance, but for now this is treated as an anomalous condition.
   2992  */
   2993 static int
   2994 door_copy(struct as *as, caddr_t src, caddr_t dest, uint_t len)
   2995 {
   2996 	caddr_t	kaddr;
   2997 	caddr_t	rdest;
   2998 	uint_t	off;
   2999 	page_t	**pplist;
   3000 	page_t	*pp = NULL;
   3001 	int	error = 0;
   3002 
   3003 	ASSERT(len <= PAGESIZE);
   3004 	off = (uintptr_t)dest & PAGEOFFSET;	/* offset within the page */
   3005 	rdest = (caddr_t)((uintptr_t)dest &
   3006 	    (uintptr_t)PAGEMASK);	/* Page boundary */
   3007 	ASSERT(off + len <= PAGESIZE);
   3008 
   3009 	/*
   3010 	 * Lock down destination page.
   3011 	 */
   3012 	if (as_pagelock(as, &pplist, rdest, PAGESIZE, S_WRITE))
   3013 		return (E2BIG);
   3014 	/*
   3015 	 * Check if we have a shadow page list from as_pagelock. If not,
   3016 	 * we took the slow path and have to find our page struct the hard
   3017 	 * way.
   3018 	 */
   3019 	if (pplist == NULL) {
   3020 		pfn_t	pfnum;
   3021 
   3022 		/* MMU mapping is already locked down */
   3023 		AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
   3024 		pfnum = hat_getpfnum(as->a_hat, rdest);
   3025 		AS_LOCK_EXIT(as, &as->a_lock);
   3026 
   3027 		/*
   3028 		 * TODO: The pfn step should not be necessary - need
   3029 		 * a hat_getpp() function.
   3030 		 */
   3031 		if (pf_is_memory(pfnum)) {
   3032 			pp = page_numtopp_nolock(pfnum);
   3033 			ASSERT(pp == NULL || PAGE_LOCKED(pp));
   3034 		} else
   3035 			pp = NULL;
   3036 		if (pp == NULL) {
   3037 			as_pageunlock(as, pplist, rdest, PAGESIZE, S_WRITE);
   3038 			return (E2BIG);
   3039 		}
   3040 	} else {
   3041 		pp = *pplist;
   3042 	}
   3043 	/*
   3044 	 * Map destination page into kernel address
   3045 	 */
   3046 	kaddr = (caddr_t)ppmapin(pp, PROT_READ | PROT_WRITE, (caddr_t)-1);
   3047 
   3048 	/*
   3049 	 * Copy from src to dest
   3050 	 */
   3051 	if (copyin_nowatch(src, kaddr + off, len) != 0)
   3052 		error = EFAULT;
   3053 	/*
   3054 	 * Unmap destination page from kernel
   3055 	 */
   3056 	ppmapout(kaddr);
   3057 	/*
   3058 	 * Unlock destination page
   3059 	 */
   3060 	as_pageunlock(as, pplist, rdest, PAGESIZE, S_WRITE);
   3061 	return (error);
   3062 }
   3063 
   3064 /*
   3065  * General kernel upcall using doors
   3066  *	Returns 0 on success, errno for failures.
   3067  *	Caller must have a hold on the door based vnode, and on any
   3068  *	references passed in desc_ptr.  The references are released
   3069  *	in the event of an error, and passed without duplication
   3070  *	otherwise.  Note that param->rbuf must be 64-bit aligned in
   3071  *	a 64-bit kernel, since it may be used to store door descriptors
   3072  *	if they are returned by the server.  The caller is responsible
   3073  *	for holding a reference to the cred passed in.
   3074  */
   3075 int
   3076 door_upcall(vnode_t *vp, door_arg_t *param, struct cred *cred,
   3077     size_t max_data, uint_t max_descs)
   3078 {
   3079 	/* Locals */
   3080 	door_upcall_t	*dup;
   3081 	door_node_t	*dp;
   3082 	kthread_t	*server_thread;
   3083 	int		error = 0;
   3084 	klwp_t		*lwp;
   3085 	door_client_t	*ct;		/* curthread door_data */
   3086 	door_server_t	*st;		/* server thread door_data */
   3087 	int		gotresults = 0;
   3088 	int		cancel_pending;
   3089 
   3090 	if (vp->v_type != VDOOR) {
   3091 		if (param->desc_num)
   3092 			door_fd_rele(param->desc_ptr, param->desc_num, 1);
   3093 		return (EINVAL);
   3094 	}
   3095 
   3096 	lwp = ttolwp(curthread);
   3097 	ct = door_my_client(1);
   3098 	dp = VTOD(vp);	/* Convert to a door_node_t */
   3099 
   3100 	dup = kmem_zalloc(sizeof (*dup), KM_SLEEP);
   3101 	dup->du_cred = (cred != NULL) ? cred : curthread->t_cred;
   3102 	dup->du_max_data = max_data;
   3103 	dup->du_max_descs = max_descs;
   3104 
   3105 	/*
   3106 	 * This should be done in shuttle_resume(), just before going to
   3107 	 * sleep, but we want to avoid overhead while holding door_knob.
   3108 	 * prstop() is just a no-op if we don't really go to sleep.
   3109 	 * We test not-kernel-address-space for the sake of clustering code.
   3110 	 */
   3111 	if (lwp && lwp->lwp_nostop == 0 && curproc->p_as != &kas)
   3112 		prstop(PR_REQUESTED, 0);
   3113 
   3114 	mutex_enter(&door_knob);
   3115 	if (DOOR_INVALID(dp)) {
   3116 		mutex_exit(&door_knob);
   3117 		if (param->desc_num)
   3118 			door_fd_rele(param->desc_ptr, param->desc_num, 1);
   3119 		error = EBADF;
   3120 		goto out;
   3121 	}
   3122 
   3123 	if (dp->door_target == &p0) {
   3124 		/* Can't do an upcall to a kernel server */
   3125 		mutex_exit(&door_knob);
   3126 		if (param->desc_num)
   3127 			door_fd_rele(param->desc_ptr, param->desc_num, 1);
   3128 		error = EINVAL;
   3129 		goto out;
   3130 	}
   3131 
   3132 	error = door_check_limits(dp, param, 1);
   3133 	if (error != 0) {
   3134 		mutex_exit(&door_knob);
   3135 		if (param->desc_num)
   3136 			door_fd_rele(param->desc_ptr, param->desc_num, 1);
   3137 		goto out;
   3138 	}
   3139 
   3140 	/*
   3141 	 * Get a server thread from the target domain
   3142 	 */
   3143 	if ((server_thread = door_get_server(dp)) == NULL) {
   3144 		if (DOOR_INVALID(dp))
   3145 			error = EBADF;
   3146 		else
   3147 			error = EAGAIN;
   3148 		mutex_exit(&door_knob);
   3149 		if (param->desc_num)
   3150 			door_fd_rele(param->desc_ptr, param->desc_num, 1);
   3151 		goto out;
   3152 	}
   3153 
   3154 	st = DOOR_SERVER(server_thread->t_door);
   3155 	ct->d_buf = param->data_ptr;
   3156 	ct->d_bufsize = param->data_size;
   3157 	ct->d_args = *param;	/* structure assignment */
   3158 
   3159 	if (ct->d_args.desc_num) {
   3160 		/*
   3161 		 * Move data from client to server
   3162 		 */
   3163 		DOOR_T_HOLD(st);
   3164 		mutex_exit(&door_knob);
   3165 		error = door_translate_out();
   3166 		mutex_enter(&door_knob);
   3167 		DOOR_T_RELEASE(st);
   3168 		if (error) {
   3169 			/*
   3170 			 * We're not going to resume this thread after all
   3171 			 */
   3172 			door_release_server(dp, server_thread);
   3173 			shuttle_sleep(server_thread);
   3174 			mutex_exit(&door_knob);
   3175 			goto out;
   3176 		}
   3177 	}
   3178 
   3179 	ct->d_upcall = dup;
   3180 	if (param->rsize == 0)
   3181 		ct->d_noresults = 1;
   3182 	else
   3183 		ct->d_noresults = 0;
   3184 
   3185 	dp->door_active++;
   3186 
   3187 	ct->d_error = DOOR_WAIT;
   3188 	st->d_caller = curthread;
   3189 	st->d_active = dp;
   3190 
   3191 	shuttle_resume(server_thread, &door_knob);
   3192 
   3193 	mutex_enter(&door_knob);
   3194 shuttle_return:
   3195 	if ((error = ct->d_error) < 0) {	/* DOOR_WAIT or DOOR_EXIT */
   3196 		/*
   3197 		 * Premature wakeup. Find out why (stop, forkall, sig, exit ...)
   3198 		 */
   3199 		mutex_exit(&door_knob);		/* May block in ISSIG */
   3200 		cancel_pending = 0;
   3201 		if (lwp && (ISSIG(curthread, FORREAL) || lwp->lwp_sysabort ||
   3202 		    MUSTRETURN(curproc, curthread) ||
   3203 		    (cancel_pending = schedctl_cancel_pending()) != 0)) {
   3204 			/* Signal, forkall, ... */
   3205 			if (cancel_pending)
   3206 				schedctl_cancel_eintr();
   3207 			lwp->lwp_sysabort = 0;
   3208 			mutex_enter(&door_knob);
   3209 			error = EINTR;
   3210 			/*
   3211 			 * If the server has finished processing our call,
   3212 			 * or exited (calling door_slam()), then d_error
   3213 			 * will have changed.  If the server hasn't finished
   3214 			 * yet, d_error will still be DOOR_WAIT, and we
   3215 			 * let it know we are not interested in any
   3216 			 * results by sending a SIGCANCEL, unless the door
   3217 			 * is marked with DOOR_NO_CANCEL.
   3218 			 */
   3219 			if (ct->d_error == DOOR_WAIT &&
   3220 			    st->d_caller == curthread) {
   3221 				proc_t	*p = ttoproc(server_thread);
   3222 
   3223 				st->d_active = NULL;
   3224 				st->d_caller = NULL;
   3225 				if (!(dp->door_flags & DOOR_NO_CANCEL)) {
   3226 					DOOR_T_HOLD(st);
   3227 					mutex_exit(&door_knob);
   3228 
   3229 					mutex_enter(&p->p_lock);
   3230 					sigtoproc(p, server_thread, SIGCANCEL);
   3231 					mutex_exit(&p->p_lock);
   3232 
   3233 					mutex_enter(&door_knob);
   3234 					DOOR_T_RELEASE(st);
   3235 				}
   3236 			}
   3237 		} else {
   3238 			/*
   3239 			 * Return from stop(), server exit...
   3240 			 *
   3241 			 * Note that the server could have done a
   3242 			 * door_return while the client was in stop state
   3243 			 * (ISSIG), in which case the error condition
   3244 			 * is updated by the server.
   3245 			 */
   3246 			mutex_enter(&door_knob);
   3247 			if (ct->d_error == DOOR_WAIT) {
   3248 				/* Still waiting for a reply */
   3249 				shuttle_swtch(&door_knob);
   3250 				mutex_enter(&door_knob);
   3251 				if (lwp)
   3252 					lwp->lwp_asleep = 0;
   3253 				goto	shuttle_return;
   3254 			} else if (ct->d_error == DOOR_EXIT) {
   3255 				/* Server exit */
   3256 				error = EINTR;
   3257 			} else {
   3258 				/* Server did a door_return during ISSIG */
   3259 				error = ct->d_error;
   3260 			}
   3261 		}
   3262 		/*
   3263 		 * Can't exit if the server is currently copying
   3264 		 * results for me
   3265 		 */
   3266 		while (DOOR_T_HELD(ct))
   3267 			cv_wait(&ct->d_cv, &door_knob);
   3268 
   3269 		/*
   3270 		 * Find out if results were successfully copied.
   3271 		 */
   3272 		if (ct->d_error == 0)
   3273 			gotresults = 1;
   3274 	}
   3275 	if (lwp) {
   3276 		lwp->lwp_asleep = 0;		/* /proc */
   3277 		lwp->lwp_sysabort = 0;		/* /proc */
   3278 	}
   3279 	if (--dp->door_active == 0 && (dp->door_flags & DOOR_DELAY))
   3280 		door_deliver_unref(dp);
   3281 	mutex_exit(&door_knob);
   3282 
   3283 	/*
   3284 	 * Translate returned doors (if any)
   3285 	 */
   3286 
   3287 	if (ct->d_noresults)
   3288 		goto out;
   3289 
   3290 	if (error) {
   3291 		/*
   3292 		 * If server returned results successfully, then we've
   3293 		 * been interrupted and may need to clean up.
   3294 		 */
   3295 		if (gotresults) {
   3296 			ASSERT(error == EINTR);
   3297 			door_fp_close(ct->d_fpp, ct->d_args.desc_num);
   3298 		}
   3299 		goto out;
   3300 	}
   3301 
   3302 	if (ct->d_args.desc_num) {
   3303 		struct file	**fpp;
   3304 		door_desc_t	*didpp;
   3305 		vnode_t		*vp;
   3306 		uint_t		n = ct->d_args.desc_num;
   3307 
   3308 		didpp = ct->d_args.desc_ptr = (door_desc_t *)(ct->d_args.rbuf +
   3309 		    roundup(ct->d_args.data_size, sizeof (door_desc_t)));
   3310 		fpp = ct->d_fpp;
   3311 
   3312 		while (n--) {
   3313 			struct file *fp;
   3314 
   3315 			fp = *fpp;
   3316 			if (VOP_REALVP(fp->f_vnode, &vp, NULL))
   3317 				vp = fp->f_vnode;
   3318 
   3319 			didpp->d_attributes = DOOR_HANDLE |
   3320 			    (VTOD(vp)->door_flags & DOOR_ATTR_MASK);
   3321 			didpp->d_data.d_handle = FTODH(fp);
   3322 
   3323 			fpp++; didpp++;
   3324 		}
   3325 	}
   3326 
   3327 	/* on return data is in rbuf */
   3328 	*param = ct->d_args;		/* structure assignment */
   3329 
   3330 out:
   3331 	kmem_free(dup, sizeof (*dup));
   3332 
   3333 	if (ct->d_fpp) {
   3334 		kmem_free(ct->d_fpp, ct->d_fpp_size);
   3335 		ct->d_fpp = NULL;
   3336 		ct->d_fpp_size = 0;
   3337 	}
   3338 
   3339 	ct->d_upcall = NULL;
   3340 	ct->d_noresults = 0;
   3341 	ct->d_buf = NULL;
   3342 	ct->d_bufsize = 0;
   3343 	return (error);
   3344 }
   3345 
   3346 /*
   3347  * Add a door to the per-process list of active doors for which the
   3348  * process is a server.
   3349  */
   3350 static void
   3351 door_list_insert(door_node_t *dp)
   3352 {
   3353 	proc_t *p = dp->door_target;
   3354 
   3355 	ASSERT(MUTEX_HELD(&door_knob));
   3356 	dp->door_list = p->p_door_list;
   3357 	p->p_door_list = dp;
   3358 }
   3359 
   3360 /*
   3361  * Remove a door from the per-process list of active doors.
   3362  */
   3363 void
   3364 door_list_delete(door_node_t *dp)
   3365 {
   3366 	door_node_t **pp;
   3367 
   3368 	ASSERT(MUTEX_HELD(&door_knob));
   3369 	/*
   3370 	 * Find the door in the list.  If the door belongs to another process,
   3371 	 * it's OK to use p_door_list since that process can't exit until all
   3372 	 * doors have been taken off the list (see door_exit).
   3373 	 */
   3374 	pp = &(dp->door_target->p_door_list);
   3375 	while (*pp != dp)
   3376 		pp = &((*pp)->door_list);
   3377 
   3378 	/* found it, take it off the list */
   3379 	*pp = dp->door_list;
   3380 }
   3381 
   3382 
   3383 /*
   3384  * External kernel interfaces for doors.  These functions are available
   3385  * outside the doorfs module for use in creating and using doors from
   3386  * within the kernel.
   3387  */
   3388 
   3389 /*
   3390  * door_ki_upcall invokes a user-level door server from the kernel, with
   3391  * the credentials associated with curthread.
   3392  */
   3393 int
   3394 door_ki_upcall(door_handle_t dh, door_arg_t *param)
   3395 {
   3396 	return (door_ki_upcall_limited(dh, param, NULL, SIZE_MAX, UINT_MAX));
   3397 }
   3398 
   3399 /*
   3400  * door_ki_upcall_limited invokes a user-level door server from the
   3401  * kernel with the given credentials and reply limits.  If the "cred"
   3402  * argument is NULL, uses the credentials associated with current
   3403  * thread.  max_data limits the maximum length of the returned data (the
   3404  * client will get E2BIG if they go over), and max_desc limits the
   3405  * number of returned descriptors (the client will get EMFILE if they
   3406  * go over).
   3407  */
   3408 int
   3409 door_ki_upcall_limited(door_handle_t dh, door_arg_t *param, struct cred *cred,
   3410     size_t max_data, uint_t max_desc)
   3411 {
   3412 	file_t *fp = DHTOF(dh);
   3413 	vnode_t *realvp;
   3414 
   3415 	if (VOP_REALVP(fp->f_vnode, &realvp, NULL))
   3416 		realvp = fp->f_vnode;
   3417 	return (door_upcall(realvp, param, cred, max_data, max_desc));
   3418 }
   3419 
   3420 /*
   3421  * Function call to create a "kernel" door server.  A kernel door
   3422  * server provides a way for a user-level process to invoke a function
   3423  * in the kernel through a door_call.  From the caller's point of
   3424  * view, a kernel door server looks the same as a user-level one
   3425  * (except the server pid is 0).  Unlike normal door calls, the
   3426  * kernel door function is invoked via a normal function call in the
   3427  * same thread and context as the caller.
   3428  */
   3429 int
   3430 door_ki_create(void (*pc_cookie)(), void *data_cookie, uint_t attributes,
   3431     door_handle_t *dhp)
   3432 {
   3433 	int err;
   3434 	file_t *fp;
   3435 
   3436 	/* no DOOR_PRIVATE */
   3437 	if ((attributes & ~DOOR_KI_CREATE_MASK) ||
   3438 	    (attributes & (DOOR_UNREF | DOOR_UNREF_MULTI)) ==
   3439 	    (DOOR_UNREF | DOOR_UNREF_MULTI))
   3440 		return (EINVAL);
   3441 
   3442 	err = door_create_common(pc_cookie, data_cookie, attributes,
   3443 	    1, NULL, &fp);
   3444 	if (err == 0 && (attributes & (DOOR_UNREF | DOOR_UNREF_MULTI)) &&
   3445 	    p0.p_unref_thread == 0) {
   3446 		/* need to create unref thread for process 0 */
   3447 		(void) thread_create(NULL, 0, door_unref_kernel, NULL, 0, &p0,
   3448 		    TS_RUN, minclsyspri);
   3449 	}
   3450 	if (err == 0) {
   3451 		*dhp = FTODH(fp);
   3452 	}
   3453 	return (err);
   3454 }
   3455 
   3456 void
   3457 door_ki_hold(door_handle_t dh)
   3458 {
   3459 	file_t *fp = DHTOF(dh);
   3460 
   3461 	mutex_enter(&fp->f_tlock);
   3462 	fp->f_count++;
   3463 	mutex_exit(&fp->f_tlock);
   3464 }
   3465 
   3466 void
   3467 door_ki_rele(door_handle_t dh)
   3468 {
   3469 	file_t *fp = DHTOF(dh);
   3470 
   3471 	(void) closef(fp);
   3472 }
   3473 
   3474 int
   3475 door_ki_open(char *pathname, door_handle_t *dhp)
   3476 {
   3477 	file_t *fp;
   3478 	vnode_t *vp;
   3479 	int err;
   3480 
   3481 	if ((err = lookupname(pathname, UIO_SYSSPACE, FOLLOW, NULL, &vp)) != 0)
   3482 		return (err);
   3483 	if (err = VOP_OPEN(&vp, FREAD, kcred, NULL)) {
   3484 		VN_RELE(vp);
   3485 		return (err);
   3486 	}
   3487 	if (vp->v_type != VDOOR) {
   3488 		VN_RELE(vp);
   3489 		return (EINVAL);
   3490 	}
   3491 	if ((err = falloc(vp, FREAD | FWRITE, &fp, NULL)) != 0) {
   3492 		VN_RELE(vp);
   3493 		return (err);
   3494 	}
   3495 	/* falloc returns with f_tlock held on success */
   3496 	mutex_exit(&fp->f_tlock);
   3497 	*dhp = FTODH(fp);
   3498 	return (0);
   3499 }
   3500 
   3501 int
   3502 door_ki_info(door_handle_t dh, struct door_info *dip)
   3503 {
   3504 	file_t *fp = DHTOF(dh);
   3505 	vnode_t *vp;
   3506 
   3507 	if (VOP_REALVP(fp->f_vnode, &vp, NULL))
   3508 		vp = fp->f_vnode;
   3509 	if (vp->v_type != VDOOR)
   3510 		return (EINVAL);
   3511 	door_info_common(VTOD(vp), dip, fp);
   3512 	return (0);
   3513 }
   3514 
   3515 door_handle_t
   3516 door_ki_lookup(int did)
   3517 {
   3518 	file_t *fp;
   3519 	door_handle_t dh;
   3520 
   3521 	/* is the descriptor really a door? */
   3522 	if (door_lookup(did, &fp) == NULL)
   3523 		return (NULL);
   3524 	/* got the door, put a hold on it and release the fd */
   3525 	dh = FTODH(fp);
   3526 	door_ki_hold(dh);
   3527 	releasef(did);
   3528 	return (dh);
   3529 }
   3530 
   3531 int
   3532 door_ki_setparam(door_handle_t dh, int type, size_t val)
   3533 {
   3534 	file_t *fp = DHTOF(dh);
   3535 	vnode_t *vp;
   3536 
   3537 	if (VOP_REALVP(fp->f_vnode, &vp, NULL))
   3538 		vp = fp->f_vnode;
   3539 	if (vp->v_type != VDOOR)
   3540 		return (EINVAL);
   3541 	return (door_setparam_common(VTOD(vp), 1, type, val));
   3542 }
   3543 
   3544 int
   3545 door_ki_getparam(door_handle_t dh, int type, size_t *out)
   3546 {
   3547 	file_t *fp = DHTOF(dh);
   3548 	vnode_t *vp;
   3549 
   3550 	if (VOP_REALVP(fp->f_vnode, &vp, NULL))
   3551 		vp = fp->f_vnode;
   3552 	if (vp->v_type != VDOOR)
   3553 		return (EINVAL);
   3554 	return (door_getparam_common(VTOD(vp), type, out));
   3555 }
   3556