[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen master] AMD/IOMMU: respect AtsDisabled device flag
commit 246a0cd415af377d26576dd9962ee78c0f83f1f9 Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Fri Oct 15 12:46:42 2021 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Fri Oct 15 12:46:42 2021 +0200 AMD/IOMMU: respect AtsDisabled device flag IVHD entries may specify that ATS is to be blocked for a device or range of devices. Honor firmware telling us so. While adding respective checks I noticed that the 2nd conditional in amd_iommu_setup_domain_device() failed to check the IOMMU's capability. Add the missing part of the condition there, as no good can come from enabling ATS on a device when the IOMMU is not capable of dealing with ATS requests. For actually using ACPI_IVHD_ATS_DISABLED, make its expansion no longer exhibit UB. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: Paul Durrant <paul@xxxxxxx> --- xen/drivers/passthrough/amd/iommu.h | 1 + xen/drivers/passthrough/amd/iommu_acpi.c | 20 +++++++++++--------- xen/drivers/passthrough/amd/pci_amd_iommu.c | 8 +++++--- xen/include/acpi/actbl2.h | 2 +- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/xen/drivers/passthrough/amd/iommu.h b/xen/drivers/passthrough/amd/iommu.h index a915433f56..49c4bbd7e1 100644 --- a/xen/drivers/passthrough/amd/iommu.h +++ b/xen/drivers/passthrough/amd/iommu.h @@ -120,6 +120,7 @@ struct ivrs_mappings { uint16_t dte_requestor_id; bool valid:1; bool dte_allow_exclusion:1; + bool block_ats:1; /* ivhd device data settings */ uint8_t device_flags; diff --git a/xen/drivers/passthrough/amd/iommu_acpi.c b/xen/drivers/passthrough/amd/iommu_acpi.c index 71c323fb33..4aed8a17fd 100644 --- a/xen/drivers/passthrough/amd/iommu_acpi.c +++ b/xen/drivers/passthrough/amd/iommu_acpi.c @@ -55,8 +55,8 @@ union acpi_ivhd_device { }; static void __init add_ivrs_mapping_entry( - uint16_t bdf, uint16_t alias_id, uint8_t flags, bool alloc_irt, - struct amd_iommu *iommu) + uint16_t bdf, uint16_t alias_id, uint8_t flags, unsigned int ext_flags, + bool alloc_irt, struct amd_iommu *iommu) { struct ivrs_mappings *ivrs_mappings = get_ivrs_mappings(iommu->seg); @@ -66,6 +66,7 @@ static void __init add_ivrs_mapping_entry( ivrs_mappings[bdf].dte_requestor_id = alias_id; /* override flags for range of devices */ + ivrs_mappings[bdf].block_ats = ext_flags & ACPI_IVHD_ATS_DISABLED; ivrs_mappings[bdf].device_flags = flags; /* Don't map an IOMMU by itself. */ @@ -499,7 +500,7 @@ static u16 __init parse_ivhd_device_select( return 0; } - add_ivrs_mapping_entry(bdf, bdf, select->header.data_setting, false, + add_ivrs_mapping_entry(bdf, bdf, select->header.data_setting, 0, false, iommu); return sizeof(*select); @@ -545,7 +546,7 @@ static u16 __init parse_ivhd_device_range( AMD_IOMMU_DEBUG(" Dev_Id Range: %#x -> %#x\n", first_bdf, last_bdf); for ( bdf = first_bdf; bdf <= last_bdf; bdf++ ) - add_ivrs_mapping_entry(bdf, bdf, range->start.header.data_setting, + add_ivrs_mapping_entry(bdf, bdf, range->start.header.data_setting, 0, false, iommu); return dev_length; @@ -580,7 +581,7 @@ static u16 __init parse_ivhd_device_alias( AMD_IOMMU_DEBUG(" Dev_Id Alias: %#x\n", alias_id); - add_ivrs_mapping_entry(bdf, alias_id, alias->header.data_setting, true, + add_ivrs_mapping_entry(bdf, alias_id, alias->header.data_setting, 0, true, iommu); return dev_length; @@ -636,7 +637,7 @@ static u16 __init parse_ivhd_device_alias_range( for ( bdf = first_bdf; bdf <= last_bdf; bdf++ ) add_ivrs_mapping_entry(bdf, alias_id, range->alias.header.data_setting, - true, iommu); + 0, true, iommu); return dev_length; } @@ -661,7 +662,8 @@ static u16 __init parse_ivhd_device_extended( return 0; } - add_ivrs_mapping_entry(bdf, bdf, ext->header.data_setting, false, iommu); + add_ivrs_mapping_entry(bdf, bdf, ext->header.data_setting, + ext->extended_data, false, iommu); return dev_length; } @@ -708,7 +710,7 @@ static u16 __init parse_ivhd_device_extended_range( for ( bdf = first_bdf; bdf <= last_bdf; bdf++ ) add_ivrs_mapping_entry(bdf, bdf, range->extended.header.data_setting, - false, iommu); + range->extended.extended_data, false, iommu); return dev_length; } @@ -800,7 +802,7 @@ static u16 __init parse_ivhd_device_special( AMD_IOMMU_DEBUG("IVHD Special: %pp variety %#x handle %#x\n", &PCI_SBDF2(seg, bdf), special->variety, special->handle); - add_ivrs_mapping_entry(bdf, bdf, special->header.data_setting, true, + add_ivrs_mapping_entry(bdf, bdf, special->header.data_setting, 0, true, iommu); switch ( special->variety ) diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c index 28f45e3fac..45d16b731f 100644 --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c @@ -105,6 +105,7 @@ static int __must_check amd_iommu_setup_domain_device( int req_id, valid = 1, rc; u8 bus = pdev->bus; struct domain_iommu *hd = dom_iommu(domain); + const struct ivrs_mappings *ivrs_dev; if ( QUARANTINE_SKIP(domain) ) return 0; @@ -122,20 +123,18 @@ static int __must_check amd_iommu_setup_domain_device( req_id = get_dma_requestor_id(iommu->seg, PCI_BDF2(bus, devfn)); table = iommu->dev_table.buffer; dte = &table[req_id]; + ivrs_dev = &get_ivrs_mappings(iommu->seg)[req_id]; spin_lock_irqsave(&iommu->lock, flags); if ( !dte->v || !dte->tv ) { - const struct ivrs_mappings *ivrs_dev; - /* bind DTE to domain page-tables */ amd_iommu_set_root_page_table( dte, page_to_maddr(hd->arch.amd.root_table), domain->domain_id, hd->arch.amd.paging_mode, valid); /* Undo what amd_iommu_disable_domain_device() may have done. */ - ivrs_dev = &get_ivrs_mappings(iommu->seg)[req_id]; if ( dte->it_root ) { dte->int_ctl = IOMMU_DEV_TABLE_INT_CONTROL_TRANSLATED; @@ -146,6 +145,7 @@ static int __must_check amd_iommu_setup_domain_device( dte->sys_mgt = MASK_EXTR(ivrs_dev->device_flags, ACPI_IVHD_SYSTEM_MGMT); if ( pci_ats_device(iommu->seg, bus, pdev->devfn) && + !ivrs_dev->block_ats && iommu_has_cap(iommu, PCI_CAP_IOTLB_SHIFT) ) dte->i = ats_enabled; @@ -166,6 +166,8 @@ static int __must_check amd_iommu_setup_domain_device( ASSERT(pcidevs_locked()); if ( pci_ats_device(iommu->seg, bus, pdev->devfn) && + !ivrs_dev->block_ats && + iommu_has_cap(iommu, PCI_CAP_IOTLB_SHIFT) && !pci_ats_enabled(iommu->seg, bus, pdev->devfn) ) { if ( devfn == pdev->devfn ) diff --git a/xen/include/acpi/actbl2.h b/xen/include/acpi/actbl2.h index 4252c90a3f..2ad08ea467 100644 --- a/xen/include/acpi/actbl2.h +++ b/xen/include/acpi/actbl2.h @@ -851,7 +851,7 @@ struct acpi_ivrs_device8b { /* Values for extended_data above */ -#define ACPI_IVHD_ATS_DISABLED (1<<31) +#define ACPI_IVHD_ATS_DISABLED (1u << 31) /* Type 72: 8-byte device entry */ -- generated by git-patchbot for /home/xen/git/xen.git#master
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |