mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
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:
parent
abdbd786c5
commit
c94252cd5b
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user