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