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