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.
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.
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]
22 * Portions Copyright (c) 2010, Oracle and/or its affiliates.
23 * All rights reserved.
26 * Copyright (c) 2009, Intel Corporation.
27 * All rights reserved.
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.
38 #include <sys/modctl.h>
40 #include <sys/pci_impl.h>
41 #include <sys/sysmacros.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>
51 #include <vm/hat_i86.h>
52 #include <sys/smp_impldefs.h>
54 #include <sys/archsystm.h>
55 #include <sys/x86_archext.h>
57 #include <sys/bootconf.h>
58 #include <sys/bootinfo.h>
59 #include <sys/atomic.h>
61 /* ########################### Globals and tunables ######################## */
63 * Global switches (boolean) that can be toggled either via boot options
64 * or via /etc/system or kmdb
67 /* Various features */
68 boolean_t immu_enable
= B_TRUE
;
69 boolean_t immu_dvma_enable
= B_TRUE
;
71 /* accessed in other files so not static */
72 boolean_t immu_gfxdvma_enable
= B_TRUE
;
73 boolean_t immu_intrmap_enable
= B_FALSE
;
74 boolean_t immu_qinv_enable
= B_TRUE
;
76 /* various quirks that need working around */
78 /* XXX We always map page 0 read/write for now */
79 boolean_t immu_quirk_usbpage0
= B_TRUE
;
80 boolean_t immu_quirk_usbrmrr
= B_TRUE
;
81 boolean_t immu_quirk_usbfullpa
;
82 boolean_t immu_quirk_mobile4
;
85 boolean_t immu_dmar_print
;
88 int64_t immu_flush_gran
= 5;
90 immu_flags_t immu_global_dvma_flags
;
92 /* ############ END OPTIONS section ################ */
95 * Global used internally by Intel IOMMU code
97 dev_info_t
*root_devinfo
;
100 boolean_t immu_setup
;
101 boolean_t immu_running
;
102 boolean_t immu_quiesced
;
104 /* ######################## END Globals and tunables ###################### */
105 /* Globals used only in this file */
106 static char **black_array
;
107 static uint_t nblacks
;
109 static char **unity_driver_array
;
110 static uint_t nunity
;
111 static char **xlate_driver_array
;
112 static uint_t nxlate
;
114 static char **premap_driver_array
;
115 static uint_t npremap
;
116 static char **nopremap_driver_array
;
117 static uint_t nnopremap
;
118 /* ###################### Utility routines ############################# */
121 * Check if the device has mobile 4 chipset
124 check_mobile4(dev_info_t
*dip
, void *arg
)
126 _NOTE(ARGUNUSED(arg
));
128 int *ip
= (int *)arg
;
130 vendor
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
132 device
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
135 if (vendor
== 0x8086 && device
== 0x2a40) {
137 ddi_err(DER_NOTE
, dip
, "iommu: Mobile 4 chipset detected. "
138 "Force setting IOMMU write buffer");
139 return (DDI_WALK_TERMINATE
);
141 return (DDI_WALK_CONTINUE
);
146 map_bios_rsvd_mem(dev_info_t
*dip
)
151 * Make sure the domain for the device is set up before
154 (void) immu_dvma_device_setup(dip
, 0);
162 ddi_err(DER_LOG
, dip
, "iommu: Mapping BIOS rsvd range "
163 "[0x%" PRIx64
" - 0x%"PRIx64
"]\n", mp
->ml_address
,
164 mp
->ml_address
+ mp
->ml_size
);
166 mrng
.mrng_start
= IMMU_ROUNDOWN(mp
->ml_address
);
167 mrng
.mrng_npages
= IMMU_ROUNDUP(mp
->ml_size
) / IMMU_PAGESIZE
;
169 (void) immu_map_memrange(dip
, &mrng
);
174 memlist_read_unlock();
179 * Check if the driver requests a specific type of mapping.
183 check_conf(dev_info_t
*dip
, void *arg
)
185 immu_devi_t
*immu_devi
;
188 int hasmapprop
= 0, haspreprop
= 0;
189 boolean_t old_premap
;
192 * Only PCI devices can use an IOMMU. Legacy ISA devices
193 * are handled in check_lpc.
195 if (!DEVI_IS_PCI(dip
))
198 dname
= ddi_driver_name(dip
);
201 immu_devi
= immu_devi_get(dip
);
203 for (i
= 0; i
< nunity
; i
++) {
204 if (strcmp(unity_driver_array
[i
], dname
) == 0) {
206 immu_devi
->imd_dvma_flags
|= IMMU_FLAGS_UNITY
;
210 for (i
= 0; i
< nxlate
; i
++) {
211 if (strcmp(xlate_driver_array
[i
], dname
) == 0) {
213 immu_devi
->imd_dvma_flags
&= ~IMMU_FLAGS_UNITY
;
217 old_premap
= immu_devi
->imd_use_premap
;
219 for (i
= 0; i
< nnopremap
; i
++) {
220 if (strcmp(nopremap_driver_array
[i
], dname
) == 0) {
222 immu_devi
->imd_use_premap
= B_FALSE
;
226 for (i
= 0; i
< npremap
; i
++) {
227 if (strcmp(premap_driver_array
[i
], dname
) == 0) {
229 immu_devi
->imd_use_premap
= B_TRUE
;
234 * Report if we changed the value from the default.
236 if (hasmapprop
&& (immu_devi
->imd_dvma_flags
^ immu_global_dvma_flags
))
237 ddi_err(DER_LOG
, dip
, "using %s DVMA mapping",
238 immu_devi
->imd_dvma_flags
& IMMU_FLAGS_UNITY
?
239 DDI_DVMA_MAPTYPE_UNITY
: DDI_DVMA_MAPTYPE_XLATE
);
241 if (haspreprop
&& (immu_devi
->imd_use_premap
!= old_premap
))
242 ddi_err(DER_LOG
, dip
, "%susing premapped DVMA space",
243 immu_devi
->imd_use_premap
? "" : "not ");
247 * Check if the device is USB controller
251 check_usb(dev_info_t
*dip
, void *arg
)
253 const char *drv
= ddi_driver_name(dip
);
254 immu_devi_t
*immu_devi
;
258 * It's not clear if xHCI really needs these quirks; however, to be on
259 * the safe side until we know for certain we add it to the list below.
262 (strcmp(drv
, "uhci") != 0 && strcmp(drv
, "ohci") != 0 &&
263 strcmp(drv
, "ehci") != 0 && strcmp(drv
, "xhci") != 0)) {
267 immu_devi
= immu_devi_get(dip
);
270 * If unit mappings are already specified, globally or
271 * locally, we're done here, since that covers both
274 if (immu_devi
->imd_dvma_flags
& IMMU_FLAGS_UNITY
)
277 /* This must come first since it does unity mapping */
278 if (immu_quirk_usbfullpa
== B_TRUE
) {
279 immu_devi
->imd_dvma_flags
|= IMMU_FLAGS_UNITY
;
280 } else if (immu_quirk_usbrmrr
== B_TRUE
) {
281 ddi_err(DER_LOG
, dip
, "Applying USB RMRR quirk");
282 map_bios_rsvd_mem(dip
);
287 * Check if the device is a LPC device
291 check_lpc(dev_info_t
*dip
, void *arg
)
293 immu_devi_t
*immu_devi
;
295 immu_devi
= immu_devi_get(dip
);
296 if (immu_devi
->imd_lpc
== B_TRUE
) {
297 ddi_err(DER_LOG
, dip
, "iommu: Found LPC device");
298 /* This will put the immu_devi on the LPC "specials" list */
299 (void) immu_dvma_device_setup(dip
, IMMU_FLAGS_SLEEP
);
304 * Check if the device is a GFX device
308 check_gfx(dev_info_t
*dip
, void *arg
)
310 immu_devi_t
*immu_devi
;
312 immu_devi
= immu_devi_get(dip
);
313 if (immu_devi
->imd_display
== B_TRUE
) {
314 immu_devi
->imd_dvma_flags
|= IMMU_FLAGS_UNITY
;
315 ddi_err(DER_LOG
, dip
, "iommu: Found GFX device");
316 /* This will put the immu_devi on the GFX "specials" list */
317 (void) immu_dvma_get_immu(dip
, IMMU_FLAGS_SLEEP
);
322 walk_tree(int (*f
)(dev_info_t
*, void *), void *arg
)
326 ndi_devi_enter(root_devinfo
, &count
);
327 ddi_walk_devs(ddi_get_child(root_devinfo
), f
, arg
);
328 ndi_devi_exit(root_devinfo
, count
);
332 check_pre_setup_quirks(dev_info_t
*dip
, void *arg
)
334 /* just 1 check right now */
335 return (check_mobile4(dip
, arg
));
339 check_pre_startup_quirks(dev_info_t
*dip
, void *arg
)
341 if (immu_devi_set(dip
, IMMU_FLAGS_SLEEP
) != DDI_SUCCESS
) {
342 ddi_err(DER_PANIC
, dip
, "Failed to get immu_devi");
349 check_conf(dip
, arg
);
353 return (DDI_WALK_CONTINUE
);
357 pre_setup_quirks(void)
359 walk_tree(check_pre_setup_quirks
, &immu_quirk_mobile4
);
363 pre_startup_quirks(void)
365 walk_tree(check_pre_startup_quirks
, NULL
);
367 immu_dmar_rmrr_map();
371 get_conf_str(char *bopt
, char **val
)
376 * Check the rootnex.conf property
377 * Fake up a dev_t since searching the global
378 * property list needs it
380 ret
= ddi_prop_lookup_string(
381 makedevice(ddi_name_to_major("rootnex"), 0),
382 root_devinfo
, DDI_PROP_DONTPASS
| DDI_PROP_ROOTNEX_GLOBAL
,
390 * get a rootnex.conf setting (always a boolean)
393 get_conf_opt(char *bopt
, boolean_t
*kvar
)
398 * Check the rootnex.conf property
399 * Fake up a dev_t since searching the global
400 * property list needs it
403 if (get_conf_str(bopt
, &val
) != DDI_PROP_SUCCESS
)
406 if (strcmp(val
, "true") == 0) {
408 } else if (strcmp(val
, "false") == 0) {
411 ddi_err(DER_WARN
, NULL
, "rootnex.conf switch %s=\"%s\" ",
412 "is not set to true or false. Ignoring option.",
420 * check a boot option (always a boolean)
423 get_boot_str(char *bopt
, char **val
)
427 ret
= ddi_prop_lookup_string(DDI_DEV_T_ANY
, root_devinfo
,
428 DDI_PROP_DONTPASS
, bopt
, val
);
434 get_bootopt(char *bopt
, boolean_t
*kvar
)
439 * All boot options set at the GRUB menu become
440 * properties on the rootnex.
442 if (get_boot_str(bopt
, &val
) != DDI_PROP_SUCCESS
)
445 if (strcmp(val
, "true") == 0) {
447 } else if (strcmp(val
, "false") == 0) {
450 ddi_err(DER_WARN
, NULL
, "boot option %s=\"%s\" ",
451 "is not set to true or false. Ignoring option.",
458 get_boot_dvma_mode(void)
462 if (get_boot_str(DDI_DVMA_MAPTYPE_ROOTNEX_PROP
, &val
)
466 if (strcmp(val
, DDI_DVMA_MAPTYPE_UNITY
) == 0) {
467 immu_global_dvma_flags
|= IMMU_FLAGS_UNITY
;
468 } else if (strcmp(val
, DDI_DVMA_MAPTYPE_XLATE
) == 0) {
469 immu_global_dvma_flags
&= ~IMMU_FLAGS_UNITY
;
471 ddi_err(DER_WARN
, NULL
, "bad value \"%s\" for boot option %s",
472 val
, DDI_DVMA_MAPTYPE_ROOTNEX_PROP
);
478 get_conf_dvma_mode(void)
482 if (get_conf_str(DDI_DVMA_MAPTYPE_ROOTNEX_PROP
, &val
)
486 if (strcmp(val
, DDI_DVMA_MAPTYPE_UNITY
) == 0) {
487 immu_global_dvma_flags
|= IMMU_FLAGS_UNITY
;
488 } else if (strcmp(val
, DDI_DVMA_MAPTYPE_XLATE
) == 0) {
489 immu_global_dvma_flags
&= ~IMMU_FLAGS_UNITY
;
491 ddi_err(DER_WARN
, NULL
, "bad value \"%s\" for rootnex "
492 "option %s", val
, DDI_DVMA_MAPTYPE_ROOTNEX_PROP
);
499 get_conf_tunables(char *bopt
, int64_t *ivar
)
505 * Check the rootnex.conf property
506 * Fake up a dev_t since searching the global
507 * property list needs it
509 if (ddi_prop_lookup_int64_array(
510 makedevice(ddi_name_to_major("rootnex"), 0), root_devinfo
,
511 DDI_PROP_DONTPASS
| DDI_PROP_ROOTNEX_GLOBAL
, bopt
,
512 &iarray
, &n
) != DDI_PROP_SUCCESS
) {
517 ddi_err(DER_WARN
, NULL
, "More than one value specified for "
518 "%s property. Ignoring and using default",
520 ddi_prop_free(iarray
);
525 ddi_err(DER_WARN
, NULL
, "Negative value specified for "
526 "%s property. Inoring and Using default value",
528 ddi_prop_free(iarray
);
534 ddi_prop_free(iarray
);
538 read_conf_options(void)
540 /* enable/disable options */
541 get_conf_opt("immu-enable", &immu_enable
);
542 get_conf_opt("immu-dvma-enable", &immu_dvma_enable
);
543 get_conf_opt("immu-gfxdvma-enable", &immu_gfxdvma_enable
);
544 get_conf_opt("immu-intrmap-enable", &immu_intrmap_enable
);
545 get_conf_opt("immu-qinv-enable", &immu_qinv_enable
);
547 /* workaround switches */
548 get_conf_opt("immu-quirk-usbpage0", &immu_quirk_usbpage0
);
549 get_conf_opt("immu-quirk-usbfullpa", &immu_quirk_usbfullpa
);
550 get_conf_opt("immu-quirk-usbrmrr", &immu_quirk_usbrmrr
);
553 get_conf_opt("immu-dmar-print", &immu_dmar_print
);
556 get_conf_tunables("immu-flush-gran", &immu_flush_gran
);
558 get_conf_dvma_mode();
562 read_boot_options(void)
564 /* enable/disable options */
565 get_bootopt("immu-enable", &immu_enable
);
566 get_bootopt("immu-dvma-enable", &immu_dvma_enable
);
567 get_bootopt("immu-gfxdvma-enable", &immu_gfxdvma_enable
);
568 get_bootopt("immu-intrmap-enable", &immu_intrmap_enable
);
569 get_bootopt("immu-qinv-enable", &immu_qinv_enable
);
571 /* workaround switches */
572 get_bootopt("immu-quirk-usbpage0", &immu_quirk_usbpage0
);
573 get_bootopt("immu-quirk-usbfullpa", &immu_quirk_usbfullpa
);
574 get_bootopt("immu-quirk-usbrmrr", &immu_quirk_usbrmrr
);
577 get_bootopt("immu-dmar-print", &immu_dmar_print
);
579 get_boot_dvma_mode();
583 mapping_list_setup(void)
588 if (ddi_prop_lookup_string_array(
589 makedevice(ddi_name_to_major("rootnex"), 0), root_devinfo
,
590 DDI_PROP_DONTPASS
| DDI_PROP_ROOTNEX_GLOBAL
,
591 "immu-dvma-unity-drivers",
592 &string_array
, &nstrings
) == DDI_PROP_SUCCESS
) {
593 unity_driver_array
= string_array
;
597 if (ddi_prop_lookup_string_array(
598 makedevice(ddi_name_to_major("rootnex"), 0), root_devinfo
,
599 DDI_PROP_DONTPASS
| DDI_PROP_ROOTNEX_GLOBAL
,
600 "immu-dvma-xlate-drivers",
601 &string_array
, &nstrings
) == DDI_PROP_SUCCESS
) {
602 xlate_driver_array
= string_array
;
606 if (ddi_prop_lookup_string_array(
607 makedevice(ddi_name_to_major("rootnex"), 0), root_devinfo
,
608 DDI_PROP_DONTPASS
| DDI_PROP_ROOTNEX_GLOBAL
,
609 "immu-dvma-premap-drivers",
610 &string_array
, &nstrings
) == DDI_PROP_SUCCESS
) {
611 premap_driver_array
= string_array
;
615 if (ddi_prop_lookup_string_array(
616 makedevice(ddi_name_to_major("rootnex"), 0), root_devinfo
,
617 DDI_PROP_DONTPASS
| DDI_PROP_ROOTNEX_GLOBAL
,
618 "immu-dvma-nopremap-drivers",
619 &string_array
, &nstrings
) == DDI_PROP_SUCCESS
) {
620 nopremap_driver_array
= string_array
;
621 nnopremap
= nstrings
;
626 * Note, this will not catch hardware not enumerated
630 blacklisted_driver(void)
636 /* need at least 2 strings */
641 for (i
= 0; nblacks
- i
> 1; i
++) {
642 strptr
= &black_array
[i
];
643 if (strcmp(*strptr
++, "DRIVER") == 0) {
644 if ((maj
= ddi_name_to_major(*strptr
++))
645 != DDI_MAJOR_T_NONE
) {
646 /* is there hardware bound to this drvr */
647 if (devnamesp
[maj
].dn_head
!= NULL
) {
651 i
+= 1; /* for loop adds 1, so add only 1 here */
659 blacklisted_smbios(void)
664 smbios_system_t smsys
;
665 char *mfg
, *product
, *version
;
669 /* need at least 4 strings for this setting */
674 smhdl
= smbios_open(NULL
, SMB_VERSION
, ksmbios_flags
, NULL
);
676 (smid
= smbios_info_system(smhdl
, &smsys
)) == SMB_ERR
||
677 smbios_info_common(smhdl
, smid
, &sminf
) == SMB_ERR
) {
681 mfg
= (char *)sminf
.smbi_manufacturer
;
682 product
= (char *)sminf
.smbi_product
;
683 version
= (char *)sminf
.smbi_version
;
685 ddi_err(DER_CONT
, NULL
, "?System SMBIOS information:\n");
686 ddi_err(DER_CONT
, NULL
, "?Manufacturer = <%s>\n", mfg
);
687 ddi_err(DER_CONT
, NULL
, "?Product = <%s>\n", product
);
688 ddi_err(DER_CONT
, NULL
, "?Version = <%s>\n", version
);
690 for (i
= 0; nblacks
- i
> 3; i
++) {
691 strptr
= &black_array
[i
];
692 if (strcmp(*strptr
++, "SMBIOS") == 0) {
693 if (strcmp(*strptr
++, mfg
) == 0 &&
694 (*strptr
[0] == '\0' ||
695 strcmp(*strptr
++, product
) == 0) &&
696 (*strptr
[0] == '\0' ||
697 strcmp(*strptr
++, version
) == 0)) {
708 blacklisted_acpi(void)
714 return (immu_dmar_blacklisted(black_array
, nblacks
));
718 * Check if system is blacklisted by Intel IOMMU driver
719 * i.e. should Intel IOMMU be disabled on this system
720 * Currently a system can be blacklistd based on the
723 * 1. DMAR ACPI table information.
724 * This information includes things like
725 * manufacturer and revision number. If rootnex.conf
726 * has matching info set in its blacklist property
727 * then Intel IOMMu will be disabled
729 * 2. SMBIOS information
731 * 3. Driver installed - useful if a particular
732 * driver or hardware is toxic if Intel IOMMU
737 blacklist_setup(void)
743 * Check the rootnex.conf blacklist property.
744 * Fake up a dev_t since searching the global
745 * property list needs it
747 if (ddi_prop_lookup_string_array(
748 makedevice(ddi_name_to_major("rootnex"), 0), root_devinfo
,
749 DDI_PROP_DONTPASS
| DDI_PROP_ROOTNEX_GLOBAL
, "immu-blacklist",
750 &string_array
, &nstrings
) != DDI_PROP_SUCCESS
) {
754 /* smallest blacklist criteria works with multiples of 2 */
755 if (nstrings
% 2 != 0) {
756 ddi_err(DER_WARN
, NULL
, "Invalid IOMMU blacklist "
757 "rootnex.conf: number of strings must be a "
759 ddi_prop_free(string_array
);
763 black_array
= string_array
;
768 blacklist_destroy(void)
771 ddi_prop_free(black_array
);
778 immu_alloc_name(const char *str
, int instance
)
783 slen
= strlen(str
) + IMMU_ISTRLEN
+ 1;
784 s
= kmem_zalloc(slen
, VM_SLEEP
);
786 (void) snprintf(s
, slen
, "%s%d", str
, instance
);
793 * Now set all the fields in the order they are defined
794 * We do this only as a defensive-coding practice, it is
795 * not a correctness issue.
798 immu_state_alloc(int seg
, void *dmar_unit
)
801 char *nodename
, *hcachename
, *pcachename
;
804 dmar_unit
= immu_dmar_walk_units(seg
, dmar_unit
);
805 if (dmar_unit
== NULL
) {
806 /* No more IOMMUs in this segment */
810 immu
= kmem_zalloc(sizeof (immu_t
), KM_SLEEP
);
812 mutex_init(&(immu
->immu_lock
), NULL
, MUTEX_DRIVER
, NULL
);
814 mutex_enter(&(immu
->immu_lock
));
816 immu
->immu_dmar_unit
= dmar_unit
;
817 immu
->immu_dip
= immu_dmar_unit_dip(dmar_unit
);
819 nodename
= ddi_node_name(immu
->immu_dip
);
820 instance
= ddi_get_instance(immu
->immu_dip
);
822 immu
->immu_name
= immu_alloc_name(nodename
, instance
);
823 if (immu
->immu_name
== NULL
)
827 * the immu_intr_lock mutex is grabbed by the IOMMU
828 * unit's interrupt handler so we need to use an
829 * interrupt cookie for the mutex
831 mutex_init(&(immu
->immu_intr_lock
), NULL
, MUTEX_DRIVER
,
832 (void *)ipltospl(IMMU_INTR_IPL
));
834 /* IOMMU regs related */
835 mutex_init(&(immu
->immu_regs_lock
), NULL
, MUTEX_DEFAULT
, NULL
);
836 cv_init(&(immu
->immu_regs_cv
), NULL
, CV_DEFAULT
, NULL
);
837 immu
->immu_regs_busy
= B_FALSE
;
840 immu
->immu_dvma_coherent
= B_FALSE
;
842 /* DVMA context related */
843 rw_init(&(immu
->immu_ctx_rwlock
), NULL
, RW_DEFAULT
, NULL
);
845 /* DVMA domain related */
846 list_create(&(immu
->immu_domain_list
), sizeof (domain_t
),
847 offsetof(domain_t
, dom_immu_node
));
849 /* DVMA special device lists */
850 immu
->immu_dvma_gfx_only
= B_FALSE
;
851 list_create(&(immu
->immu_dvma_lpc_list
), sizeof (immu_devi_t
),
852 offsetof(immu_devi_t
, imd_spc_node
));
853 list_create(&(immu
->immu_dvma_gfx_list
), sizeof (immu_devi_t
),
854 offsetof(immu_devi_t
, imd_spc_node
));
856 /* interrupt remapping related */
857 mutex_init(&(immu
->immu_intrmap_lock
), NULL
, MUTEX_DEFAULT
, NULL
);
860 mutex_init(&(immu
->immu_qinv_lock
), NULL
, MUTEX_DEFAULT
, NULL
);
863 * insert this immu unit into the system-wide list
865 list_insert_tail(&immu_list
, immu
);
867 pcachename
= immu_alloc_name("immu_pgtable_cache", instance
);
868 if (pcachename
== NULL
)
871 hcachename
= immu_alloc_name("immu_hdl_cache", instance
);
872 if (hcachename
== NULL
)
875 immu
->immu_pgtable_cache
= kmem_cache_create(pcachename
,
876 sizeof (pgtable_t
), 0, pgtable_ctor
, pgtable_dtor
, NULL
, immu
,
878 immu
->immu_hdl_cache
= kmem_cache_create(hcachename
,
879 sizeof (immu_hdl_priv_t
), 64, immu_hdl_priv_ctor
,
880 NULL
, NULL
, immu
, NULL
, 0);
882 mutex_exit(&(immu
->immu_lock
));
884 ddi_err(DER_LOG
, immu
->immu_dip
, "unit setup");
886 immu_dmar_set_immu(dmar_unit
, immu
);
892 immu_subsystems_setup(void)
897 ddi_err(DER_VERB
, NULL
,
898 "Creating state structures for Intel IOMMU units");
900 mutex_init(&immu_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
901 list_create(&immu_list
, sizeof (immu_t
), offsetof(immu_t
, immu_node
));
903 mutex_enter(&immu_lock
);
906 for (seg
= 0; seg
< IMMU_MAXSEG
; seg
++) {
907 while (unit_hdl
= immu_state_alloc(seg
, unit_hdl
)) {
912 immu_regs_setup(&immu_list
); /* subsequent code needs this first */
913 immu_dvma_setup(&immu_list
);
914 if (immu_qinv_setup(&immu_list
) == DDI_SUCCESS
)
915 immu_intrmap_setup(&immu_list
);
917 immu_intrmap_enable
= B_FALSE
;
919 mutex_exit(&immu_lock
);
923 * immu_subsystems_startup()
924 * startup all units that were setup
927 immu_subsystems_startup(void)
930 iommulib_ops_t
*iommulib_ops
;
932 mutex_enter(&immu_lock
);
936 immu
= list_head(&immu_list
);
937 for (; immu
; immu
= list_next(&immu_list
, immu
)) {
939 mutex_enter(&(immu
->immu_lock
));
941 immu_intr_register(immu
);
942 immu_dvma_startup(immu
);
943 immu_intrmap_startup(immu
);
944 immu_qinv_startup(immu
);
947 * Set IOMMU unit's regs to do
948 * the actual startup. This will
949 * set immu->immu_running field
950 * if the unit is successfully
953 immu_regs_startup(immu
);
955 mutex_exit(&(immu
->immu_lock
));
957 iommulib_ops
= kmem_alloc(sizeof (iommulib_ops_t
), KM_SLEEP
);
958 *iommulib_ops
= immulib_ops
;
959 iommulib_ops
->ilops_data
= (void *)immu
;
960 (void) iommulib_iommu_register(immu
->immu_dip
, iommulib_ops
,
961 &immu
->immu_iommulib_handle
);
964 mutex_exit(&immu_lock
);
967 /* ################## Intel IOMMU internal interfaces ###################### */
970 * Internal interfaces for IOMMU code (i.e. not exported to rootnex
975 * ddip can be NULL, in which case we walk up until we find the root dip
976 * NOTE: We never visit the root dip since its not a hardware node
982 int (*func
)(dev_info_t
*, void *arg
),
985 immu_flags_t immu_flags
)
989 int error
= DDI_SUCCESS
;
991 /* ddip and immu can be NULL */
993 /* Hold rdip so that branch is not detached */
995 for (pdip
= rdip
, level
= 1; pdip
&& pdip
!= root_devinfo
;
996 pdip
= ddi_get_parent(pdip
), level
++) {
998 if (immu_devi_set(pdip
, immu_flags
) != DDI_SUCCESS
) {
1002 if (func(pdip
, arg
) == DDI_WALK_TERMINATE
) {
1005 if (immu_flags
& IMMU_FLAGS_DONTPASS
) {
1013 ndi_rele_devi(rdip
);
1021 /* ######################## Intel IOMMU entry points ####################### */
1024 * called from rootnex_attach(). setup but don't startup the Intel IOMMU
1025 * This is the first function called in Intel IOMMU code
1030 char *phony_reg
= "A thing of beauty is a joy forever";
1032 /* Set some global shorthands that are needed by all of IOMMU code */
1033 root_devinfo
= ddi_root_node();
1036 * Intel IOMMU only supported only if MMU(CPU) page size is ==
1040 if (MMU_PAGESIZE
!= IMMU_PAGESIZE
) {
1041 ddi_err(DER_WARN
, NULL
,
1042 "MMU page size (%d) is not equal to\n"
1043 "IOMMU page size (%d). "
1044 "Disabling Intel IOMMU. ",
1045 MMU_PAGESIZE
, IMMU_PAGESIZE
);
1046 immu_enable
= B_FALSE
;
1051 * Read rootnex.conf options. Do this before
1052 * boot options so boot options can override .conf options.
1054 read_conf_options();
1057 * retrieve the Intel IOMMU boot options.
1058 * Do this before parsing immu ACPI table
1059 * as a boot option could potentially affect
1062 ddi_err(DER_CONT
, NULL
, "?Reading Intel IOMMU boot options\n");
1063 read_boot_options();
1066 * Check the IOMMU enable boot-option first.
1067 * This is so that we can skip parsing the ACPI table
1068 * if necessary because that may cause problems in
1069 * systems with buggy BIOS or ACPI tables
1071 if (immu_enable
== B_FALSE
) {
1075 if (immu_intrmap_enable
== B_TRUE
)
1076 immu_qinv_enable
= B_TRUE
;
1079 * Next, check if the system even has an Intel IOMMU
1080 * We use the presence or absence of the IOMMU ACPI
1081 * table to detect Intel IOMMU.
1083 if (immu_dmar_setup() != DDI_SUCCESS
) {
1084 immu_enable
= B_FALSE
;
1088 mapping_list_setup();
1095 if (blacklisted_smbios() == B_TRUE
) {
1096 blacklist_destroy();
1097 immu_enable
= B_FALSE
;
1101 if (blacklisted_driver() == B_TRUE
) {
1102 blacklist_destroy();
1103 immu_enable
= B_FALSE
;
1108 * Read the "raw" DMAR ACPI table to get information
1109 * and convert into a form we can use.
1111 if (immu_dmar_parse() != DDI_SUCCESS
) {
1112 blacklist_destroy();
1113 immu_enable
= B_FALSE
;
1118 * now that we have processed the ACPI table
1119 * check if we need to blacklist this system
1120 * based on ACPI info
1122 if (blacklisted_acpi() == B_TRUE
) {
1123 immu_dmar_destroy();
1124 blacklist_destroy();
1125 immu_enable
= B_FALSE
;
1129 blacklist_destroy();
1132 * Check if system has HW quirks.
1136 /* Now do the rest of the setup */
1137 immu_subsystems_setup();
1140 * Now that the IMMU is setup, create a phony
1141 * reg prop so that suspend/resume works
1143 if (ddi_prop_update_byte_array(DDI_DEV_T_NONE
, root_devinfo
, "reg",
1144 (uchar_t
*)phony_reg
, strlen(phony_reg
) + 1) != DDI_PROP_SUCCESS
) {
1145 ddi_err(DER_PANIC
, NULL
, "Failed to create reg prop for "
1150 immu_setup
= B_TRUE
;
1155 * called directly by boot code to startup
1156 * all units of the IOMMU
1162 * If IOMMU is disabled, do nothing
1164 if (immu_enable
== B_FALSE
) {
1168 if (immu_setup
== B_FALSE
) {
1169 ddi_err(DER_WARN
, NULL
, "Intel IOMMU not setup, "
1170 "skipping IOMMU startup");
1174 pre_startup_quirks();
1176 ddi_err(DER_CONT
, NULL
,
1177 "?Starting Intel IOMMU (dmar) units...\n");
1179 immu_subsystems_startup();
1181 immu_running
= B_TRUE
;
1185 * Hook to notify IOMMU code of device tree changes
1188 immu_device_tree_changed(void)
1190 if (immu_setup
== B_FALSE
) {
1194 ddi_err(DER_WARN
, NULL
, "Intel IOMMU currently "
1195 "does not use device tree updates");
1199 * Hook to notify IOMMU code of memory changes
1202 immu_physmem_update(uint64_t addr
, uint64_t size
)
1204 if (immu_setup
== B_FALSE
) {
1207 immu_dvma_physmem_update(addr
, size
);
1212 * quiesce all units that are running
1218 int ret
= DDI_SUCCESS
;
1220 mutex_enter(&immu_lock
);
1222 if (immu_running
== B_FALSE
) {
1223 mutex_exit(&immu_lock
);
1224 return (DDI_SUCCESS
);
1227 immu
= list_head(&immu_list
);
1228 for (; immu
; immu
= list_next(&immu_list
, immu
)) {
1230 /* if immu is not running, we dont quiesce */
1231 if (immu
->immu_regs_running
== B_FALSE
)
1235 rw_enter(&(immu
->immu_ctx_rwlock
), RW_WRITER
);
1236 immu_flush_context_gbl(immu
, &immu
->immu_ctx_inv_wait
);
1237 immu_flush_iotlb_gbl(immu
, &immu
->immu_ctx_inv_wait
);
1238 rw_exit(&(immu
->immu_ctx_rwlock
));
1239 immu_regs_wbf_flush(immu
);
1241 mutex_enter(&(immu
->immu_lock
));
1244 * Set IOMMU unit's regs to do
1245 * the actual shutdown.
1247 immu_regs_shutdown(immu
);
1248 immu_regs_suspend(immu
);
1250 /* if immu is still running, we failed */
1251 if (immu
->immu_regs_running
== B_TRUE
)
1254 immu
->immu_regs_quiesced
= B_TRUE
;
1256 mutex_exit(&(immu
->immu_lock
));
1259 if (ret
== DDI_SUCCESS
) {
1260 immu_running
= B_FALSE
;
1261 immu_quiesced
= B_TRUE
;
1263 mutex_exit(&immu_lock
);
1270 * unquiesce all units
1273 immu_unquiesce(void)
1276 int ret
= DDI_SUCCESS
;
1278 mutex_enter(&immu_lock
);
1280 if (immu_quiesced
== B_FALSE
) {
1281 mutex_exit(&immu_lock
);
1282 return (DDI_SUCCESS
);
1285 immu
= list_head(&immu_list
);
1286 for (; immu
; immu
= list_next(&immu_list
, immu
)) {
1288 mutex_enter(&(immu
->immu_lock
));
1290 /* if immu was not quiesced, i.e was not running before */
1291 if (immu
->immu_regs_quiesced
== B_FALSE
) {
1292 mutex_exit(&(immu
->immu_lock
));
1296 if (immu_regs_resume(immu
) != DDI_SUCCESS
) {
1298 mutex_exit(&(immu
->immu_lock
));
1302 /* flush caches before unquiesce */
1303 rw_enter(&(immu
->immu_ctx_rwlock
), RW_WRITER
);
1304 immu_flush_context_gbl(immu
, &immu
->immu_ctx_inv_wait
);
1305 immu_flush_iotlb_gbl(immu
, &immu
->immu_ctx_inv_wait
);
1306 rw_exit(&(immu
->immu_ctx_rwlock
));
1309 * Set IOMMU unit's regs to do
1310 * the actual startup. This will
1311 * set immu->immu_regs_running field
1312 * if the unit is successfully
1315 immu_regs_startup(immu
);
1317 if (immu
->immu_regs_running
== B_FALSE
) {
1320 immu_quiesced
= B_TRUE
;
1321 immu_running
= B_TRUE
;
1322 immu
->immu_regs_quiesced
= B_FALSE
;
1325 mutex_exit(&(immu
->immu_lock
));
1328 mutex_exit(&immu_lock
);
1334 immu_init_inv_wait(immu_inv_wait_t
*iwp
, const char *name
, boolean_t sync
)
1339 iwp
->iwp_sync
= sync
;
1341 vaddr
= (caddr_t
)&iwp
->iwp_vstatus
;
1342 paddr
= pfn_to_pa(hat_getpfnum(kas
.a_hat
, vaddr
));
1343 paddr
+= ((uintptr_t)vaddr
) & MMU_PAGEOFFSET
;
1345 iwp
->iwp_pstatus
= paddr
;
1346 iwp
->iwp_name
= name
;
1349 /* ############## END Intel IOMMU entry points ################## */