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