Skip to content

Commit 74e54d5

Browse files
committed
Merge branch 'iommu/iommufd/attach-handles' into iommu/next
* iommu/iommufd/attach-handles: iommu: Extend domain attach group with handle support iommu: Add attach handle to struct iopf_group iommu: Remove sva handle list iommu: Introduce domain attachment handle
2 parents 578cc98 + 8519e68 commit 74e54d5

File tree

6 files changed

+238
-100
lines changed

6 files changed

+238
-100
lines changed

drivers/dma/idxd/init.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ static int idxd_enable_system_pasid(struct idxd_device *idxd)
584584
* DMA domain is owned by the driver, it should support all valid
585585
* types such as DMA-FQ, identity, etc.
586586
*/
587-
ret = iommu_attach_device_pasid(domain, dev, pasid);
587+
ret = iommu_attach_device_pasid(domain, dev, pasid, NULL);
588588
if (ret) {
589589
dev_err(dev, "failed to attach device pasid %d, domain type %d",
590590
pasid, domain->type);

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-priv.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,15 @@ void iommu_device_unregister_bus(struct iommu_device *iommu,
3535
const struct bus_type *bus,
3636
struct notifier_block *nb);
3737

38+
struct iommu_attach_handle *iommu_attach_handle_get(struct iommu_group *group,
39+
ioasid_t pasid,
40+
unsigned int type);
41+
int iommu_attach_group_handle(struct iommu_domain *domain,
42+
struct iommu_group *group,
43+
struct iommu_attach_handle *handle);
44+
void iommu_detach_group_handle(struct iommu_domain *domain,
45+
struct iommu_group *group);
46+
int iommu_replace_group_handle(struct iommu_group *group,
47+
struct iommu_domain *new_domain,
48+
struct iommu_attach_handle *handle);
3849
#endif /* __LINUX_IOMMU_PRIV_H */

drivers/iommu/iommu-sva.c

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ static struct iommu_mm_data *iommu_alloc_mm_data(struct mm_struct *mm, struct de
4343
}
4444
iommu_mm->pasid = pasid;
4545
INIT_LIST_HEAD(&iommu_mm->sva_domains);
46-
INIT_LIST_HEAD(&iommu_mm->sva_handles);
4746
/*
4847
* Make sure the write to mm->iommu_mm is not reordered in front of
4948
* initialization to iommu_mm fields. If it does, readers may see a
@@ -71,11 +70,16 @@ static struct iommu_mm_data *iommu_alloc_mm_data(struct mm_struct *mm, struct de
7170
*/
7271
struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm)
7372
{
73+
struct iommu_group *group = dev->iommu_group;
74+
struct iommu_attach_handle *attach_handle;
7475
struct iommu_mm_data *iommu_mm;
7576
struct iommu_domain *domain;
7677
struct iommu_sva *handle;
7778
int ret;
7879

80+
if (!group)
81+
return ERR_PTR(-ENODEV);
82+
7983
mutex_lock(&iommu_sva_lock);
8084

8185
/* Allocate mm->pasid if necessary. */
@@ -85,12 +89,22 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
8589
goto out_unlock;
8690
}
8791

88-
list_for_each_entry(handle, &mm->iommu_mm->sva_handles, handle_item) {
89-
if (handle->dev == dev) {
90-
refcount_inc(&handle->users);
91-
mutex_unlock(&iommu_sva_lock);
92-
return handle;
92+
/* A bond already exists, just take a reference`. */
93+
attach_handle = iommu_attach_handle_get(group, iommu_mm->pasid, IOMMU_DOMAIN_SVA);
94+
if (!IS_ERR(attach_handle)) {
95+
handle = container_of(attach_handle, struct iommu_sva, handle);
96+
if (attach_handle->domain->mm != mm) {
97+
ret = -EBUSY;
98+
goto out_unlock;
9399
}
100+
refcount_inc(&handle->users);
101+
mutex_unlock(&iommu_sva_lock);
102+
return handle;
103+
}
104+
105+
if (PTR_ERR(attach_handle) != -ENOENT) {
106+
ret = PTR_ERR(attach_handle);
107+
goto out_unlock;
94108
}
95109

96110
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
@@ -101,7 +115,8 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
101115

102116
/* Search for an existing domain. */
103117
list_for_each_entry(domain, &mm->iommu_mm->sva_domains, next) {
104-
ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid);
118+
ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
119+
&handle->handle);
105120
if (!ret) {
106121
domain->users++;
107122
goto out;
@@ -115,18 +130,17 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
115130
goto out_free_handle;
116131
}
117132

118-
ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid);
133+
ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
134+
&handle->handle);
119135
if (ret)
120136
goto out_free_domain;
121137
domain->users = 1;
122138
list_add(&domain->next, &mm->iommu_mm->sva_domains);
123139

124140
out:
125141
refcount_set(&handle->users, 1);
126-
list_add(&handle->handle_item, &mm->iommu_mm->sva_handles);
127142
mutex_unlock(&iommu_sva_lock);
128143
handle->dev = dev;
129-
handle->domain = domain;
130144
return handle;
131145

132146
out_free_domain:
@@ -149,7 +163,7 @@ EXPORT_SYMBOL_GPL(iommu_sva_bind_device);
149163
*/
150164
void iommu_sva_unbind_device(struct iommu_sva *handle)
151165
{
152-
struct iommu_domain *domain = handle->domain;
166+
struct iommu_domain *domain = handle->handle.domain;
153167
struct iommu_mm_data *iommu_mm = domain->mm->iommu_mm;
154168
struct device *dev = handle->dev;
155169

@@ -158,7 +172,6 @@ void iommu_sva_unbind_device(struct iommu_sva *handle)
158172
mutex_unlock(&iommu_sva_lock);
159173
return;
160174
}
161-
list_del(&handle->handle_item);
162175

163176
iommu_detach_device_pasid(domain, dev, iommu_mm->pasid);
164177
if (--domain->users == 0) {
@@ -172,7 +185,7 @@ EXPORT_SYMBOL_GPL(iommu_sva_unbind_device);
172185

173186
u32 iommu_sva_get_pasid(struct iommu_sva *handle)
174187
{
175-
struct iommu_domain *domain = handle->domain;
188+
struct iommu_domain *domain = handle->handle.domain;
176189

177190
return mm_get_enqcmd_pasid(domain->mm);
178191
}
@@ -261,7 +274,8 @@ static void iommu_sva_handle_iopf(struct work_struct *work)
261274
if (status != IOMMU_PAGE_RESP_SUCCESS)
262275
break;
263276

264-
status = iommu_sva_handle_mm(&iopf->fault, group->domain->mm);
277+
status = iommu_sva_handle_mm(&iopf->fault,
278+
group->attach_handle->domain->mm);
265279
}
266280

267281
iopf_group_response(group, status);

0 commit comments

Comments
 (0)