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