Commit 387caf0b authored by Adrian Huang's avatar Adrian Huang Committed by Joerg Roedel

iommu/amd: Treat per-device exclusion ranges as r/w unity-mapped regions

Some buggy BIOSes might define multiple exclusion ranges of the
IVMD entries which are associated with the same IOMMU hardware.
This leads to the overwritten exclusion range (exclusion_start
and exclusion_length members) in set_device_exclusion_range().

Here is a real case:
When attaching two Broadcom RAID controllers to a server, the first
one reports the failure during booting (the disks connecting to the
RAID controller cannot be detected).

This patch prevents the issue by treating per-device exclusion
ranges as r/w unity-mapped regions.

Discussion:
  * https://lists.linuxfoundation.org/pipermail/iommu/2019-November/040140.htmlSuggested-by: default avatarJoerg Roedel <joro@8bytes.org>
Signed-off-by: default avatarAdrian Huang <ahuang12@lenovo.com>
Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 46cf053e
...@@ -71,6 +71,8 @@ ...@@ -71,6 +71,8 @@
#define IVHD_FLAG_ISOC_EN_MASK 0x08 #define IVHD_FLAG_ISOC_EN_MASK 0x08
#define IVMD_FLAG_EXCL_RANGE 0x08 #define IVMD_FLAG_EXCL_RANGE 0x08
#define IVMD_FLAG_IW 0x04
#define IVMD_FLAG_IR 0x02
#define IVMD_FLAG_UNITY_MAP 0x01 #define IVMD_FLAG_UNITY_MAP 0x01
#define ACPI_DEVFLAG_INITPASS 0x01 #define ACPI_DEVFLAG_INITPASS 0x01
...@@ -1121,16 +1123,14 @@ static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m) ...@@ -1121,16 +1123,14 @@ static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m)
if (!(m->flags & IVMD_FLAG_EXCL_RANGE)) if (!(m->flags & IVMD_FLAG_EXCL_RANGE))
return; return;
if (iommu) {
/* /*
* We only can configure exclusion ranges per IOMMU, not * Treat per-device exclusion ranges as r/w unity-mapped regions
* per device. But we can enable the exclusion range per * since some buggy BIOSes might lead to the overwritten exclusion
* device. This is done here * range (exclusion_start and exclusion_length members). This
* happens when there are multiple exclusion ranges (IVMD entries)
* defined in ACPI table.
*/ */
set_dev_entry_bit(devid, DEV_ENTRY_EX); m->flags = (IVMD_FLAG_IW | IVMD_FLAG_IR | IVMD_FLAG_UNITY_MAP);
iommu->exclusion_start = m->range_start;
iommu->exclusion_length = m->range_length;
}
} }
/* /*
......
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