* [PATCH v2 1/5] iommu/amd: Fix incorrect device ID in invalid PASID error message
2026-08-11 4:08 [PATCH v2 0/5] iommu/amd: PRI related cleanup and fixes for v7.3 Vasant Hegde
@ 2026-08-11 4:08 ` Vasant Hegde
2026-08-11 4:08 ` [PATCH v2 2/5] iommu/amd: Introduce PPR_TAG_LAST_PAGE() macro Vasant Hegde
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Vasant Hegde @ 2026-08-11 4:08 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, Vasant Hegde,
Ankit Soni
The IO page fault notifier handler logs pdev->dev.id when reporting an
invalid PASID, but pdev->dev.id is the kernel-internal device ID and
not the IOMMU device ID (BDF). Use dev_data->devid instead, which
reflects actual devid.
Fixes: 978d626b8f1a ("iommu/amd: Add IO page fault notifier handler")
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Ankit Soni <Ankit.Soni@amd.com>
---
drivers/iommu/amd/ppr.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/iommu/amd/ppr.c b/drivers/iommu/amd/ppr.c
index 80369ca1e316..1dde19a79e80 100644
--- a/drivers/iommu/amd/ppr.c
+++ b/drivers/iommu/amd/ppr.c
@@ -140,7 +140,7 @@ static void iommu_call_iopf_notifier(struct amd_iommu *iommu, u64 *raw)
if (event.fault.prm.pasid == 0 ||
event.fault.prm.pasid >= dev_data->max_pasids) {
pr_info_ratelimited("Invalid PASID : 0x%x, device : 0x%x\n",
- event.fault.prm.pasid, pdev->dev.id);
+ event.fault.prm.pasid, dev_data->devid);
goto out;
}
--
2.31.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 2/5] iommu/amd: Introduce PPR_TAG_LAST_PAGE() macro
2026-08-11 4:08 [PATCH v2 0/5] iommu/amd: PRI related cleanup and fixes for v7.3 Vasant Hegde
2026-08-11 4:08 ` [PATCH v2 1/5] iommu/amd: Fix incorrect device ID in invalid PASID error message Vasant Hegde
@ 2026-08-11 4:08 ` Vasant Hegde
2026-08-11 4:08 ` [PATCH v2 3/5] iommu/amd: Fix missing CMD_COMPLETE_PPR response for invalid PPR requests Vasant Hegde
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Vasant Hegde @ 2026-08-11 4:08 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, Vasant Hegde,
Wei Huang, Ankit Soni
The PPR tag field (PPRtag) encodes two distinct fields: the 9-bit tag
value (bits 8-0) and the last-page indicator L bit (bit 9).
Fix PPR_TAG() to mask only the 9-bit tag field and introduce
PPR_TAG_LAST_PAGE to explicitly extract the L bit. This way it becomes
easy to read.
Cc: Wei Huang <wei.huang2@amd.com>
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Ankit Soni <Ankit.Soni@amd.com>
---
drivers/iommu/amd/amd_iommu_types.h | 3 ++-
drivers/iommu/amd/ppr.c | 7 +++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h
index 3c292fdfa95a..a7aa9411b2e9 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -280,7 +280,8 @@
#define PPR_REQ_TYPE(x) (((x) >> 60) & 0xfULL)
#define PPR_FLAGS(x) (((x) >> 48) & 0xfffULL)
#define PPR_DEVID(x) ((x) & 0xffffULL)
-#define PPR_TAG(x) (((x) >> 32) & 0x3ffULL)
+#define PPR_TAG(x) (((x) >> 32) & 0x1ffULL)
+#define PPR_TAG_LAST_PAGE(x) (((x) >> 32) & 0x200ULL)
#define PPR_PASID1(x) (((x) >> 16) & 0xffffULL)
#define PPR_PASID2(x) (((x) >> 42) & 0xfULL)
#define PPR_PASID(x) ((PPR_PASID2(x) << 16) | PPR_PASID1(x))
diff --git a/drivers/iommu/amd/ppr.c b/drivers/iommu/amd/ppr.c
index 1dde19a79e80..76296079bb8b 100644
--- a/drivers/iommu/amd/ppr.c
+++ b/drivers/iommu/amd/ppr.c
@@ -130,7 +130,7 @@ static void iommu_call_iopf_notifier(struct amd_iommu *iommu, u64 *raw)
event.fault.prm.perm = ppr_flag_to_fault_perm(PPR_FLAGS(raw[0]));
event.fault.prm.addr = (u64)(raw[1] & PAGE_MASK);
event.fault.prm.pasid = PPR_PASID(raw[0]);
- event.fault.prm.grpid = PPR_TAG(raw[0]) & 0x1FF;
+ event.fault.prm.grpid = PPR_TAG(raw[0]);
/*
* PASID zero is used for requests from the I/O device without
@@ -146,7 +146,7 @@ static void iommu_call_iopf_notifier(struct amd_iommu *iommu, u64 *raw)
event.fault.prm.flags |= IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID;
event.fault.prm.flags |= IOMMU_FAULT_PAGE_REQUEST_PASID_VALID;
- if (PPR_TAG(raw[0]) & 0x200)
+ if (PPR_TAG_LAST_PAGE(raw[0]))
event.fault.prm.flags |= IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE;
/* Submit event */
@@ -157,8 +157,7 @@ static void iommu_call_iopf_notifier(struct amd_iommu *iommu, u64 *raw)
out:
/* Nobody cared, abort */
amd_iommu_complete_ppr(&pdev->dev, PPR_PASID(raw[0]),
- IOMMU_PAGE_RESP_FAILURE,
- PPR_TAG(raw[0]) & 0x1FF);
+ IOMMU_PAGE_RESP_FAILURE, PPR_TAG(raw[0]));
pci_dev_put(pdev);
}
--
2.31.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 3/5] iommu/amd: Fix missing CMD_COMPLETE_PPR response for invalid PPR requests
2026-08-11 4:08 [PATCH v2 0/5] iommu/amd: PRI related cleanup and fixes for v7.3 Vasant Hegde
2026-08-11 4:08 ` [PATCH v2 1/5] iommu/amd: Fix incorrect device ID in invalid PASID error message Vasant Hegde
2026-08-11 4:08 ` [PATCH v2 2/5] iommu/amd: Introduce PPR_TAG_LAST_PAGE() macro Vasant Hegde
@ 2026-08-11 4:08 ` Vasant Hegde
2026-08-11 4:08 ` [PATCH v2 4/5] iommu/amd: Rate limit INVALID_PPR_REQUEST error logging Vasant Hegde
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Vasant Hegde @ 2026-08-11 4:08 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, Vasant Hegde,
Gaultier Delbarre, Wei Huang, Ankit Soni
The AMD IOMMU spec, requires the host to respond with a CMD_COMPLETE_PPR
command when an EVENT_TYPE_INV_PPR_REQ event is received with the RX bit
cleared. This response was missing in the current implementation, leaving
invalid PPR requests unacknowledged.
Introduce amd_iommu_report_ppr_err() to handle EVENT_TYPE_INV_PPR_REQ
events. The new function logs the invalid PPR request and when the RX
bit is cleared, sends CMD_COMPLETE_PPR response.
Reported-by: Gaultier Delbarre <Gaultier.Delbarre@amd.com>
Co-developed-by: Wei Huang <wei.huang2@amd.com>
Signed-off-by: Wei Huang <wei.huang2@amd.com>
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Ankit Soni <Ankit.Soni@amd.com>
---
drivers/iommu/amd/amd_iommu_types.h | 1 +
drivers/iommu/amd/iommu.c | 38 ++++++++++++++++++++++++-----
2 files changed, 33 insertions(+), 6 deletions(-)
diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h
index a7aa9411b2e9..500952e752b4 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -159,6 +159,7 @@
#define EVENT_FLAGS_SHIFT 0x10
#define EVENT_FLAG_RW 0x020
#define EVENT_FLAG_I 0x008
+#define EVENT_FLAG_PPR_RX 0x001
/* feature control bits */
#define CONTROL_IOMMU_EN 0
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 563f9c2672d5..4372d3908e67 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -905,10 +905,40 @@ static void amd_iommu_report_page_fault(struct amd_iommu *iommu,
pci_dev_put(pdev);
}
+static void amd_iommu_report_ppr_err(struct amd_iommu *iommu, volatile u32 *event,
+ u16 devid, u64 address, int flags)
+{
+ struct pci_dev *pdev;
+ struct device *dev = iommu->iommu.dev;
+ u32 pasid = PPR_PASID(*((u64 *)event));
+ int tag = event[1] & 0x03FF;
+
+ dev_err(dev, "Event logged [INVALID_PPR_REQUEST device=%04x:%02x:%02x.%x pasid=0x%05x address=0x%llx flags=0x%04x tag=0x%03x]\n",
+ iommu->pci_seg->id, PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+ pasid, address, flags, tag);
+
+ /* Skip COMPLETE_PPR_REQUEST response if RX=1 */
+ if (flags & EVENT_FLAG_PPR_RX)
+ return;
+
+ pdev = pci_get_domain_bus_and_slot(iommu->pci_seg->id, PCI_BUS_NUM(devid),
+ devid & 0xff);
+ if (!pdev)
+ return;
+
+ if (!dev_iommu_priv_get(&pdev->dev)) {
+ pci_dev_put(pdev);
+ return;
+ }
+
+ amd_iommu_complete_ppr(&pdev->dev, pasid, IOMMU_PAGE_RESP_FAILURE, tag);
+ pci_dev_put(pdev);
+}
+
static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
{
struct device *dev = iommu->iommu.dev;
- int type, devid, flags, tag;
+ int type, devid, flags;
volatile u32 *event = __evt;
int count = 0;
u64 address, ctrl;
@@ -982,11 +1012,7 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
amd_iommu_report_rmp_hw_error(iommu, event);
break;
case EVENT_TYPE_INV_PPR_REQ:
- pasid = PPR_PASID(*((u64 *)__evt));
- tag = event[1] & 0x03FF;
- dev_err(dev, "Event logged [INVALID_PPR_REQUEST device=%04x:%02x:%02x.%x pasid=0x%05x address=0x%llx flags=0x%04x tag=0x%03x]\n",
- iommu->pci_seg->id, PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
- pasid, address, flags, tag);
+ amd_iommu_report_ppr_err(iommu, event, devid, address, flags);
break;
default:
dev_err(dev, "Event logged [UNKNOWN event[0]=0x%08x event[1]=0x%08x event[2]=0x%08x event[3]=0x%08x\n",
--
2.31.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 4/5] iommu/amd: Rate limit INVALID_PPR_REQUEST error logging
2026-08-11 4:08 [PATCH v2 0/5] iommu/amd: PRI related cleanup and fixes for v7.3 Vasant Hegde
` (2 preceding siblings ...)
2026-08-11 4:08 ` [PATCH v2 3/5] iommu/amd: Fix missing CMD_COMPLETE_PPR response for invalid PPR requests Vasant Hegde
@ 2026-08-11 4:08 ` Vasant Hegde
2026-08-11 4:09 ` [PATCH v2 5/5] iommu/amd: Fix GN bit setting in COMPLETE_PPR_REQUEST command Vasant Hegde
2026-08-11 7:03 ` [PATCH v2 0/5] iommu/amd: PRI related cleanup and fixes for v7.3 Jörg Rödel
5 siblings, 0 replies; 7+ messages in thread
From: Vasant Hegde @ 2026-08-11 4:08 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, Vasant Hegde,
Ankit Soni
The amd_iommu_report_ppr_err() function logs an error message for every
INVALID_PPR_REQUEST event. Under certain fault conditions, a misbehaving
or malicious device can flood the IOMMU event log with PPR faults, causing
the kernel log to be overwhelmed with repeated error messages.
Switch from dev_err() to dev_err_ratelimited() to suppress duplicate
messages when INVALID_PPR_REQUEST events occur at a high rate.
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Ankit Soni <Ankit.Soni@amd.com>
---
drivers/iommu/amd/iommu.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 4372d3908e67..17df9b28ebaf 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -913,9 +913,10 @@ static void amd_iommu_report_ppr_err(struct amd_iommu *iommu, volatile u32 *even
u32 pasid = PPR_PASID(*((u64 *)event));
int tag = event[1] & 0x03FF;
- dev_err(dev, "Event logged [INVALID_PPR_REQUEST device=%04x:%02x:%02x.%x pasid=0x%05x address=0x%llx flags=0x%04x tag=0x%03x]\n",
- iommu->pci_seg->id, PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
- pasid, address, flags, tag);
+ dev_err_ratelimited(dev, "Event logged [INVALID_PPR_REQUEST device=%04x:%02x:%02x.%x "
+ "pasid=0x%05x address=0x%llx flags=0x%04x tag=0x%03x]\n",
+ iommu->pci_seg->id, PCI_BUS_NUM(devid), PCI_SLOT(devid),
+ PCI_FUNC(devid), pasid, address, flags, tag);
/* Skip COMPLETE_PPR_REQUEST response if RX=1 */
if (flags & EVENT_FLAG_PPR_RX)
--
2.31.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 5/5] iommu/amd: Fix GN bit setting in COMPLETE_PPR_REQUEST command
2026-08-11 4:08 [PATCH v2 0/5] iommu/amd: PRI related cleanup and fixes for v7.3 Vasant Hegde
` (3 preceding siblings ...)
2026-08-11 4:08 ` [PATCH v2 4/5] iommu/amd: Rate limit INVALID_PPR_REQUEST error logging Vasant Hegde
@ 2026-08-11 4:09 ` Vasant Hegde
2026-08-11 7:03 ` [PATCH v2 0/5] iommu/amd: PRI related cleanup and fixes for v7.3 Jörg Rödel
5 siblings, 0 replies; 7+ messages in thread
From: Vasant Hegde @ 2026-08-11 4:09 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, Vasant Hegde,
Ankit Soni
The GN bit in the COMPLETE_PPR_REQUEST command indicates whether the
device is operating under a guest (v2) page table. Currently,
dev_data->pri_tlp is incorrectly used to derive this bit. However,
pri_tlp indicates whether the device uses PRI TLP which is unrelated
to page table mode.
Fix this by refactoring amd_iommu_complete_ppr() into a static internal
helper __amd_iommu_complete_ppr() that accepts an explicit 'gn' argument.
The amd_iommu_complete_ppr() wrapper then derives the GN bit correctly
from the device's active protection domain via pdom_is_v2_pgtbl_mode().
In the INVALID_PPR_REQUEST error handling path, the device's protection
domain may not be accessible, so derive the GN bit directly from the
EVENT_FLAG_PPR_GN flag in the event log entry instead.
While at it, change the 'gn' parameter type in build_complete_ppr()
from u8 to bool to better reflect its semantics.
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Ankit Soni <Ankit.Soni@amd.com>
---
drivers/iommu/amd/amd_iommu_types.h | 1 +
drivers/iommu/amd/iommu.c | 26 +++++++++++++++++++++-----
2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h
index 500952e752b4..36c0df418ce5 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -160,6 +160,7 @@
#define EVENT_FLAG_RW 0x020
#define EVENT_FLAG_I 0x008
#define EVENT_FLAG_PPR_RX 0x001
+#define EVENT_FLAG_PPR_GN 0x200
/* feature control bits */
#define CONTROL_IOMMU_EN 0
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 17df9b28ebaf..856948a5192c 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -92,6 +92,9 @@ static void clone_aliases(struct amd_iommu *iommu, struct device *dev);
static int iommu_completion_wait(struct amd_iommu *iommu);
+static int __amd_iommu_complete_ppr(struct device *dev, u32 pasid,
+ int status, int tag, bool gn);
+
/****************************************************************************
*
* Helper functions
@@ -912,6 +915,7 @@ static void amd_iommu_report_ppr_err(struct amd_iommu *iommu, volatile u32 *even
struct device *dev = iommu->iommu.dev;
u32 pasid = PPR_PASID(*((u64 *)event));
int tag = event[1] & 0x03FF;
+ bool gn;
dev_err_ratelimited(dev, "Event logged [INVALID_PPR_REQUEST device=%04x:%02x:%02x.%x "
"pasid=0x%05x address=0x%llx flags=0x%04x tag=0x%03x]\n",
@@ -932,7 +936,9 @@ static void amd_iommu_report_ppr_err(struct amd_iommu *iommu, volatile u32 *even
return;
}
- amd_iommu_complete_ppr(&pdev->dev, pasid, IOMMU_PAGE_RESP_FAILURE, tag);
+ gn = (flags & EVENT_FLAG_PPR_GN);
+
+ __amd_iommu_complete_ppr(&pdev->dev, pasid, IOMMU_PAGE_RESP_FAILURE, tag, gn);
pci_dev_put(pdev);
}
@@ -1372,7 +1378,7 @@ static void build_inv_iotlb_pages(struct iommu_cmd *cmd, u16 devid, int qdep,
}
static void build_complete_ppr(struct iommu_cmd *cmd, u16 devid, u32 pasid,
- int status, int tag, u8 gn)
+ int status, int tag, bool gn)
{
memset(cmd, 0, sizeof(*cmd));
@@ -1867,7 +1873,8 @@ static void dev_flush_pasid_all(struct iommu_dev_data *dev_data,
amd_iommu_dev_flush_pasid_pages(dev_data, pasid, 0, U64_MAX);
}
-int amd_iommu_complete_ppr(struct device *dev, u32 pasid, int status, int tag)
+static int __amd_iommu_complete_ppr(struct device *dev, u32 pasid,
+ int status, int tag, bool gn)
{
struct iommu_dev_data *dev_data;
struct amd_iommu *iommu;
@@ -1876,12 +1883,21 @@ int amd_iommu_complete_ppr(struct device *dev, u32 pasid, int status, int tag)
dev_data = dev_iommu_priv_get(dev);
iommu = get_amd_iommu_from_dev(dev);
- build_complete_ppr(&cmd, dev_data->devid, pasid, status,
- tag, dev_data->pri_tlp);
+ build_complete_ppr(&cmd, dev_data->devid, pasid, status, tag, gn);
return iommu_queue_command(iommu, &cmd);
}
+int amd_iommu_complete_ppr(struct device *dev, u32 pasid, int status, int tag)
+{
+ struct iommu_dev_data *dev_data = dev_iommu_priv_get(dev);
+ bool gn;
+
+ gn = pdom_is_v2_pgtbl_mode(dev_data->domain);
+
+ return __amd_iommu_complete_ppr(dev, pasid, status, tag, gn);
+}
+
/****************************************************************************
*
* The next functions belong to the domain allocation. A domain is
--
2.31.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v2 0/5] iommu/amd: PRI related cleanup and fixes for v7.3
2026-08-11 4:08 [PATCH v2 0/5] iommu/amd: PRI related cleanup and fixes for v7.3 Vasant Hegde
` (4 preceding siblings ...)
2026-08-11 4:09 ` [PATCH v2 5/5] iommu/amd: Fix GN bit setting in COMPLETE_PPR_REQUEST command Vasant Hegde
@ 2026-08-11 7:03 ` Jörg Rödel
5 siblings, 0 replies; 7+ messages in thread
From: Jörg Rödel @ 2026-08-11 7:03 UTC (permalink / raw)
To: Vasant Hegde; +Cc: iommu, will, robin.murphy, suravee.suthikulpanit
On Tue, Aug 11, 2026 at 04:08:55AM +0000, Vasant Hegde wrote:
> Joerg,
> V2 is rebased on top of iommu/amd-vi branch (Commit af3b69b16383). No other
> changes.
Applied, thanks.
^ permalink raw reply [flat|nested] 7+ messages in thread