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