Skip to content

Commit 8aafaaf

Browse files
committed
iommu/amd: Reserve exclusion range in iova-domain
If a device has an exclusion range specified in the IVRS table, this region needs to be reserved in the iova-domain of that device. This hasn't happened until now and can cause data corruption on data transfered with these devices. Treat exclusion ranges as reserved regions in the iommu-core to fix the problem. Fixes: be2a022 ('x86, AMD IOMMU: add functions to parse IOMMU memory mapping requirements for devices') Signed-off-by: Joerg Roedel <jroedel@suse.de> Reviewed-by: Gary R Hook <gary.hook@amd.com>
1 parent 8bc32a2 commit 8aafaaf

File tree

3 files changed

+12
-6
lines changed

3 files changed

+12
-6
lines changed

drivers/iommu/amd_iommu.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3169,21 +3169,24 @@ static void amd_iommu_get_resv_regions(struct device *dev,
31693169
return;
31703170

31713171
list_for_each_entry(entry, &amd_iommu_unity_map, list) {
3172+
int type, prot = 0;
31723173
size_t length;
3173-
int prot = 0;
31743174

31753175
if (devid < entry->devid_start || devid > entry->devid_end)
31763176
continue;
31773177

3178+
type = IOMMU_RESV_DIRECT;
31783179
length = entry->address_end - entry->address_start;
31793180
if (entry->prot & IOMMU_PROT_IR)
31803181
prot |= IOMMU_READ;
31813182
if (entry->prot & IOMMU_PROT_IW)
31823183
prot |= IOMMU_WRITE;
3184+
if (entry->prot & IOMMU_UNITY_MAP_FLAG_EXCL_RANGE)
3185+
/* Exclusion range */
3186+
type = IOMMU_RESV_RESERVED;
31833187

31843188
region = iommu_alloc_resv_region(entry->address_start,
3185-
length, prot,
3186-
IOMMU_RESV_DIRECT);
3189+
length, prot, type);
31873190
if (!region) {
31883191
dev_err(dev, "Out of memory allocating dm-regions\n");
31893192
return;

drivers/iommu/amd_iommu_init.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,6 +2013,9 @@ static int __init init_unity_map_range(struct ivmd_header *m)
20132013
if (e == NULL)
20142014
return -ENOMEM;
20152015

2016+
if (m->flags & IVMD_FLAG_EXCL_RANGE)
2017+
init_exclusion_range(m);
2018+
20162019
switch (m->type) {
20172020
default:
20182021
kfree(e);
@@ -2059,9 +2062,7 @@ static int __init init_memory_definitions(struct acpi_table_header *table)
20592062

20602063
while (p < end) {
20612064
m = (struct ivmd_header *)p;
2062-
if (m->flags & IVMD_FLAG_EXCL_RANGE)
2063-
init_exclusion_range(m);
2064-
else if (m->flags & IVMD_FLAG_UNITY_MAP)
2065+
if (m->flags & (IVMD_FLAG_UNITY_MAP | IVMD_FLAG_EXCL_RANGE))
20652066
init_unity_map_range(m);
20662067

20672068
p += m->length;

drivers/iommu/amd_iommu_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,8 @@
374374
#define IOMMU_PROT_IR 0x01
375375
#define IOMMU_PROT_IW 0x02
376376

377+
#define IOMMU_UNITY_MAP_FLAG_EXCL_RANGE (1 << 2)
378+
377379
/* IOMMU capabilities */
378380
#define IOMMU_CAP_IOTLB 24
379381
#define IOMMU_CAP_NPCACHE 26

0 commit comments

Comments
 (0)