diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc index b1f7978aa4..f7797ea233 100644 --- a/docs/misc/xen-command-line.pandoc +++ b/docs/misc/xen-command-line.pandoc @@ -1494,8 +1494,8 @@ The following options are specific to Intel VT-d hardware: version 6 and greater as Registered-Based Invalidation isn't supported by them. -* The `igfx` boolean is active by default, and controls whether the IOMMU in - front of an Intel Graphics Device is enabled or not. +* The `igfx` boolean is active by default, and controls whether IOMMUs in + front of solely graphics devices get enabled or not. It is intended as a debugging mechanism for graphics issues, and to be similar to Linux's `intel_iommu=igfx_off` option. If specifying `no-igfx` diff --git a/xen/drivers/passthrough/vtd/dmar.c b/xen/drivers/passthrough/vtd/dmar.c index 36d909b06d..d5ee367599 100644 --- a/xen/drivers/passthrough/vtd/dmar.c +++ b/xen/drivers/passthrough/vtd/dmar.c @@ -315,6 +315,7 @@ static int __init acpi_parse_dev_scope( struct acpi_drhd_unit *drhd = type == DMAR_TYPE ? container_of(scope, struct acpi_drhd_unit, scope) : NULL; int depth, cnt, didx = 0, ret; + bool gfx_only = false; if ( (cnt = scope_device_count(start, end)) < 0 ) return cnt; @@ -324,6 +325,8 @@ static int __init acpi_parse_dev_scope( scope->devices = xzalloc_array(u16, cnt); if ( !scope->devices ) return -ENOMEM; + + gfx_only = drhd && !drhd->include_all; } scope->devices_cnt = cnt; @@ -354,6 +357,7 @@ static int __init acpi_parse_dev_scope( acpi_scope->bus, sec_bus, sub_bus); dmar_scope_add_buses(scope, sec_bus, sub_bus); + gfx_only = false; break; case ACPI_DMAR_SCOPE_TYPE_HPET: @@ -374,6 +378,8 @@ static int __init acpi_parse_dev_scope( acpi_hpet_unit->dev = path->dev; acpi_hpet_unit->func = path->fn; list_add(&acpi_hpet_unit->list, &drhd->hpet_list); + + gfx_only = false; } break; @@ -388,6 +394,12 @@ static int __init acpi_parse_dev_scope( if ( (seg == 0) && (bus == 0) && (path->dev == 2) && (path->fn == 0) ) igd_drhd_address = drhd->address; + + if ( gfx_only && + pci_conf_read8(PCI_SBDF(seg, bus, path->dev, path->fn), + PCI_CLASS_DEVICE + 1) != 0x03 + /* PCI_BASE_CLASS_DISPLAY */ ) + gfx_only = false; } break; @@ -408,6 +420,8 @@ static int __init acpi_parse_dev_scope( acpi_ioapic_unit->ioapic.bdf.dev = path->dev; acpi_ioapic_unit->ioapic.bdf.func = path->fn; list_add(&acpi_ioapic_unit->list, &drhd->ioapic_list); + + gfx_only = false; } break; @@ -417,11 +431,15 @@ static int __init acpi_parse_dev_scope( printk(XENLOG_WARNING VTDPREFIX "Unknown scope type %#x\n", acpi_scope->entry_type); start += acpi_scope->length; + gfx_only = false; continue; } scope->devices[didx++] = PCI_BDF(bus, path->dev, path->fn); start += acpi_scope->length; - } + } + + if ( drhd && gfx_only ) + drhd->gfx_only = true; ret = 0; diff --git a/xen/drivers/passthrough/vtd/dmar.h b/xen/drivers/passthrough/vtd/dmar.h index a44820a5e7..a1f2353a51 100644 --- a/xen/drivers/passthrough/vtd/dmar.h +++ b/xen/drivers/passthrough/vtd/dmar.h @@ -62,7 +62,8 @@ struct acpi_drhd_unit { struct list_head list; u64 address; /* register base address of the unit */ u16 segment; - u8 include_all:1; + bool include_all:1; + bool gfx_only:1; struct vtd_iommu *iommu; struct list_head ioapic_list; struct list_head hpet_list; diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index 0519dfc9e7..137aea2c92 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -751,7 +751,7 @@ static void iommu_enable_translation(struct acpi_drhd_unit *drhd) unsigned long flags; struct vtd_iommu *iommu = drhd->iommu; - if ( is_igd_drhd(drhd) ) + if ( drhd->gfx_only ) { if ( !iommu_igfx ) {