iommu/amd: Fix GN bit setting in COMPLETE_PPR_REQUEST command

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>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
This commit is contained in:
Vasant Hegde 2026-08-11 04:09:00 +00:00 committed by Joerg Roedel
parent abdbd786c5
commit c94252cd5b
2 changed files with 22 additions and 5 deletions

View File

@ -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

View File

@ -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