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