Skip to content

Commit dca8b19

Browse files
committed
Merge: [RHEL9.6] Recent upstream fixes for iommufd
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/6283 JIRA: https://issues.redhat.com/browse/RHEL-75942 Upstream Status: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Recent upstream fixes for iommufd: iommufd/iova_bitmap: Fix shift-out-of-bounds in iova_bitmap_offset_to_index() iommu: iommufd: fix WARNING in iommufd_device_unbind iommufd/fault: Destroy response and mutex in iommufd_fault_destroy() iommufd/fault: Use a separate spinlock to protect fault->deliver list iommufd: Fix struct iommu_hwpt_pgfault init and padding Signed-off-by: Eder Zulian <ezulian@redhat.com> Approved-by: Jerry Snitselaar <jsnitsel@redhat.com> Approved-by: Mark Salter <msalter@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Approved-by: Donald Dutile <ddutile@redhat.com> Merged-by: Patrick Talbert <ptalbert@redhat.com>
2 parents 69e6048 + d7be74e commit dca8b19

File tree

5 files changed

+63
-18
lines changed

5 files changed

+63
-18
lines changed

drivers/iommu/iommufd/fault.c

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -98,15 +98,23 @@ static void iommufd_auto_response_faults(struct iommufd_hw_pagetable *hwpt,
9898
{
9999
struct iommufd_fault *fault = hwpt->fault;
100100
struct iopf_group *group, *next;
101+
struct list_head free_list;
101102
unsigned long index;
102103

103104
if (!fault)
104105
return;
106+
INIT_LIST_HEAD(&free_list);
105107

106108
mutex_lock(&fault->mutex);
109+
spin_lock(&fault->lock);
107110
list_for_each_entry_safe(group, next, &fault->deliver, node) {
108111
if (group->attach_handle != &handle->handle)
109112
continue;
113+
list_move(&group->node, &free_list);
114+
}
115+
spin_unlock(&fault->lock);
116+
117+
list_for_each_entry_safe(group, next, &free_list, node) {
110118
list_del(&group->node);
111119
iopf_group_response(group, IOMMU_PAGE_RESP_INVALID);
112120
iopf_free_group(group);
@@ -208,6 +216,7 @@ void iommufd_fault_destroy(struct iommufd_object *obj)
208216
{
209217
struct iommufd_fault *fault = container_of(obj, struct iommufd_fault, obj);
210218
struct iopf_group *group, *next;
219+
unsigned long index;
211220

212221
/*
213222
* The iommufd object's reference count is zero at this point.
@@ -220,6 +229,13 @@ void iommufd_fault_destroy(struct iommufd_object *obj)
220229
iopf_group_response(group, IOMMU_PAGE_RESP_INVALID);
221230
iopf_free_group(group);
222231
}
232+
xa_for_each(&fault->response, index, group) {
233+
xa_erase(&fault->response, index);
234+
iopf_group_response(group, IOMMU_PAGE_RESP_INVALID);
235+
iopf_free_group(group);
236+
}
237+
xa_destroy(&fault->response);
238+
mutex_destroy(&fault->mutex);
223239
}
224240

225241
static void iommufd_compose_fault_message(struct iommu_fault *fault,
@@ -242,7 +258,7 @@ static ssize_t iommufd_fault_fops_read(struct file *filep, char __user *buf,
242258
{
243259
size_t fault_size = sizeof(struct iommu_hwpt_pgfault);
244260
struct iommufd_fault *fault = filep->private_data;
245-
struct iommu_hwpt_pgfault data;
261+
struct iommu_hwpt_pgfault data = {};
246262
struct iommufd_device *idev;
247263
struct iopf_group *group;
248264
struct iopf_fault *iopf;
@@ -253,17 +269,19 @@ static ssize_t iommufd_fault_fops_read(struct file *filep, char __user *buf,
253269
return -ESPIPE;
254270

255271
mutex_lock(&fault->mutex);
256-
while (!list_empty(&fault->deliver) && count > done) {
257-
group = list_first_entry(&fault->deliver,
258-
struct iopf_group, node);
259-
260-
if (group->fault_count * fault_size > count - done)
272+
while ((group = iommufd_fault_deliver_fetch(fault))) {
273+
if (done >= count ||
274+
group->fault_count * fault_size > count - done) {
275+
iommufd_fault_deliver_restore(fault, group);
261276
break;
277+
}
262278

263279
rc = xa_alloc(&fault->response, &group->cookie, group,
264280
xa_limit_32b, GFP_KERNEL);
265-
if (rc)
281+
if (rc) {
282+
iommufd_fault_deliver_restore(fault, group);
266283
break;
284+
}
267285

268286
idev = to_iommufd_handle(group->attach_handle)->idev;
269287
list_for_each_entry(iopf, &group->faults, list) {
@@ -272,13 +290,12 @@ static ssize_t iommufd_fault_fops_read(struct file *filep, char __user *buf,
272290
group->cookie);
273291
if (copy_to_user(buf + done, &data, fault_size)) {
274292
xa_erase(&fault->response, group->cookie);
293+
iommufd_fault_deliver_restore(fault, group);
275294
rc = -EFAULT;
276295
break;
277296
}
278297
done += fault_size;
279298
}
280-
281-
list_del(&group->node);
282299
}
283300
mutex_unlock(&fault->mutex);
284301

@@ -336,10 +353,10 @@ static __poll_t iommufd_fault_fops_poll(struct file *filep,
336353
__poll_t pollflags = EPOLLOUT;
337354

338355
poll_wait(filep, &fault->wait_queue, wait);
339-
mutex_lock(&fault->mutex);
356+
spin_lock(&fault->lock);
340357
if (!list_empty(&fault->deliver))
341358
pollflags |= EPOLLIN | EPOLLRDNORM;
342-
mutex_unlock(&fault->mutex);
359+
spin_unlock(&fault->lock);
343360

344361
return pollflags;
345362
}
@@ -382,6 +399,7 @@ int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)
382399
INIT_LIST_HEAD(&fault->deliver);
383400
xa_init_flags(&fault->response, XA_FLAGS_ALLOC1);
384401
mutex_init(&fault->mutex);
402+
spin_lock_init(&fault->lock);
385403
init_waitqueue_head(&fault->wait_queue);
386404

387405
filep = anon_inode_getfile("[iommufd-pgfault]", &iommufd_fault_fops,
@@ -430,9 +448,9 @@ int iommufd_fault_iopf_handler(struct iopf_group *group)
430448
hwpt = group->attach_handle->domain->fault_data;
431449
fault = hwpt->fault;
432450

433-
mutex_lock(&fault->mutex);
451+
spin_lock(&fault->lock);
434452
list_add_tail(&group->node, &fault->deliver);
435-
mutex_unlock(&fault->mutex);
453+
spin_unlock(&fault->lock);
436454

437455
wake_up_interruptible(&fault->wait_queue);
438456

drivers/iommu/iommufd/iommufd_private.h

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,14 +462,39 @@ struct iommufd_fault {
462462
struct iommufd_ctx *ictx;
463463
struct file *filep;
464464

465-
/* The lists of outstanding faults protected by below mutex. */
466-
struct mutex mutex;
465+
spinlock_t lock; /* protects the deliver list */
467466
struct list_head deliver;
467+
struct mutex mutex; /* serializes response flows */
468468
struct xarray response;
469469

470470
struct wait_queue_head wait_queue;
471471
};
472472

473+
/* Fetch the first node out of the fault->deliver list */
474+
static inline struct iopf_group *
475+
iommufd_fault_deliver_fetch(struct iommufd_fault *fault)
476+
{
477+
struct list_head *list = &fault->deliver;
478+
struct iopf_group *group = NULL;
479+
480+
spin_lock(&fault->lock);
481+
if (!list_empty(list)) {
482+
group = list_first_entry(list, struct iopf_group, node);
483+
list_del(&group->node);
484+
}
485+
spin_unlock(&fault->lock);
486+
return group;
487+
}
488+
489+
/* Restore a node back to the head of the fault->deliver list */
490+
static inline void iommufd_fault_deliver_restore(struct iommufd_fault *fault,
491+
struct iopf_group *group)
492+
{
493+
spin_lock(&fault->lock);
494+
list_add(&group->node, &fault->deliver);
495+
spin_unlock(&fault->lock);
496+
}
497+
473498
struct iommufd_attach_handle {
474499
struct iommu_attach_handle handle;
475500
struct iommufd_device *idev;

drivers/iommu/iommufd/iova_bitmap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ struct iova_bitmap {
130130
static unsigned long iova_bitmap_offset_to_index(struct iova_bitmap *bitmap,
131131
unsigned long iova)
132132
{
133-
unsigned long pgsize = 1 << bitmap->mapped.pgshift;
133+
unsigned long pgsize = 1UL << bitmap->mapped.pgshift;
134134

135135
return iova / (BITS_PER_TYPE(*bitmap->bitmap) * pgsize);
136136
}

drivers/iommu/iommufd/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ static int iommufd_object_dec_wait_shortterm(struct iommufd_ctx *ictx,
130130
if (wait_event_timeout(ictx->destroy_wait,
131131
refcount_read(&to_destroy->shortterm_users) ==
132132
0,
133-
msecs_to_jiffies(10000)))
133+
msecs_to_jiffies(60000)))
134134
return 0;
135135

136136
pr_crit("Time out waiting for iommufd object to become free\n");

include/uapi/linux/iommufd.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,7 @@ enum iommu_hwpt_pgfault_perm {
737737
* @pasid: Process Address Space ID
738738
* @grpid: Page Request Group Index
739739
* @perm: Combination of enum iommu_hwpt_pgfault_perm
740+
* @__reserved: Must be 0.
740741
* @addr: Fault address
741742
* @length: a hint of how much data the requestor is expecting to fetch. For
742743
* example, if the PRI initiator knows it is going to do a 10MB
@@ -752,7 +753,8 @@ struct iommu_hwpt_pgfault {
752753
__u32 pasid;
753754
__u32 grpid;
754755
__u32 perm;
755-
__u64 addr;
756+
__u32 __reserved;
757+
__aligned_u64 addr;
756758
__u32 length;
757759
__u32 cookie;
758760
};

0 commit comments

Comments
 (0)