Skip to content

Commit 9f78e44

Browse files
buytenhjoergroedel
authored andcommitted
iommu/amd: Use report_iommu_fault()
This patch makes iommu/amd call report_iommu_fault() when an I/O page fault occurs, which has two effects: 1) It allows device drivers to register a callback to be notified of I/O page faults, via the iommu_set_fault_handler() API. 2) It triggers the io_page_fault tracepoint in report_iommu_fault() when an I/O page fault occurs. The latter point is the main aim of this patch, as it allows rasdaemon-like daemons to be notified of I/O page faults, and to possibly initiate corrective action in response. A number of other IOMMU drivers already use report_iommu_fault(), and I/O page faults on those IOMMUs therefore already trigger this tracepoint -- but this isn't yet the case for AMD-Vi and Intel DMAR. The AMD IOMMU specification suggests that the bit in an I/O page fault event log entry that signals whether an I/O page fault was for a read request or for a write request is only meaningful when the faulting access was to a present page, but some testing on a Ryzen 3700X suggests that this bit encodes the correct value even for I/O page faults to non-present pages, and therefore, this patch passes the R/W information up the stack even for I/O page faults to non-present pages. Signed-off-by: Lennert Buytenhek <buytenh@arista.com> Link: https://lore.kernel.org/r/YVLyBW97vZLpOaAp@wantstofly.org Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent 5816b3e commit 9f78e44

2 files changed

Lines changed: 23 additions & 0 deletions

File tree

drivers/iommu/amd/amd_iommu_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@
138138
#define EVENT_DOMID_MASK_HI 0xf0000
139139
#define EVENT_FLAGS_MASK 0xfff
140140
#define EVENT_FLAGS_SHIFT 0x10
141+
#define EVENT_FLAG_RW 0x020
142+
#define EVENT_FLAG_I 0x008
141143

142144
/* feature control bits */
143145
#define CONTROL_IOMMU_EN 0x00ULL

drivers/iommu/amd/iommu.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,12 @@ static void amd_iommu_report_rmp_fault(volatile u32 *event)
473473
pci_dev_put(pdev);
474474
}
475475

476+
#define IS_IOMMU_MEM_TRANSACTION(flags) \
477+
(((flags) & EVENT_FLAG_I) == 0)
478+
479+
#define IS_WRITE_REQUEST(flags) \
480+
((flags) & EVENT_FLAG_RW)
481+
476482
static void amd_iommu_report_page_fault(u16 devid, u16 domain_id,
477483
u64 address, int flags)
478484
{
@@ -485,6 +491,20 @@ static void amd_iommu_report_page_fault(u16 devid, u16 domain_id,
485491
dev_data = dev_iommu_priv_get(&pdev->dev);
486492

487493
if (dev_data) {
494+
/*
495+
* If this is a DMA fault (for which the I(nterrupt)
496+
* bit will be unset), allow report_iommu_fault() to
497+
* prevent logging it.
498+
*/
499+
if (IS_IOMMU_MEM_TRANSACTION(flags)) {
500+
if (!report_iommu_fault(&dev_data->domain->domain,
501+
&pdev->dev, address,
502+
IS_WRITE_REQUEST(flags) ?
503+
IOMMU_FAULT_WRITE :
504+
IOMMU_FAULT_READ))
505+
goto out;
506+
}
507+
488508
if (__ratelimit(&dev_data->rs)) {
489509
pci_err(pdev, "Event logged [IO_PAGE_FAULT domain=0x%04x address=0x%llx flags=0x%04x]\n",
490510
domain_id, address, flags);
@@ -495,6 +515,7 @@ static void amd_iommu_report_page_fault(u16 devid, u16 domain_id,
495515
domain_id, address, flags);
496516
}
497517

518+
out:
498519
if (pdev)
499520
pci_dev_put(pdev);
500521
}

0 commit comments

Comments
 (0)