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