Commit c0b7f2a5 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'iommu-fixes-v5.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu

Pull IOMMU fixes from Joerg Roedel:

 - Fix a bug in the AMD IOMMU driver not handling exclusion ranges
   correctly. In fact the driver did not reserve these ranges for IOVA
   allocations, so that dma-handles could be allocated in an exclusion
   range, leading to data corruption. Exclusion ranges have not been
   used by any firmware up to now, so this issue remained undiscovered
   for quite some time.

 - Fix wrong warning messages that the IOMMU core code prints when it
   tries to allocate the default domain for an iommu group and the
   driver does not support any of the default domain types (like Intel
   VT-d).

* tag 'iommu-fixes-v5.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
  iommu/amd: Reserve exclusion range in iova-domain
  iommu: Don't print warning when IOMMU driver only supports unmanaged domains
parents eed4897d 8aafaaf2
...@@ -3169,21 +3169,24 @@ static void amd_iommu_get_resv_regions(struct device *dev, ...@@ -3169,21 +3169,24 @@ static void amd_iommu_get_resv_regions(struct device *dev,
return; return;
list_for_each_entry(entry, &amd_iommu_unity_map, list) { list_for_each_entry(entry, &amd_iommu_unity_map, list) {
int type, prot = 0;
size_t length; size_t length;
int prot = 0;
if (devid < entry->devid_start || devid > entry->devid_end) if (devid < entry->devid_start || devid > entry->devid_end)
continue; continue;
type = IOMMU_RESV_DIRECT;
length = entry->address_end - entry->address_start; length = entry->address_end - entry->address_start;
if (entry->prot & IOMMU_PROT_IR) if (entry->prot & IOMMU_PROT_IR)
prot |= IOMMU_READ; prot |= IOMMU_READ;
if (entry->prot & IOMMU_PROT_IW) if (entry->prot & IOMMU_PROT_IW)
prot |= IOMMU_WRITE; prot |= IOMMU_WRITE;
if (entry->prot & IOMMU_UNITY_MAP_FLAG_EXCL_RANGE)
/* Exclusion range */
type = IOMMU_RESV_RESERVED;
region = iommu_alloc_resv_region(entry->address_start, region = iommu_alloc_resv_region(entry->address_start,
length, prot, length, prot, type);
IOMMU_RESV_DIRECT);
if (!region) { if (!region) {
dev_err(dev, "Out of memory allocating dm-regions\n"); dev_err(dev, "Out of memory allocating dm-regions\n");
return; return;
......
...@@ -2013,6 +2013,9 @@ static int __init init_unity_map_range(struct ivmd_header *m) ...@@ -2013,6 +2013,9 @@ static int __init init_unity_map_range(struct ivmd_header *m)
if (e == NULL) if (e == NULL)
return -ENOMEM; return -ENOMEM;
if (m->flags & IVMD_FLAG_EXCL_RANGE)
init_exclusion_range(m);
switch (m->type) { switch (m->type) {
default: default:
kfree(e); kfree(e);
...@@ -2059,9 +2062,7 @@ static int __init init_memory_definitions(struct acpi_table_header *table) ...@@ -2059,9 +2062,7 @@ static int __init init_memory_definitions(struct acpi_table_header *table)
while (p < end) { while (p < end) {
m = (struct ivmd_header *)p; m = (struct ivmd_header *)p;
if (m->flags & IVMD_FLAG_EXCL_RANGE) if (m->flags & (IVMD_FLAG_UNITY_MAP | IVMD_FLAG_EXCL_RANGE))
init_exclusion_range(m);
else if (m->flags & IVMD_FLAG_UNITY_MAP)
init_unity_map_range(m); init_unity_map_range(m);
p += m->length; p += m->length;
......
...@@ -374,6 +374,8 @@ ...@@ -374,6 +374,8 @@
#define IOMMU_PROT_IR 0x01 #define IOMMU_PROT_IR 0x01
#define IOMMU_PROT_IW 0x02 #define IOMMU_PROT_IW 0x02
#define IOMMU_UNITY_MAP_FLAG_EXCL_RANGE (1 << 2)
/* IOMMU capabilities */ /* IOMMU capabilities */
#define IOMMU_CAP_IOTLB 24 #define IOMMU_CAP_IOTLB 24
#define IOMMU_CAP_NPCACHE 26 #define IOMMU_CAP_NPCACHE 26
......
...@@ -1105,10 +1105,12 @@ struct iommu_group *iommu_group_get_for_dev(struct device *dev) ...@@ -1105,10 +1105,12 @@ struct iommu_group *iommu_group_get_for_dev(struct device *dev)
dom = __iommu_domain_alloc(dev->bus, iommu_def_domain_type); dom = __iommu_domain_alloc(dev->bus, iommu_def_domain_type);
if (!dom && iommu_def_domain_type != IOMMU_DOMAIN_DMA) { if (!dom && iommu_def_domain_type != IOMMU_DOMAIN_DMA) {
dev_warn(dev,
"failed to allocate default IOMMU domain of type %u; falling back to IOMMU_DOMAIN_DMA",
iommu_def_domain_type);
dom = __iommu_domain_alloc(dev->bus, IOMMU_DOMAIN_DMA); dom = __iommu_domain_alloc(dev->bus, IOMMU_DOMAIN_DMA);
if (dom) {
dev_warn(dev,
"failed to allocate default IOMMU domain of type %u; falling back to IOMMU_DOMAIN_DMA",
iommu_def_domain_type);
}
} }
group->default_domain = dom; group->default_domain = dom;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment