Skip to content

Commit 06cdcc3

Browse files
LuBaoluwilldeacon
authored andcommitted
iommu: Add attach handle to struct iopf_group
Previously, the domain that a page fault targets is stored in an iopf_group, which represents a minimal set of page faults. With the introduction of attach handle, replace the domain with the handle so that the fault handler can obtain more information as needed when handling the faults. iommu_report_device_fault() is currently used for SVA page faults, which handles the page fault in an internal cycle. The domain is retrieved with iommu_get_domain_for_dev_pasid() if the pasid in the fault message is valid. This doesn't work in IOMMUFD case, where if the pasid table of a device is wholly managed by user space, there is no domain attached to the PASID of the device, and all page faults are forwarded through a NESTING domain attaching to RID. Add a static flag in iommu ops, which indicates if the IOMMU driver supports user-managed PASID tables. In the iopf deliver path, if no attach handle found for the iopf PASID, roll back to RID domain when the IOMMU driver supports this capability. iommu_get_domain_for_dev_pasid() is no longer used and can be removed. Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Link: https://lore.kernel.org/r/20240702063444.105814-4-baolu.lu@linux.intel.com Signed-off-by: Will Deacon <will@kernel.org>
1 parent 3e7f57d commit 06cdcc3

File tree

4 files changed

+42
-78
lines changed

4 files changed

+42
-78
lines changed

drivers/iommu/io-pgfault.c

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -59,30 +59,6 @@ void iopf_free_group(struct iopf_group *group)
5959
}
6060
EXPORT_SYMBOL_GPL(iopf_free_group);
6161

62-
static struct iommu_domain *get_domain_for_iopf(struct device *dev,
63-
struct iommu_fault *fault)
64-
{
65-
struct iommu_domain *domain;
66-
67-
if (fault->prm.flags & IOMMU_FAULT_PAGE_REQUEST_PASID_VALID) {
68-
domain = iommu_get_domain_for_dev_pasid(dev, fault->prm.pasid, 0);
69-
if (IS_ERR(domain))
70-
domain = NULL;
71-
} else {
72-
domain = iommu_get_domain_for_dev(dev);
73-
}
74-
75-
if (!domain || !domain->iopf_handler) {
76-
dev_warn_ratelimited(dev,
77-
"iopf (pasid %d) without domain attached or handler installed\n",
78-
fault->prm.pasid);
79-
80-
return NULL;
81-
}
82-
83-
return domain;
84-
}
85-
8662
/* Non-last request of a group. Postpone until the last one. */
8763
static int report_partial_fault(struct iommu_fault_param *fault_param,
8864
struct iommu_fault *fault)
@@ -206,20 +182,51 @@ void iommu_report_device_fault(struct device *dev, struct iopf_fault *evt)
206182
if (group == &abort_group)
207183
goto err_abort;
208184

209-
group->domain = get_domain_for_iopf(dev, fault);
210-
if (!group->domain)
185+
if (fault->prm.flags & IOMMU_FAULT_PAGE_REQUEST_PASID_VALID) {
186+
group->attach_handle = iommu_attach_handle_get(dev->iommu_group,
187+
fault->prm.pasid,
188+
0);
189+
if (IS_ERR(group->attach_handle)) {
190+
const struct iommu_ops *ops = dev_iommu_ops(dev);
191+
192+
if (!ops->user_pasid_table)
193+
goto err_abort;
194+
195+
/*
196+
* The iommu driver for this device supports user-
197+
* managed PASID table. Therefore page faults for
198+
* any PASID should go through the NESTING domain
199+
* attached to the device RID.
200+
*/
201+
group->attach_handle =
202+
iommu_attach_handle_get(dev->iommu_group,
203+
IOMMU_NO_PASID,
204+
IOMMU_DOMAIN_NESTED);
205+
if (IS_ERR(group->attach_handle))
206+
goto err_abort;
207+
}
208+
} else {
209+
group->attach_handle =
210+
iommu_attach_handle_get(dev->iommu_group, IOMMU_NO_PASID, 0);
211+
if (IS_ERR(group->attach_handle))
212+
goto err_abort;
213+
}
214+
215+
if (!group->attach_handle->domain->iopf_handler)
211216
goto err_abort;
212217

213218
/*
214219
* On success iopf_handler must call iopf_group_response() and
215220
* iopf_free_group()
216221
*/
217-
if (group->domain->iopf_handler(group))
222+
if (group->attach_handle->domain->iopf_handler(group))
218223
goto err_abort;
219224

220225
return;
221226

222227
err_abort:
228+
dev_warn_ratelimited(dev, "iopf with pasid %d aborted\n",
229+
fault->prm.pasid);
223230
iopf_group_response(group, IOMMU_PAGE_RESP_FAILURE);
224231
if (group == &abort_group)
225232
__iopf_free_group(group);

