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