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