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