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 (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <sys/param.h> 26 #include <sys/modctl.h> 27 #include <sys/modhash.h> 28 #include <sys/open.h> 29 #include <sys/conf.h> 30 #include <sys/errno.h> 31 #include <sys/sysmacros.h> 32 #include <sys/kmem.h> 33 #include <sys/cmn_err.h> 34 #include <sys/stat.h> 35 #include <sys/mode.h> 36 #include <sys/pathname.h> 37 #include <sys/vnode.h> 38 #include <sys/ddi_impldefs.h> 39 #include <sys/ddi_implfuncs.h> 40 #include <sys/esunddi.h> 41 #include <sys/sunddi.h> 42 #include <sys/sunndi.h> 43 #include <sys/systeminfo.h> 44 #include <sys/hwconf.h> 45 #include <sys/file.h> 46 #include <sys/varargs.h> 47 #include <sys/thread.h> 48 #include <sys/cred.h> 49 #include <sys/autoconf.h> 50 #include <sys/kobj.h> 51 #include <sys/consdev.h> 52 #include <sys/systm.h> 53 #include <sys/debug.h> 54 #include <sys/atomic.h> 55 56 extern struct dev_ops nodev_ops; 57 extern struct dev_ops mod_nodev_ops; 58 59 struct mod_noload { 60 struct mod_noload *mn_next; 61 char *mn_name; 62 }; 63 64 /* 65 * Function prototypes 66 */ 67 static int init_stubs(struct modctl *, struct mod_modinfo *); 68 static int nm_hash(const char *); 69 static void make_syscallname(const char *, int); 70 static void hwc_hash_init(); 71 static void hwc_hash(struct hwc_spec *, major_t); 72 static void hwc_unhash(struct hwc_spec *); 73 74 int 75 major_valid(major_t major) 76 { 77 return (major != DDI_MAJOR_T_NONE && major < devcnt); 78 } 79 80 int 81 driver_installed(major_t major) 82 { 83 return (major_valid(major) && devnamesp[major].dn_name != NULL); 84 } 85 86 int 87 driver_active(major_t major) 88 { 89 return (driver_installed(major) && !(devnamesp[major].dn_flags & 90 (DN_DRIVER_REMOVED|DN_DRIVER_INACTIVE))); 91 } 92 93 struct dev_ops * 94 mod_hold_dev_by_major(major_t major) 95 { 96 struct dev_ops **devopspp, *ops; 97 int loaded; 98 char *drvname; 99 100 if (!driver_active(major)) 101 return (NULL); 102 103 LOCK_DEV_OPS(&(devnamesp[major].dn_lock)); 104 devopspp = &devopsp[major]; 105 loaded = 1; 106 while (loaded && !CB_DRV_INSTALLED(*devopspp)) { 107 UNLOCK_DEV_OPS(&(devnamesp[major].dn_lock)); 108 drvname = mod_major_to_name(major); 109 if (drvname == NULL) 110 return (NULL); 111 loaded = (modload("drv", drvname) != -1); 112 LOCK_DEV_OPS(&(devnamesp[major].dn_lock)); 113 } 114 if (loaded) { 115 INCR_DEV_OPS_REF(*devopspp); 116 ops = *devopspp; 117 } else { 118 ops = NULL; 119 } 120 UNLOCK_DEV_OPS(&(devnamesp[major].dn_lock)); 121 return (ops); 122 } 123 124 #ifdef DEBUG_RELE 125 static int mod_rele_pause = DEBUG_RELE; 126 #endif /* DEBUG_RELE */ 127 128 void 129 mod_rele_dev_by_major(major_t major) 130 { 131 struct dev_ops *ops; 132 struct devnames *dnp; 133 134 if (!driver_active(major)) 135 return; 136 137 dnp = &devnamesp[major]; 138 LOCK_DEV_OPS(&dnp->dn_lock); 139 ops = devopsp[major]; 140 ASSERT(CB_DRV_INSTALLED(ops)); 141 142 #ifdef DEBUG_RELE 143 if (!DEV_OPS_HELD(ops)) { 144 char *s; 145 static char *msg = "mod_rele_dev_by_major: unheld driver!"; 146 147 printf("mod_rele_dev_by_major: Major dev <%u>, name <%s>\n", 148 (uint_t)major, 149 (s = mod_major_to_name(major)) ? s : "unknown"); 150 if (mod_rele_pause) 151 debug_enter(msg); 152 else 153 printf("%s\n", msg); 154 UNLOCK_DEV_OPS(&dnp->dn_lock); 155 return; /* XXX: Note changed behavior */ 156 } 157 158 #endif /* DEBUG_RELE */ 159 160 if (!DEV_OPS_HELD(ops)) { 161 cmn_err(CE_PANIC, 162 "mod_rele_dev_by_major: Unheld driver: major number <%u>", 163 (uint_t)major); 164 } 165 DECR_DEV_OPS_REF(ops); 166 UNLOCK_DEV_OPS(&dnp->dn_lock); 167 } 168 169 struct dev_ops * 170 mod_hold_dev_by_devi(dev_info_t *devi) 171 { 172 major_t major; 173 char *name; 174 175 name = ddi_get_name(devi); 176 if ((major = mod_name_to_major(name)) == DDI_MAJOR_T_NONE) 177 return (NULL); 178 return (mod_hold_dev_by_major(major)); 179 } 180 181 void 182 mod_rele_dev_by_devi(dev_info_t *devi) 183 { 184 major_t major; 185 char *name; 186 187 name = ddi_get_name(devi); 188 if ((major = mod_name_to_major(name)) == DDI_MAJOR_T_NONE) 189 return; 190 mod_rele_dev_by_major(major); 191 } 192 193 int 194 nomod_zero() 195 { 196 return (0); 197 } 198 199 int 200 nomod_minus_one() 201 { 202 return (-1); 203 } 204 205 int 206 nomod_einval() 207 { 208 return (EINVAL); 209 } 210 211 void 212 nomod_void() 213 { 214 /* nothing */ 215 } 216 217 /* 218 * Install all the stubs for a module. 219 * Return zero if there were no errors or an errno value. 220 */ 221 int 222 install_stubs_by_name(struct modctl *modp, const char *name) 223 { 224 char *p; 225 const char *filenamep, *iter; 226 char namebuf[MODMAXNAMELEN + 12]; 227 struct mod_modinfo *mp; 228 229 iter = name; 230 filenamep = name; 231 232 while (*iter) { 233 if (*iter++ == '/') 234 filenamep = iter; 235 } 236 237 /* 238 * Concatenate "name" with "_modname" then look up this symbol 239 * in the kernel. If not found, we're done. 240 * If found, then find the "mod" info structure and call init_stubs(). 241 */ 242 p = namebuf; 243 244 while (*filenamep && *filenamep != '.') 245 *p++ = *filenamep++; 246 247 (void) strcpy(p, "_modinfo"); 248 249 if ((mp = (struct mod_modinfo *)modgetsymvalue(namebuf, 1)) != 0) 250 return (init_stubs(modp, mp)); 251 else 252 return (0); 253 } 254 255 static int 256 init_stubs(struct modctl *modp, struct mod_modinfo *mp) 257 { 258 struct mod_stub_info *sp; 259 int i; 260 ulong_t offset; 261 uintptr_t funcadr; 262 char *funcname; 263 264 modp->mod_modinfo = mp; 265 266 /* 267 * Fill in all stubs for this module. We can't be lazy, since 268 * some calls could come in from interrupt level, and we 269 * can't modlookup then (symbols may be paged out). 270 */ 271 sp = mp->modm_stubs; 272 for (i = 0; sp->mods_func_adr; i++, sp++) { 273 funcname = modgetsymname(sp->mods_stub_adr, &offset); 274 if (funcname == NULL) { 275 printf("init_stubs: couldn't find symbol " 276 "in module %s\n", mp->modm_module_name); 277 return (EFAULT); 278 } 279 funcadr = kobj_lookup(modp->mod_mp, funcname); 280 281 if (kobj_addrcheck(modp->mod_mp, (caddr_t)funcadr)) { 282 printf("%s:%s() not defined properly\n", 283 mp->modm_module_name, funcname); 284 return (EFAULT); 285 } 286 sp->mods_func_adr = funcadr; 287 } 288 mp->mp = modp; 289 return (0); 290 } 291 292 /* 293 * modp->mod_modinfo has to be checked in these functions before 294 * mod_stub_info is accessed because it's not guranteed that all 295 * modules define mod_stub_info structures. 296 */ 297 void 298 install_stubs(struct modctl *modp) 299 { 300 struct mod_stub_info *stub; 301 302 if (modp->mod_modinfo) { 303 membar_producer(); 304 for (stub = modp->mod_modinfo->modm_stubs; 305 stub->mods_func_adr; stub++) { 306 stub->mods_flag |= MODS_INSTALLED; 307 } 308 membar_producer(); 309 } 310 } 311 312 void 313 uninstall_stubs(struct modctl *modp) 314 { 315 struct mod_stub_info *stub; 316 317 if (modp->mod_modinfo) { 318 membar_producer(); 319 for (stub = modp->mod_modinfo->modm_stubs; 320 stub->mods_func_adr; stub++) { 321 stub->mods_flag &= ~MODS_INSTALLED; 322 } 323 membar_producer(); 324 } 325 } 326 327 void 328 reset_stubs(struct modctl *modp) 329 { 330 struct mod_stub_info *stub; 331 332 if (modp->mod_modinfo) { 333 for (stub = modp->mod_modinfo->modm_stubs; 334 stub->mods_func_adr; stub++) { 335 if (stub->mods_flag & (MODS_WEAK | MODS_NOUNLOAD)) 336 stub->mods_func_adr = 337 (uintptr_t)stub->mods_errfcn; 338 else 339 stub->mods_func_adr = 340 (uintptr_t)mod_hold_stub; 341 } 342 modp->mod_modinfo->mp = NULL; 343 } 344 } 345 346 struct modctl * 347 mod_getctl(struct modlinkage *modlp) 348 { 349 struct modctl *modp; 350 351 mutex_enter(&mod_lock); 352 modp = &modules; 353 do { 354 if (modp->mod_linkage == modlp) { 355 mutex_exit(&mod_lock); 356 return (modp); 357 } 358 } while ((modp = modp->mod_next) != &modules); 359 mutex_exit(&mod_lock); 360 return (NULL); 361 } 362 363 364 /* 365 * Attach driver.conf info to devnames for a driver 366 */ 367 struct par_list * 368 impl_make_parlist(major_t major) 369 { 370 int err; 371 struct par_list *pl = NULL, *tmp; 372 ddi_prop_t *props = NULL; 373 char *confname, *drvname; 374 struct devnames *dnp; 375 376 dnp = &devnamesp[major]; 377 378 ASSERT(mutex_owned(&dnp->dn_lock)); 379 380 /* 381 * If .conf file already parsed or driver removed, just return. 382 * May return NULL. 383 */ 384 if (dnp->dn_flags & (DN_CONF_PARSED | DN_DRIVER_REMOVED)) 385 return (dnp->dn_pl); 386 387 drvname = mod_major_to_name(major); 388 if (drvname == NULL) 389 return (NULL); 390 391 confname = kmem_alloc(MAXNAMELEN, KM_SLEEP); 392 (void) snprintf(confname, MAXNAMELEN, "drv/%s.conf", drvname); 393 err = hwc_parse(confname, &pl, &props); 394 kmem_free(confname, MAXNAMELEN); 395 if (err) /* file doesn't exist */ 396 return (NULL); 397 398 /* 399 * If there are global properties, reference it from dnp. 400 */ 401 if (props) 402 dnp->dn_global_prop_ptr = i_ddi_prop_list_create(props); 403 404 /* 405 * Hash specs to be looked up by nexus drivers 406 */ 407 tmp = pl; 408 while (tmp) { 409 (void) hwc_hash(tmp->par_specs, major); 410 tmp = tmp->par_next; 411 } 412 413 if (!i_ddi_io_initialized()) { 414 if (i_ddi_prop_search(DDI_DEV_T_ANY, DDI_FORCEATTACH, 415 DDI_PROP_TYPE_INT, &props)) 416 dnp->dn_flags |= DN_FORCE_ATTACH; 417 if (i_ddi_prop_search(DDI_DEV_T_ANY, DDI_OPEN_RETURNS_EINTR, 418 DDI_PROP_TYPE_INT, &props)) 419 dnp->dn_flags |= DN_OPEN_RETURNS_EINTR; 420 if (i_ddi_prop_search(DDI_DEV_T_ANY, "scsi-size-clean", 421 DDI_PROP_TYPE_INT, &props)) 422 dnp->dn_flags |= DN_SCSI_SIZE_CLEAN; 423 } 424 425 if (i_ddi_prop_search(DDI_DEV_T_ANY, DDI_VHCI_CLASS, 426 DDI_PROP_TYPE_STRING, &props)) 427 dnp->dn_flags |= DN_PHCI_DRIVER; 428 429 if (i_ddi_prop_search(DDI_DEV_T_ANY, DDI_DEVID_REGISTRANT, 430 DDI_PROP_TYPE_INT, &props)) { 431 dnp->dn_flags |= DN_DEVID_REGISTRANT; 432 } 433 434 dnp->dn_flags |= DN_CONF_PARSED; 435 dnp->dn_pl = pl; 436 return (pl); 437 } 438 439 /* 440 * Destroy driver.conf info in devnames array for a driver 441 */ 442 int 443 impl_free_parlist(major_t major) 444 { 445 struct par_list *pl; 446 struct devnames *dnp = &devnamesp[major]; 447 448 /* 449 * Unref driver global property list. Don't destroy it 450 * because some instances may still be referencing it. 451 * The property list will be freed when the last ref 452 * goes away. 453 */ 454 if (dnp->dn_global_prop_ptr) { 455 i_ddi_prop_list_rele(dnp->dn_global_prop_ptr, dnp); 456 dnp->dn_global_prop_ptr = NULL; 457 } 458 459 /* 460 * remove specs from hash table 461 */ 462 for (pl = dnp->dn_pl; pl; pl = pl->par_next) 463 hwc_unhash(pl->par_specs); 464 465 impl_delete_par_list(dnp->dn_pl); 466 dnp->dn_pl = NULL; 467 dnp->dn_flags &= ~DN_CONF_PARSED; 468 return (0); 469 } 470 471 struct bind *mb_hashtab[MOD_BIND_HASHSIZE]; 472 struct bind *sb_hashtab[MOD_BIND_HASHSIZE]; 473 474 static int 475 nm_hash(const char *name) 476 { 477 char c; 478 int hash = 0; 479 480 for (c = *name++; c; c = *name++) 481 hash ^= c; 482 483 return (hash & MOD_BIND_HASHMASK); 484 } 485 486 void 487 clear_binding_hash(struct bind **bhash) 488 { 489 int i; 490 struct bind *bp, *bp1; 491 492 for (i = 0; i < MOD_BIND_HASHSIZE; i++) { 493 bp = bhash[i]; 494 while (bp != NULL) { 495 kmem_free(bp->b_name, strlen(bp->b_name) + 1); 496 if (bp->b_bind_name) { 497 kmem_free(bp->b_bind_name, 498 strlen(bp->b_bind_name) + 1); 499 } 500 bp1 = bp; 501 bp = bp->b_next; 502 kmem_free(bp1, sizeof (struct bind)); 503 } 504 bhash[i] = NULL; 505 } 506 } 507 508 /* Find an mbind by name match (caller can ask for deleted match) */ 509 static struct bind * 510 find_mbind(const char *name, struct bind **hashtab, int deleted) 511 { 512 struct bind *mb; 513 514 for (mb = hashtab[nm_hash(name)]; mb; mb = mb->b_next) { 515 if (deleted && (mb->b_num >= 0)) 516 continue; /* skip active */ 517 if (!deleted && (mb->b_num < 0)) 518 continue; /* skip deleted */ 519 520 /* return if name matches */ 521 if (strcmp(name, mb->b_name) == 0) { 522 break; 523 } 524 } 525 return (mb); 526 } 527 528 /* 529 * Create an entry for the given (name, major, bind_name) tuple in the 530 * hash table supplied. Reject the attempt to do so if 'name' is already 531 * in the hash table. 532 * 533 * Does not provide synchronization, so use only during boot or with 534 * externally provided locking. 535 */ 536 int 537 make_mbind(char *name, int num, char *bind_name, struct bind **hashtab) 538 { 539 struct bind *mb; 540 struct bind **pmb; 541 542 ASSERT(hashtab != NULL); 543 ASSERT(num >= 0); 544 545 /* Fail if the key being added is already established */ 546 if (find_mbind(name, hashtab, 0) != NULL) 547 return (-1); 548 549 /* Allocate new mbind */ 550 mb = kmem_zalloc(sizeof (struct bind), KM_SLEEP); 551 mb->b_name = i_ddi_strdup(name, KM_SLEEP); 552 mb->b_num = num; 553 if (bind_name != NULL) 554 mb->b_bind_name = i_ddi_strdup(bind_name, KM_SLEEP); 555 556 /* Insert at head of hash */ 557 pmb = &hashtab[nm_hash(name)]; 558 mb->b_next = *pmb; 559 *pmb = mb; 560 return (0); 561 } 562 563 /* 564 * Delete a binding from a binding-hash. Since there is no locking we 565 * delete an mbind by making its b_num negative. We also support find_mbind 566 * of deleted entries, so we still need deleted items on the list. 567 */ 568 void 569 delete_mbind(const char *name, struct bind **hashtab) 570 { 571 struct bind *mb; 572 573 for (mb = hashtab[nm_hash(name)]; mb; mb = mb->b_next) { 574 if ((mb->b_num >= 0) && (strcmp(name, mb->b_name) == 0)) { 575 /* delete by making b_num negative */ 576 if (moddebug & MODDEBUG_BINDING) { 577 cmn_err(CE_CONT, "mbind: %s %d deleted\n", 578 name, mb->b_num); 579 } 580 mb->b_num = -mb->b_num; 581 break; 582 } 583 } 584 } 585 586 /* 587 * Delete all items in an mbind associated with specified num. 588 * An example would be rem_drv deleting all aliases associated with a 589 * driver major number. 590 */ 591 void 592 purge_mbind(int num, struct bind **hashtab) 593 { 594 int i; 595 struct bind *mb; 596 597 /* search all hash lists for items that associated with 'num' */ 598 for (i = 0; i < MOD_BIND_HASHSIZE; i++) { 599 for (mb = hashtab[i]; mb; mb = mb->b_next) { 600 if (mb->b_num == num) { 601 if (moddebug & MODDEBUG_BINDING) 602 cmn_err(CE_CONT, 603 "mbind: %s %d purged\n", 604 mb->b_name, num); 605 /* purge by changing the sign */ 606 mb->b_num = -num; 607 } 608 } 609 } 610 } 611 612 major_t 613 mod_name_to_major(const char *name) 614 { 615 struct bind *mbind; 616 major_t maj; 617 618 /* Search for non-deleted match. */ 619 if ((mbind = find_mbind(name, mb_hashtab, 0)) != NULL) { 620 if (moddebug & MODDEBUG_BINDING) { 621 if (find_mbind(name, mb_hashtab, 1)) 622 cmn_err(CE_CONT, 623 "'%s' has deleted match too\n", name); 624 } 625 return ((major_t)mbind->b_num); 626 } 627 628 /* 629 * Search for deleted match: We may find that we have dependencies 630 * on drivers that have been deleted (but the old driver may still 631 * be bound to a node). These callers should be converted to use 632 * ddi_driver_major(i.e. devi_major). 633 */ 634 if (moddebug & MODDEBUG_BINDING) { 635 if ((mbind = find_mbind(name, mb_hashtab, 1)) != NULL) { 636 maj = (major_t)(-(mbind->b_num)); 637 cmn_err(CE_CONT, "Reference to deleted alias '%s' %d\n", 638 name, maj); 639 } 640 } 641 642 return (DDI_MAJOR_T_NONE); 643 } 644 645 char * 646 mod_major_to_name(major_t major) 647 { 648 if (!driver_installed(major)) 649 return (NULL); 650 return ((&devnamesp[major])->dn_name); 651 } 652 653 /* 654 * Set up the devnames array. Error check for duplicate entries. 655 */ 656 void 657 init_devnamesp(int size) 658 { 659 int hshndx; 660 struct bind *bp; 661 static char dupwarn[] = 662 "!Device entry \"%s %d\" conflicts with previous entry \"%s %d\" " 663 "in /etc/name_to_major."; 664 static char badmaj[] = "The major number %u is invalid."; 665 666 ASSERT(size <= L_MAXMAJ32 && size > 0); 667 668 /* 669 * Allocate the devnames array. All mutexes and cv's will be 670 * automagically initialized. 671 */ 672 devnamesp = kobj_zalloc(size * sizeof (struct devnames), KM_SLEEP); 673 674 /* 675 * Stick the contents of mb_hashtab into the devnames array. Warn if 676 * two hash entries correspond to the same major number, or if a 677 * major number is out of range. 678 */ 679 for (hshndx = 0; hshndx < MOD_BIND_HASHSIZE; hshndx++) { 680 for (bp = mb_hashtab[hshndx]; bp; bp = bp->b_next) { 681 if (make_devname(bp->b_name, 682 (major_t)bp->b_num, 0) != 0) { 683 /* 684 * If there is not an entry at b_num already, 685 * then this must be a bad major number. 686 */ 687 char *nm = mod_major_to_name(bp->b_num); 688 if (nm == NULL) { 689 cmn_err(CE_WARN, badmaj, 690 (uint_t)bp->b_num); 691 } else { 692 cmn_err(CE_WARN, dupwarn, bp->b_name, 693 bp->b_num, nm, bp->b_num); 694 } 695 } 696 } 697 } 698 699 /* Initialize hash table for hwc_spec's */ 700 hwc_hash_init(); 701 } 702 703 int 704 make_devname(const char *name, major_t major, int dn_flags) 705 { 706 struct devnames *dnp; 707 char *copy; 708 709 /* 710 * Until on-disk support for major nums > 14 bits arrives, fail 711 * any major numbers that are too big. 712 */ 713 if (major > L_MAXMAJ32) 714 return (EINVAL); 715 716 dnp = &devnamesp[major]; 717 LOCK_DEV_OPS(&dnp->dn_lock); 718 if (dnp->dn_name) { 719 if (strcmp(dnp->dn_name, name) != 0) { 720 /* Another driver already here */ 721 UNLOCK_DEV_OPS(&dnp->dn_lock); 722 return (EINVAL); 723 } 724 /* Adding back a removed driver */ 725 dnp->dn_flags &= ~DN_DRIVER_REMOVED; 726 dnp->dn_flags |= dn_flags; 727 UNLOCK_DEV_OPS(&dnp->dn_lock); 728 return (0); 729 } 730 731 /* 732 * Check if flag is taken by getudev() 733 */ 734 if (dnp->dn_flags & DN_TAKEN_GETUDEV) { 735 UNLOCK_DEV_OPS(&dnp->dn_lock); 736 return (EINVAL); 737 } 738 739 copy = kmem_alloc(strlen(name) + 1, KM_SLEEP); 740 (void) strcpy(copy, name); 741 742 /* Make sure string is copied before setting dn_name */ 743 membar_producer(); 744 dnp->dn_name = copy; 745 dnp->dn_flags = dn_flags; 746 UNLOCK_DEV_OPS(&dnp->dn_lock); 747 return (0); 748 } 749 750 /* 751 * Set up the syscallnames array. 752 */ 753 void 754 init_syscallnames(int size) 755 { 756 int hshndx; 757 struct bind *bp; 758 759 syscallnames = kobj_zalloc(size * sizeof (char *), KM_SLEEP); 760 761 for (hshndx = 0; hshndx < MOD_BIND_HASHSIZE; hshndx++) { 762 for (bp = sb_hashtab[hshndx]; bp; bp = bp->b_next) { 763 if (bp->b_num < 0 || bp->b_num >= size) { 764 cmn_err(CE_WARN, 765 "!Couldn't add system call \"%s %d\". " 766 "Value out of range (0..%d) in " 767 "/etc/name_to_sysnum.", 768 bp->b_name, bp->b_num, size - 1); 769 continue; 770 } 771 make_syscallname(bp->b_name, bp->b_num); 772 } 773 } 774 } 775 776 static void 777 make_syscallname(const char *name, int sysno) 778 { 779 char **cp = &syscallnames[sysno]; 780 781 if (*cp != NULL) { 782 cmn_err(CE_WARN, "!Couldn't add system call \"%s %d\". " 783 "It conflicts with \"%s %d\" in /etc/name_to_sysnum.", 784 name, sysno, *cp, sysno); 785 return; 786 } 787 *cp = kmem_alloc(strlen(name) + 1, KM_SLEEP); 788 (void) strcpy(*cp, name); 789 } 790 791 /* 792 * Given a system call name, get its number. 793 */ 794 int 795 mod_getsysnum(const char *name) 796 { 797 struct bind *mbind; 798 799 if ((mbind = find_mbind(name, sb_hashtab, 0)) != NULL) 800 return (mbind->b_num); 801 802 return (-1); 803 } 804 805 /* 806 * Given a system call number, get the system call name. 807 */ 808 char * 809 mod_getsysname(int sysnum) 810 { 811 return (syscallnames[sysnum]); 812 } 813 814 /* 815 * Find the name of the module containing the specified pc. 816 * Returns the name on success, "<unknown>" on failure. 817 * No mod_lock locking is required because things are never deleted from 818 * the &modules list. 819 */ 820 char * 821 mod_containing_pc(caddr_t pc) 822 { 823 struct modctl *mcp = &modules; 824 825 do { 826 if (mcp->mod_mp != NULL && 827 (size_t)pc - (size_t)mcp->mod_text < mcp->mod_text_size) 828 return (mcp->mod_modname); 829 } while ((mcp = mcp->mod_next) != &modules); 830 return ("<unknown>"); 831 } 832 833 /* 834 * Hash tables for hwc_spec 835 * 836 * The purpose of these hash tables are to allow the framework to discover 837 * all possible .conf children for a given nexus. There are two hash tables. 838 * One is hashed based on parent name, the on the class name. Each 839 * driver.conf file translates to a list of hwc_spec's. Adding and 840 * removing the entire list is an atomic operation, protected by 841 * the hwc_hash_lock. 842 * 843 * What we get from all the hashing is the function hwc_get_child_spec(). 844 */ 845 #define HWC_SPEC_HASHSIZE (1 << 6) /* 64 */ 846 847 static mod_hash_t *hwc_par_hash; /* hash by parent name */ 848 static mod_hash_t *hwc_class_hash; /* hash by class name */ 849 static kmutex_t hwc_hash_lock; /* lock protecting hwc hashes */ 850 851 /* 852 * Initialize hash tables for parent and class specs 853 */ 854 static void 855 hwc_hash_init() 856 { 857 hwc_par_hash = mod_hash_create_strhash("hwc parent spec hash", 858 HWC_SPEC_HASHSIZE, mod_hash_null_valdtor); 859 hwc_class_hash = mod_hash_create_strhash("hwc class spec hash", 860 HWC_SPEC_HASHSIZE, mod_hash_null_valdtor); 861 } 862 863 /* 864 * Insert a spec into hash table. hwc_hash_lock must be held 865 */ 866 static void 867 hwc_hash_insert(struct hwc_spec *spec, const char *name, mod_hash_t *hash) 868 { 869 mod_hash_key_t key; 870 struct hwc_spec *entry = NULL; 871 872 ASSERT(name != NULL); 873 874 if (mod_hash_find(hash, (mod_hash_key_t)name, 875 (mod_hash_val_t)&entry) != 0) { 876 /* Name doesn't exist, insert a new key */ 877 key = kmem_alloc(strlen(name) + 1, KM_SLEEP); 878 (void) strcpy((char *)key, name); 879 if (mod_hash_insert(hash, key, (mod_hash_val_t)spec) != 0) { 880 kmem_free(key, strlen(name) + 1); 881 cmn_err(CE_WARN, "hwc hash state inconsistent"); 882 } 883 return; 884 } 885 886 /* 887 * Name is already present, append spec to the list. 888 * This is the case when driver.conf specifies multiple 889 * nodes under a single parent or class. 890 */ 891 while (entry->hwc_hash_next) 892 entry = entry->hwc_hash_next; 893 entry->hwc_hash_next = spec; 894 } 895 896 /* 897 * Remove a spec entry from spec hash table, the spec itself is 898 * destroyed external to this function. 899 */ 900 static void 901 hwc_hash_remove(struct hwc_spec *spec, const char *name, mod_hash_t *hash) 902 { 903 char *key; 904 struct hwc_spec *entry; 905 906 ASSERT(name != NULL); 907 908 if (mod_hash_find(hash, (mod_hash_key_t)name, 909 (mod_hash_val_t)&entry) != 0) { 910 return; /* name not found in hash */ 911 } 912 913 /* 914 * If the head is the spec to be removed, either destroy the 915 * entry or replace it with the remaining list. 916 */ 917 if (entry == spec) { 918 if (spec->hwc_hash_next == NULL) { 919 (void) mod_hash_destroy(hash, (mod_hash_key_t)name); 920 return; 921 } 922 key = kmem_alloc(strlen(name) + 1, KM_SLEEP); 923 (void) strcpy(key, name); 924 (void) mod_hash_replace(hash, (mod_hash_key_t)key, 925 (mod_hash_val_t)spec->hwc_hash_next); 926 spec->hwc_hash_next = NULL; 927 return; 928 } 929 930 /* 931 * If the head is not the one, look for the spec in the 932 * hwc_hash_next linkage. 933 */ 934 while (entry->hwc_hash_next && (entry->hwc_hash_next != spec)) 935 entry = entry->hwc_hash_next; 936 937 if (entry->hwc_hash_next) { 938 entry->hwc_hash_next = spec->hwc_hash_next; 939 spec->hwc_hash_next = NULL; 940 } 941 } 942 943 /* 944 * Hash a list of specs based on either parent name or class name 945 */ 946 static void 947 hwc_hash(struct hwc_spec *spec_list, major_t major) 948 { 949 struct hwc_spec *spec = spec_list; 950 951 mutex_enter(&hwc_hash_lock); 952 while (spec) { 953 /* Put driver major here so parent can find it */ 954 spec->hwc_major = major; 955 956 if (spec->hwc_parent_name != NULL) { 957 hwc_hash_insert(spec, spec->hwc_parent_name, 958 hwc_par_hash); 959 } else if (spec->hwc_class_name != NULL) { 960 hwc_hash_insert(spec, spec->hwc_class_name, 961 hwc_class_hash); 962 } else { 963 cmn_err(CE_WARN, 964 "hwc_hash: No class or parent specified"); 965 } 966 spec = spec->hwc_next; 967 } 968 mutex_exit(&hwc_hash_lock); 969 } 970 971 /* 972 * Remove a list of specs from hash tables. Don't destroy the specs yet. 973 */ 974 static void 975 hwc_unhash(struct hwc_spec *spec_list) 976 { 977 struct hwc_spec *spec = spec_list; 978 979 mutex_enter(&hwc_hash_lock); 980 while (spec) { 981 if (spec->hwc_parent_name != NULL) { 982 hwc_hash_remove(spec, spec->hwc_parent_name, 983 hwc_par_hash); 984 } else if (spec->hwc_class_name != NULL) { 985 hwc_hash_remove(spec, spec->hwc_class_name, 986 hwc_class_hash); 987 } else { 988 cmn_err(CE_WARN, 989 "hwc_unhash: No class or parent specified"); 990 } 991 spec = spec->hwc_next; 992 } 993 mutex_exit(&hwc_hash_lock); 994 } 995 996 /* 997 * Make a copy of specs in a hash entry and add to the end of listp. 998 * Called by nexus to locate a list of child specs. 999 * 1000 * entry is a list of hwc_spec chained together with hwc_hash_next. 1001 * listp points to list chained together with hwc_next. 1002 */ 1003 static void 1004 hwc_spec_add(struct hwc_spec **listp, struct hwc_spec *entry, 1005 major_t match_major) 1006 { 1007 /* Find the tail of the list */ 1008 while (*listp) 1009 listp = &(*listp)->hwc_next; 1010 1011 while (entry) { 1012 struct hwc_spec *spec; 1013 1014 if ((match_major != DDI_MAJOR_T_NONE) && 1015 (match_major != entry->hwc_major)) { 1016 entry = entry->hwc_hash_next; 1017 continue; 1018 } 1019 1020 /* 1021 * Allocate spec and copy the content of entry. 1022 * No need to copy class/parent name since caller 1023 * already knows the parent dip. 1024 */ 1025 spec = kmem_zalloc(sizeof (*spec), KM_SLEEP); 1026 spec->hwc_devi_name = i_ddi_strdup( 1027 entry->hwc_devi_name, KM_SLEEP); 1028 spec->hwc_major = entry->hwc_major; 1029 spec->hwc_devi_sys_prop_ptr = i_ddi_prop_list_dup( 1030 entry->hwc_devi_sys_prop_ptr, KM_SLEEP); 1031 1032 *listp = spec; 1033 listp = &spec->hwc_next; 1034 entry = entry->hwc_hash_next; 1035 } 1036 } 1037 1038 /* 1039 * Given a dip, find the list of child .conf specs from most specific 1040 * (parent pathname) to least specific (class name). 1041 * 1042 * This function allows top-down loading to be implemented without 1043 * changing the format of driver.conf file. 1044 */ 1045 struct hwc_spec * 1046 hwc_get_child_spec(dev_info_t *dip, major_t match_major) 1047 { 1048 extern char *i_ddi_parname(dev_info_t *, char *); 1049 extern int i_ddi_get_exported_classes(dev_info_t *, char ***); 1050 extern void i_ddi_free_exported_classes(char **, int); 1051 1052 int i, nclass; 1053 char **classes; 1054 struct hwc_spec *list = NULL; 1055 mod_hash_val_t val; 1056 char *parname, *parname_buf; 1057 char *deviname, *deviname_buf; 1058 char *pathname, *pathname_buf; 1059 char *bindname; 1060 char *drvname; 1061 1062 pathname_buf = kmem_alloc(3 * MAXPATHLEN, KM_SLEEP); 1063 deviname_buf = pathname_buf + MAXPATHLEN; 1064 parname_buf = pathname_buf + (2 * MAXPATHLEN); 1065 1066 mutex_enter(&hwc_hash_lock); 1067 1068 /* 1069 * Lookup based on full path. 1070 * In the case of root node, ddi_pathname would return 1071 * null string so just skip calling it. 1072 * As the pathname always begins with /, no simpler 1073 * name can duplicate it. 1074 */ 1075 pathname = (dip == ddi_root_node()) ? "/" : 1076 ddi_pathname(dip, pathname_buf); 1077 ASSERT(pathname != NULL); 1078 ASSERT(*pathname == '/'); 1079 1080 if (mod_hash_find(hwc_par_hash, (mod_hash_key_t)pathname, &val) == 0) { 1081 hwc_spec_add(&list, (struct hwc_spec *)val, match_major); 1082 } 1083 1084 /* 1085 * Lookup nodename@address. 1086 * Note deviname cannot match pathname. 1087 */ 1088 deviname = ddi_deviname(dip, deviname_buf); 1089 if (*deviname != '\0') { 1090 /* 1091 * Skip leading / returned by ddi_deviname. 1092 */ 1093 ASSERT(*deviname == '/'); 1094 deviname++; 1095 if ((*deviname != '\0') && (mod_hash_find(hwc_par_hash, 1096 (mod_hash_key_t)deviname, &val) == 0)) 1097 hwc_spec_add(&list, 1098 (struct hwc_spec *)val, match_major); 1099 } 1100 1101 /* 1102 * Lookup bindingname@address. 1103 * Take care not to perform duplicate lookups. 1104 */ 1105 parname = i_ddi_parname(dip, parname_buf); 1106 if (*parname != '\0') { 1107 ASSERT(*parname != '/'); 1108 if ((strcmp(parname, deviname) != 0) && 1109 (mod_hash_find(hwc_par_hash, 1110 (mod_hash_key_t)parname, &val) == 0)) { 1111 hwc_spec_add(&list, 1112 (struct hwc_spec *)val, match_major); 1113 } 1114 } 1115 1116 /* 1117 * Lookup driver binding name 1118 */ 1119 bindname = ddi_binding_name(dip); 1120 ASSERT(*bindname != '/'); 1121 if ((strcmp(bindname, parname) != 0) && 1122 (strcmp(bindname, deviname) != 0) && 1123 (mod_hash_find(hwc_par_hash, (mod_hash_key_t)bindname, &val) == 0)) 1124 hwc_spec_add(&list, (struct hwc_spec *)val, match_major); 1125 1126 /* 1127 * Lookup driver name 1128 */ 1129 drvname = (char *)ddi_driver_name(dip); 1130 ASSERT(*drvname != '/'); 1131 if ((strcmp(drvname, bindname) != 0) && 1132 (strcmp(drvname, parname) != 0) && 1133 (strcmp(drvname, deviname) != 0) && 1134 (mod_hash_find(hwc_par_hash, (mod_hash_key_t)drvname, &val) == 0)) 1135 hwc_spec_add(&list, (struct hwc_spec *)val, match_major); 1136 1137 kmem_free(pathname_buf, 3 * MAXPATHLEN); 1138 1139 /* 1140 * Lookup classes exported by this node and lookup the 1141 * class hash table for all .conf specs 1142 */ 1143 nclass = i_ddi_get_exported_classes(dip, &classes); 1144 for (i = 0; i < nclass; i++) { 1145 if (mod_hash_find(hwc_class_hash, (mod_hash_key_t)classes[i], 1146 &val) == 0) 1147 hwc_spec_add(&list, (struct hwc_spec *)val, 1148 match_major); 1149 } 1150 i_ddi_free_exported_classes(classes, nclass); 1151 1152 mutex_exit(&hwc_hash_lock); 1153 return (list); 1154 } 1155