Home | History | Annotate | Download | only in os
      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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <sys/types.h>
     27 #include <sys/systm.h>
     28 #include <sys/param.h>
     29 #include <sys/user.h>
     30 #include <sys/vm.h>
     31 #include <sys/conf.h>
     32 #include <sys/class.h>
     33 #include <sys/vfs.h>
     34 #include <sys/vnode.h>
     35 #include <sys/mount.h>
     36 #include <sys/systm.h>
     37 #include <sys/modctl.h>
     38 #include <sys/exec.h>
     39 #include <sys/exechdr.h>
     40 #include <sys/devops.h>
     41 #include <sys/ddi.h>
     42 #include <sys/sunddi.h>
     43 #include <sys/cmn_err.h>
     44 #include <sys/hwconf.h>
     45 #include <sys/ddi_impldefs.h>
     46 #include <sys/autoconf.h>
     47 #include <sys/disp.h>
     48 #include <sys/kmem.h>
     49 #include <sys/instance.h>
     50 #include <sys/modhash.h>
     51 #include <sys/dacf.h>
     52 #include <sys/debug.h>
     53 #include <ipp/ipp.h>
     54 #include <sys/strsubr.h>
     55 #include <sys/kcpc.h>
     56 #include <sys/brand.h>
     57 #include <sys/cpc_pcbe.h>
     58 #include <sys/kstat.h>
     59 #include <sys/socketvar.h>
     60 #include <sys/kiconv.h>
     61 
     62 extern int moddebug;
     63 
     64 extern struct cb_ops no_cb_ops;
     65 extern struct dev_ops nodev_ops;
     66 extern struct dev_ops mod_nodev_ops;
     67 
     68 extern struct modctl *mod_getctl(struct modlinkage *);
     69 extern int errsys(), nodev(), nulldev();
     70 
     71 extern int findmodbyname(char *);
     72 extern int mod_getsysnum(char *);
     73 
     74 extern struct execsw execsw[];
     75 
     76 /*
     77  * Define dev_ops for unused devopsp entry.
     78  */
     79 struct dev_ops mod_nodev_ops = {
     80 	DEVO_REV,		/* devo_rev	*/
     81 	0,			/* refcnt	*/
     82 	ddi_no_info,		/* info */
     83 	nulldev,		/* identify	*/
     84 	nulldev,		/* probe	*/
     85 	ddifail,		/* attach	*/
     86 	nodev,			/* detach	*/
     87 	nulldev,		/* reset	*/
     88 	&no_cb_ops,		/* character/block driver operations */
     89 	(struct bus_ops *)0	/* bus operations for nexus drivers */
     90 };
     91 
     92 /*
     93  * Define mod_ops for each supported module type
     94  */
     95 
     96 /*
     97  * Null operations; used for uninitialized and "misc" modules.
     98  */
     99 static int mod_null(struct modldrv *, struct modlinkage *);
    100 static int mod_infonull(void *, struct modlinkage *, int *);
    101 
    102 struct mod_ops mod_miscops = {
    103 	mod_null, mod_null, mod_infonull
    104 };
    105 
    106 /* CPU Modules */
    107 struct mod_ops mod_cpuops = {
    108 	mod_null, mod_null, mod_infonull
    109 };
    110 
    111 /*
    112  * Cryptographic Modules
    113  */
    114 struct mod_ops mod_cryptoops = {
    115 	mod_null, mod_null, mod_infonull
    116 };
    117 
    118 /*
    119  * IP Policy Modules
    120  */
    121 static int mod_installipp(struct modlipp *, struct modlinkage *);
    122 static int mod_removeipp(struct modlipp *, struct modlinkage *);
    123 static int mod_infoipp(struct modlipp *, struct modlinkage *, int *);
    124 
    125 struct mod_ops mod_ippops = {
    126 	mod_installipp, mod_removeipp, mod_infoipp
    127 };
    128 
    129 /*
    130  * Device drivers
    131  */
    132 static int mod_infodrv(struct modldrv *, struct modlinkage *, int *);
    133 static int mod_installdrv(struct modldrv *, struct modlinkage *);
    134 static int mod_removedrv(struct modldrv *, struct modlinkage *);
    135 
    136 struct mod_ops mod_driverops = {
    137 	mod_installdrv, mod_removedrv, mod_infodrv
    138 };
    139 
    140 /*
    141  * System calls (new interface)
    142  */
    143 static int mod_infosys(struct modlsys *, struct modlinkage *, int *);
    144 static int mod_installsys(struct modlsys *, struct modlinkage *);
    145 static int mod_removesys(struct modlsys *, struct modlinkage *);
    146 
    147 struct mod_ops mod_syscallops = {
    148 	mod_installsys, mod_removesys, mod_infosys
    149 };
    150 
    151 #ifdef _SYSCALL32_IMPL
    152 /*
    153  * 32-bit system calls in 64-bit kernel
    154  */
    155 static int mod_infosys32(struct modlsys *, struct modlinkage *, int *);
    156 static int mod_installsys32(struct modlsys *, struct modlinkage *);
    157 static int mod_removesys32(struct modlsys *, struct modlinkage *);
    158 
    159 struct mod_ops mod_syscallops32 = {
    160 	mod_installsys32, mod_removesys32, mod_infosys32
    161 };
    162 #endif	/* _SYSCALL32_IMPL */
    163 
    164 /*
    165  * Filesystems
    166  */
    167 static int mod_infofs(struct modlfs *, struct modlinkage *, int *);
    168 static int mod_installfs(struct modlfs *, struct modlinkage *);
    169 static int mod_removefs(struct modlfs *, struct modlinkage *);
    170 
    171 struct mod_ops mod_fsops = {
    172 	mod_installfs, mod_removefs, mod_infofs
    173 };
    174 
    175 /*
    176  * Streams modules.
    177  */
    178 static int mod_infostrmod(struct modlstrmod *, struct modlinkage *, int *);
    179 static int mod_installstrmod(struct modlstrmod *, struct modlinkage *);
    180 static int mod_removestrmod(struct modlstrmod *, struct modlinkage *);
    181 
    182 struct mod_ops mod_strmodops = {
    183 	mod_installstrmod, mod_removestrmod, mod_infostrmod
    184 };
    185 
    186 /*
    187  * Socket modules.
    188  */
    189 static int mod_infosockmod(struct modlsockmod *, struct modlinkage *, int *);
    190 static int mod_installsockmod(struct modlsockmod *, struct modlinkage *);
    191 static int mod_removesockmod(struct modlsockmod *, struct modlinkage *);
    192 
    193 struct mod_ops mod_sockmodops = {
    194 	mod_installsockmod, mod_removesockmod, mod_infosockmod
    195 };
    196 
    197 /*
    198  * Scheduling classes.
    199  */
    200 static int mod_infosched(struct modlsched *, struct modlinkage *, int *);
    201 static int mod_installsched(struct modlsched *, struct modlinkage *);
    202 static int mod_removesched(struct modlsched *, struct modlinkage *);
    203 
    204 struct mod_ops mod_schedops = {
    205 	mod_installsched, mod_removesched, mod_infosched
    206 };
    207 
    208 /*
    209  * Exec file type (like ELF, ...).
    210  */
    211 static int mod_infoexec(struct modlexec *, struct modlinkage *, int *);
    212 static int mod_installexec(struct modlexec *, struct modlinkage *);
    213 static int mod_removeexec(struct modlexec *, struct modlinkage *);
    214 
    215 struct mod_ops mod_execops = {
    216 	mod_installexec, mod_removeexec, mod_infoexec
    217 };
    218 
    219 /*
    220  * Dacf (Dynamic Autoconfiguration) modules.
    221  */
    222 static int mod_infodacf(struct modldacf *, struct modlinkage *, int *);
    223 static int mod_installdacf(struct modldacf *, struct modlinkage *);
    224 static int mod_removedacf(struct modldacf *, struct modlinkage *);
    225 
    226 struct mod_ops mod_dacfops = {
    227 	mod_installdacf, mod_removedacf, mod_infodacf
    228 };
    229 
    230 /*
    231  * PCBE (Performance Counter BackEnd) modules.
    232  */
    233 static int mod_installpcbe(struct modlpcbe *, struct modlinkage *);
    234 static int mod_removepcbe(struct modlpcbe *, struct modlinkage *);
    235 
    236 struct mod_ops mod_pcbeops = {
    237 	mod_installpcbe, mod_removepcbe, mod_infonull
    238 };
    239 
    240 /*
    241  * Brand modules.
    242  */
    243 static int mod_installbrand(struct modlbrand *, struct modlinkage *);
    244 static int mod_removebrand(struct modlbrand *, struct modlinkage *);
    245 
    246 struct mod_ops mod_brandops = {
    247 	mod_installbrand, mod_removebrand, mod_infonull
    248 };
    249 
    250 /*
    251  * kiconv modules.
    252  */
    253 static int mod_installkiconv(struct modlkiconv *, struct modlinkage *);
    254 static int mod_removekiconv(struct modlkiconv *, struct modlinkage *);
    255 
    256 struct mod_ops mod_kiconvops = {
    257 	mod_installkiconv, mod_removekiconv, mod_infonull
    258 };
    259 
    260 static struct sysent *mod_getsysent(struct modlinkage *, struct sysent *);
    261 
    262 static char uninstall_err[] = "Cannot uninstall %s; not installed";
    263 
    264 /*
    265  * Debugging support
    266  */
    267 #define	DRV_DBG		MODDEBUG_LOADMSG2
    268 
    269 /*PRINTFLIKE2*/
    270 static void mod_dprintf(int flag, const char *format, ...) __KPRINTFLIKE(2);
    271 
    272 static void
    273 mod_dprintf(int flag, const char *format, ...)
    274 {
    275 	va_list alist;
    276 
    277 	if ((moddebug & flag) != 0) {
    278 		va_start(alist, format);
    279 		(void) vprintf(format, alist);
    280 		va_end(alist);
    281 	}
    282 }
    283 
    284 /*
    285  * Install a module.
    286  * (This routine is in the Solaris SPARC DDI/DKI)
    287  */
    288 int
    289 mod_install(struct modlinkage *modlp)
    290 {
    291 	int retval = -1;	/* No linkage structures */
    292 	struct modlmisc **linkpp;
    293 	struct modlmisc **linkpp1;
    294 
    295 	if (modlp->ml_rev != MODREV_1) {
    296 		printf("mod_install:  modlinkage structure is not MODREV_1\n");
    297 		return (EINVAL);
    298 	}
    299 	linkpp = (struct modlmisc **)&modlp->ml_linkage[0];
    300 
    301 	while (*linkpp != NULL) {
    302 		if ((retval = MODL_INSTALL(*linkpp, modlp)) != 0) {
    303 			linkpp1 = (struct modlmisc **)&modlp->ml_linkage[0];
    304 
    305 			while (linkpp1 != linkpp) {
    306 				MODL_REMOVE(*linkpp1, modlp); /* clean up */
    307 				linkpp1++;
    308 			}
    309 			break;
    310 		}
    311 		linkpp++;
    312 	}
    313 	return (retval);
    314 }
    315 
    316 static char *reins_err =
    317 	"Could not reinstall %s\nReboot to correct the problem";
    318 
    319 /*
    320  * Remove a module.  This is called by the module wrapper routine.
    321  * (This routine is in the Solaris SPARC DDI/DKI)
    322  */
    323 int
    324 mod_remove(struct modlinkage *modlp)
    325 {
    326 	int retval = 0;
    327 	struct modlmisc **linkpp, *last_linkp;
    328 
    329 	linkpp = (struct modlmisc **)&modlp->ml_linkage[0];
    330 
    331 	while (*linkpp != NULL) {
    332 		if ((retval = MODL_REMOVE(*linkpp, modlp)) != 0) {
    333 			last_linkp = *linkpp;
    334 			linkpp = (struct modlmisc **)&modlp->ml_linkage[0];
    335 			while (*linkpp != last_linkp) {
    336 				if (MODL_INSTALL(*linkpp, modlp) != 0) {
    337 					cmn_err(CE_WARN, reins_err,
    338 					    (*linkpp)->misc_linkinfo);
    339 					break;
    340 				}
    341 				linkpp++;
    342 			}
    343 			break;
    344 		}
    345 		linkpp++;
    346 	}
    347 	return (retval);
    348 }
    349 
    350 /*
    351  * Get module status.
    352  * (This routine is in the Solaris SPARC DDI/DKI)
    353  */
    354 int
    355 mod_info(struct modlinkage *modlp, struct modinfo *modinfop)
    356 {
    357 	int i;
    358 	int retval = 0;
    359 	struct modspecific_info *msip;
    360 	struct modlmisc **linkpp;
    361 
    362 	modinfop->mi_rev = modlp->ml_rev;
    363 
    364 	linkpp = (struct modlmisc **)modlp->ml_linkage;
    365 	msip = &modinfop->mi_msinfo[0];
    366 
    367 	for (i = 0; i < MODMAXLINK; i++) {
    368 		if (*linkpp == NULL) {
    369 			msip->msi_linkinfo[0] = '\0';
    370 		} else {
    371 			(void) strncpy(msip->msi_linkinfo,
    372 			    (*linkpp)->misc_linkinfo, MODMAXLINKINFOLEN);
    373 			retval = MODL_INFO(*linkpp, modlp, &msip->msi_p0);
    374 			if (retval != 0)
    375 				break;
    376 			linkpp++;
    377 		}
    378 		msip++;
    379 	}
    380 
    381 	if (modinfop->mi_info == MI_INFO_LINKAGE) {
    382 		/*
    383 		 * Slight kludge used to extract the address of the
    384 		 * modlinkage structure from the module (just after
    385 		 * loading a module for the very first time)
    386 		 */
    387 		modinfop->mi_base = (void *)modlp;
    388 	}
    389 
    390 	if (retval == 0)
    391 		return (1);
    392 	return (0);
    393 }
    394 
    395 /*
    396  * Get module name.
    397  */
    398 const char *
    399 mod_modname(struct modlinkage *modlp)
    400 {
    401 	struct modctl	*mcp;
    402 
    403 	if ((mcp = mod_getctl(modlp)) == NULL)
    404 		return (NULL);
    405 
    406 	return (mcp->mod_modname);
    407 }
    408 
    409 /*
    410  * Null operation; return 0.
    411  */
    412 /*ARGSUSED*/
    413 static int
    414 mod_null(struct modldrv *modl, struct modlinkage *modlp)
    415 {
    416 	return (0);
    417 }
    418 
    419 /*
    420  * Status for User modules.
    421  */
    422 /*ARGSUSED*/
    423 static int
    424 mod_infonull(void *modl, struct modlinkage *modlp, int *p0)
    425 {
    426 	*p0 = -1;		/* for modinfo display */
    427 	return (0);
    428 }
    429 
    430 /*
    431  * Driver status info
    432  */
    433 /*ARGSUSED*/
    434 static int
    435 mod_infodrv(struct modldrv *modl, struct modlinkage *modlp, int *p0)
    436 {
    437 	struct modctl *mcp;
    438 	char *mod_name;
    439 
    440 	if ((mcp = mod_getctl(modlp)) == NULL) {
    441 		*p0 = -1;
    442 		return (0);	/* driver is not yet installed */
    443 	}
    444 
    445 	mod_name = mcp->mod_modname;
    446 
    447 	*p0 = ddi_name_to_major(mod_name);
    448 	return (0);
    449 }
    450 
    451 /*
    452  * Manage dacf (device autoconfiguration) modules
    453  */
    454 
    455 /*ARGSUSED*/
    456 static int
    457 mod_infodacf(struct modldacf *modl, struct modlinkage *modlp, int *p0)
    458 {
    459 	if (mod_getctl(modlp) == NULL) {
    460 		*p0 = -1;
    461 		return (0);	/* module is not yet installed */
    462 	}
    463 
    464 	*p0 = 0;
    465 	return (0);
    466 }
    467 
    468 static int
    469 mod_installdacf(struct modldacf *modl, struct modlinkage *modlp)
    470 {
    471 	struct modctl	*mcp;
    472 
    473 	if ((mcp = mod_getctl(modlp)) == NULL)
    474 		return (EINVAL);
    475 	return (dacf_module_register(mcp->mod_modname, modl->dacf_dacfsw));
    476 }
    477 
    478 /*ARGSUSED*/
    479 static int
    480 mod_removedacf(struct modldacf *modl, struct modlinkage *modlp)
    481 {
    482 	struct modctl	*mcp;
    483 
    484 	if ((mcp = mod_getctl(modlp)) == NULL)
    485 		return (EINVAL);
    486 	return (dacf_module_unregister(mcp->mod_modname));
    487 }
    488 
    489 /*
    490  * Manage PCBE (Performance Counter BackEnd) modules.
    491  */
    492 /*ARGSUSED*/
    493 static int
    494 mod_installpcbe(struct modlpcbe *modl, struct modlinkage *modlp)
    495 {
    496 	if (modl->pcbe_ops->pcbe_ver != PCBE_VER_1) {
    497 		cmn_err(CE_WARN, "pcbe '%s' version mismatch",
    498 		    modl->pcbe_linkinfo);
    499 		return (EINVAL);
    500 	}
    501 
    502 	kcpc_register_pcbe(modl->pcbe_ops);
    503 	return (0);
    504 }
    505 
    506 /*
    507  * PCBEs may not be unloaded. It would make CPC locking too complex, and since
    508  * PCBEs are loaded once and used for life, there is no harm done in leaving
    509  * them in the system.
    510  */
    511 /*ARGSUSED*/
    512 static int
    513 mod_removepcbe(struct modlpcbe *modl, struct modlinkage *modlp)
    514 {
    515 	return (EBUSY);
    516 }
    517 
    518 /*
    519  * Manage BrandZ modules.
    520  */
    521 /*ARGSUSED*/
    522 static int
    523 mod_installbrand(struct modlbrand *modl, struct modlinkage *modlp)
    524 {
    525 	return (brand_register(modl->brand_branddef));
    526 }
    527 
    528 /*ARGSUSED*/
    529 static int
    530 mod_removebrand(struct modlbrand *modl, struct modlinkage *modlp)
    531 {
    532 	return (brand_unregister(modl->brand_branddef));
    533 }
    534 
    535 /*
    536  * Install a new driver
    537  */
    538 static int
    539 mod_installdrv(struct modldrv *modl, struct modlinkage *modlp)
    540 {
    541 	struct modctl *mcp;
    542 	struct dev_ops *ops;
    543 	char *modname;
    544 	major_t major;
    545 	struct dev_ops *dp;
    546 	struct devnames *dnp;
    547 	struct streamtab *str;
    548 	cdevsw_impl_t *cdp;
    549 	uint_t sqtype;
    550 	uint_t qflag;
    551 	uint_t flag;
    552 	int err = 0;
    553 
    554 	/* sanity check module */
    555 	if ((mcp = mod_getctl(modlp)) == NULL) {
    556 		cmn_err(CE_WARN, "mod_install: bad module linkage data");
    557 		err = ENXIO;
    558 		goto done;
    559 	}
    560 	modname = mcp->mod_modname;
    561 
    562 	/* Sanity check modname */
    563 	if ((major = ddi_name_to_major(modname)) == DDI_MAJOR_T_NONE) {
    564 #ifdef DEBUG
    565 		cmn_err(CE_WARN,
    566 		    "mod_installdrv: no major number for %s", modname);
    567 #endif
    568 		err = ENXIO;
    569 		goto done;
    570 	}
    571 
    572 	/* Verify MP safety flag */
    573 	ops = modl->drv_dev_ops;
    574 	if (ops->devo_bus_ops == NULL && ops->devo_cb_ops != NULL &&
    575 	    !(ops->devo_cb_ops->cb_flag & D_MP)) {
    576 		cmn_err(CE_WARN,
    577 		    "mod_installdrv: MT-unsafe driver '%s' rejected", modname);
    578 		err = ENXIO;
    579 		goto done;
    580 	}
    581 
    582 
    583 	/* Is bus_map_fault signature correct (version 8 and higher)? */
    584 	if (ops->devo_bus_ops != NULL &&
    585 	    ops->devo_bus_ops->bus_map_fault != NULL &&
    586 	    ops->devo_bus_ops->bus_map_fault != i_ddi_map_fault &&
    587 	    ops->devo_bus_ops->busops_rev < BUSO_REV_8) {
    588 
    589 		cmn_err(CE_WARN,
    590 		    "mod_installdrv: busops' revision of '%s' is too low"
    591 		    " (must be at least 8)", modname);
    592 		err = ENXIO;
    593 		goto done;
    594 	}
    595 
    596 
    597 	/* Make sure the driver is uninstalled */
    598 	dnp = &devnamesp[major];
    599 	LOCK_DEV_OPS(&dnp->dn_lock);
    600 	dp = devopsp[major];
    601 
    602 	if (dnp->dn_flags & (DN_DRIVER_REMOVED|DN_DRIVER_INACTIVE)) {
    603 #ifdef DEBUG
    604 		cmn_err(CE_CONT,
    605 		    "mod_installdrv: driver %s not installed", modname);
    606 #endif
    607 		err = ENXIO;
    608 		goto unlock;
    609 	}
    610 
    611 	if (dp != &nodev_ops && dp != &mod_nodev_ops) {
    612 		cmn_err(CE_WARN,
    613 		    "mod_installdrv: driver already installed %s", modname);
    614 		err = EALREADY;
    615 		goto unlock;
    616 	}
    617 
    618 	devopsp[major] = ops; /* setup devopsp */
    619 
    620 	if ((str = STREAMSTAB(major)) != NULL) {	/* streams driver */
    621 		flag = CBFLAG(major);
    622 		if ((err = devflg_to_qflag(str, flag, &qflag, &sqtype)) != 0)
    623 			goto unlock;
    624 		cdp = &devimpl[major];
    625 		ASSERT(cdp->d_str == NULL);
    626 		cdp->d_str = str;
    627 		cdp->d_qflag = qflag | QISDRV;
    628 		cdp->d_sqtype = sqtype;
    629 	}
    630 
    631 	if (ops->devo_bus_ops == NULL)
    632 		dnp->dn_flags |= DN_LEAF_DRIVER;
    633 
    634 unlock:
    635 	UNLOCK_DEV_OPS(&dnp->dn_lock);
    636 done:
    637 	return (err);
    638 }
    639 
    640 static int
    641 mod_removedrv(struct modldrv *modl, struct modlinkage *modlp)
    642 {
    643 	struct modctl *mcp;
    644 	struct dev_ops *ops;
    645 	struct devnames *dnp;
    646 	struct dev_ops *dp;
    647 	major_t major;
    648 	char *modname;
    649 	extern kthread_id_t mod_aul_thread;
    650 	struct streamtab *str;
    651 	cdevsw_impl_t *cdp;
    652 	int err = 0;
    653 
    654 	/* Don't auto unload modules on if moddebug flag is set */
    655 	if ((moddebug & MODDEBUG_NOAUL_DRV) && (mod_aul_thread == curthread)) {
    656 		err = EBUSY;
    657 		goto done;
    658 	}
    659 
    660 	/* Verify modname has a driver major */
    661 	mcp = mod_getctl(modlp);
    662 	ASSERT(mcp != NULL);
    663 	modname = mcp->mod_modname;
    664 
    665 	if ((major = ddi_name_to_major(modname)) == -1) {
    666 		cmn_err(CE_WARN, uninstall_err, modname);
    667 		err = EINVAL;
    668 		goto done;
    669 	}
    670 
    671 	ops = modl->drv_dev_ops;
    672 	dnp = &(devnamesp[major]);
    673 	LOCK_DEV_OPS(&(dnp->dn_lock));
    674 
    675 	dp = devopsp[major];
    676 
    677 	if (dp != ops)  {
    678 		cmn_err(CE_NOTE, "mod_removedrv: mismatched driver for %s",
    679 		    modname);
    680 		err = EBUSY;
    681 		goto unlock;
    682 	}
    683 
    684 	/*
    685 	 * A driver is not unloadable if its dev_ops are held
    686 	 */
    687 	if (!DRV_UNLOADABLE(dp)) {
    688 		mod_dprintf(DRV_DBG, "Cannot unload device driver <%s>,"
    689 		    " refcnt %d\n", modname, dp->devo_refcnt);
    690 		err = EBUSY;
    691 		goto unlock;
    692 	}
    693 
    694 	/*
    695 	 * OK to unload.
    696 	 */
    697 	if ((str = STREAMSTAB(major)) != NULL) {	/* streams driver */
    698 		cdp = &devimpl[major];
    699 		ASSERT(cdp->d_str == str);
    700 		cdp->d_str = NULL;
    701 
    702 		/* check for reference to per-dev syncq */
    703 		if (cdp->d_dmp != NULL) {
    704 			rele_dm(cdp->d_dmp);
    705 			cdp->d_dmp = NULL;
    706 		}
    707 	}
    708 
    709 	devopsp[major] = &mod_nodev_ops;
    710 	dnp->dn_flags &= ~(DN_DRIVER_HELD|DN_NO_AUTODETACH);
    711 
    712 unlock:
    713 	UNLOCK_DEV_OPS(&(dnp->dn_lock));
    714 done:
    715 	return (err);
    716 }
    717 
    718 /*
    719  * System call subroutines
    720  */
    721 
    722 /*
    723  * Compute system call number for given sysent and sysent table
    724  */
    725 static int
    726 mod_infosysnum(struct modlinkage *modlp, struct sysent table[])
    727 {
    728 	struct sysent *sysp;
    729 
    730 	if ((sysp = mod_getsysent(modlp, table)) == NULL)
    731 		return (-1);
    732 	return ((int)(sysp - table));
    733 }
    734 
    735 /*
    736  * Put a loadable system call entry into a sysent table.
    737  */
    738 static int
    739 mod_installsys_sysent(
    740 	struct modlsys		*modl,
    741 	struct modlinkage	*modlp,
    742 	struct sysent		table[])
    743 {
    744 	struct sysent *sysp;
    745 	struct sysent *mp;
    746 
    747 #ifdef DEBUG
    748 	/*
    749 	 * Before we even play with the sysent table, sanity check the
    750 	 * incoming flags to make sure the entry is valid
    751 	 */
    752 	switch (modl->sys_sysent->sy_flags & SE_RVAL_MASK) {
    753 	case SE_32RVAL1:
    754 		/* only r_val1 returned */
    755 	case SE_32RVAL1 | SE_32RVAL2:
    756 		/* r_val1 and r_val2 returned */
    757 	case SE_64RVAL:
    758 		/* 64-bit rval returned */
    759 		break;
    760 	default:
    761 		cmn_err(CE_WARN, "loadable syscall: %p: bad rval flags %x",
    762 		    (void *)modl, modl->sys_sysent->sy_flags);
    763 		return (ENOSYS);
    764 	}
    765 #endif
    766 	if ((sysp = mod_getsysent(modlp, table)) == NULL)
    767 		return (ENOSPC);
    768 
    769 	/*
    770 	 * We should only block here until the reader in syscall gives
    771 	 * up the lock.  Multiple writers are prevented in the mod layer.
    772 	 */
    773 	rw_enter(sysp->sy_lock, RW_WRITER);
    774 	mp = modl->sys_sysent;
    775 	sysp->sy_narg = mp->sy_narg;
    776 	sysp->sy_call = mp->sy_call;
    777 
    778 	/*
    779 	 * clear the old call method flag, and get the new one from the module.
    780 	 */
    781 	sysp->sy_flags &= ~SE_ARGC;
    782 	sysp->sy_flags |= SE_LOADED |
    783 	    (mp->sy_flags & (SE_ARGC | SE_NOUNLOAD | SE_RVAL_MASK));
    784 
    785 	/*
    786 	 * If the syscall doesn't need or want unloading, it can avoid
    787 	 * the locking overhead on each entry.  Convert the sysent to a
    788 	 * normal non-loadable entry in that case.
    789 	 */
    790 	if (mp->sy_flags & SE_NOUNLOAD) {
    791 		if (mp->sy_flags & SE_ARGC) {
    792 			sysp->sy_callc = (int64_t (*)())mp->sy_call;
    793 		} else {
    794 			sysp->sy_callc = syscall_ap;
    795 		}
    796 		sysp->sy_flags &= ~SE_LOADABLE;
    797 	}
    798 	rw_exit(sysp->sy_lock);
    799 	return (0);
    800 }
    801 
    802 /*
    803  * Remove a loadable system call entry from a sysent table.
    804  */
    805 static int
    806 mod_removesys_sysent(
    807 	struct modlsys		*modl,
    808 	struct modlinkage	*modlp,
    809 	struct sysent		table[])
    810 {
    811 	struct sysent	*sysp;
    812 
    813 	if ((sysp = mod_getsysent(modlp, table)) == NULL ||
    814 	    (sysp->sy_flags & (SE_LOADABLE | SE_NOUNLOAD)) == 0 ||
    815 	    sysp->sy_call != modl->sys_sysent->sy_call) {
    816 
    817 		struct modctl *mcp = mod_getctl(modlp);
    818 		char *modname = mcp->mod_modname;
    819 
    820 		cmn_err(CE_WARN, uninstall_err, modname);
    821 		return (EINVAL);
    822 	}
    823 
    824 	/* If we can't get the write lock, we can't unlink from the system */
    825 
    826 	if (!(moddebug & MODDEBUG_NOAUL_SYS) &&
    827 	    rw_tryenter(sysp->sy_lock, RW_WRITER)) {
    828 		/*
    829 		 * Check the flags to be sure the syscall is still
    830 		 * (un)loadable.
    831 		 * If SE_NOUNLOAD is set, SE_LOADABLE will not be.
    832 		 */
    833 		if ((sysp->sy_flags & (SE_LOADED | SE_LOADABLE)) ==
    834 		    (SE_LOADED | SE_LOADABLE)) {
    835 			sysp->sy_flags &= ~SE_LOADED;
    836 			sysp->sy_callc = loadable_syscall;
    837 			sysp->sy_call = (int (*)())nosys;
    838 			rw_exit(sysp->sy_lock);
    839 			return (0);
    840 		}
    841 		rw_exit(sysp->sy_lock);
    842 	}
    843 	return (EBUSY);
    844 }
    845 
    846 /*
    847  * System call status info
    848  */
    849 /*ARGSUSED*/
    850 static int
    851 mod_infosys(struct modlsys *modl, struct modlinkage *modlp, int *p0)
    852 {
    853 	*p0 = mod_infosysnum(modlp, sysent);
    854 	return (0);
    855 }
    856 
    857 /*
    858  * Link a system call into the system by setting the proper sysent entry.
    859  * Called from the module's _init routine.
    860  */
    861 static int
    862 mod_installsys(struct modlsys *modl, struct modlinkage *modlp)
    863 {
    864 	return (mod_installsys_sysent(modl, modlp, sysent));
    865 }
    866 
    867 /*
    868  * Unlink a system call from the system.
    869  * Called from a modules _fini routine.
    870  */
    871 static int
    872 mod_removesys(struct modlsys *modl, struct modlinkage *modlp)
    873 {
    874 	return (mod_removesys_sysent(modl, modlp, sysent));
    875 }
    876 
    877 #ifdef _SYSCALL32_IMPL
    878 
    879 /*
    880  * 32-bit system call status info
    881  */
    882 /*ARGSUSED*/
    883 static int
    884 mod_infosys32(struct modlsys *modl, struct modlinkage *modlp, int *p0)
    885 {
    886 	*p0 = mod_infosysnum(modlp, sysent32);
    887 	return (0);
    888 }
    889 
    890 /*
    891  * Link the 32-bit syscall into the system by setting the proper sysent entry.
    892  * Also called from the module's _init routine.
    893  */
    894 static int
    895 mod_installsys32(struct modlsys *modl, struct modlinkage *modlp)
    896 {
    897 	return (mod_installsys_sysent(modl, modlp, sysent32));
    898 }
    899 
    900 /*
    901  * Unlink the 32-bit flavor of a system call from the system.
    902  * Also called from a module's _fini routine.
    903  */
    904 static int
    905 mod_removesys32(struct modlsys *modl, struct modlinkage *modlp)
    906 {
    907 	return (mod_removesys_sysent(modl, modlp, sysent32));
    908 }
    909 
    910 #endif	/* _SYSCALL32_IMPL */
    911 
    912 /*
    913  * Filesystem status info
    914  */
    915 /*ARGSUSED*/
    916 static int
    917 mod_infofs(struct modlfs *modl, struct modlinkage *modlp, int *p0)
    918 {
    919 	struct vfssw *vswp;
    920 
    921 	RLOCK_VFSSW();
    922 	if ((vswp = vfs_getvfsswbyname(modl->fs_vfsdef->name)) == NULL)
    923 		*p0 = -1;
    924 	else {
    925 		*p0 = vswp - vfssw;
    926 		vfs_unrefvfssw(vswp);
    927 	}
    928 	RUNLOCK_VFSSW();
    929 	return (0);
    930 }
    931 
    932 /*
    933  * Install a filesystem.
    934  */
    935 /*ARGSUSED1*/
    936 static int
    937 mod_installfs(struct modlfs *modl, struct modlinkage *modlp)
    938 {
    939 	struct vfssw *vswp;
    940 	struct modctl *mcp;
    941 	char *fsname;
    942 	char ksname[KSTAT_STRLEN + 1];
    943 	int fstype;	/* index into vfssw[] and vsanchor_fstype[] */
    944 	int allocated;
    945 	int err;
    946 	int vsw_stats_enabled;
    947 	/* Not for public consumption so these aren't in a header file */
    948 	extern int	vopstats_enabled;
    949 	extern vopstats_t **vopstats_fstype;
    950 	extern kstat_t *new_vskstat(char *, vopstats_t *);
    951 	extern void initialize_vopstats(vopstats_t *);
    952 
    953 	if (modl->fs_vfsdef->def_version == VFSDEF_VERSION) {
    954 		/* Version matched */
    955 		fsname = modl->fs_vfsdef->name;
    956 	} else {
    957 		if ((modl->fs_vfsdef->def_version > 0) &&
    958 		    (modl->fs_vfsdef->def_version < VFSDEF_VERSION)) {
    959 			/* Older VFSDEF_VERSION */
    960 			fsname = modl->fs_vfsdef->name;
    961 		} else if ((mcp = mod_getctl(modlp)) != NULL) {
    962 			/* Pre-VFSDEF_VERSION */
    963 			fsname = mcp->mod_modname;
    964 		} else {
    965 			/* If all else fails... */
    966 			fsname = "<unknown file system type>";
    967 		}
    968 
    969 		cmn_err(CE_WARN, "file system '%s' version mismatch", fsname);
    970 		return (ENXIO);
    971 	}
    972 
    973 	allocated = 0;
    974 
    975 	WLOCK_VFSSW();
    976 	if ((vswp = vfs_getvfsswbyname(fsname)) == NULL) {
    977 		if ((vswp = allocate_vfssw(fsname)) == NULL) {
    978 			WUNLOCK_VFSSW();
    979 			/*
    980 			 * See 1095689.  If this message appears, then
    981 			 * we either need to make the vfssw table bigger
    982 			 * statically, or make it grow dynamically.
    983 			 */
    984 			cmn_err(CE_WARN, "no room for '%s' in vfssw!", fsname);
    985 			return (ENXIO);
    986 		}
    987 		allocated = 1;
    988 	}
    989 	ASSERT(vswp != NULL);
    990 
    991 	fstype = vswp - vfssw;	/* Pointer arithmetic to get the fstype */
    992 
    993 	/* Turn on everything by default *except* VSW_STATS */
    994 	vswp->vsw_flag = modl->fs_vfsdef->flags & ~(VSW_STATS);
    995 
    996 	if (modl->fs_vfsdef->flags & VSW_HASPROTO) {
    997 		vfs_mergeopttbl(&vfs_mntopts, modl->fs_vfsdef->optproto,
    998 		    &vswp->vsw_optproto);
    999 	} else {
   1000 		vfs_copyopttbl(&vfs_mntopts, &vswp->vsw_optproto);
   1001 	}
   1002 
   1003 	if (modl->fs_vfsdef->flags & VSW_CANRWRO) {
   1004 		/*
   1005 		 * This obviously implies VSW_CANREMOUNT.
   1006 		 */
   1007 		vswp->vsw_flag |= VSW_CANREMOUNT;
   1008 	}
   1009 
   1010 	/*
   1011 	 * If stats are enabled system wide and for this fstype, then
   1012 	 * set the VSW_STATS flag in the proper vfssw[] table entry.
   1013 	 */
   1014 	if (vopstats_enabled && modl->fs_vfsdef->flags & VSW_STATS) {
   1015 		vswp->vsw_flag |= VSW_STATS;
   1016 	}
   1017 
   1018 	if (modl->fs_vfsdef->init == NULL)
   1019 		err = EFAULT;
   1020 	else
   1021 		err = (*(modl->fs_vfsdef->init))(fstype, fsname);
   1022 
   1023 	if (err != 0) {
   1024 		if (allocated) {
   1025 			kmem_free(vswp->vsw_name, strlen(vswp->vsw_name)+1);
   1026 			vswp->vsw_name = "";
   1027 		}
   1028 		vswp->vsw_flag = 0;
   1029 		vswp->vsw_init = NULL;
   1030 	}
   1031 
   1032 	/* We don't want to hold the vfssw[] write lock over a kmem_alloc() */
   1033 	vsw_stats_enabled = vswp->vsw_flag & VSW_STATS;
   1034 
   1035 	vfs_unrefvfssw(vswp);
   1036 	WUNLOCK_VFSSW();
   1037 
   1038 	/* If everything is on, set up the per-fstype vopstats */
   1039 	if (vsw_stats_enabled && vopstats_enabled &&
   1040 	    vopstats_fstype && vopstats_fstype[fstype] == NULL) {
   1041 		(void) strlcpy(ksname, VOPSTATS_STR, sizeof (ksname));
   1042 		(void) strlcat(ksname, vfssw[fstype].vsw_name, sizeof (ksname));
   1043 		vopstats_fstype[fstype] =
   1044 		    kmem_alloc(sizeof (vopstats_t), KM_SLEEP);
   1045 		initialize_vopstats(vopstats_fstype[fstype]);
   1046 		(void) new_vskstat(ksname, vopstats_fstype[fstype]);
   1047 	}
   1048 	return (err);
   1049 }
   1050 
   1051 /*
   1052  * Remove a filesystem
   1053  */
   1054 static int
   1055 mod_removefs(struct modlfs *modl, struct modlinkage *modlp)
   1056 {
   1057 	struct vfssw *vswp;
   1058 	struct modctl *mcp;
   1059 	char *modname;
   1060 
   1061 	if (moddebug & MODDEBUG_NOAUL_FS)
   1062 		return (EBUSY);
   1063 
   1064 	WLOCK_VFSSW();
   1065 	if ((vswp = vfs_getvfsswbyname(modl->fs_vfsdef->name)) == NULL) {
   1066 		mcp = mod_getctl(modlp);
   1067 		ASSERT(mcp != NULL);
   1068 		modname = mcp->mod_modname;
   1069 		WUNLOCK_VFSSW();
   1070 		cmn_err(CE_WARN, uninstall_err, modname);
   1071 		return (EINVAL);
   1072 	}
   1073 	if (vswp->vsw_count != 1) {
   1074 		vfs_unrefvfssw(vswp);
   1075 		WUNLOCK_VFSSW();
   1076 		return (EBUSY);
   1077 	}
   1078 
   1079 	/*
   1080 	 * A mounted filesystem could still have vsw_count = 0
   1081 	 * so we must check whether anyone is actually using our ops
   1082 	 */
   1083 	if (vfs_opsinuse(&vswp->vsw_vfsops)) {
   1084 		vfs_unrefvfssw(vswp);
   1085 		WUNLOCK_VFSSW();
   1086 		return (EBUSY);
   1087 	}
   1088 
   1089 	vfs_freeopttbl(&vswp->vsw_optproto);
   1090 	vswp->vsw_optproto.mo_count = 0;
   1091 
   1092 	vswp->vsw_flag = 0;
   1093 	vswp->vsw_init = NULL;
   1094 	vfs_unrefvfssw(vswp);
   1095 	WUNLOCK_VFSSW();
   1096 	return (0);
   1097 }
   1098 
   1099 /*
   1100  * Get status of a streams module.
   1101  */
   1102 /*ARGSUSED*/
   1103 static int
   1104 mod_infostrmod(struct modlstrmod *modl, struct modlinkage *modlp, int *p0)
   1105 {
   1106 	*p0 = -1;	/* no useful info */
   1107 	return (0);
   1108 }
   1109 
   1110 
   1111 /*
   1112  * Install a streams module.
   1113  */
   1114 /*ARGSUSED*/
   1115 static int
   1116 mod_installstrmod(struct modlstrmod *modl, struct modlinkage *modlp)
   1117 {
   1118 	struct fmodsw *fp = modl->strmod_fmodsw;
   1119 
   1120 	if (!(fp->f_flag & D_MP)) {
   1121 		cmn_err(CE_WARN, "mod_install: MT-unsafe strmod '%s' rejected",
   1122 		    fp->f_name);
   1123 		return (ENXIO);
   1124 	}
   1125 
   1126 	return (fmodsw_register(fp->f_name, fp->f_str, fp->f_flag));
   1127 }
   1128 
   1129 /*
   1130  * Remove a streams module.
   1131  */
   1132 /*ARGSUSED*/
   1133 static int
   1134 mod_removestrmod(struct modlstrmod *modl, struct modlinkage *modlp)
   1135 {
   1136 	if (moddebug & MODDEBUG_NOAUL_STR)
   1137 		return (EBUSY);
   1138 
   1139 	return (fmodsw_unregister(modl->strmod_fmodsw->f_name));
   1140 }
   1141 
   1142 /*
   1143  * Get status of a socket module.
   1144  */
   1145 /*ARGSUSED*/
   1146 static int
   1147 mod_infosockmod(struct modlsockmod *modl, struct modlinkage *modlp, int *p0)
   1148 {
   1149 	*p0 = -1;	/* no useful info */
   1150 	return (0);
   1151 }
   1152 
   1153 /*
   1154  * Install a socket module.
   1155  */
   1156 /*ARGSUSED*/
   1157 static int
   1158 mod_installsockmod(struct modlsockmod *modl, struct modlinkage *modlp)
   1159 {
   1160 	struct modctl *mcp;
   1161 	char *mod_name;
   1162 
   1163 	mcp = mod_getctl(modlp);
   1164 	ASSERT(mcp != NULL);
   1165 	mod_name = mcp->mod_modname;
   1166 	if (strcmp(mod_name, modl->sockmod_reg_info->smod_name) != 0) {
   1167 #ifdef DEBUG
   1168 		cmn_err(CE_CONT, "mod_installsockmod: different names"
   1169 		    " %s != %s \n", mod_name,
   1170 		    modl->sockmod_reg_info->smod_name);
   1171 #endif
   1172 		return (EINVAL);
   1173 	}
   1174 
   1175 	/*
   1176 	 * Register module.
   1177 	 */
   1178 	return (smod_register(modl->sockmod_reg_info));
   1179 }
   1180 
   1181 /*
   1182  * Remove a socket module.
   1183  */
   1184 /*ARGSUSED*/
   1185 static int
   1186 mod_removesockmod(struct modlsockmod *modl, struct modlinkage *modlp)
   1187 {
   1188 	/*
   1189 	 * unregister from the global socket creation table
   1190 	 * check the refcnt in the lookup table
   1191 	 */
   1192 	return (smod_unregister(modl->sockmod_reg_info->smod_name));
   1193 }
   1194 
   1195 /*
   1196  * Get status of a scheduling class module.
   1197  */
   1198 /*ARGSUSED1*/
   1199 static int
   1200 mod_infosched(struct modlsched *modl, struct modlinkage *modlp, int *p0)
   1201 {
   1202 	int	status;
   1203 	auto id_t	cid;
   1204 
   1205 	status = getcidbyname(modl->sched_class->cl_name, &cid);
   1206 
   1207 	if (status != 0)
   1208 		*p0 = -1;
   1209 	else
   1210 		*p0 = cid;
   1211 
   1212 	return (0);
   1213 }
   1214 
   1215 /*
   1216  * Install a scheduling class module.
   1217  */
   1218 /*ARGSUSED1*/
   1219 static int
   1220 mod_installsched(struct modlsched *modl, struct modlinkage *modlp)
   1221 {
   1222 	sclass_t *clp;
   1223 	int status;
   1224 	id_t cid;
   1225 
   1226 	/*
   1227 	 * See if module is already installed.
   1228 	 */
   1229 	mutex_enter(&class_lock);
   1230 	status = alloc_cid(modl->sched_class->cl_name, &cid);
   1231 	mutex_exit(&class_lock);
   1232 	ASSERT(status == 0);
   1233 	clp = &sclass[cid];
   1234 	rw_enter(clp->cl_lock, RW_WRITER);
   1235 	if (SCHED_INSTALLED(clp)) {
   1236 		printf("scheduling class %s is already installed\n",
   1237 		    modl->sched_class->cl_name);
   1238 		rw_exit(clp->cl_lock);
   1239 		return (EBUSY);		/* it's already there */
   1240 	}
   1241 
   1242 	clp->cl_init = modl->sched_class->cl_init;
   1243 	clp->cl_funcs = modl->sched_class->cl_funcs;
   1244 	modl->sched_class = clp;
   1245 	disp_add(clp);
   1246 	loaded_classes++;		/* for priocntl system call */
   1247 	rw_exit(clp->cl_lock);
   1248 	return (0);
   1249 }
   1250 
   1251 /*
   1252  * Remove a scheduling class module.
   1253  *
   1254  * we only null out the init func and the class functions because
   1255  * once a class has been loaded it has that slot in the class
   1256  * array until the next reboot. We don't decrement loaded_classes
   1257  * because this keeps count of the number of classes that have
   1258  * been loaded for this session. It will have to be this way until
   1259  * we implement the class array as a linked list and do true
   1260  * dynamic allocation.
   1261  */
   1262 static int
   1263 mod_removesched(struct modlsched *modl, struct modlinkage *modlp)
   1264 {
   1265 	int status;
   1266 	sclass_t *clp;
   1267 	struct modctl *mcp;
   1268 	char *modname;
   1269 	id_t cid;
   1270 
   1271 	status = getcidbyname(modl->sched_class->cl_name, &cid);
   1272 	if (status != 0) {
   1273 		mcp = mod_getctl(modlp);
   1274 		ASSERT(mcp != NULL);
   1275 		modname = mcp->mod_modname;
   1276 		cmn_err(CE_WARN, uninstall_err, modname);
   1277 		return (EINVAL);
   1278 	}
   1279 	clp = &sclass[cid];
   1280 	if (moddebug & MODDEBUG_NOAUL_SCHED ||
   1281 	    !rw_tryenter(clp->cl_lock, RW_WRITER))
   1282 		return (EBUSY);
   1283 
   1284 	clp->cl_init = NULL;
   1285 	clp->cl_funcs = NULL;
   1286 	rw_exit(clp->cl_lock);
   1287 	return (0);
   1288 }
   1289 
   1290 /*
   1291  * Get status of an exec module.
   1292  */
   1293 /*ARGSUSED1*/
   1294 static int
   1295 mod_infoexec(struct modlexec *modl, struct modlinkage *modlp, int *p0)
   1296 {
   1297 	struct execsw *eswp;
   1298 
   1299 	if ((eswp = findexecsw(modl->exec_execsw->exec_magic)) == NULL)
   1300 		*p0 = -1;
   1301 	else
   1302 		*p0 = eswp - execsw;
   1303 
   1304 	return (0);
   1305 }
   1306 
   1307 /*
   1308  * Install an exec module.
   1309  */
   1310 static int
   1311 mod_installexec(struct modlexec *modl, struct modlinkage *modlp)
   1312 {
   1313 	struct execsw *eswp;
   1314 	struct modctl *mcp;
   1315 	char *modname;
   1316 	char *magic;
   1317 	size_t magic_size;
   1318 
   1319 	/*
   1320 	 * See if execsw entry is already allocated.  Can't use findexectype()
   1321 	 * because we may get a recursive call to here.
   1322 	 */
   1323 
   1324 	if ((eswp = findexecsw(modl->exec_execsw->exec_magic)) == NULL) {
   1325 		mcp = mod_getctl(modlp);
   1326 		ASSERT(mcp != NULL);
   1327 		modname = mcp->mod_modname;
   1328 		magic = modl->exec_execsw->exec_magic;
   1329 		magic_size = modl->exec_execsw->exec_maglen;
   1330 		if ((eswp = allocate_execsw(modname, magic, magic_size)) ==
   1331 		    NULL) {
   1332 			printf("no unused entries in 'execsw'\n");
   1333 			return (ENOSPC);
   1334 		}
   1335 	}
   1336 	if (eswp->exec_func != NULL) {
   1337 		printf("exec type %x is already installed\n",
   1338 		    *eswp->exec_magic);
   1339 			return (EBUSY);		 /* it's already there! */
   1340 	}
   1341 
   1342 	rw_enter(eswp->exec_lock, RW_WRITER);
   1343 	eswp->exec_func = modl->exec_execsw->exec_func;
   1344 	eswp->exec_core = modl->exec_execsw->exec_core;
   1345 	rw_exit(eswp->exec_lock);
   1346 
   1347 	return (0);
   1348 }
   1349 
   1350 /*
   1351  * Remove an exec module.
   1352  */
   1353 static int
   1354 mod_removeexec(struct modlexec *modl, struct modlinkage *modlp)
   1355 {
   1356 	struct execsw *eswp;
   1357 	struct modctl *mcp;
   1358 	char *modname;
   1359 
   1360 	eswp = findexecsw(modl->exec_execsw->exec_magic);
   1361 	if (eswp == NULL) {
   1362 		mcp = mod_getctl(modlp);
   1363 		ASSERT(mcp != NULL);
   1364 		modname = mcp->mod_modname;
   1365 		cmn_err(CE_WARN, uninstall_err, modname);
   1366 		return (EINVAL);
   1367 	}
   1368 	if (moddebug & MODDEBUG_NOAUL_EXEC ||
   1369 	    !rw_tryenter(eswp->exec_lock, RW_WRITER))
   1370 		return (EBUSY);
   1371 	eswp->exec_func = NULL;
   1372 	eswp->exec_core = NULL;
   1373 	rw_exit(eswp->exec_lock);
   1374 	return (0);
   1375 }
   1376 
   1377 /*
   1378  * Find a free sysent entry or check if the specified one is free.
   1379  */
   1380 static struct sysent *
   1381 mod_getsysent(struct modlinkage *modlp, struct sysent *se)
   1382 {
   1383 	int sysnum;
   1384 	struct modctl *mcp;
   1385 	char *mod_name;
   1386 
   1387 	if ((mcp = mod_getctl(modlp)) == NULL) {
   1388 		/*
   1389 		 * This happens when we're looking up the module
   1390 		 * pointer as part of a stub installation.  So
   1391 		 * there's no need to whine at this point.
   1392 		 */
   1393 		return (NULL);
   1394 	}
   1395 
   1396 	mod_name = mcp->mod_modname;
   1397 
   1398 	if ((sysnum = mod_getsysnum(mod_name)) == -1) {
   1399 		cmn_err(CE_WARN, "system call missing from bind file");
   1400 		return (NULL);
   1401 	}
   1402 
   1403 	if (sysnum > 0 && sysnum < NSYSCALL &&
   1404 	    (se[sysnum].sy_flags & (SE_LOADABLE | SE_NOUNLOAD)))
   1405 		return (se + sysnum);
   1406 
   1407 	cmn_err(CE_WARN, "system call entry %d is already in use", sysnum);
   1408 	return (NULL);
   1409 }
   1410 
   1411 /*
   1412  * IP Policy Modules.
   1413  */
   1414 /*ARGSUSED*/
   1415 static int
   1416 mod_infoipp(struct modlipp *modl, struct modlinkage *modlp, int *p0)
   1417 {
   1418 	struct modctl *mcp = mod_getctl(modlp);
   1419 	ipp_mod_id_t mid;
   1420 
   1421 	if (mcp == NULL) {
   1422 		*p0 = -1;
   1423 		return (0);	/* module is not yet installed */
   1424 	}
   1425 
   1426 	mid = ipp_mod_lookup(mcp->mod_modname);
   1427 
   1428 	*p0 = mid;
   1429 	return (0);
   1430 }
   1431 
   1432 static int
   1433 mod_installipp(struct modlipp *modl, struct modlinkage *modlp)
   1434 {
   1435 	struct modctl *mcp = mod_getctl(modlp);
   1436 
   1437 	ASSERT(mcp != NULL);
   1438 	return (ipp_mod_register(mcp->mod_modname, modl->ipp_ops));
   1439 }
   1440 
   1441 /*ARGSUSED*/
   1442 static int
   1443 mod_removeipp(struct modlipp *modl, struct modlinkage *modlp)
   1444 {
   1445 	struct modctl *mcp = mod_getctl(modlp);
   1446 	extern kthread_id_t mod_aul_thread;
   1447 	ipp_mod_id_t mid;
   1448 
   1449 	ASSERT(mcp != NULL);
   1450 
   1451 	if ((moddebug & MODDEBUG_NOAUL_IPP) && (mod_aul_thread == curthread))
   1452 		return (EBUSY);
   1453 
   1454 	mid = ipp_mod_lookup(mcp->mod_modname);
   1455 	ASSERT(mid != IPP_MOD_INVAL);
   1456 
   1457 	return (ipp_mod_unregister(mid));
   1458 }
   1459 
   1460 /*
   1461  * Manage kiconv modules.
   1462  */
   1463 /*ARGSUSED*/
   1464 static int
   1465 mod_installkiconv(struct modlkiconv *modl, struct modlinkage *modlp)
   1466 {
   1467 	return (kiconv_register_module(modl->kiconv_moddef));
   1468 }
   1469 
   1470 /*ARGSUSED*/
   1471 static int
   1472 mod_removekiconv(struct modlkiconv *modl, struct modlinkage *modlp)
   1473 {
   1474 	return (kiconv_unregister_module(modl->kiconv_moddef));
   1475 }
   1476