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 * Portions Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* 26 * Copyright (c) 2009, Intel Corporation. 27 * All rights reserved. 28 */ 29 30 /* 31 * Intel IOMMU implementation 32 * This file contains Intel IOMMU code exported 33 * to the rest of the system and code that deals 34 * with the Intel IOMMU as a whole. 35 */ 36 37 #include <sys/conf.h> 38 #include <sys/modctl.h> 39 #include <sys/pci.h> 40 #include <sys/pci_impl.h> 41 #include <sys/sysmacros.h> 42 #include <sys/ddi.h> 43 #include <sys/ddidmareq.h> 44 #include <sys/ddi_impldefs.h> 45 #include <sys/ddifm.h> 46 #include <sys/sunndi.h> 47 #include <sys/debug.h> 48 #include <sys/fm/protocol.h> 49 #include <sys/note.h> 50 #include <sys/apic.h> 51 #include <vm/hat_i86.h> 52 #include <sys/smp_impldefs.h> 53 #include <sys/spl.h> 54 #include <sys/archsystm.h> 55 #include <sys/x86_archext.h> 56 #include <sys/rootnex.h> 57 #include <sys/avl.h> 58 #include <sys/bootconf.h> 59 #include <sys/bootinfo.h> 60 #include <sys/atomic.h> 61 #include <sys/immu.h> 62 /* ########################### Globals and tunables ######################## */ 63 /* 64 * Global switches (boolean) that can be toggled either via boot options 65 * or via /etc/system or kmdb 66 */ 67 68 /* Various features */ 69 boolean_t immu_enable = B_TRUE; 70 boolean_t immu_dvma_enable = B_TRUE; 71 72 /* accessed in other files so not static */ 73 boolean_t immu_gfxdvma_enable = B_TRUE; 74 boolean_t immu_intrmap_enable = B_FALSE; 75 boolean_t immu_qinv_enable = B_FALSE; 76 77 /* various quirks that need working around */ 78 79 /* XXX We always map page 0 read/write for now */ 80 boolean_t immu_quirk_usbpage0 = B_TRUE; 81 boolean_t immu_quirk_usbrmrr = B_TRUE; 82 boolean_t immu_quirk_usbfullpa; 83 boolean_t immu_quirk_mobile4; 84 85 /* debug messages */ 86 boolean_t immu_dmar_print; 87 88 /* Tunables */ 89 int64_t immu_flush_gran = 5; 90 91 /* ############ END OPTIONS section ################ */ 92 93 /* 94 * Global used internally by Intel IOMMU code 95 */ 96 dev_info_t *root_devinfo; 97 kmutex_t immu_lock; 98 list_t immu_list; 99 void *immu_pgtable_cache; 100 boolean_t immu_setup; 101 boolean_t immu_running; 102 boolean_t immu_quiesced; 103 104 /* ######################## END Globals and tunables ###################### */ 105 /* Globals used only in this file */ 106 static char **black_array; 107 static uint_t nblacks; 108 /* ###################### Utility routines ############################# */ 109 110 /* 111 * Check if the device has mobile 4 chipset 112 */ 113 static int 114 check_mobile4(dev_info_t *dip, void *arg) 115 { 116 _NOTE(ARGUNUSED(arg)); 117 int vendor, device; 118 int *ip = (int *)arg; 119 120 ASSERT(arg); 121 122 vendor = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 123 "vendor-id", -1); 124 device = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 125 "device-id", -1); 126 127 if (vendor == 0x8086 && device == 0x2a40) { 128 *ip = B_TRUE; 129 ddi_err(DER_NOTE, dip, "IMMU: Mobile 4 chipset detected. " 130 "Force setting IOMMU write buffer"); 131 return (DDI_WALK_TERMINATE); 132 } else { 133 return (DDI_WALK_CONTINUE); 134 } 135 } 136 137 static void 138 map_bios_rsvd_mem(dev_info_t *dip) 139 { 140 struct memlist *mp; 141 int e; 142 143 memlist_read_lock(); 144 145 mp = bios_rsvd; 146 while (mp != NULL) { 147 memrng_t mrng = {0}; 148 149 ddi_err(DER_LOG, dip, "IMMU: Mapping BIOS rsvd range " 150 "[0x%" PRIx64 " - 0x%"PRIx64 "]\n", mp->ml_address, 151 mp->ml_address + mp->ml_size); 152 153 mrng.mrng_start = IMMU_ROUNDOWN(mp->ml_address); 154 mrng.mrng_npages = IMMU_ROUNDUP(mp->ml_size) / IMMU_PAGESIZE; 155 156 e = immu_dvma_map(NULL, NULL, &mrng, 0, dip, IMMU_FLAGS_MEMRNG); 157 ASSERT(e == DDI_DMA_MAPPED || e == DDI_DMA_USE_PHYSICAL); 158 159 mp = mp->ml_next; 160 } 161 162 memlist_read_unlock(); 163 } 164 165 166 /* 167 * Check if the driver requests physical mapping 168 */ 169 /*ARGSUSED*/ 170 static void 171 check_physical(dev_info_t *dip, void *arg) 172 { 173 char *val; 174 175 /* 176 * Check for the DVMA unity mapping property on the device 177 */ 178 val = NULL; 179 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 180 DDI_PROP_DONTPASS, DDI_DVMA_MAPTYPE_PROP, &val) == DDI_SUCCESS) { 181 ASSERT(val); 182 if (strcmp(val, DDI_DVMA_MAPTYPE_UNITY) != 0) { 183 ddi_err(DER_WARN, dip, "%s value \"%s\" is not valid", 184 DDI_DVMA_MAPTYPE_PROP, val); 185 } else { 186 int e; 187 188 ddi_err(DER_NOTE, dip, 189 "Using unity DVMA mapping for device"); 190 e = immu_dvma_map(NULL, NULL, NULL, 0, dip, 191 IMMU_FLAGS_UNITY); 192 /* for unity mode, map will return USE_PHYSICAL */ 193 ASSERT(e == DDI_DMA_USE_PHYSICAL); 194 } 195 ddi_prop_free(val); 196 } 197 } 198 199 /* 200 * Check if the device is USB controller 201 */ 202 /*ARGSUSED*/ 203 static void 204 check_usb(dev_info_t *dip, void *arg) 205 { 206 const char *drv = ddi_driver_name(dip); 207 208 if (drv == NULL || 209 (strcmp(drv, "uhci") != 0 && strcmp(drv, "ohci") != 0 && 210 strcmp(drv, "ehci") != 0)) { 211 return; 212 } 213 214 /* This must come first since it does unity mapping */ 215 if (immu_quirk_usbfullpa == B_TRUE) { 216 int e; 217 ddi_err(DER_NOTE, dip, "Applying USB FULL PA quirk"); 218 e = immu_dvma_map(NULL, NULL, NULL, 0, dip, IMMU_FLAGS_UNITY); 219 /* for unity mode, map will return USE_PHYSICAL */ 220 ASSERT(e == DDI_DMA_USE_PHYSICAL); 221 } 222 223 if (immu_quirk_usbrmrr == B_TRUE) { 224 ddi_err(DER_LOG, dip, "Applying USB RMRR quirk"); 225 map_bios_rsvd_mem(dip); 226 } 227 } 228 229 /* 230 * Check if the device is a LPC device 231 */ 232 /*ARGSUSED*/ 233 static void 234 check_lpc(dev_info_t *dip, void *arg) 235 { 236 immu_devi_t *immu_devi; 237 238 immu_devi = immu_devi_get(dip); 239 ASSERT(immu_devi); 240 if (immu_devi->imd_lpc == B_TRUE) { 241 ddi_err(DER_LOG, dip, "IMMU: Found LPC device"); 242 /* This will put the immu_devi on the LPC "specials" list */ 243 (void) immu_dvma_get_immu(dip, IMMU_FLAGS_SLEEP); 244 } 245 } 246 247 /* 248 * Check if the device is a GFX device 249 */ 250 /*ARGSUSED*/ 251 static void 252 check_gfx(dev_info_t *dip, void *arg) 253 { 254 immu_devi_t *immu_devi; 255 int e; 256 257 immu_devi = immu_devi_get(dip); 258 ASSERT(immu_devi); 259 if (immu_devi->imd_display == B_TRUE) { 260 ddi_err(DER_LOG, dip, "IMMU: Found GFX device"); 261 /* This will put the immu_devi on the GFX "specials" list */ 262 (void) immu_dvma_get_immu(dip, IMMU_FLAGS_SLEEP); 263 e = immu_dvma_map(NULL, NULL, NULL, 0, dip, IMMU_FLAGS_UNITY); 264 /* for unity mode, map will return USE_PHYSICAL */ 265 ASSERT(e == DDI_DMA_USE_PHYSICAL); 266 } 267 } 268 269 static void 270 walk_tree(int (*f)(dev_info_t *, void *), void *arg) 271 { 272 int count; 273 274 ndi_devi_enter(root_devinfo, &count); 275 ddi_walk_devs(ddi_get_child(root_devinfo), f, arg); 276 ndi_devi_exit(root_devinfo, count); 277 } 278 279 static int 280 check_pre_setup_quirks(dev_info_t *dip, void *arg) 281 { 282 /* just 1 check right now */ 283 return (check_mobile4(dip, arg)); 284 } 285 286 static int 287 check_pre_startup_quirks(dev_info_t *dip, void *arg) 288 { 289 if (immu_devi_set(dip, IMMU_FLAGS_SLEEP) != DDI_SUCCESS) { 290 ddi_err(DER_PANIC, dip, "Failed to get immu_devi"); 291 } 292 293 check_gfx(dip, arg); 294 295 check_lpc(dip, arg); 296 297 check_usb(dip, arg); 298 299 check_physical(dip, arg); 300 301 return (DDI_WALK_CONTINUE); 302 } 303 304 static void 305 pre_setup_quirks(void) 306 { 307 walk_tree(check_pre_setup_quirks, &immu_quirk_mobile4); 308 } 309 310 static void 311 pre_startup_quirks(void) 312 { 313 walk_tree(check_pre_startup_quirks, NULL); 314 315 immu_dmar_rmrr_map(); 316 } 317 318 /* 319 * get_conf_opt() 320 * get a rootnex.conf setting (always a boolean) 321 */ 322 static void 323 get_conf_opt(char *bopt, boolean_t *kvar) 324 { 325 char *val = NULL; 326 327 ASSERT(bopt); 328 ASSERT(kvar); 329 330 /* 331 * Check the rootnex.conf property 332 * Fake up a dev_t since searching the global 333 * property list needs it 334 */ 335 if (ddi_prop_lookup_string(makedevice(ddi_name_to_major("rootnex"), 0), 336 root_devinfo, DDI_PROP_DONTPASS | DDI_PROP_ROOTNEX_GLOBAL, 337 bopt, &val) != DDI_PROP_SUCCESS) { 338 return; 339 } 340 341 ASSERT(val); 342 if (strcmp(val, "true") == 0) { 343 *kvar = B_TRUE; 344 } else if (strcmp(val, "false") == 0) { 345 *kvar = B_FALSE; 346 } else { 347 ddi_err(DER_WARN, NULL, "rootnex.conf switch %s=\"%s\" ", 348 "is not set to true or false. Ignoring option.", 349 bopt, val); 350 } 351 ddi_prop_free(val); 352 } 353 354 /* 355 * get_bootopt() 356 * check a boot option (always a boolean) 357 */ 358 static void 359 get_bootopt(char *bopt, boolean_t *kvar) 360 { 361 char *val = NULL; 362 363 ASSERT(bopt); 364 ASSERT(kvar); 365 366 /* 367 * All boot options set at the GRUB menu become 368 * properties on the rootnex. 369 */ 370 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, root_devinfo, 371 DDI_PROP_DONTPASS, bopt, &val) == DDI_SUCCESS) { 372 ASSERT(val); 373 if (strcmp(val, "true") == 0) { 374 *kvar = B_TRUE; 375 } else if (strcmp(val, "false") == 0) { 376 *kvar = B_FALSE; 377 } else { 378 ddi_err(DER_WARN, NULL, "boot option %s=\"%s\" ", 379 "is not set to true or false. Ignoring option.", 380 bopt, val); 381 } 382 ddi_prop_free(val); 383 } 384 } 385 386 static void 387 get_conf_tunables(char *bopt, int64_t *ivar) 388 { 389 int64_t *iarray; 390 uint_t n; 391 392 /* 393 * Check the rootnex.conf property 394 * Fake up a dev_t since searching the global 395 * property list needs it 396 */ 397 if (ddi_prop_lookup_int64_array( 398 makedevice(ddi_name_to_major("rootnex"), 0), root_devinfo, 399 DDI_PROP_DONTPASS | DDI_PROP_ROOTNEX_GLOBAL, bopt, 400 &iarray, &n) != DDI_PROP_SUCCESS) { 401 return; 402 } 403 404 if (n != 1) { 405 ddi_err(DER_WARN, NULL, "More than one value specified for " 406 "%s property. Ignoring and using default", 407 "immu-flush-gran"); 408 ddi_prop_free(iarray); 409 return; 410 } 411 412 if (iarray[0] < 0) { 413 ddi_err(DER_WARN, NULL, "Negative value specified for " 414 "%s property. Inoring and Using default value", 415 "immu-flush-gran"); 416 ddi_prop_free(iarray); 417 return; 418 } 419 420 *ivar = iarray[0]; 421 422 ddi_prop_free(iarray); 423 } 424 425 static void 426 read_conf_options(void) 427 { 428 /* enable/disable options */ 429 get_conf_opt("immu-enable", &immu_enable); 430 get_conf_opt("immu-dvma-enable", &immu_dvma_enable); 431 get_conf_opt("immu-gfxdvma-enable", &immu_gfxdvma_enable); 432 get_conf_opt("immu-intrmap-enable", &immu_intrmap_enable); 433 get_conf_opt("immu-qinv-enable", &immu_qinv_enable); 434 435 /* workaround switches */ 436 get_conf_opt("immu-quirk-usbpage0", &immu_quirk_usbpage0); 437 get_conf_opt("immu-quirk-usbfullpa", &immu_quirk_usbfullpa); 438 get_conf_opt("immu-quirk-usbrmrr", &immu_quirk_usbrmrr); 439 440 /* debug printing */ 441 get_conf_opt("immu-dmar-print", &immu_dmar_print); 442 443 /* get tunables */ 444 get_conf_tunables("immu-flush-gran", &immu_flush_gran); 445 } 446 447 static void 448 read_boot_options(void) 449 { 450 /* enable/disable options */ 451 get_bootopt("immu-enable", &immu_enable); 452 get_bootopt("immu-dvma-enable", &immu_dvma_enable); 453 get_bootopt("immu-gfxdvma-enable", &immu_gfxdvma_enable); 454 get_bootopt("immu-intrmap-enable", &immu_intrmap_enable); 455 get_bootopt("immu-qinv-enable", &immu_qinv_enable); 456 457 /* workaround switches */ 458 get_bootopt("immu-quirk-usbpage0", &immu_quirk_usbpage0); 459 get_bootopt("immu-quirk-usbfullpa", &immu_quirk_usbfullpa); 460 get_bootopt("immu-quirk-usbrmrr", &immu_quirk_usbrmrr); 461 462 /* debug printing */ 463 get_bootopt("immu-dmar-print", &immu_dmar_print); 464 } 465 466 /* 467 * Note, this will not catch hardware not enumerated 468 * in early boot 469 */ 470 static boolean_t 471 blacklisted_driver(void) 472 { 473 char **strptr; 474 int i; 475 major_t maj; 476 477 ASSERT((black_array == NULL) ^ (nblacks != 0)); 478 479 /* need at least 2 strings */ 480 if (nblacks < 2) { 481 return (B_FALSE); 482 } 483 484 for (i = 0; nblacks - i > 1; i++) { 485 strptr = &black_array[i]; 486 if (strcmp(*strptr++, "DRIVER") == 0) { 487 if ((maj = ddi_name_to_major(*strptr++)) 488 != DDI_MAJOR_T_NONE) { 489 /* is there hardware bound to this drvr */ 490 if (devnamesp[maj].dn_head != NULL) { 491 return (B_TRUE); 492 } 493 } 494 i += 1; /* for loop adds 1, so add only 1 here */ 495 } 496 } 497 498 return (B_FALSE); 499 } 500 501 static boolean_t 502 blacklisted_smbios(void) 503 { 504 id_t smid; 505 smbios_hdl_t *smhdl; 506 smbios_info_t sminf; 507 smbios_system_t smsys; 508 char *mfg, *product, *version; 509 char **strptr; 510 int i; 511 512 ASSERT((black_array == NULL) ^ (nblacks != 0)); 513 514 /* need at least 4 strings for this setting */ 515 if (nblacks < 4) { 516 return (B_FALSE); 517 } 518 519 smhdl = smbios_open(NULL, SMB_VERSION, ksmbios_flags, NULL); 520 if (smhdl == NULL || 521 (smid = smbios_info_system(smhdl, &smsys)) == SMB_ERR || 522 smbios_info_common(smhdl, smid, &sminf) == SMB_ERR) { 523 return (B_FALSE); 524 } 525 526 mfg = (char *)sminf.smbi_manufacturer; 527 product = (char *)sminf.smbi_product; 528 version = (char *)sminf.smbi_version; 529 530 ddi_err(DER_CONT, NULL, "?System SMBIOS information:\n"); 531 ddi_err(DER_CONT, NULL, "?Manufacturer = <%s>\n", mfg); 532 ddi_err(DER_CONT, NULL, "?Product = <%s>\n", product); 533 ddi_err(DER_CONT, NULL, "?Version = <%s>\n", version); 534 535 for (i = 0; nblacks - i > 3; i++) { 536 strptr = &black_array[i]; 537 if (strcmp(*strptr++, "SMBIOS") == 0) { 538 if (strcmp(*strptr++, mfg) == 0 && 539 ((char *)strptr == '\0' || 540 strcmp(*strptr++, product) == 0) && 541 ((char *)strptr == '\0' || 542 strcmp(*strptr++, version) == 0)) { 543 return (B_TRUE); 544 } 545 i += 3; 546 } 547 } 548 549 return (B_FALSE); 550 } 551 552 static boolean_t 553 blacklisted_acpi(void) 554 { 555 ASSERT((black_array == NULL) ^ (nblacks != 0)); 556 if (nblacks == 0) { 557 return (B_FALSE); 558 } 559 560 return (immu_dmar_blacklisted(black_array, nblacks)); 561 } 562 563 /* 564 * Check if system is blacklisted by Intel IOMMU driver 565 * i.e. should Intel IOMMU be disabled on this system 566 * Currently a system can be blacklistd based on the 567 * following bases: 568 * 569 * 1. DMAR ACPI table information. 570 * This information includes things like 571 * manufacturer and revision number. If rootnex.conf 572 * has matching info set in its blacklist property 573 * then Intel IOMMu will be disabled 574 * 575 * 2. SMBIOS information 576 * 577 * 3. Driver installed - useful if a particular 578 * driver or hardware is toxic if Intel IOMMU 579 * is turned on. 580 */ 581 582 static void 583 blacklist_setup(void) 584 { 585 char **string_array; 586 uint_t nstrings; 587 588 /* 589 * Check the rootnex.conf blacklist property. 590 * Fake up a dev_t since searching the global 591 * property list needs it 592 */ 593 if (ddi_prop_lookup_string_array( 594 makedevice(ddi_name_to_major("rootnex"), 0), root_devinfo, 595 DDI_PROP_DONTPASS | DDI_PROP_ROOTNEX_GLOBAL, "immu-blacklist", 596 &string_array, &nstrings) != DDI_PROP_SUCCESS) { 597 return; 598 } 599 600 /* smallest blacklist criteria works with multiples of 2 */ 601 if (nstrings % 2 != 0) { 602 ddi_err(DER_WARN, NULL, "Invalid IOMMU blacklist " 603 "rootnex.conf: number of strings must be a " 604 "multiple of 2"); 605 ddi_prop_free(string_array); 606 return; 607 } 608 609 black_array = string_array; 610 nblacks = nstrings; 611 } 612 613 static void 614 blacklist_destroy(void) 615 { 616 if (black_array) { 617 ddi_prop_free(black_array); 618 black_array = NULL; 619 nblacks = 0; 620 } 621 622 ASSERT(black_array == NULL); 623 ASSERT(nblacks == 0); 624 } 625 626 627 /* 628 * Now set all the fields in the order they are defined 629 * We do this only as a defensive-coding practice, it is 630 * not a correctness issue. 631 */ 632 static void * 633 immu_state_alloc(int seg, void *dmar_unit) 634 { 635 immu_t *immu; 636 637 dmar_unit = immu_dmar_walk_units(seg, dmar_unit); 638 if (dmar_unit == NULL) { 639 /* No more IOMMUs in this segment */ 640 return (NULL); 641 } 642 643 immu = kmem_zalloc(sizeof (immu_t), KM_SLEEP); 644 645 mutex_init(&(immu->immu_lock), NULL, MUTEX_DRIVER, NULL); 646 647 mutex_enter(&(immu->immu_lock)); 648 649 immu->immu_dmar_unit = dmar_unit; 650 immu->immu_name = ddi_strdup(immu_dmar_unit_name(dmar_unit), 651 KM_SLEEP); 652 immu->immu_dip = immu_dmar_unit_dip(dmar_unit); 653 654 /* 655 * the immu_intr_lock mutex is grabbed by the IOMMU 656 * unit's interrupt handler so we need to use an 657 * interrupt cookie for the mutex 658 */ 659 mutex_init(&(immu->immu_intr_lock), NULL, MUTEX_DRIVER, 660 (void *)ipltospl(IMMU_INTR_IPL)); 661 662 /* IOMMU regs related */ 663 mutex_init(&(immu->immu_regs_lock), NULL, MUTEX_DEFAULT, NULL); 664 cv_init(&(immu->immu_regs_cv), NULL, CV_DEFAULT, NULL); 665 immu->immu_regs_busy = B_FALSE; 666 667 /* DVMA related */ 668 immu->immu_dvma_coherent = B_FALSE; 669 670 /* DVMA context related */ 671 rw_init(&(immu->immu_ctx_rwlock), NULL, RW_DEFAULT, NULL); 672 673 /* DVMA domain related */ 674 list_create(&(immu->immu_domain_list), sizeof (domain_t), 675 offsetof(domain_t, dom_immu_node)); 676 677 /* DVMA special device lists */ 678 immu->immu_dvma_gfx_only = B_FALSE; 679 list_create(&(immu->immu_dvma_lpc_list), sizeof (immu_devi_t), 680 offsetof(immu_devi_t, imd_spc_node)); 681 list_create(&(immu->immu_dvma_gfx_list), sizeof (immu_devi_t), 682 offsetof(immu_devi_t, imd_spc_node)); 683 684 /* interrupt remapping related */ 685 mutex_init(&(immu->immu_intrmap_lock), NULL, MUTEX_DEFAULT, NULL); 686 687 /* qinv related */ 688 mutex_init(&(immu->immu_qinv_lock), NULL, MUTEX_DEFAULT, NULL); 689 690 /* 691 * insert this immu unit into the system-wide list 692 */ 693 list_insert_tail(&immu_list, immu); 694 695 mutex_exit(&(immu->immu_lock)); 696 697 ddi_err(DER_LOG, immu->immu_dip, "IMMU: unit setup"); 698 699 immu_dmar_set_immu(dmar_unit, immu); 700 701 return (dmar_unit); 702 } 703 704 static void 705 immu_subsystems_setup(void) 706 { 707 int seg; 708 void *unit_hdl; 709 710 ddi_err(DER_VERB, NULL, 711 "Creating state structures for Intel IOMMU units\n"); 712 713 ASSERT(immu_setup == B_FALSE); 714 ASSERT(immu_running == B_FALSE); 715 716 mutex_init(&immu_lock, NULL, MUTEX_DEFAULT, NULL); 717 list_create(&immu_list, sizeof (immu_t), offsetof(immu_t, immu_node)); 718 719 mutex_enter(&immu_lock); 720 721 ASSERT(immu_pgtable_cache == NULL); 722 723 immu_pgtable_cache = kmem_cache_create("immu_pgtable_cache", 724 sizeof (pgtable_t), 0, 725 pgtable_ctor, pgtable_dtor, NULL, NULL, NULL, 0); 726 727 unit_hdl = NULL; 728 for (seg = 0; seg < IMMU_MAXSEG; seg++) { 729 while (unit_hdl = immu_state_alloc(seg, unit_hdl)) { 730 ; 731 } 732 } 733 734 immu_regs_setup(&immu_list); /* subsequent code needs this first */ 735 immu_dvma_setup(&immu_list); 736 immu_intrmap_setup(&immu_list); 737 immu_qinv_setup(&immu_list); 738 739 mutex_exit(&immu_lock); 740 } 741 742 /* 743 * immu_subsystems_startup() 744 * startup all units that were setup 745 */ 746 static void 747 immu_subsystems_startup(void) 748 { 749 immu_t *immu; 750 751 mutex_enter(&immu_lock); 752 753 ASSERT(immu_setup == B_TRUE); 754 ASSERT(immu_running == B_FALSE); 755 756 immu_dmar_startup(); 757 758 immu = list_head(&immu_list); 759 for (; immu; immu = list_next(&immu_list, immu)) { 760 761 mutex_enter(&(immu->immu_lock)); 762 763 immu_intr_register(immu); 764 immu_dvma_startup(immu); 765 immu_intrmap_startup(immu); 766 immu_qinv_startup(immu); 767 768 /* 769 * Set IOMMU unit's regs to do 770 * the actual startup. This will 771 * set immu->immu_running field 772 * if the unit is successfully 773 * started 774 */ 775 immu_regs_startup(immu); 776 777 mutex_exit(&(immu->immu_lock)); 778 } 779 780 mutex_exit(&immu_lock); 781 } 782 783 /* ################## Intel IOMMU internal interfaces ###################### */ 784 785 /* 786 * Internal interfaces for IOMMU code (i.e. not exported to rootnex 787 * or rest of system) 788 */ 789 790 /* 791 * ddip can be NULL, in which case we walk up until we find the root dip 792 * NOTE: We never visit the root dip since its not a hardware node 793 */ 794 int 795 immu_walk_ancestor( 796 dev_info_t *rdip, 797 dev_info_t *ddip, 798 int (*func)(dev_info_t *, void *arg), 799 void *arg, 800 int *lvlp, 801 immu_flags_t immu_flags) 802 { 803 dev_info_t *pdip; 804 int level; 805 int error = DDI_SUCCESS; 806 807 ASSERT(root_devinfo); 808 ASSERT(rdip); 809 ASSERT(rdip != root_devinfo); 810 ASSERT(func); 811 812 /* ddip and immu can be NULL */ 813 814 /* Hold rdip so that branch is not detached */ 815 ndi_hold_devi(rdip); 816 for (pdip = rdip, level = 1; pdip && pdip != root_devinfo; 817 pdip = ddi_get_parent(pdip), level++) { 818 819 if (immu_devi_set(pdip, immu_flags) != DDI_SUCCESS) { 820 error = DDI_FAILURE; 821 break; 822 } 823 if (func(pdip, arg) == DDI_WALK_TERMINATE) { 824 break; 825 } 826 if (immu_flags & IMMU_FLAGS_DONTPASS) { 827 break; 828 } 829 if (pdip == ddip) { 830 break; 831 } 832 } 833 834 ndi_rele_devi(rdip); 835 836 if (lvlp) 837 *lvlp = level; 838 839 return (error); 840 } 841 842 /* ######################## Intel IOMMU entry points ####################### */ 843 /* 844 * immu_init() 845 * called from rootnex_attach(). setup but don't startup the Intel IOMMU 846 * This is the first function called in Intel IOMMU code 847 */ 848 void 849 immu_init(void) 850 { 851 char *phony_reg = "A thing of beauty is a joy forever"; 852 853 /* Set some global shorthands that are needed by all of IOMMU code */ 854 ASSERT(root_devinfo == NULL); 855 root_devinfo = ddi_root_node(); 856 857 /* 858 * Intel IOMMU only supported only if MMU(CPU) page size is == 859 * IOMMU pages size. 860 */ 861 /*LINTED*/ 862 if (MMU_PAGESIZE != IMMU_PAGESIZE) { 863 ddi_err(DER_WARN, NULL, 864 "MMU page size (%d) is not equal to\n" 865 "IOMMU page size (%d). " 866 "Disabling Intel IOMMU. ", 867 MMU_PAGESIZE, IMMU_PAGESIZE); 868 immu_enable = B_FALSE; 869 return; 870 } 871 872 /* 873 * Read rootnex.conf options. Do this before 874 * boot options so boot options can override .conf options. 875 */ 876 read_conf_options(); 877 878 /* 879 * retrieve the Intel IOMMU boot options. 880 * Do this before parsing immu ACPI table 881 * as a boot option could potentially affect 882 * ACPI parsing. 883 */ 884 ddi_err(DER_CONT, NULL, "?Reading Intel IOMMU boot options\n"); 885 read_boot_options(); 886 887 /* 888 * Check the IOMMU enable boot-option first. 889 * This is so that we can skip parsing the ACPI table 890 * if necessary because that may cause problems in 891 * systems with buggy BIOS or ACPI tables 892 */ 893 if (immu_enable == B_FALSE) { 894 return; 895 } 896 897 /* 898 * Next, check if the system even has an Intel IOMMU 899 * We use the presence or absence of the IOMMU ACPI 900 * table to detect Intel IOMMU. 901 */ 902 if (immu_dmar_setup() != DDI_SUCCESS) { 903 immu_enable = B_FALSE; 904 return; 905 } 906 907 /* 908 * Check blacklists 909 */ 910 blacklist_setup(); 911 912 if (blacklisted_smbios() == B_TRUE) { 913 blacklist_destroy(); 914 immu_enable = B_FALSE; 915 return; 916 } 917 918 if (blacklisted_driver() == B_TRUE) { 919 blacklist_destroy(); 920 immu_enable = B_FALSE; 921 return; 922 } 923 924 /* 925 * Read the "raw" DMAR ACPI table to get information 926 * and convert into a form we can use. 927 */ 928 if (immu_dmar_parse() != DDI_SUCCESS) { 929 blacklist_destroy(); 930 immu_enable = B_FALSE; 931 return; 932 } 933 934 /* 935 * now that we have processed the ACPI table 936 * check if we need to blacklist this system 937 * based on ACPI info 938 */ 939 if (blacklisted_acpi() == B_TRUE) { 940 immu_dmar_destroy(); 941 blacklist_destroy(); 942 immu_enable = B_FALSE; 943 return; 944 } 945 946 blacklist_destroy(); 947 948 /* 949 * Check if system has HW quirks. 950 */ 951 pre_setup_quirks(); 952 953 /* Now do the rest of the setup */ 954 immu_subsystems_setup(); 955 956 /* 957 * Now that the IMMU is setup, create a phony 958 * reg prop so that suspend/resume works 959 */ 960 if (ddi_prop_update_byte_array(DDI_DEV_T_NONE, root_devinfo, "reg", 961 (uchar_t *)phony_reg, strlen(phony_reg) + 1) != DDI_PROP_SUCCESS) { 962 ddi_err(DER_PANIC, NULL, "Failed to create reg prop for " 963 "rootnex node"); 964 /*NOTREACHED*/ 965 } 966 967 immu_setup = B_TRUE; 968 } 969 970 /* 971 * immu_startup() 972 * called directly by boot code to startup 973 * all units of the IOMMU 974 */ 975 void 976 immu_startup(void) 977 { 978 /* 979 * If IOMMU is disabled, do nothing 980 */ 981 if (immu_enable == B_FALSE) { 982 return; 983 } 984 985 if (immu_setup == B_FALSE) { 986 ddi_err(DER_WARN, NULL, "Intel IOMMU not setup, " 987 "skipping IOMU startup"); 988 return; 989 } 990 991 pre_startup_quirks(); 992 993 ddi_err(DER_CONT, NULL, 994 "?Starting Intel IOMMU (dmar) units...\n"); 995 996 immu_subsystems_startup(); 997 998 immu_running = B_TRUE; 999 } 1000 1001 /* 1002 * immu_map_sgl() 1003 * called from rootnex_coredma_bindhdl() when Intel 1004 * IOMMU is enabled to build DVMA cookies and map them. 1005 */ 1006 int 1007 immu_map_sgl(ddi_dma_impl_t *hp, struct ddi_dma_req *dmareq, 1008 int prealloc_count, dev_info_t *rdip) 1009 { 1010 if (immu_running == B_FALSE) { 1011 return (DDI_DMA_USE_PHYSICAL); 1012 } 1013 1014 return (immu_dvma_map(hp, dmareq, NULL, prealloc_count, rdip, 1015 IMMU_FLAGS_DMAHDL)); 1016 } 1017 1018 /* 1019 * immu_unmap_sgl() 1020 * called from rootnex_coredma_unbindhdl(), to unmap DVMA 1021 * cookies and free them 1022 */ 1023 int 1024 immu_unmap_sgl(ddi_dma_impl_t *hp, dev_info_t *rdip) 1025 { 1026 if (immu_running == B_FALSE) { 1027 return (DDI_DMA_USE_PHYSICAL); 1028 } 1029 1030 return (immu_dvma_unmap(hp, rdip)); 1031 } 1032 1033 /* 1034 * Hook to notify IOMMU code of device tree changes 1035 */ 1036 void 1037 immu_device_tree_changed(void) 1038 { 1039 if (immu_setup == B_FALSE) { 1040 return; 1041 } 1042 1043 ddi_err(DER_WARN, NULL, "Intel IOMMU currently " 1044 "does not use device tree updates"); 1045 } 1046 1047 /* 1048 * Hook to notify IOMMU code of memory changes 1049 */ 1050 void 1051 immu_physmem_update(uint64_t addr, uint64_t size) 1052 { 1053 if (immu_setup == B_FALSE) { 1054 return; 1055 } 1056 immu_dvma_physmem_update(addr, size); 1057 } 1058 1059 /* 1060 * immu_quiesce() 1061 * quiesce all units that are running 1062 */ 1063 int 1064 immu_quiesce(void) 1065 { 1066 immu_t *immu; 1067 int ret = DDI_SUCCESS; 1068 1069 mutex_enter(&immu_lock); 1070 1071 if (immu_running == B_FALSE) 1072 return (DDI_SUCCESS); 1073 1074 ASSERT(immu_setup == B_TRUE); 1075 1076 immu = list_head(&immu_list); 1077 for (; immu; immu = list_next(&immu_list, immu)) { 1078 1079 /* if immu is not running, we dont quiesce */ 1080 if (immu->immu_regs_running == B_FALSE) 1081 continue; 1082 1083 /* flush caches */ 1084 rw_enter(&(immu->immu_ctx_rwlock), RW_WRITER); 1085 immu_regs_context_flush(immu, 0, 0, 0, CONTEXT_GLOBAL); 1086 rw_exit(&(immu->immu_ctx_rwlock)); 1087 immu_regs_iotlb_flush(immu, 0, 0, 0, 0, IOTLB_GLOBAL); 1088 immu_regs_wbf_flush(immu); 1089 1090 mutex_enter(&(immu->immu_lock)); 1091 1092 /* 1093 * Set IOMMU unit's regs to do 1094 * the actual shutdown. 1095 */ 1096 immu_regs_shutdown(immu); 1097 immu_regs_suspend(immu); 1098 1099 /* if immu is still running, we failed */ 1100 if (immu->immu_regs_running == B_TRUE) 1101 ret = DDI_FAILURE; 1102 else 1103 immu->immu_regs_quiesced = B_TRUE; 1104 1105 mutex_exit(&(immu->immu_lock)); 1106 } 1107 mutex_exit(&immu_lock); 1108 1109 if (ret == DDI_SUCCESS) { 1110 immu_running = B_FALSE; 1111 immu_quiesced = B_TRUE; 1112 } 1113 1114 return (ret); 1115 } 1116 1117 /* 1118 * immu_unquiesce() 1119 * unquiesce all units 1120 */ 1121 int 1122 immu_unquiesce(void) 1123 { 1124 immu_t *immu; 1125 int ret = DDI_SUCCESS; 1126 1127 mutex_enter(&immu_lock); 1128 1129 if (immu_quiesced == B_FALSE) 1130 return (DDI_SUCCESS); 1131 1132 ASSERT(immu_setup == B_TRUE); 1133 ASSERT(immu_running == B_FALSE); 1134 1135 immu = list_head(&immu_list); 1136 for (; immu; immu = list_next(&immu_list, immu)) { 1137 1138 mutex_enter(&(immu->immu_lock)); 1139 1140 /* if immu was not quiesced, i.e was not running before */ 1141 if (immu->immu_regs_quiesced == B_FALSE) { 1142 mutex_exit(&(immu->immu_lock)); 1143 continue; 1144 } 1145 1146 if (immu_regs_resume(immu) != DDI_SUCCESS) { 1147 ret = DDI_FAILURE; 1148 mutex_exit(&(immu->immu_lock)); 1149 continue; 1150 } 1151 1152 /* flush caches before unquiesce */ 1153 rw_enter(&(immu->immu_ctx_rwlock), RW_WRITER); 1154 immu_regs_context_flush(immu, 0, 0, 0, CONTEXT_GLOBAL); 1155 rw_exit(&(immu->immu_ctx_rwlock)); 1156 immu_regs_iotlb_flush(immu, 0, 0, 0, 0, IOTLB_GLOBAL); 1157 1158 /* 1159 * Set IOMMU unit's regs to do 1160 * the actual startup. This will 1161 * set immu->immu_regs_running field 1162 * if the unit is successfully 1163 * started 1164 */ 1165 immu_regs_startup(immu); 1166 1167 if (immu->immu_regs_running == B_FALSE) { 1168 ret = DDI_FAILURE; 1169 } else { 1170 immu_quiesced = B_TRUE; 1171 immu_running = B_TRUE; 1172 immu->immu_regs_quiesced = B_FALSE; 1173 } 1174 1175 mutex_exit(&(immu->immu_lock)); 1176 } 1177 1178 mutex_exit(&immu_lock); 1179 1180 return (ret); 1181 } 1182 1183 /* ############## END Intel IOMMU entry points ################## */ 1184