10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <sys/types.h> 300Sstevel@tonic-gate #include <sys/systm.h> 310Sstevel@tonic-gate #include <sys/param.h> 320Sstevel@tonic-gate #include <sys/user.h> 330Sstevel@tonic-gate #include <sys/vm.h> 340Sstevel@tonic-gate #include <sys/conf.h> 350Sstevel@tonic-gate #include <sys/class.h> 360Sstevel@tonic-gate #include <sys/vfs.h> 370Sstevel@tonic-gate #include <sys/mount.h> 380Sstevel@tonic-gate #include <sys/systm.h> 390Sstevel@tonic-gate #include <sys/modctl.h> 400Sstevel@tonic-gate #include <sys/exec.h> 410Sstevel@tonic-gate #include <sys/exechdr.h> 420Sstevel@tonic-gate #include <sys/devops.h> 430Sstevel@tonic-gate #include <sys/ddi.h> 440Sstevel@tonic-gate #include <sys/sunddi.h> 450Sstevel@tonic-gate #include <sys/cmn_err.h> 460Sstevel@tonic-gate #include <sys/hwconf.h> 470Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 480Sstevel@tonic-gate #include <sys/autoconf.h> 490Sstevel@tonic-gate #include <sys/disp.h> 500Sstevel@tonic-gate #include <sys/kmem.h> 510Sstevel@tonic-gate #include <sys/instance.h> 520Sstevel@tonic-gate #include <sys/modhash.h> 530Sstevel@tonic-gate #include <sys/dacf.h> 540Sstevel@tonic-gate #include <sys/debug.h> 550Sstevel@tonic-gate #include <ipp/ipp.h> 560Sstevel@tonic-gate #include <sys/strsubr.h> 570Sstevel@tonic-gate #include <sys/kcpc.h> 580Sstevel@tonic-gate #include <sys/cpc_pcbe.h> 590Sstevel@tonic-gate 600Sstevel@tonic-gate extern int moddebug; 610Sstevel@tonic-gate 620Sstevel@tonic-gate extern struct cb_ops no_cb_ops; 630Sstevel@tonic-gate extern struct dev_ops nodev_ops; 640Sstevel@tonic-gate extern struct dev_ops mod_nodev_ops; 650Sstevel@tonic-gate 660Sstevel@tonic-gate extern struct modctl *mod_getctl(struct modlinkage *); 670Sstevel@tonic-gate extern int errsys(), nodev(), nulldev(); 680Sstevel@tonic-gate 690Sstevel@tonic-gate extern int findmodbyname(char *); 700Sstevel@tonic-gate extern int mod_getsysnum(char *); 710Sstevel@tonic-gate 720Sstevel@tonic-gate extern struct execsw execsw[]; 730Sstevel@tonic-gate 740Sstevel@tonic-gate /* 750Sstevel@tonic-gate * Define dev_ops for unused devopsp entry. 760Sstevel@tonic-gate */ 770Sstevel@tonic-gate struct dev_ops mod_nodev_ops = { 780Sstevel@tonic-gate DEVO_REV, /* devo_rev */ 790Sstevel@tonic-gate 0, /* refcnt */ 800Sstevel@tonic-gate ddi_no_info, /* info */ 810Sstevel@tonic-gate nulldev, /* identify */ 820Sstevel@tonic-gate nulldev, /* probe */ 830Sstevel@tonic-gate ddifail, /* attach */ 840Sstevel@tonic-gate nodev, /* detach */ 850Sstevel@tonic-gate nulldev, /* reset */ 860Sstevel@tonic-gate &no_cb_ops, /* character/block driver operations */ 870Sstevel@tonic-gate (struct bus_ops *)0 /* bus operations for nexus drivers */ 880Sstevel@tonic-gate }; 890Sstevel@tonic-gate 900Sstevel@tonic-gate /* 910Sstevel@tonic-gate * Define mod_ops for each supported module type 920Sstevel@tonic-gate */ 930Sstevel@tonic-gate 940Sstevel@tonic-gate /* 950Sstevel@tonic-gate * Null operations; used for uninitialized and "misc" modules. 960Sstevel@tonic-gate */ 970Sstevel@tonic-gate static int mod_null(struct modldrv *, struct modlinkage *); 980Sstevel@tonic-gate static int mod_infonull(void *, struct modlinkage *, int *); 990Sstevel@tonic-gate 1000Sstevel@tonic-gate struct mod_ops mod_miscops = { 1010Sstevel@tonic-gate mod_null, mod_null, mod_infonull 1020Sstevel@tonic-gate }; 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate /* 1050Sstevel@tonic-gate * Cryptographic Modules 1060Sstevel@tonic-gate */ 1070Sstevel@tonic-gate struct mod_ops mod_cryptoops = { 1080Sstevel@tonic-gate mod_null, mod_null, mod_infonull 1090Sstevel@tonic-gate }; 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate /* 1120Sstevel@tonic-gate * IP Policy Modules 1130Sstevel@tonic-gate */ 1140Sstevel@tonic-gate static int mod_installipp(struct modlipp *, struct modlinkage *); 1150Sstevel@tonic-gate static int mod_removeipp(struct modlipp *, struct modlinkage *); 1160Sstevel@tonic-gate static int mod_infoipp(struct modlipp *, struct modlinkage *, int *); 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate struct mod_ops mod_ippops = { 1190Sstevel@tonic-gate mod_installipp, mod_removeipp, mod_infoipp 1200Sstevel@tonic-gate }; 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate /* 1230Sstevel@tonic-gate * Device drivers 1240Sstevel@tonic-gate */ 1250Sstevel@tonic-gate static int mod_infodrv(struct modldrv *, struct modlinkage *, int *); 1260Sstevel@tonic-gate static int mod_installdrv(struct modldrv *, struct modlinkage *); 1270Sstevel@tonic-gate static int mod_removedrv(struct modldrv *, struct modlinkage *); 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate struct mod_ops mod_driverops = { 1300Sstevel@tonic-gate mod_installdrv, mod_removedrv, mod_infodrv 1310Sstevel@tonic-gate }; 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate /* 1340Sstevel@tonic-gate * System calls (new interface) 1350Sstevel@tonic-gate */ 1360Sstevel@tonic-gate static int mod_infosys(struct modlsys *, struct modlinkage *, int *); 1370Sstevel@tonic-gate static int mod_installsys(struct modlsys *, struct modlinkage *); 1380Sstevel@tonic-gate static int mod_removesys(struct modlsys *, struct modlinkage *); 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate struct mod_ops mod_syscallops = { 1410Sstevel@tonic-gate mod_installsys, mod_removesys, mod_infosys 1420Sstevel@tonic-gate }; 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 1450Sstevel@tonic-gate /* 1460Sstevel@tonic-gate * 32-bit system calls in 64-bit kernel 1470Sstevel@tonic-gate */ 1480Sstevel@tonic-gate static int mod_infosys32(struct modlsys *, struct modlinkage *, int *); 1490Sstevel@tonic-gate static int mod_installsys32(struct modlsys *, struct modlinkage *); 1500Sstevel@tonic-gate static int mod_removesys32(struct modlsys *, struct modlinkage *); 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate struct mod_ops mod_syscallops32 = { 1530Sstevel@tonic-gate mod_installsys32, mod_removesys32, mod_infosys32 1540Sstevel@tonic-gate }; 1550Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate /* 1580Sstevel@tonic-gate * Filesystems 1590Sstevel@tonic-gate */ 1600Sstevel@tonic-gate static int mod_infofs(struct modlfs *, struct modlinkage *, int *); 1610Sstevel@tonic-gate static int mod_installfs(struct modlfs *, struct modlinkage *); 1620Sstevel@tonic-gate static int mod_removefs(struct modlfs *, struct modlinkage *); 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate struct mod_ops mod_fsops = { 1650Sstevel@tonic-gate mod_installfs, mod_removefs, mod_infofs 1660Sstevel@tonic-gate }; 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate /* 1690Sstevel@tonic-gate * Streams modules. 1700Sstevel@tonic-gate */ 1710Sstevel@tonic-gate static int mod_infostrmod(struct modlstrmod *, struct modlinkage *, int *); 1720Sstevel@tonic-gate static int mod_installstrmod(struct modlstrmod *, struct modlinkage *); 1730Sstevel@tonic-gate static int mod_removestrmod(struct modlstrmod *, struct modlinkage *); 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate struct mod_ops mod_strmodops = { 1760Sstevel@tonic-gate mod_installstrmod, mod_removestrmod, mod_infostrmod 1770Sstevel@tonic-gate }; 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate /* 1800Sstevel@tonic-gate * Scheduling classes. 1810Sstevel@tonic-gate */ 1820Sstevel@tonic-gate static int mod_infosched(struct modlsched *, struct modlinkage *, int *); 1830Sstevel@tonic-gate static int mod_installsched(struct modlsched *, struct modlinkage *); 1840Sstevel@tonic-gate static int mod_removesched(struct modlsched *, struct modlinkage *); 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate struct mod_ops mod_schedops = { 1870Sstevel@tonic-gate mod_installsched, mod_removesched, mod_infosched 1880Sstevel@tonic-gate }; 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate /* 1910Sstevel@tonic-gate * Exec file type (like ELF, ...). 1920Sstevel@tonic-gate */ 1930Sstevel@tonic-gate static int mod_infoexec(struct modlexec *, struct modlinkage *, int *); 1940Sstevel@tonic-gate static int mod_installexec(struct modlexec *, struct modlinkage *); 1950Sstevel@tonic-gate static int mod_removeexec(struct modlexec *, struct modlinkage *); 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate struct mod_ops mod_execops = { 1980Sstevel@tonic-gate mod_installexec, mod_removeexec, mod_infoexec 1990Sstevel@tonic-gate }; 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate /* 2020Sstevel@tonic-gate * Dacf (Dynamic Autoconfiguration) modules. 2030Sstevel@tonic-gate */ 2040Sstevel@tonic-gate static int mod_infodacf(struct modldacf *, struct modlinkage *, int *); 2050Sstevel@tonic-gate static int mod_installdacf(struct modldacf *, struct modlinkage *); 2060Sstevel@tonic-gate static int mod_removedacf(struct modldacf *, struct modlinkage *); 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate struct mod_ops mod_dacfops = { 2090Sstevel@tonic-gate mod_installdacf, mod_removedacf, mod_infodacf 2100Sstevel@tonic-gate }; 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate /* 2130Sstevel@tonic-gate * PCBE (Performance Counter BackEnd) modules. 2140Sstevel@tonic-gate */ 2150Sstevel@tonic-gate static int mod_installpcbe(struct modlpcbe *, struct modlinkage *); 2160Sstevel@tonic-gate static int mod_removepcbe(struct modlpcbe *, struct modlinkage *); 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate struct mod_ops mod_pcbeops = { 2190Sstevel@tonic-gate mod_installpcbe, mod_removepcbe, mod_infonull 2200Sstevel@tonic-gate }; 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate static struct sysent *mod_getsysent(struct modlinkage *, struct sysent *); 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate static char uninstall_err[] = "Cannot uninstall %s; not installed"; 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate /* 2270Sstevel@tonic-gate * Debugging support 2280Sstevel@tonic-gate */ 2290Sstevel@tonic-gate #define DRV_DBG MODDEBUG_LOADMSG2 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate /*PRINTFLIKE2*/ 2320Sstevel@tonic-gate static void mod_dprintf(int flag, const char *format, ...) __KPRINTFLIKE(2); 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate static void 2350Sstevel@tonic-gate mod_dprintf(int flag, const char *format, ...) 2360Sstevel@tonic-gate { 2370Sstevel@tonic-gate va_list alist; 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate if ((moddebug & flag) != 0) { 2400Sstevel@tonic-gate va_start(alist, format); 2410Sstevel@tonic-gate (void) vprintf(format, alist); 2420Sstevel@tonic-gate va_end(alist); 2430Sstevel@tonic-gate } 2440Sstevel@tonic-gate } 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate /* 2470Sstevel@tonic-gate * Install a module. 2480Sstevel@tonic-gate * (This routine is in the Solaris SPARC DDI/DKI) 2490Sstevel@tonic-gate */ 2500Sstevel@tonic-gate int 2510Sstevel@tonic-gate mod_install(struct modlinkage *modlp) 2520Sstevel@tonic-gate { 2530Sstevel@tonic-gate int retval = -1; /* No linkage structures */ 2540Sstevel@tonic-gate struct modlmisc **linkpp; 2550Sstevel@tonic-gate struct modlmisc **linkpp1; 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate if (modlp->ml_rev != MODREV_1) { 2580Sstevel@tonic-gate printf("mod_install: modlinkage structure is not MODREV_1\n"); 2590Sstevel@tonic-gate return (EINVAL); 2600Sstevel@tonic-gate } 2610Sstevel@tonic-gate linkpp = (struct modlmisc **)&modlp->ml_linkage[0]; 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate while (*linkpp != NULL) { 2640Sstevel@tonic-gate if ((retval = MODL_INSTALL(*linkpp, modlp)) != 0) { 2650Sstevel@tonic-gate linkpp1 = (struct modlmisc **)&modlp->ml_linkage[0]; 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate while (linkpp1 != linkpp) { 2680Sstevel@tonic-gate MODL_REMOVE(*linkpp1, modlp); /* clean up */ 2690Sstevel@tonic-gate linkpp1++; 2700Sstevel@tonic-gate } 2710Sstevel@tonic-gate break; 2720Sstevel@tonic-gate } 2730Sstevel@tonic-gate linkpp++; 2740Sstevel@tonic-gate } 2750Sstevel@tonic-gate return (retval); 2760Sstevel@tonic-gate } 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate static char *reins_err = 2790Sstevel@tonic-gate "Could not reinstall %s\nReboot to correct the problem"; 2800Sstevel@tonic-gate 2810Sstevel@tonic-gate /* 2820Sstevel@tonic-gate * Remove a module. This is called by the module wrapper routine. 2830Sstevel@tonic-gate * (This routine is in the Solaris SPARC DDI/DKI) 2840Sstevel@tonic-gate */ 2850Sstevel@tonic-gate int 2860Sstevel@tonic-gate mod_remove(struct modlinkage *modlp) 2870Sstevel@tonic-gate { 2880Sstevel@tonic-gate int retval = 0; 2890Sstevel@tonic-gate struct modlmisc **linkpp, *last_linkp; 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate linkpp = (struct modlmisc **)&modlp->ml_linkage[0]; 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate while (*linkpp != NULL) { 2940Sstevel@tonic-gate if ((retval = MODL_REMOVE(*linkpp, modlp)) != 0) { 2950Sstevel@tonic-gate last_linkp = *linkpp; 2960Sstevel@tonic-gate linkpp = (struct modlmisc **)&modlp->ml_linkage[0]; 2970Sstevel@tonic-gate while (*linkpp != last_linkp) { 2980Sstevel@tonic-gate if (MODL_INSTALL(*linkpp, modlp) != 0) { 2990Sstevel@tonic-gate cmn_err(CE_WARN, reins_err, 3000Sstevel@tonic-gate (*linkpp)->misc_linkinfo); 3010Sstevel@tonic-gate break; 3020Sstevel@tonic-gate } 3030Sstevel@tonic-gate linkpp++; 3040Sstevel@tonic-gate } 3050Sstevel@tonic-gate break; 3060Sstevel@tonic-gate } 3070Sstevel@tonic-gate linkpp++; 3080Sstevel@tonic-gate } 3090Sstevel@tonic-gate return (retval); 3100Sstevel@tonic-gate } 3110Sstevel@tonic-gate 3120Sstevel@tonic-gate /* 3130Sstevel@tonic-gate * Get module status. 3140Sstevel@tonic-gate * (This routine is in the Solaris SPARC DDI/DKI) 3150Sstevel@tonic-gate */ 3160Sstevel@tonic-gate int 3170Sstevel@tonic-gate mod_info(struct modlinkage *modlp, struct modinfo *modinfop) 3180Sstevel@tonic-gate { 3190Sstevel@tonic-gate int i; 3200Sstevel@tonic-gate int retval = 0; 3210Sstevel@tonic-gate struct modspecific_info *msip; 3220Sstevel@tonic-gate struct modlmisc **linkpp; 3230Sstevel@tonic-gate 3240Sstevel@tonic-gate modinfop->mi_rev = modlp->ml_rev; 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate linkpp = (struct modlmisc **)modlp->ml_linkage; 3270Sstevel@tonic-gate msip = &modinfop->mi_msinfo[0]; 3280Sstevel@tonic-gate 3290Sstevel@tonic-gate for (i = 0; i < MODMAXLINK; i++) { 3300Sstevel@tonic-gate if (*linkpp == NULL) { 3310Sstevel@tonic-gate msip->msi_linkinfo[0] = '\0'; 3320Sstevel@tonic-gate } else { 3330Sstevel@tonic-gate (void) strncpy(msip->msi_linkinfo, 3340Sstevel@tonic-gate (*linkpp)->misc_linkinfo, MODMAXLINKINFOLEN); 3350Sstevel@tonic-gate retval = MODL_INFO(*linkpp, modlp, &msip->msi_p0); 3360Sstevel@tonic-gate if (retval != 0) 3370Sstevel@tonic-gate break; 3380Sstevel@tonic-gate linkpp++; 3390Sstevel@tonic-gate } 3400Sstevel@tonic-gate msip++; 3410Sstevel@tonic-gate } 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate if (modinfop->mi_info == MI_INFO_LINKAGE) { 3440Sstevel@tonic-gate /* 3450Sstevel@tonic-gate * Slight kludge used to extract the address of the 3460Sstevel@tonic-gate * modlinkage structure from the module (just after 3470Sstevel@tonic-gate * loading a module for the very first time) 3480Sstevel@tonic-gate */ 3490Sstevel@tonic-gate modinfop->mi_base = (void *)modlp; 3500Sstevel@tonic-gate } 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate if (retval == 0) 3530Sstevel@tonic-gate return (1); 3540Sstevel@tonic-gate return (0); 3550Sstevel@tonic-gate } 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate /* 3580Sstevel@tonic-gate * Get module name. 3590Sstevel@tonic-gate */ 3600Sstevel@tonic-gate char * 3610Sstevel@tonic-gate mod_modname(struct modlinkage *modlp) 3620Sstevel@tonic-gate { 3630Sstevel@tonic-gate struct modctl *mcp; 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate if ((mcp = mod_getctl(modlp)) == NULL) 3660Sstevel@tonic-gate return (NULL); 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate return (mcp->mod_modname); 3690Sstevel@tonic-gate } 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate /* 3720Sstevel@tonic-gate * Null operation; return 0. 3730Sstevel@tonic-gate */ 3740Sstevel@tonic-gate /*ARGSUSED*/ 3750Sstevel@tonic-gate static int 3760Sstevel@tonic-gate mod_null(struct modldrv *modl, struct modlinkage *modlp) 3770Sstevel@tonic-gate { 3780Sstevel@tonic-gate return (0); 3790Sstevel@tonic-gate } 3800Sstevel@tonic-gate 3810Sstevel@tonic-gate /* 3820Sstevel@tonic-gate * Status for User modules. 3830Sstevel@tonic-gate */ 3840Sstevel@tonic-gate /*ARGSUSED*/ 3850Sstevel@tonic-gate static int 3860Sstevel@tonic-gate mod_infonull(void *modl, struct modlinkage *modlp, int *p0) 3870Sstevel@tonic-gate { 3880Sstevel@tonic-gate *p0 = -1; /* for modinfo display */ 3890Sstevel@tonic-gate return (0); 3900Sstevel@tonic-gate } 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate /* 3930Sstevel@tonic-gate * Driver status info 3940Sstevel@tonic-gate */ 3950Sstevel@tonic-gate /*ARGSUSED*/ 3960Sstevel@tonic-gate static int 3970Sstevel@tonic-gate mod_infodrv(struct modldrv *modl, struct modlinkage *modlp, int *p0) 3980Sstevel@tonic-gate { 3990Sstevel@tonic-gate struct modctl *mcp; 4000Sstevel@tonic-gate char *mod_name; 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate if ((mcp = mod_getctl(modlp)) == NULL) { 4030Sstevel@tonic-gate *p0 = -1; 4040Sstevel@tonic-gate return (0); /* driver is not yet installed */ 4050Sstevel@tonic-gate } 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate mod_name = mcp->mod_modname; 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate *p0 = ddi_name_to_major(mod_name); 4100Sstevel@tonic-gate return (0); 4110Sstevel@tonic-gate } 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate /* 4140Sstevel@tonic-gate * Manage dacf (device autoconfiguration) modules 4150Sstevel@tonic-gate */ 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate /*ARGSUSED*/ 4180Sstevel@tonic-gate static int 4190Sstevel@tonic-gate mod_infodacf(struct modldacf *modl, struct modlinkage *modlp, int *p0) 4200Sstevel@tonic-gate { 4210Sstevel@tonic-gate if (mod_getctl(modlp) == NULL) { 4220Sstevel@tonic-gate *p0 = -1; 4230Sstevel@tonic-gate return (0); /* module is not yet installed */ 4240Sstevel@tonic-gate } 4250Sstevel@tonic-gate 4260Sstevel@tonic-gate *p0 = 0; 4270Sstevel@tonic-gate return (0); 4280Sstevel@tonic-gate } 4290Sstevel@tonic-gate 4300Sstevel@tonic-gate static int 4310Sstevel@tonic-gate mod_installdacf(struct modldacf *modl, struct modlinkage *modlp) 4320Sstevel@tonic-gate { 4330Sstevel@tonic-gate struct modctl *mcp; 4340Sstevel@tonic-gate 4350Sstevel@tonic-gate if ((mcp = mod_getctl(modlp)) == NULL) 4360Sstevel@tonic-gate return (EINVAL); 4370Sstevel@tonic-gate return (dacf_module_register(mcp->mod_modname, modl->dacf_dacfsw)); 4380Sstevel@tonic-gate } 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate /*ARGSUSED*/ 4410Sstevel@tonic-gate static int 4420Sstevel@tonic-gate mod_removedacf(struct modldacf *modl, struct modlinkage *modlp) 4430Sstevel@tonic-gate { 4440Sstevel@tonic-gate struct modctl *mcp; 4450Sstevel@tonic-gate 4460Sstevel@tonic-gate if ((mcp = mod_getctl(modlp)) == NULL) 4470Sstevel@tonic-gate return (EINVAL); 4480Sstevel@tonic-gate return (dacf_module_unregister(mcp->mod_modname)); 4490Sstevel@tonic-gate } 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate /* 4520Sstevel@tonic-gate * Manage PCBE (Performance Counter BackEnd) modules. 4530Sstevel@tonic-gate */ 4540Sstevel@tonic-gate /*ARGSUSED*/ 4550Sstevel@tonic-gate static int 4560Sstevel@tonic-gate mod_installpcbe(struct modlpcbe *modl, struct modlinkage *modlp) 4570Sstevel@tonic-gate { 4580Sstevel@tonic-gate if (modl->pcbe_ops->pcbe_ver != PCBE_VER_1) { 4590Sstevel@tonic-gate cmn_err(CE_WARN, "pcbe '%s' version mismatch", 4600Sstevel@tonic-gate modl->pcbe_linkinfo); 4610Sstevel@tonic-gate return (EINVAL); 4620Sstevel@tonic-gate } 4630Sstevel@tonic-gate 4640Sstevel@tonic-gate kcpc_register_pcbe(modl->pcbe_ops); 4650Sstevel@tonic-gate return (0); 4660Sstevel@tonic-gate } 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate /* 4690Sstevel@tonic-gate * PCBEs may not be unloaded. It would make CPC locking too complex, and since 4700Sstevel@tonic-gate * PCBEs are loaded once and used for life, there is no harm done in leaving 4710Sstevel@tonic-gate * them in the system. 4720Sstevel@tonic-gate */ 4730Sstevel@tonic-gate /*ARGSUSED*/ 4740Sstevel@tonic-gate static int 4750Sstevel@tonic-gate mod_removepcbe(struct modlpcbe *modl, struct modlinkage *modlp) 4760Sstevel@tonic-gate { 4770Sstevel@tonic-gate return (EBUSY); 4780Sstevel@tonic-gate } 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate /* 4820Sstevel@tonic-gate * Install a new driver 4830Sstevel@tonic-gate */ 4840Sstevel@tonic-gate static int 4850Sstevel@tonic-gate mod_installdrv(struct modldrv *modl, struct modlinkage *modlp) 4860Sstevel@tonic-gate { 4870Sstevel@tonic-gate struct modctl *mcp; 4880Sstevel@tonic-gate struct dev_ops *ops; 4890Sstevel@tonic-gate char *modname; 4900Sstevel@tonic-gate major_t major; 4910Sstevel@tonic-gate struct dev_ops *dp; 4920Sstevel@tonic-gate struct devnames *dnp; 4930Sstevel@tonic-gate struct streamtab *str; 4940Sstevel@tonic-gate cdevsw_impl_t *cdp; 4950Sstevel@tonic-gate uint_t sqtype; 4960Sstevel@tonic-gate uint_t qflag; 4970Sstevel@tonic-gate uint_t flag; 4980Sstevel@tonic-gate int err = 0; 4990Sstevel@tonic-gate 5000Sstevel@tonic-gate /* sanity check module */ 5010Sstevel@tonic-gate if ((mcp = mod_getctl(modlp)) == NULL) { 5020Sstevel@tonic-gate cmn_err(CE_WARN, "mod_install: bad module linkage data"); 5030Sstevel@tonic-gate err = ENXIO; 5040Sstevel@tonic-gate goto done; 5050Sstevel@tonic-gate } 5060Sstevel@tonic-gate modname = mcp->mod_modname; 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate /* Sanity check modname */ 5090Sstevel@tonic-gate if ((major = ddi_name_to_major(modname)) == (major_t)-1) { 5100Sstevel@tonic-gate #ifdef DEBUG 5110Sstevel@tonic-gate cmn_err(CE_WARN, 5120Sstevel@tonic-gate "mod_installdrv: no major number for %s", modname); 5130Sstevel@tonic-gate #endif 5140Sstevel@tonic-gate err = ENXIO; 5150Sstevel@tonic-gate goto done; 5160Sstevel@tonic-gate } 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate /* Verify MP safety flag */ 5190Sstevel@tonic-gate ops = modl->drv_dev_ops; 5200Sstevel@tonic-gate if (ops->devo_bus_ops == NULL && ops->devo_cb_ops != NULL && 5210Sstevel@tonic-gate !(ops->devo_cb_ops->cb_flag & D_MP)) { 5220Sstevel@tonic-gate cmn_err(CE_WARN, 5230Sstevel@tonic-gate "mod_installdrv: MT-unsafe driver '%s' rejected", modname); 5240Sstevel@tonic-gate err = ENXIO; 5250Sstevel@tonic-gate goto done; 5260Sstevel@tonic-gate } 5270Sstevel@tonic-gate 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate /* Is bus_map_fault signature correct (version 8 and higher)? */ 5300Sstevel@tonic-gate if (ops->devo_bus_ops != NULL && 5310Sstevel@tonic-gate ops->devo_bus_ops->bus_map_fault != NULL && 5320Sstevel@tonic-gate ops->devo_bus_ops->bus_map_fault != i_ddi_map_fault && 5330Sstevel@tonic-gate ops->devo_bus_ops->busops_rev < BUSO_REV_8) { 5340Sstevel@tonic-gate 5350Sstevel@tonic-gate cmn_err(CE_WARN, 5360Sstevel@tonic-gate "mod_installdrv: busops' revision of '%s' is too low" 5370Sstevel@tonic-gate " (must be at least 8)", modname); 5380Sstevel@tonic-gate err = ENXIO; 5390Sstevel@tonic-gate goto done; 5400Sstevel@tonic-gate } 5410Sstevel@tonic-gate 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate /* Make sure the driver is uninstalled */ 5440Sstevel@tonic-gate dnp = &devnamesp[major]; 5450Sstevel@tonic-gate LOCK_DEV_OPS(&dnp->dn_lock); 5460Sstevel@tonic-gate dp = devopsp[major]; 5470Sstevel@tonic-gate 5480Sstevel@tonic-gate if (dnp->dn_flags & DN_DRIVER_REMOVED) { 5490Sstevel@tonic-gate #ifdef DEBUG 5500Sstevel@tonic-gate cmn_err(CE_NOTE, 5510Sstevel@tonic-gate "mod_installdrv: driver has been removed %s", modname); 5520Sstevel@tonic-gate #endif 5530Sstevel@tonic-gate err = ENXIO; 5540Sstevel@tonic-gate goto unlock; 5550Sstevel@tonic-gate } 5560Sstevel@tonic-gate 5570Sstevel@tonic-gate if (dp != &nodev_ops && dp != &mod_nodev_ops) { 5580Sstevel@tonic-gate cmn_err(CE_WARN, 5590Sstevel@tonic-gate "mod_installdrv: driver already installed %s", modname); 5600Sstevel@tonic-gate err = EALREADY; 5610Sstevel@tonic-gate goto unlock; 5620Sstevel@tonic-gate } 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate devopsp[major] = ops; /* setup devopsp */ 5650Sstevel@tonic-gate 5660Sstevel@tonic-gate if ((str = STREAMSTAB(major)) != NULL) { /* streams driver */ 5670Sstevel@tonic-gate flag = CBFLAG(major); 5680Sstevel@tonic-gate if ((err = devflg_to_qflag(str, flag, &qflag, &sqtype)) != 0) 5690Sstevel@tonic-gate goto unlock; 5700Sstevel@tonic-gate cdp = &devimpl[major]; 5710Sstevel@tonic-gate ASSERT(cdp->d_str == NULL); 5720Sstevel@tonic-gate cdp->d_str = str; 5730Sstevel@tonic-gate cdp->d_qflag = qflag | QISDRV; 5740Sstevel@tonic-gate cdp->d_sqtype = sqtype; 5750Sstevel@tonic-gate } 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate if (ops->devo_bus_ops == NULL) 5780Sstevel@tonic-gate dnp->dn_flags |= DN_LEAF_DRIVER; 5790Sstevel@tonic-gate 5800Sstevel@tonic-gate unlock: 5810Sstevel@tonic-gate UNLOCK_DEV_OPS(&dnp->dn_lock); 5820Sstevel@tonic-gate done: 5830Sstevel@tonic-gate return (err); 5840Sstevel@tonic-gate } 5850Sstevel@tonic-gate 5860Sstevel@tonic-gate static int 5870Sstevel@tonic-gate mod_removedrv(struct modldrv *modl, struct modlinkage *modlp) 5880Sstevel@tonic-gate { 5890Sstevel@tonic-gate struct modctl *mcp; 5900Sstevel@tonic-gate struct dev_ops *ops; 5910Sstevel@tonic-gate struct devnames *dnp; 5920Sstevel@tonic-gate struct dev_ops *dp; 5930Sstevel@tonic-gate major_t major; 5940Sstevel@tonic-gate char *modname; 5950Sstevel@tonic-gate extern kthread_id_t mod_aul_thread; 5960Sstevel@tonic-gate struct streamtab *str; 5970Sstevel@tonic-gate cdevsw_impl_t *cdp; 5980Sstevel@tonic-gate int err = 0; 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate /* Don't auto unload modules on if moddebug flag is set */ 6010Sstevel@tonic-gate if ((moddebug & MODDEBUG_NOAUL_DRV) && (mod_aul_thread == curthread)) { 6020Sstevel@tonic-gate err = EBUSY; 6030Sstevel@tonic-gate goto done; 6040Sstevel@tonic-gate } 6050Sstevel@tonic-gate 6060Sstevel@tonic-gate /* Verify modname has a driver major */ 6070Sstevel@tonic-gate mcp = mod_getctl(modlp); 6080Sstevel@tonic-gate ASSERT(mcp != NULL); 6090Sstevel@tonic-gate modname = mcp->mod_modname; 6100Sstevel@tonic-gate 6110Sstevel@tonic-gate if ((major = ddi_name_to_major(modname)) == -1) { 6120Sstevel@tonic-gate cmn_err(CE_WARN, uninstall_err, modname); 6130Sstevel@tonic-gate err = EINVAL; 6140Sstevel@tonic-gate goto done; 6150Sstevel@tonic-gate } 6160Sstevel@tonic-gate 6170Sstevel@tonic-gate ops = modl->drv_dev_ops; 6180Sstevel@tonic-gate dnp = &(devnamesp[major]); 6190Sstevel@tonic-gate LOCK_DEV_OPS(&(dnp->dn_lock)); 6200Sstevel@tonic-gate 6210Sstevel@tonic-gate dp = devopsp[major]; 6220Sstevel@tonic-gate 6230Sstevel@tonic-gate if (dp != ops) { 6240Sstevel@tonic-gate cmn_err(CE_NOTE, "mod_removedrv: mismatched driver for %s", 6250Sstevel@tonic-gate modname); 6260Sstevel@tonic-gate err = EBUSY; 6270Sstevel@tonic-gate goto unlock; 6280Sstevel@tonic-gate } 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate /* 6310Sstevel@tonic-gate * A driver is not unloadable if its dev_ops are held 6320Sstevel@tonic-gate */ 6330Sstevel@tonic-gate if (!DRV_UNLOADABLE(dp)) { 6340Sstevel@tonic-gate mod_dprintf(DRV_DBG, "Cannot unload device driver <%s>," 6350Sstevel@tonic-gate " refcnt %d\n", modname, dp->devo_refcnt); 6360Sstevel@tonic-gate err = EBUSY; 6370Sstevel@tonic-gate goto unlock; 6380Sstevel@tonic-gate } 6390Sstevel@tonic-gate 6400Sstevel@tonic-gate /* 6410Sstevel@tonic-gate * OK to unload. 6420Sstevel@tonic-gate */ 6430Sstevel@tonic-gate if ((str = STREAMSTAB(major)) != NULL) { /* streams driver */ 6440Sstevel@tonic-gate cdp = &devimpl[major]; 6450Sstevel@tonic-gate ASSERT(cdp->d_str == str); 6460Sstevel@tonic-gate cdp->d_str = NULL; 6470Sstevel@tonic-gate 6480Sstevel@tonic-gate /* check for reference to per-dev syncq */ 6490Sstevel@tonic-gate if (cdp->d_dmp != NULL) { 6500Sstevel@tonic-gate rele_dm(cdp->d_dmp); 6510Sstevel@tonic-gate cdp->d_dmp = NULL; 6520Sstevel@tonic-gate } 6530Sstevel@tonic-gate } 6540Sstevel@tonic-gate 6550Sstevel@tonic-gate devopsp[major] = &mod_nodev_ops; 6560Sstevel@tonic-gate dnp->dn_flags &= ~(DN_DRIVER_HELD|DN_NO_AUTODETACH); 6570Sstevel@tonic-gate 6580Sstevel@tonic-gate unlock: 6590Sstevel@tonic-gate UNLOCK_DEV_OPS(&(dnp->dn_lock)); 6600Sstevel@tonic-gate done: 6610Sstevel@tonic-gate return (err); 6620Sstevel@tonic-gate } 6630Sstevel@tonic-gate 6640Sstevel@tonic-gate /* 6650Sstevel@tonic-gate * System call subroutines 6660Sstevel@tonic-gate */ 6670Sstevel@tonic-gate 6680Sstevel@tonic-gate /* 6690Sstevel@tonic-gate * Compute system call number for given sysent and sysent table 6700Sstevel@tonic-gate */ 6710Sstevel@tonic-gate static int 6720Sstevel@tonic-gate mod_infosysnum(struct modlinkage *modlp, struct sysent table[]) 6730Sstevel@tonic-gate { 6740Sstevel@tonic-gate struct sysent *sysp; 6750Sstevel@tonic-gate 6760Sstevel@tonic-gate if ((sysp = mod_getsysent(modlp, table)) == NULL) 6770Sstevel@tonic-gate return (-1); 6780Sstevel@tonic-gate return ((int)(sysp - table)); 6790Sstevel@tonic-gate } 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate /* 6820Sstevel@tonic-gate * Put a loadable system call entry into a sysent table. 6830Sstevel@tonic-gate */ 6840Sstevel@tonic-gate static int 6850Sstevel@tonic-gate mod_installsys_sysent( 6860Sstevel@tonic-gate struct modlsys *modl, 6870Sstevel@tonic-gate struct modlinkage *modlp, 6880Sstevel@tonic-gate struct sysent table[]) 6890Sstevel@tonic-gate { 6900Sstevel@tonic-gate struct sysent *sysp; 6910Sstevel@tonic-gate struct sysent *mp; 6920Sstevel@tonic-gate 6930Sstevel@tonic-gate #ifdef DEBUG 6940Sstevel@tonic-gate /* 6950Sstevel@tonic-gate * Before we even play with the sysent table, sanity check the 6960Sstevel@tonic-gate * incoming flags to make sure the entry is valid 6970Sstevel@tonic-gate */ 6980Sstevel@tonic-gate switch (modl->sys_sysent->sy_flags & SE_RVAL_MASK) { 6990Sstevel@tonic-gate case SE_32RVAL1: 7000Sstevel@tonic-gate /* only r_val1 returned */ 7010Sstevel@tonic-gate case SE_32RVAL1 | SE_32RVAL2: 7020Sstevel@tonic-gate /* r_val1 and r_val2 returned */ 7030Sstevel@tonic-gate case SE_64RVAL: 7040Sstevel@tonic-gate /* 64-bit rval returned */ 7050Sstevel@tonic-gate break; 7060Sstevel@tonic-gate default: 7070Sstevel@tonic-gate cmn_err(CE_WARN, "loadable syscall: %p: bad rval flags %x", 7080Sstevel@tonic-gate (void *)modl, modl->sys_sysent->sy_flags); 7090Sstevel@tonic-gate return (ENOSYS); 7100Sstevel@tonic-gate } 7110Sstevel@tonic-gate #endif 7120Sstevel@tonic-gate if ((sysp = mod_getsysent(modlp, table)) == NULL) 7130Sstevel@tonic-gate return (ENOSPC); 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate /* 7160Sstevel@tonic-gate * We should only block here until the reader in syscall gives 7170Sstevel@tonic-gate * up the lock. Multiple writers are prevented in the mod layer. 7180Sstevel@tonic-gate */ 7190Sstevel@tonic-gate rw_enter(sysp->sy_lock, RW_WRITER); 7200Sstevel@tonic-gate mp = modl->sys_sysent; 7210Sstevel@tonic-gate sysp->sy_narg = mp->sy_narg; 7220Sstevel@tonic-gate sysp->sy_call = mp->sy_call; 7230Sstevel@tonic-gate 7240Sstevel@tonic-gate /* 7250Sstevel@tonic-gate * clear the old call method flag, and get the new one from the module. 7260Sstevel@tonic-gate */ 7270Sstevel@tonic-gate sysp->sy_flags &= ~SE_ARGC; 7280Sstevel@tonic-gate sysp->sy_flags |= SE_LOADED | 7290Sstevel@tonic-gate (mp->sy_flags & (SE_ARGC | SE_NOUNLOAD | SE_RVAL_MASK)); 7300Sstevel@tonic-gate 7310Sstevel@tonic-gate /* 7320Sstevel@tonic-gate * If the syscall doesn't need or want unloading, it can avoid 7330Sstevel@tonic-gate * the locking overhead on each entry. Convert the sysent to a 7340Sstevel@tonic-gate * normal non-loadable entry in that case. 7350Sstevel@tonic-gate */ 7360Sstevel@tonic-gate if (mp->sy_flags & SE_NOUNLOAD) { 7370Sstevel@tonic-gate if (mp->sy_flags & SE_ARGC) { 7380Sstevel@tonic-gate sysp->sy_callc = (int64_t (*)())mp->sy_call; 7390Sstevel@tonic-gate } else { 7400Sstevel@tonic-gate sysp->sy_callc = syscall_ap; 7410Sstevel@tonic-gate } 7420Sstevel@tonic-gate sysp->sy_flags &= ~SE_LOADABLE; 7430Sstevel@tonic-gate } 7440Sstevel@tonic-gate rw_exit(sysp->sy_lock); 7450Sstevel@tonic-gate return (0); 7460Sstevel@tonic-gate } 7470Sstevel@tonic-gate 7480Sstevel@tonic-gate /* 7490Sstevel@tonic-gate * Remove a loadable system call entry from a sysent table. 7500Sstevel@tonic-gate */ 7510Sstevel@tonic-gate static int 7520Sstevel@tonic-gate mod_removesys_sysent( 7530Sstevel@tonic-gate struct modlsys *modl, 7540Sstevel@tonic-gate struct modlinkage *modlp, 7550Sstevel@tonic-gate struct sysent table[]) 7560Sstevel@tonic-gate { 7570Sstevel@tonic-gate struct sysent *sysp; 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate if ((sysp = mod_getsysent(modlp, table)) == NULL || 7600Sstevel@tonic-gate (sysp->sy_flags & (SE_LOADABLE | SE_NOUNLOAD)) == 0 || 7610Sstevel@tonic-gate sysp->sy_call != modl->sys_sysent->sy_call) { 7620Sstevel@tonic-gate 7630Sstevel@tonic-gate struct modctl *mcp = mod_getctl(modlp); 7640Sstevel@tonic-gate char *modname = mcp->mod_modname; 7650Sstevel@tonic-gate 7660Sstevel@tonic-gate cmn_err(CE_WARN, uninstall_err, modname); 7670Sstevel@tonic-gate return (EINVAL); 7680Sstevel@tonic-gate } 7690Sstevel@tonic-gate 7700Sstevel@tonic-gate /* If we can't get the write lock, we can't unlink from the system */ 7710Sstevel@tonic-gate 7720Sstevel@tonic-gate if (!(moddebug & MODDEBUG_NOAUL_SYS) && 7730Sstevel@tonic-gate rw_tryenter(sysp->sy_lock, RW_WRITER)) { 7740Sstevel@tonic-gate /* 7750Sstevel@tonic-gate * Check the flags to be sure the syscall is still 7760Sstevel@tonic-gate * (un)loadable. 7770Sstevel@tonic-gate * If SE_NOUNLOAD is set, SE_LOADABLE will not be. 7780Sstevel@tonic-gate */ 7790Sstevel@tonic-gate if ((sysp->sy_flags & (SE_LOADED | SE_LOADABLE)) == 7800Sstevel@tonic-gate (SE_LOADED | SE_LOADABLE)) { 7810Sstevel@tonic-gate sysp->sy_flags &= ~SE_LOADED; 7820Sstevel@tonic-gate sysp->sy_callc = loadable_syscall; 7830Sstevel@tonic-gate sysp->sy_call = (int (*)())nosys; 7840Sstevel@tonic-gate rw_exit(sysp->sy_lock); 7850Sstevel@tonic-gate return (0); 7860Sstevel@tonic-gate } 7870Sstevel@tonic-gate rw_exit(sysp->sy_lock); 7880Sstevel@tonic-gate } 7890Sstevel@tonic-gate return (EBUSY); 7900Sstevel@tonic-gate } 7910Sstevel@tonic-gate 7920Sstevel@tonic-gate /* 7930Sstevel@tonic-gate * System call status info 7940Sstevel@tonic-gate */ 7950Sstevel@tonic-gate /*ARGSUSED*/ 7960Sstevel@tonic-gate static int 7970Sstevel@tonic-gate mod_infosys(struct modlsys *modl, struct modlinkage *modlp, int *p0) 7980Sstevel@tonic-gate { 7990Sstevel@tonic-gate *p0 = mod_infosysnum(modlp, sysent); 8000Sstevel@tonic-gate return (0); 8010Sstevel@tonic-gate } 8020Sstevel@tonic-gate 8030Sstevel@tonic-gate /* 8040Sstevel@tonic-gate * Link a system call into the system by setting the proper sysent entry. 8050Sstevel@tonic-gate * Called from the module's _init routine. 8060Sstevel@tonic-gate */ 8070Sstevel@tonic-gate static int 8080Sstevel@tonic-gate mod_installsys(struct modlsys *modl, struct modlinkage *modlp) 8090Sstevel@tonic-gate { 8100Sstevel@tonic-gate return (mod_installsys_sysent(modl, modlp, sysent)); 8110Sstevel@tonic-gate } 8120Sstevel@tonic-gate 8130Sstevel@tonic-gate /* 8140Sstevel@tonic-gate * Unlink a system call from the system. 8150Sstevel@tonic-gate * Called from a modules _fini routine. 8160Sstevel@tonic-gate */ 8170Sstevel@tonic-gate static int 8180Sstevel@tonic-gate mod_removesys(struct modlsys *modl, struct modlinkage *modlp) 8190Sstevel@tonic-gate { 8200Sstevel@tonic-gate return (mod_removesys_sysent(modl, modlp, sysent)); 8210Sstevel@tonic-gate } 8220Sstevel@tonic-gate 8230Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 8240Sstevel@tonic-gate 8250Sstevel@tonic-gate /* 8260Sstevel@tonic-gate * 32-bit system call status info 8270Sstevel@tonic-gate */ 8280Sstevel@tonic-gate /*ARGSUSED*/ 8290Sstevel@tonic-gate static int 8300Sstevel@tonic-gate mod_infosys32(struct modlsys *modl, struct modlinkage *modlp, int *p0) 8310Sstevel@tonic-gate { 8320Sstevel@tonic-gate *p0 = mod_infosysnum(modlp, sysent32); 8330Sstevel@tonic-gate return (0); 8340Sstevel@tonic-gate } 8350Sstevel@tonic-gate 8360Sstevel@tonic-gate /* 8370Sstevel@tonic-gate * Link the 32-bit syscall into the system by setting the proper sysent entry. 8380Sstevel@tonic-gate * Also called from the module's _init routine. 8390Sstevel@tonic-gate */ 8400Sstevel@tonic-gate static int 8410Sstevel@tonic-gate mod_installsys32(struct modlsys *modl, struct modlinkage *modlp) 8420Sstevel@tonic-gate { 8430Sstevel@tonic-gate return (mod_installsys_sysent(modl, modlp, sysent32)); 8440Sstevel@tonic-gate } 8450Sstevel@tonic-gate 8460Sstevel@tonic-gate /* 8470Sstevel@tonic-gate * Unlink the 32-bit flavor of a system call from the system. 8480Sstevel@tonic-gate * Also called from a module's _fini routine. 8490Sstevel@tonic-gate */ 8500Sstevel@tonic-gate static int 8510Sstevel@tonic-gate mod_removesys32(struct modlsys *modl, struct modlinkage *modlp) 8520Sstevel@tonic-gate { 8530Sstevel@tonic-gate return (mod_removesys_sysent(modl, modlp, sysent32)); 8540Sstevel@tonic-gate } 8550Sstevel@tonic-gate 8560Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 8570Sstevel@tonic-gate 8580Sstevel@tonic-gate /* 8590Sstevel@tonic-gate * Filesystem status info 8600Sstevel@tonic-gate */ 8610Sstevel@tonic-gate /*ARGSUSED*/ 8620Sstevel@tonic-gate static int 8630Sstevel@tonic-gate mod_infofs(struct modlfs *modl, struct modlinkage *modlp, int *p0) 8640Sstevel@tonic-gate { 8650Sstevel@tonic-gate struct vfssw *vswp; 8660Sstevel@tonic-gate 8670Sstevel@tonic-gate RLOCK_VFSSW(); 8680Sstevel@tonic-gate if ((vswp = vfs_getvfsswbyname(modl->fs_vfsdef->name)) == NULL) 8690Sstevel@tonic-gate *p0 = -1; 8700Sstevel@tonic-gate else { 8710Sstevel@tonic-gate *p0 = vswp - vfssw; 8720Sstevel@tonic-gate vfs_unrefvfssw(vswp); 8730Sstevel@tonic-gate } 8740Sstevel@tonic-gate RUNLOCK_VFSSW(); 8750Sstevel@tonic-gate return (0); 8760Sstevel@tonic-gate } 8770Sstevel@tonic-gate 8780Sstevel@tonic-gate /* 8790Sstevel@tonic-gate * Install a filesystem. 8800Sstevel@tonic-gate */ 8810Sstevel@tonic-gate /*ARGSUSED1*/ 8820Sstevel@tonic-gate static int 8830Sstevel@tonic-gate mod_installfs(struct modlfs *modl, struct modlinkage *modlp) 8840Sstevel@tonic-gate { 8850Sstevel@tonic-gate struct vfssw *vswp; 8860Sstevel@tonic-gate struct modctl *mcp; 8870Sstevel@tonic-gate char *fsname; 8880Sstevel@tonic-gate int allocated; 8890Sstevel@tonic-gate int err; 8900Sstevel@tonic-gate 8910Sstevel@tonic-gate if (modl->fs_vfsdef->def_version == VFSDEF_VERSION) { 8920Sstevel@tonic-gate /* Version matched */ 8930Sstevel@tonic-gate fsname = modl->fs_vfsdef->name; 8940Sstevel@tonic-gate } else { 8950Sstevel@tonic-gate if ((modl->fs_vfsdef->def_version > 0) && 8960Sstevel@tonic-gate (modl->fs_vfsdef->def_version < VFSDEF_VERSION)) { 8970Sstevel@tonic-gate /* Older VFSDEF_VERSION */ 8980Sstevel@tonic-gate fsname = modl->fs_vfsdef->name; 8990Sstevel@tonic-gate } else if ((mcp = mod_getctl(modlp)) != NULL) { 9000Sstevel@tonic-gate /* Pre-VFSDEF_VERSION */ 9010Sstevel@tonic-gate fsname = mcp->mod_modname; 9020Sstevel@tonic-gate } else { 9030Sstevel@tonic-gate /* If all else fails... */ 9040Sstevel@tonic-gate fsname = "<unknown file system type>"; 9050Sstevel@tonic-gate } 9060Sstevel@tonic-gate 9070Sstevel@tonic-gate cmn_err(CE_WARN, "file system '%s' version mismatch", fsname); 9080Sstevel@tonic-gate return (ENXIO); 9090Sstevel@tonic-gate } 9100Sstevel@tonic-gate 9110Sstevel@tonic-gate allocated = 0; 9120Sstevel@tonic-gate 9130Sstevel@tonic-gate WLOCK_VFSSW(); 9140Sstevel@tonic-gate if ((vswp = vfs_getvfsswbyname(fsname)) == NULL) { 9150Sstevel@tonic-gate if ((vswp = allocate_vfssw(fsname)) == NULL) { 9160Sstevel@tonic-gate WUNLOCK_VFSSW(); 9170Sstevel@tonic-gate /* 9180Sstevel@tonic-gate * See 1095689. If this message appears, then 9190Sstevel@tonic-gate * we either need to make the vfssw table bigger 9200Sstevel@tonic-gate * statically, or make it grow dynamically. 9210Sstevel@tonic-gate */ 9220Sstevel@tonic-gate cmn_err(CE_WARN, "no room for '%s' in vfssw!", fsname); 9230Sstevel@tonic-gate return (ENXIO); 9240Sstevel@tonic-gate } 9250Sstevel@tonic-gate allocated = 1; 9260Sstevel@tonic-gate } 9270Sstevel@tonic-gate ASSERT(vswp != NULL); 9280Sstevel@tonic-gate 9290Sstevel@tonic-gate vswp->vsw_flag = modl->fs_vfsdef->flags; 9300Sstevel@tonic-gate if (modl->fs_vfsdef->flags & VSW_HASPROTO) { 9310Sstevel@tonic-gate vfs_mergeopttbl(&vfs_mntopts, modl->fs_vfsdef->optproto, 9320Sstevel@tonic-gate &vswp->vsw_optproto); 9330Sstevel@tonic-gate } else { 9340Sstevel@tonic-gate vfs_copyopttbl(&vfs_mntopts, &vswp->vsw_optproto); 9350Sstevel@tonic-gate } 9360Sstevel@tonic-gate 9370Sstevel@tonic-gate if (modl->fs_vfsdef->flags & VSW_CANRWRO) { 9380Sstevel@tonic-gate /* 9390Sstevel@tonic-gate * This obviously implies VSW_CANREMOUNT. 9400Sstevel@tonic-gate */ 9410Sstevel@tonic-gate vswp->vsw_flag |= VSW_CANREMOUNT; 9420Sstevel@tonic-gate } 9430Sstevel@tonic-gate if (modl->fs_vfsdef->init == NULL) 9440Sstevel@tonic-gate err = EFAULT; 9450Sstevel@tonic-gate else 9460Sstevel@tonic-gate err = (*(modl->fs_vfsdef->init))(vswp - vfssw, fsname); 9470Sstevel@tonic-gate 9480Sstevel@tonic-gate if (err != 0) { 9490Sstevel@tonic-gate if (allocated) { 9500Sstevel@tonic-gate kmem_free(vswp->vsw_name, strlen(vswp->vsw_name)+1); 9510Sstevel@tonic-gate vswp->vsw_name = ""; 9520Sstevel@tonic-gate } 9530Sstevel@tonic-gate vswp->vsw_flag = 0; 9540Sstevel@tonic-gate vswp->vsw_init = NULL; 9550Sstevel@tonic-gate } 9560Sstevel@tonic-gate 9570Sstevel@tonic-gate vfs_unrefvfssw(vswp); 9580Sstevel@tonic-gate WUNLOCK_VFSSW(); 9590Sstevel@tonic-gate 9600Sstevel@tonic-gate return (err); 9610Sstevel@tonic-gate } 9620Sstevel@tonic-gate 9630Sstevel@tonic-gate /* 9640Sstevel@tonic-gate * Remove a filesystem 9650Sstevel@tonic-gate */ 9660Sstevel@tonic-gate static int 9670Sstevel@tonic-gate mod_removefs(struct modlfs *modl, struct modlinkage *modlp) 9680Sstevel@tonic-gate { 9690Sstevel@tonic-gate struct vfssw *vswp; 9700Sstevel@tonic-gate struct modctl *mcp; 9710Sstevel@tonic-gate char *modname; 9720Sstevel@tonic-gate 9730Sstevel@tonic-gate if (moddebug & MODDEBUG_NOAUL_FS) 9740Sstevel@tonic-gate return (EBUSY); 9750Sstevel@tonic-gate 9760Sstevel@tonic-gate WLOCK_VFSSW(); 9770Sstevel@tonic-gate if ((vswp = vfs_getvfsswbyname(modl->fs_vfsdef->name)) == NULL) { 9780Sstevel@tonic-gate mcp = mod_getctl(modlp); 9790Sstevel@tonic-gate ASSERT(mcp != NULL); 9800Sstevel@tonic-gate modname = mcp->mod_modname; 9810Sstevel@tonic-gate WUNLOCK_VFSSW(); 9820Sstevel@tonic-gate cmn_err(CE_WARN, uninstall_err, modname); 9830Sstevel@tonic-gate return (EINVAL); 9840Sstevel@tonic-gate } 9850Sstevel@tonic-gate if (vswp->vsw_count != 1) { 9860Sstevel@tonic-gate vfs_unrefvfssw(vswp); 9870Sstevel@tonic-gate WUNLOCK_VFSSW(); 9880Sstevel@tonic-gate return (EBUSY); 9890Sstevel@tonic-gate } 9900Sstevel@tonic-gate 9910Sstevel@tonic-gate /* XXX - Shouldn't the refcount be sufficient? */ 9920Sstevel@tonic-gate 9930Sstevel@tonic-gate if (vfs_opsinuse(&vswp->vsw_vfsops)) { 994*1403Ssp92102 vfs_unrefvfssw(vswp); 9950Sstevel@tonic-gate WUNLOCK_VFSSW(); 9960Sstevel@tonic-gate return (EBUSY); 9970Sstevel@tonic-gate } 9980Sstevel@tonic-gate 9990Sstevel@tonic-gate vfs_freeopttbl(&vswp->vsw_optproto); 10000Sstevel@tonic-gate vswp->vsw_optproto.mo_count = 0; 10010Sstevel@tonic-gate 10020Sstevel@tonic-gate vswp->vsw_flag = 0; 10030Sstevel@tonic-gate vswp->vsw_init = NULL; 10040Sstevel@tonic-gate vfs_unrefvfssw(vswp); 10050Sstevel@tonic-gate WUNLOCK_VFSSW(); 10060Sstevel@tonic-gate return (0); 10070Sstevel@tonic-gate } 10080Sstevel@tonic-gate 10090Sstevel@tonic-gate /* 10100Sstevel@tonic-gate * Get status of a streams module. 10110Sstevel@tonic-gate */ 10120Sstevel@tonic-gate /*ARGSUSED*/ 10130Sstevel@tonic-gate static int 10140Sstevel@tonic-gate mod_infostrmod(struct modlstrmod *modl, struct modlinkage *modlp, int *p0) 10150Sstevel@tonic-gate { 10160Sstevel@tonic-gate *p0 = -1; /* no useful info */ 10170Sstevel@tonic-gate return (0); 10180Sstevel@tonic-gate } 10190Sstevel@tonic-gate 10200Sstevel@tonic-gate 10210Sstevel@tonic-gate /* 10220Sstevel@tonic-gate * Install a streams module. 10230Sstevel@tonic-gate */ 10240Sstevel@tonic-gate /*ARGSUSED*/ 10250Sstevel@tonic-gate static int 10260Sstevel@tonic-gate mod_installstrmod(struct modlstrmod *modl, struct modlinkage *modlp) 10270Sstevel@tonic-gate { 10280Sstevel@tonic-gate struct fmodsw *fp = modl->strmod_fmodsw; 10290Sstevel@tonic-gate 10300Sstevel@tonic-gate if (!(fp->f_flag & D_MP)) { 10310Sstevel@tonic-gate cmn_err(CE_WARN, "mod_install: MT-unsafe strmod '%s' rejected", 10320Sstevel@tonic-gate fp->f_name); 10330Sstevel@tonic-gate return (ENXIO); 10340Sstevel@tonic-gate } 10350Sstevel@tonic-gate 10360Sstevel@tonic-gate return (fmodsw_register(fp->f_name, fp->f_str, fp->f_flag)); 10370Sstevel@tonic-gate } 10380Sstevel@tonic-gate 10390Sstevel@tonic-gate /* 10400Sstevel@tonic-gate * Remove a streams module. 10410Sstevel@tonic-gate */ 10420Sstevel@tonic-gate /*ARGSUSED*/ 10430Sstevel@tonic-gate static int 10440Sstevel@tonic-gate mod_removestrmod(struct modlstrmod *modl, struct modlinkage *modlp) 10450Sstevel@tonic-gate { 10460Sstevel@tonic-gate if (moddebug & MODDEBUG_NOAUL_STR) 10470Sstevel@tonic-gate return (EBUSY); 10480Sstevel@tonic-gate 10490Sstevel@tonic-gate return (fmodsw_unregister(modl->strmod_fmodsw->f_name)); 10500Sstevel@tonic-gate } 10510Sstevel@tonic-gate 10520Sstevel@tonic-gate /* 10530Sstevel@tonic-gate * Get status of a scheduling class module. 10540Sstevel@tonic-gate */ 10550Sstevel@tonic-gate /*ARGSUSED1*/ 10560Sstevel@tonic-gate static int 10570Sstevel@tonic-gate mod_infosched(struct modlsched *modl, struct modlinkage *modlp, int *p0) 10580Sstevel@tonic-gate { 10590Sstevel@tonic-gate int status; 10600Sstevel@tonic-gate auto id_t cid; 10610Sstevel@tonic-gate 10620Sstevel@tonic-gate status = getcidbyname(modl->sched_class->cl_name, &cid); 10630Sstevel@tonic-gate 10640Sstevel@tonic-gate if (status != 0) 10650Sstevel@tonic-gate *p0 = -1; 10660Sstevel@tonic-gate else 10670Sstevel@tonic-gate *p0 = cid; 10680Sstevel@tonic-gate 10690Sstevel@tonic-gate return (0); 10700Sstevel@tonic-gate } 10710Sstevel@tonic-gate 10720Sstevel@tonic-gate /* 10730Sstevel@tonic-gate * Install a scheduling class module. 10740Sstevel@tonic-gate */ 10750Sstevel@tonic-gate /*ARGSUSED1*/ 10760Sstevel@tonic-gate static int 10770Sstevel@tonic-gate mod_installsched(struct modlsched *modl, struct modlinkage *modlp) 10780Sstevel@tonic-gate { 10790Sstevel@tonic-gate sclass_t *clp; 10800Sstevel@tonic-gate int status; 10810Sstevel@tonic-gate id_t cid; 10820Sstevel@tonic-gate 10830Sstevel@tonic-gate /* 10840Sstevel@tonic-gate * See if module is already installed. 10850Sstevel@tonic-gate */ 10860Sstevel@tonic-gate mutex_enter(&class_lock); 10870Sstevel@tonic-gate status = alloc_cid(modl->sched_class->cl_name, &cid); 10880Sstevel@tonic-gate mutex_exit(&class_lock); 10890Sstevel@tonic-gate ASSERT(status == 0); 10900Sstevel@tonic-gate clp = &sclass[cid]; 10910Sstevel@tonic-gate rw_enter(clp->cl_lock, RW_WRITER); 10920Sstevel@tonic-gate if (SCHED_INSTALLED(clp)) { 10930Sstevel@tonic-gate printf("scheduling class %s is already installed\n", 10940Sstevel@tonic-gate modl->sched_class->cl_name); 10950Sstevel@tonic-gate rw_exit(clp->cl_lock); 10960Sstevel@tonic-gate return (EBUSY); /* it's already there */ 10970Sstevel@tonic-gate } 10980Sstevel@tonic-gate 10990Sstevel@tonic-gate clp->cl_init = modl->sched_class->cl_init; 11000Sstevel@tonic-gate clp->cl_funcs = modl->sched_class->cl_funcs; 11010Sstevel@tonic-gate modl->sched_class = clp; 11020Sstevel@tonic-gate disp_add(clp); 11030Sstevel@tonic-gate loaded_classes++; /* for priocntl system call */ 11040Sstevel@tonic-gate rw_exit(clp->cl_lock); 11050Sstevel@tonic-gate return (0); 11060Sstevel@tonic-gate } 11070Sstevel@tonic-gate 11080Sstevel@tonic-gate /* 11090Sstevel@tonic-gate * Remove a scheduling class module. 11100Sstevel@tonic-gate * 11110Sstevel@tonic-gate * we only null out the init func and the class functions because 11120Sstevel@tonic-gate * once a class has been loaded it has that slot in the class 11130Sstevel@tonic-gate * array until the next reboot. We don't decrement loaded_classes 11140Sstevel@tonic-gate * because this keeps count of the number of classes that have 11150Sstevel@tonic-gate * been loaded for this session. It will have to be this way until 11160Sstevel@tonic-gate * we implement the class array as a linked list and do true 11170Sstevel@tonic-gate * dynamic allocation. 11180Sstevel@tonic-gate */ 11190Sstevel@tonic-gate static int 11200Sstevel@tonic-gate mod_removesched(struct modlsched *modl, struct modlinkage *modlp) 11210Sstevel@tonic-gate { 11220Sstevel@tonic-gate int status; 11230Sstevel@tonic-gate sclass_t *clp; 11240Sstevel@tonic-gate struct modctl *mcp; 11250Sstevel@tonic-gate char *modname; 11260Sstevel@tonic-gate id_t cid; 11270Sstevel@tonic-gate 11280Sstevel@tonic-gate status = getcidbyname(modl->sched_class->cl_name, &cid); 11290Sstevel@tonic-gate if (status != 0) { 11300Sstevel@tonic-gate mcp = mod_getctl(modlp); 11310Sstevel@tonic-gate ASSERT(mcp != NULL); 11320Sstevel@tonic-gate modname = mcp->mod_modname; 11330Sstevel@tonic-gate cmn_err(CE_WARN, uninstall_err, modname); 11340Sstevel@tonic-gate return (EINVAL); 11350Sstevel@tonic-gate } 11360Sstevel@tonic-gate clp = &sclass[cid]; 11370Sstevel@tonic-gate if (moddebug & MODDEBUG_NOAUL_SCHED || 11380Sstevel@tonic-gate !rw_tryenter(clp->cl_lock, RW_WRITER)) 11390Sstevel@tonic-gate return (EBUSY); 11400Sstevel@tonic-gate 11410Sstevel@tonic-gate clp->cl_init = NULL; 11420Sstevel@tonic-gate clp->cl_funcs = NULL; 11430Sstevel@tonic-gate rw_exit(clp->cl_lock); 11440Sstevel@tonic-gate return (0); 11450Sstevel@tonic-gate } 11460Sstevel@tonic-gate 11470Sstevel@tonic-gate /* 11480Sstevel@tonic-gate * Get status of an exec module. 11490Sstevel@tonic-gate */ 11500Sstevel@tonic-gate /*ARGSUSED1*/ 11510Sstevel@tonic-gate static int 11520Sstevel@tonic-gate mod_infoexec(struct modlexec *modl, struct modlinkage *modlp, int *p0) 11530Sstevel@tonic-gate { 11540Sstevel@tonic-gate struct execsw *eswp; 11550Sstevel@tonic-gate 11560Sstevel@tonic-gate if ((eswp = findexecsw(modl->exec_execsw->exec_magic)) == NULL) 11570Sstevel@tonic-gate *p0 = -1; 11580Sstevel@tonic-gate else 11590Sstevel@tonic-gate *p0 = eswp - execsw; 11600Sstevel@tonic-gate 11610Sstevel@tonic-gate return (0); 11620Sstevel@tonic-gate } 11630Sstevel@tonic-gate 11640Sstevel@tonic-gate /* 11650Sstevel@tonic-gate * Install an exec module. 11660Sstevel@tonic-gate */ 11670Sstevel@tonic-gate static int 11680Sstevel@tonic-gate mod_installexec(struct modlexec *modl, struct modlinkage *modlp) 11690Sstevel@tonic-gate { 11700Sstevel@tonic-gate struct execsw *eswp; 11710Sstevel@tonic-gate struct modctl *mcp; 11720Sstevel@tonic-gate char *modname; 11730Sstevel@tonic-gate char *magic; 11740Sstevel@tonic-gate size_t magic_size; 11750Sstevel@tonic-gate 11760Sstevel@tonic-gate /* 11770Sstevel@tonic-gate * See if execsw entry is already allocated. Can't use findexectype() 11780Sstevel@tonic-gate * because we may get a recursive call to here. 11790Sstevel@tonic-gate */ 11800Sstevel@tonic-gate 11810Sstevel@tonic-gate if ((eswp = findexecsw(modl->exec_execsw->exec_magic)) == NULL) { 11820Sstevel@tonic-gate mcp = mod_getctl(modlp); 11830Sstevel@tonic-gate ASSERT(mcp != NULL); 11840Sstevel@tonic-gate modname = mcp->mod_modname; 11850Sstevel@tonic-gate magic = modl->exec_execsw->exec_magic; 11860Sstevel@tonic-gate magic_size = modl->exec_execsw->exec_maglen; 11870Sstevel@tonic-gate if ((eswp = allocate_execsw(modname, magic, magic_size)) == 11880Sstevel@tonic-gate NULL) { 11890Sstevel@tonic-gate printf("no unused entries in 'execsw'\n"); 11900Sstevel@tonic-gate return (ENOSPC); 11910Sstevel@tonic-gate } 11920Sstevel@tonic-gate } 11930Sstevel@tonic-gate if (eswp->exec_func != NULL) { 11940Sstevel@tonic-gate printf("exec type %x is already installed\n", 11950Sstevel@tonic-gate *eswp->exec_magic); 11960Sstevel@tonic-gate return (EBUSY); /* it's already there! */ 11970Sstevel@tonic-gate } 11980Sstevel@tonic-gate 11990Sstevel@tonic-gate rw_enter(eswp->exec_lock, RW_WRITER); 12000Sstevel@tonic-gate eswp->exec_func = modl->exec_execsw->exec_func; 12010Sstevel@tonic-gate eswp->exec_core = modl->exec_execsw->exec_core; 12020Sstevel@tonic-gate rw_exit(eswp->exec_lock); 12030Sstevel@tonic-gate 12040Sstevel@tonic-gate return (0); 12050Sstevel@tonic-gate } 12060Sstevel@tonic-gate 12070Sstevel@tonic-gate /* 12080Sstevel@tonic-gate * Remove an exec module. 12090Sstevel@tonic-gate */ 12100Sstevel@tonic-gate static int 12110Sstevel@tonic-gate mod_removeexec(struct modlexec *modl, struct modlinkage *modlp) 12120Sstevel@tonic-gate { 12130Sstevel@tonic-gate struct execsw *eswp; 12140Sstevel@tonic-gate struct modctl *mcp; 12150Sstevel@tonic-gate char *modname; 12160Sstevel@tonic-gate 12170Sstevel@tonic-gate eswp = findexecsw(modl->exec_execsw->exec_magic); 12180Sstevel@tonic-gate if (eswp == NULL) { 12190Sstevel@tonic-gate mcp = mod_getctl(modlp); 12200Sstevel@tonic-gate ASSERT(mcp != NULL); 12210Sstevel@tonic-gate modname = mcp->mod_modname; 12220Sstevel@tonic-gate cmn_err(CE_WARN, uninstall_err, modname); 12230Sstevel@tonic-gate return (EINVAL); 12240Sstevel@tonic-gate } 12250Sstevel@tonic-gate if (moddebug & MODDEBUG_NOAUL_EXEC || 12260Sstevel@tonic-gate !rw_tryenter(eswp->exec_lock, RW_WRITER)) 12270Sstevel@tonic-gate return (EBUSY); 12280Sstevel@tonic-gate eswp->exec_func = NULL; 12290Sstevel@tonic-gate eswp->exec_core = NULL; 12300Sstevel@tonic-gate rw_exit(eswp->exec_lock); 12310Sstevel@tonic-gate return (0); 12320Sstevel@tonic-gate } 12330Sstevel@tonic-gate 12340Sstevel@tonic-gate /* 12350Sstevel@tonic-gate * Find a free sysent entry or check if the specified one is free. 12360Sstevel@tonic-gate */ 12370Sstevel@tonic-gate static struct sysent * 12380Sstevel@tonic-gate mod_getsysent(struct modlinkage *modlp, struct sysent *se) 12390Sstevel@tonic-gate { 12400Sstevel@tonic-gate int sysnum; 12410Sstevel@tonic-gate struct modctl *mcp; 12420Sstevel@tonic-gate char *mod_name; 12430Sstevel@tonic-gate 12440Sstevel@tonic-gate if ((mcp = mod_getctl(modlp)) == NULL) { 12450Sstevel@tonic-gate /* 12460Sstevel@tonic-gate * This happens when we're looking up the module 12470Sstevel@tonic-gate * pointer as part of a stub installation. So 12480Sstevel@tonic-gate * there's no need to whine at this point. 12490Sstevel@tonic-gate */ 12500Sstevel@tonic-gate return (NULL); 12510Sstevel@tonic-gate } 12520Sstevel@tonic-gate 12530Sstevel@tonic-gate mod_name = mcp->mod_modname; 12540Sstevel@tonic-gate 12550Sstevel@tonic-gate if ((sysnum = mod_getsysnum(mod_name)) == -1) { 12560Sstevel@tonic-gate cmn_err(CE_WARN, "system call missing from bind file"); 12570Sstevel@tonic-gate return (NULL); 12580Sstevel@tonic-gate } 12590Sstevel@tonic-gate 12600Sstevel@tonic-gate if (sysnum > 0 && sysnum < NSYSCALL && 12610Sstevel@tonic-gate (se[sysnum].sy_flags & (SE_LOADABLE | SE_NOUNLOAD))) 12620Sstevel@tonic-gate return (se + sysnum); 12630Sstevel@tonic-gate 12640Sstevel@tonic-gate cmn_err(CE_WARN, "system call entry %d is already in use", sysnum); 12650Sstevel@tonic-gate return (NULL); 12660Sstevel@tonic-gate } 12670Sstevel@tonic-gate 12680Sstevel@tonic-gate /* 12690Sstevel@tonic-gate * IP Policy Modules. 12700Sstevel@tonic-gate */ 12710Sstevel@tonic-gate /*ARGSUSED*/ 12720Sstevel@tonic-gate static int 12730Sstevel@tonic-gate mod_infoipp(struct modlipp *modl, struct modlinkage *modlp, int *p0) 12740Sstevel@tonic-gate { 12750Sstevel@tonic-gate struct modctl *mcp = mod_getctl(modlp); 12760Sstevel@tonic-gate ipp_mod_id_t mid; 12770Sstevel@tonic-gate 12780Sstevel@tonic-gate if (mcp == NULL) { 12790Sstevel@tonic-gate *p0 = -1; 12800Sstevel@tonic-gate return (0); /* module is not yet installed */ 12810Sstevel@tonic-gate } 12820Sstevel@tonic-gate 12830Sstevel@tonic-gate mid = ipp_mod_lookup(mcp->mod_modname); 12840Sstevel@tonic-gate 12850Sstevel@tonic-gate *p0 = mid; 12860Sstevel@tonic-gate return (0); 12870Sstevel@tonic-gate } 12880Sstevel@tonic-gate 12890Sstevel@tonic-gate static int 12900Sstevel@tonic-gate mod_installipp(struct modlipp *modl, struct modlinkage *modlp) 12910Sstevel@tonic-gate { 12920Sstevel@tonic-gate struct modctl *mcp = mod_getctl(modlp); 12930Sstevel@tonic-gate 12940Sstevel@tonic-gate ASSERT(mcp != NULL); 12950Sstevel@tonic-gate return (ipp_mod_register(mcp->mod_modname, modl->ipp_ops)); 12960Sstevel@tonic-gate } 12970Sstevel@tonic-gate 12980Sstevel@tonic-gate /*ARGSUSED*/ 12990Sstevel@tonic-gate static int 13000Sstevel@tonic-gate mod_removeipp(struct modlipp *modl, struct modlinkage *modlp) 13010Sstevel@tonic-gate { 13020Sstevel@tonic-gate struct modctl *mcp = mod_getctl(modlp); 13030Sstevel@tonic-gate extern kthread_id_t mod_aul_thread; 13040Sstevel@tonic-gate ipp_mod_id_t mid; 13050Sstevel@tonic-gate 13060Sstevel@tonic-gate ASSERT(mcp != NULL); 13070Sstevel@tonic-gate 13080Sstevel@tonic-gate if ((moddebug & MODDEBUG_NOAUL_IPP) && (mod_aul_thread == curthread)) 13090Sstevel@tonic-gate return (EBUSY); 13100Sstevel@tonic-gate 13110Sstevel@tonic-gate mid = ipp_mod_lookup(mcp->mod_modname); 13120Sstevel@tonic-gate ASSERT(mid != IPP_MOD_INVAL); 13130Sstevel@tonic-gate 13140Sstevel@tonic-gate return (ipp_mod_unregister(mid)); 13150Sstevel@tonic-gate } 1316