drivers/iommu/iommu-sva.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,8 @@ static void iommu_sva_handle_iopf(struct work_struct *work)
272272
if (status != IOMMU_PAGE_RESP_SUCCESS)
273273
break;
274274

275-
status = iommu_sva_handle_mm(&iopf->fault, group->domain->mm);
275+
status = iommu_sva_handle_mm(&iopf->fault,
276+
group->attach_handle->domain->mm);
276277
}
277278

278279
iopf_group_response(group, status);

drivers/iommu/iommu.c

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3421,45 +3421,6 @@ void iommu_detach_device_pasid(struct iommu_domain *domain, struct device *dev,
34213421
}
34223422
EXPORT_SYMBOL_GPL(iommu_detach_device_pasid);
34233423

3424-
/*
3425-
* iommu_get_domain_for_dev_pasid() - Retrieve domain for @pasid of @dev
3426-
* @dev: the queried device
3427-
* @pasid: the pasid of the device
3428-
* @type: matched domain type, 0 for any match
3429-
*
3430-
* This is a variant of iommu_get_domain_for_dev(). It returns the existing
3431-
* domain attached to pasid of a device. Callers must hold a lock around this
3432-
* function, and both iommu_attach/detach_dev_pasid() whenever a domain of
3433-
* type is being manipulated. This API does not internally resolve races with
3434-
* attach/detach.
3435-
*
3436-
* Return: attached domain on success, NULL otherwise.
3437-
*/
3438-
struct iommu_domain *iommu_get_domain_for_dev_pasid(struct device *dev,
3439-
ioasid_t pasid,
3440-
unsigned int type)
3441-
{
3442-
/* Caller must be a probed driver on dev */
3443-
struct iommu_group *group = dev->iommu_group;
3444-
struct iommu_attach_handle *handle;
3445-
struct iommu_domain *domain = NULL;
3446-
3447-
if (!group)
3448-
return NULL;
3449-
3450-
xa_lock(&group->pasid_array);
3451-
handle = xa_load(&group->pasid_array, pasid);
3452-
if (handle)
3453-
domain = handle->domain;
3454-
3455-
if (type && domain && domain->type != type)
3456-
domain = NULL;
3457-
xa_unlock(&group->pasid_array);
3458-
3459-
return domain;
3460-
}
3461-
EXPORT_SYMBOL_GPL(iommu_get_domain_for_dev_pasid);
3462-
34633424
ioasid_t iommu_alloc_global_pasid(struct device *dev)
34643425
{
34653426
int ret;

include/linux/iommu.h

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ struct iopf_group {
127127
/* list node for iommu_fault_param::faults */
128128
struct list_head pending_node;
129129
struct work_struct work;
130-
struct iommu_domain *domain;
130+
struct iommu_attach_handle *attach_handle;
131131
/* The device's fault data parameter. */
132132
struct iommu_fault_param *fault_param;
133133
};
@@ -547,6 +547,10 @@ static inline int __iommu_copy_struct_from_user_array(
547547
* @default_domain: If not NULL this will always be set as the default domain.
548548
* This should be an IDENTITY/BLOCKED/PLATFORM domain.
549549
* Do not use in new drivers.
550+
* @user_pasid_table: IOMMU driver supports user-managed PASID table. There is
551+
* no user domain for each PASID and the I/O page faults are
552+
* forwarded through the user domain attached to the device
553+
* RID.
550554
*/
551555
struct iommu_ops {
552556
bool (*capable)(struct device *dev, enum iommu_cap);
@@ -590,6 +594,7 @@ struct iommu_ops {
590594
struct iommu_domain *blocked_domain;
591595
struct iommu_domain *release_domain;
592596
struct iommu_domain *default_domain;
597+
u8 user_pasid_table:1;
593598
};
594599

595600
/**
@@ -1064,9 +1069,6 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
10641069
struct iommu_attach_handle *handle);
10651070
void iommu_detach_device_pasid(struct iommu_domain *domain,
10661071
struct device *dev, ioasid_t pasid);
1067-
struct iommu_domain *
1068-
iommu_get_domain_for_dev_pasid(struct device *dev, ioasid_t pasid,
1069-
unsigned int type);
10701072
ioasid_t iommu_alloc_global_pasid(struct device *dev);
10711073
void iommu_free_global_pasid(ioasid_t pasid);
10721074
#else /* CONFIG_IOMMU_API */
@@ -1408,13 +1410,6 @@ static inline void iommu_detach_device_pasid(struct iommu_domain *domain,
14081410
{
14091411
}
14101412

1411-
static inline struct iommu_domain *
1412-
iommu_get_domain_for_dev_pasid(struct device *dev, ioasid_t pasid,
1413-
unsigned int type)
1414-
{
1415-
return NULL;
1416-
}
1417-
14181413
static inline ioasid_t iommu_alloc_global_pasid(struct device *dev)
14191414
{
14201415
return IOMMU_PASID_INVALID;

0 commit comments

Comments
 (0)