Skip to content

Commit 9704719

Browse files
jpbruckerjoergroedel
authored andcommitted
iommu: Allow page responses without PASID
Some PCIe devices do not expect a PASID value in PRI Page Responses. If the "PRG Response PASID Required" bit in the PRI capability is zero, then the OS should not set the PASID field. Similarly on Arm SMMU, responses to stall events do not have a PASID. Currently iommu_page_response() systematically checks that the PASID in the page response corresponds to the one in the page request. This can't work with virtualization because a page response coming from a guest OS won't have a PASID if the passed-through device does not require one. Add a flag to page requests that declares whether the corresponding response needs to have a PASID. When this flag isn't set, allow page responses without PASID. Reported-by: Shameerali Kolothum Thodi <[email protected]> Signed-off-by: Jean-Philippe Brucker <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent d3e3d2b commit 9704719

File tree

2 files changed

+22
-7
lines changed

2 files changed

+22
-7
lines changed

drivers/iommu/iommu.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,11 +1185,12 @@ EXPORT_SYMBOL_GPL(iommu_report_device_fault);
11851185
int iommu_page_response(struct device *dev,
11861186
struct iommu_page_response *msg)
11871187
{
1188-
bool pasid_valid;
1188+
bool needs_pasid;
11891189
int ret = -EINVAL;
11901190
struct iommu_fault_event *evt;
11911191
struct iommu_fault_page_request *prm;
11921192
struct dev_iommu *param = dev->iommu;
1193+
bool has_pasid = msg->flags & IOMMU_PAGE_RESP_PASID_VALID;
11931194
struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
11941195

11951196
if (!domain || !domain->ops->page_response)
@@ -1214,14 +1215,24 @@ int iommu_page_response(struct device *dev,
12141215
*/
12151216
list_for_each_entry(evt, &param->fault_param->faults, list) {
12161217
prm = &evt->fault.prm;
1217-
pasid_valid = prm->flags & IOMMU_FAULT_PAGE_REQUEST_PASID_VALID;
1218+
if (prm->grpid != msg->grpid)
1219+
continue;
12181220

1219-
if ((pasid_valid && prm->pasid != msg->pasid) ||
1220-
prm->grpid != msg->grpid)
1221+
/*
1222+
* If the PASID is required, the corresponding request is
1223+
* matched using the group ID, the PASID valid bit and the PASID
1224+
* value. Otherwise only the group ID matches request and
1225+
* response.
1226+
*/
1227+
needs_pasid = prm->flags & IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID;
1228+
if (needs_pasid && (!has_pasid || msg->pasid != prm->pasid))
12211229
continue;
12221230

1223-
/* Sanitize the reply */
1224-
msg->flags = pasid_valid ? IOMMU_PAGE_RESP_PASID_VALID : 0;
1231+
if (!needs_pasid && has_pasid) {
1232+
/* No big deal, just clear it. */
1233+
msg->flags &= ~IOMMU_PAGE_RESP_PASID_VALID;
1234+
msg->pasid = 0;
1235+
}
12251236

12261237
ret = domain->ops->page_response(dev, evt, msg);
12271238
list_del(&evt->list);

include/uapi/linux/iommu.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,10 @@ struct iommu_fault_unrecoverable {
8181
/**
8282
* struct iommu_fault_page_request - Page Request data
8383
* @flags: encodes whether the corresponding fields are valid and whether this
84-
* is the last page in group (IOMMU_FAULT_PAGE_REQUEST_* values)
84+
* is the last page in group (IOMMU_FAULT_PAGE_REQUEST_* values).
85+
* When IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID is set, the page response
86+
* must have the same PASID value as the page request. When it is clear,
87+
* the page response should not have a PASID.
8588
* @pasid: Process Address Space ID
8689
* @grpid: Page Request Group Index
8790
* @perm: requested page permissions (IOMMU_FAULT_PERM_* values)
@@ -92,6 +95,7 @@ struct iommu_fault_page_request {
9295
#define IOMMU_FAULT_PAGE_REQUEST_PASID_VALID (1 << 0)
9396
#define IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE (1 << 1)
9497
#define IOMMU_FAULT_PAGE_REQUEST_PRIV_DATA (1 << 2)
98+
#define IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID (1 << 3)
9599
__u32 flags;
96100
__u32 pasid;
97101
__u32 grpid;

0 commit comments

Comments
 (0)