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