diff options
Diffstat (limited to 'drivers/iommu/amd/iommu.c')
-rw-r--r-- | drivers/iommu/amd/iommu.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index 1722bb161841..461f1844ed1f 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -31,6 +31,7 @@ #include <linux/irqdomain.h> #include <linux/percpu.h> #include <linux/io-pgtable.h> +#include <linux/cc_platform.h> #include <asm/irq_remapping.h> #include <asm/io_apic.h> #include <asm/apic.h> @@ -473,6 +474,12 @@ static void amd_iommu_report_rmp_fault(volatile u32 *event) pci_dev_put(pdev); } +#define IS_IOMMU_MEM_TRANSACTION(flags) \ + (((flags) & EVENT_FLAG_I) == 0) + +#define IS_WRITE_REQUEST(flags) \ + ((flags) & EVENT_FLAG_RW) + static void amd_iommu_report_page_fault(u16 devid, u16 domain_id, u64 address, int flags) { @@ -485,6 +492,20 @@ static void amd_iommu_report_page_fault(u16 devid, u16 domain_id, dev_data = dev_iommu_priv_get(&pdev->dev); if (dev_data) { + /* + * If this is a DMA fault (for which the I(nterrupt) + * bit will be unset), allow report_iommu_fault() to + * prevent logging it. + */ + if (IS_IOMMU_MEM_TRANSACTION(flags)) { + if (!report_iommu_fault(&dev_data->domain->domain, + &pdev->dev, address, + IS_WRITE_REQUEST(flags) ? + IOMMU_FAULT_WRITE : + IOMMU_FAULT_READ)) + goto out; + } + if (__ratelimit(&dev_data->rs)) { pci_err(pdev, "Event logged [IO_PAGE_FAULT domain=0x%04x address=0x%llx flags=0x%04x]\n", domain_id, address, flags); @@ -495,6 +516,7 @@ static void amd_iommu_report_page_fault(u16 devid, u16 domain_id, domain_id, address, flags); } +out: if (pdev) pci_dev_put(pdev); } @@ -2238,7 +2260,7 @@ static int amd_iommu_def_domain_type(struct device *dev) * active, because some of those devices (AMD GPUs) don't have the * encryption bit in their DMA-mask and require remapping. */ - if (!mem_encrypt_active() && dev_data->iommu_v2) + if (!cc_platform_has(CC_ATTR_MEM_ENCRYPT) && dev_data->iommu_v2) return IOMMU_DOMAIN_IDENTITY; return 0; |