Skip to content

Commit db78436

Browse files
committed
Merge tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd
Pull iommufd updates from Jason Gunthorpe: "Collection of small cleanup and one fix: - Sort headers and struct forward declarations - Fix random selftest failures in some cases due to dirty tracking tests - Have the reserved IOVA regions mechanism work when a HWPT is used as a nesting parent. This updates the nesting parent's IOAS with the reserved regions of the device and will also install the ITS doorbell page on ARM. - Add missed validation of parent domain ops against the current iommu - Fix a syzkaller bug related to integer overflow during ALIGN() - Tidy two iommu_domain attach paths" * tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd: iommu: Set iommu_attach_handle->domain in core iommufd: Avoid duplicated __iommu_group_set_core_domain() call iommufd: Protect against overflow of ALIGN() during iova allocation iommufd: Reorder struct forward declarations iommufd: Check the domain owner of the parent before creating a nesting domain iommufd/device: Enforce reserved IOVA also when attached to hwpt_nested iommufd/selftest: Fix buffer read overrrun in the dirty test iommufd: Reorder include files
2 parents 54d7e81 + 79805c1 commit db78436

File tree

15 files changed

+101
-71
lines changed

15 files changed

+101
-71
lines changed

drivers/iommu/iommu.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3578,6 +3578,7 @@ int iommu_replace_group_handle(struct iommu_group *group,
35783578
ret = xa_reserve(&group->pasid_array, IOMMU_NO_PASID, GFP_KERNEL);
35793579
if (ret)
35803580
goto err_unlock;
3581+
handle->domain = new_domain;
35813582
}
35823583

35833584
ret = __iommu_group_set_domain(group, new_domain);

drivers/iommu/iommufd/device.c

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// SPDX-License-Identifier: GPL-2.0-only
22
/* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES
33
*/
4+
#include <linux/iommu.h>
45
#include <linux/iommufd.h>
56
#include <linux/slab.h>
6-
#include <linux/iommu.h>
77
#include <uapi/linux/iommufd.h>
8-
#include "../iommu-priv.h"
98

9+
#include "../iommu-priv.h"
1010
#include "io_pagetable.h"
1111
#include "iommufd_private.h"
1212

@@ -327,8 +327,9 @@ static int iommufd_group_setup_msi(struct iommufd_group *igroup,
327327
return 0;
328328
}
329329

330-
static int iommufd_hwpt_paging_attach(struct iommufd_hwpt_paging *hwpt_paging,
331-
struct iommufd_device *idev)
330+
static int
331+
iommufd_device_attach_reserved_iova(struct iommufd_device *idev,
332+
struct iommufd_hwpt_paging *hwpt_paging)
332333
{
333334
int rc;
334335

@@ -354,6 +355,7 @@ static int iommufd_hwpt_paging_attach(struct iommufd_hwpt_paging *hwpt_paging,
354355
int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
355356
struct iommufd_device *idev)
356357
{
358+
struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt);
357359
int rc;
358360

359361
mutex_lock(&idev->igroup->lock);
@@ -363,8 +365,8 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
363365
goto err_unlock;
364366
}
365367

366-
if (hwpt_is_paging(hwpt)) {
367-
rc = iommufd_hwpt_paging_attach(to_hwpt_paging(hwpt), idev);
368+
if (hwpt_paging) {
369+
rc = iommufd_device_attach_reserved_iova(idev, hwpt_paging);
368370
if (rc)
369371
goto err_unlock;
370372
}
@@ -387,9 +389,8 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
387389
mutex_unlock(&idev->igroup->lock);
388390
return 0;
389391
err_unresv:
390-
if (hwpt_is_paging(hwpt))
391-
iopt_remove_reserved_iova(&to_hwpt_paging(hwpt)->ioas->iopt,
392-
idev->dev);
392+
if (hwpt_paging)
393+
iopt_remove_reserved_iova(&hwpt_paging->ioas->iopt, idev->dev);
393394
err_unlock:
394395
mutex_unlock(&idev->igroup->lock);
395396
return rc;
@@ -399,16 +400,16 @@ struct iommufd_hw_pagetable *
399400
iommufd_hw_pagetable_detach(struct iommufd_device *idev)
400401
{
401402
struct iommufd_hw_pagetable *hwpt = idev->igroup->hwpt;
403+
struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt);
402404

403405
mutex_lock(&idev->igroup->lock);
404406
list_del(&idev->group_item);
405407
if (list_empty(&idev->igroup->device_list)) {
406408
iommufd_hwpt_detach_device(hwpt, idev);
407409
idev->igroup->hwpt = NULL;
408410
}
409-
if (hwpt_is_paging(hwpt))
410-
iopt_remove_reserved_iova(&to_hwpt_paging(hwpt)->ioas->iopt,
411-
idev->dev);
411+
if (hwpt_paging)
412+
iopt_remove_reserved_iova(&hwpt_paging->ioas->iopt, idev->dev);
412413
mutex_unlock(&idev->igroup->lock);
413414

414415
/* Caller must destroy hwpt */
@@ -440,17 +441,17 @@ iommufd_group_remove_reserved_iova(struct iommufd_group *igroup,
440441
}
441442

442443
static int
443-
iommufd_group_do_replace_paging(struct iommufd_group *igroup,
444-
struct iommufd_hwpt_paging *hwpt_paging)
444+
iommufd_group_do_replace_reserved_iova(struct iommufd_group *igroup,
445+
struct iommufd_hwpt_paging *hwpt_paging)
445446
{
446-
struct iommufd_hw_pagetable *old_hwpt = igroup->hwpt;
447+
struct iommufd_hwpt_paging *old_hwpt_paging;
447448
struct iommufd_device *cur;
448449
int rc;
449450

450451
lockdep_assert_held(&igroup->lock);
451452

452-
if (!hwpt_is_paging(old_hwpt) ||
453-
hwpt_paging->ioas != to_hwpt_paging(old_hwpt)->ioas) {
453+
old_hwpt_paging = find_hwpt_paging(igroup->hwpt);
454+
if (!old_hwpt_paging || hwpt_paging->ioas != old_hwpt_paging->ioas) {
454455
list_for_each_entry(cur, &igroup->device_list, group_item) {
455456
rc = iopt_table_enforce_dev_resv_regions(
456457
&hwpt_paging->ioas->iopt, cur->dev, NULL);
@@ -473,6 +474,8 @@ static struct iommufd_hw_pagetable *
473474
iommufd_device_do_replace(struct iommufd_device *idev,
474475
struct iommufd_hw_pagetable *hwpt)
475476
{
477+
struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt);
478+
struct iommufd_hwpt_paging *old_hwpt_paging;
476479
struct iommufd_group *igroup = idev->igroup;
477480
struct iommufd_hw_pagetable *old_hwpt;
478481
unsigned int num_devices;
@@ -491,9 +494,8 @@ iommufd_device_do_replace(struct iommufd_device *idev,
491494
}
492495

493496
old_hwpt = igroup->hwpt;
494-
if (hwpt_is_paging(hwpt)) {
495-
rc = iommufd_group_do_replace_paging(igroup,
496-
to_hwpt_paging(hwpt));
497+
if (hwpt_paging) {
498+
rc = iommufd_group_do_replace_reserved_iova(igroup, hwpt_paging);
497499
if (rc)
498500
goto err_unlock;
499501
}
@@ -502,11 +504,10 @@ iommufd_device_do_replace(struct iommufd_device *idev,
502504
if (rc)
503505
goto err_unresv;
504506

505-
if (hwpt_is_paging(old_hwpt) &&
506-
(!hwpt_is_paging(hwpt) ||
507-
to_hwpt_paging(hwpt)->ioas != to_hwpt_paging(old_hwpt)->ioas))
508-
iommufd_group_remove_reserved_iova(igroup,
509-
to_hwpt_paging(old_hwpt));
507+
old_hwpt_paging = find_hwpt_paging(old_hwpt);
508+
if (old_hwpt_paging &&
509+
(!hwpt_paging || hwpt_paging->ioas != old_hwpt_paging->ioas))
510+
iommufd_group_remove_reserved_iova(igroup, old_hwpt_paging);
510511

511512
igroup->hwpt = hwpt;
512513

@@ -524,9 +525,8 @@ iommufd_device_do_replace(struct iommufd_device *idev,
524525
/* Caller must destroy old_hwpt */
525526
return old_hwpt;
526527
err_unresv:
527-
if (hwpt_is_paging(hwpt))
528-
iommufd_group_remove_reserved_iova(igroup,
529-
to_hwpt_paging(hwpt));
528+
if (hwpt_paging)
529+
iommufd_group_remove_reserved_iova(igroup, hwpt_paging);
530530
err_unlock:
531531
mutex_unlock(&idev->igroup->lock);
532532
return ERR_PTR(rc);

drivers/iommu/iommufd/fault.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
*/
44
#define pr_fmt(fmt) "iommufd: " fmt
55

6+
#include <linux/anon_inodes.h>
67
#include <linux/file.h>
78
#include <linux/fs.h>
9+
#include <linux/iommufd.h>
810
#include <linux/module.h>
911
#include <linux/mutex.h>
10-
#include <linux/iommufd.h>
1112
#include <linux/pci.h>
1213
#include <linux/poll.h>
13-
#include <linux/anon_inodes.h>
1414
#include <uapi/linux/iommufd.h>
1515

1616
#include "../iommu-priv.h"
@@ -161,7 +161,6 @@ static int __fault_domain_replace_dev(struct iommufd_device *idev,
161161
if (!handle)
162162
return -ENOMEM;
163163

164-
handle->handle.domain = hwpt->domain;
165164
handle->idev = idev;
166165
ret = iommu_replace_group_handle(idev->igroup->group,
167166
hwpt->domain, &handle->handle);

drivers/iommu/iommufd/hw_pagetable.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx,
225225
if ((flags & ~IOMMU_HWPT_FAULT_ID_VALID) ||
226226
!user_data->len || !ops->domain_alloc_user)
227227
return ERR_PTR(-EOPNOTSUPP);
228-
if (parent->auto_domain || !parent->nest_parent)
228+
if (parent->auto_domain || !parent->nest_parent ||
229+
parent->common.domain->owner != ops)
229230
return ERR_PTR(-EINVAL);
230231

231232
hwpt_nested = __iommufd_object_alloc(

drivers/iommu/iommufd/io_pagetable.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@
88
* The datastructure uses the iopt_pages to optimize the storage of the PFNs
99
* between the domains and xarray.
1010
*/
11+
#include <linux/err.h>
12+
#include <linux/errno.h>
13+
#include <linux/iommu.h>
1114
#include <linux/iommufd.h>
1215
#include <linux/lockdep.h>
13-
#include <linux/iommu.h>
1416
#include <linux/sched/mm.h>
15-
#include <linux/err.h>
1617
#include <linux/slab.h>
17-
#include <linux/errno.h>
1818
#include <uapi/linux/iommufd.h>
1919

20-
#include "io_pagetable.h"
2120
#include "double_span.h"
21+
#include "io_pagetable.h"
2222

2323
struct iopt_pages_list {
2424
struct iopt_pages *pages;
@@ -112,6 +112,7 @@ static int iopt_alloc_iova(struct io_pagetable *iopt, unsigned long *iova,
112112
unsigned long page_offset = uptr % PAGE_SIZE;
113113
struct interval_tree_double_span_iter used_span;
114114
struct interval_tree_span_iter allowed_span;
115+
unsigned long max_alignment = PAGE_SIZE;
115116
unsigned long iova_alignment;
116117

117118
lockdep_assert_held(&iopt->iova_rwsem);
@@ -131,6 +132,13 @@ static int iopt_alloc_iova(struct io_pagetable *iopt, unsigned long *iova,
131132
roundup_pow_of_two(length),
132133
1UL << __ffs64(uptr));
133134

135+
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
136+
max_alignment = HPAGE_SIZE;
137+
#endif
138+
/* Protect against ALIGN() overflow */
139+
if (iova_alignment >= max_alignment)
140+
iova_alignment = max_alignment;
141+
134142
if (iova_alignment < iopt->iova_alignment)
135143
return -EINVAL;
136144

drivers/iommu/iommufd/io_pagetable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
#define __IO_PAGETABLE_H
77

88
#include <linux/interval_tree.h>
9-
#include <linux/mutex.h>
109
#include <linux/kref.h>
10+
#include <linux/mutex.h>
1111
#include <linux/xarray.h>
1212

1313
#include "iommufd_private.h"

drivers/iommu/iommufd/ioas.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES
44
*/
55
#include <linux/interval_tree.h>
6-
#include <linux/iommufd.h>
76
#include <linux/iommu.h>
7+
#include <linux/iommufd.h>
88
#include <uapi/linux/iommufd.h>
99

1010
#include "io_pagetable.h"

drivers/iommu/iommufd/iommufd_private.h

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
#ifndef __IOMMUFD_PRIVATE_H
55
#define __IOMMUFD_PRIVATE_H
66

7-
#include <linux/rwsem.h>
8-
#include <linux/xarray.h>
9-
#include <linux/refcount.h>
10-
#include <linux/uaccess.h>
117
#include <linux/iommu.h>
128
#include <linux/iova_bitmap.h>
9+
#include <linux/refcount.h>
10+
#include <linux/rwsem.h>
11+
#include <linux/uaccess.h>
12+
#include <linux/xarray.h>
1313
#include <uapi/linux/iommufd.h>
14+
1415
#include "../iommu-priv.h"
1516

1617
struct iommu_domain;
@@ -324,6 +325,25 @@ to_hwpt_paging(struct iommufd_hw_pagetable *hwpt)
324325
return container_of(hwpt, struct iommufd_hwpt_paging, common);
325326
}
326327

328+
static inline struct iommufd_hwpt_nested *
329+
to_hwpt_nested(struct iommufd_hw_pagetable *hwpt)
330+
{
331+
return container_of(hwpt, struct iommufd_hwpt_nested, common);
332+
}
333+
334+
static inline struct iommufd_hwpt_paging *
335+
find_hwpt_paging(struct iommufd_hw_pagetable *hwpt)
336+
{
337+
switch (hwpt->obj.type) {
338+
case IOMMUFD_OBJ_HWPT_PAGING:
339+
return to_hwpt_paging(hwpt);
340+
case IOMMUFD_OBJ_HWPT_NESTED:
341+
return to_hwpt_nested(hwpt)->parent;
342+
default:
343+
return NULL;
344+
}
345+
}
346+
327347
static inline struct iommufd_hwpt_paging *
328348
iommufd_get_hwpt_paging(struct iommufd_ucmd *ucmd, u32 id)
329349
{
@@ -490,8 +510,10 @@ static inline int iommufd_hwpt_attach_device(struct iommufd_hw_pagetable *hwpt,
490510
static inline void iommufd_hwpt_detach_device(struct iommufd_hw_pagetable *hwpt,
491511
struct iommufd_device *idev)
492512
{
493-
if (hwpt->fault)
513+
if (hwpt->fault) {
494514
iommufd_fault_domain_detach_dev(hwpt, idev);
515+
return;
516+
}
495517

496518
iommu_detach_group(hwpt->domain, idev->igroup->group);
497519
}

drivers/iommu/iommufd/iommufd_test.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
#ifndef _UAPI_IOMMUFD_TEST_H
55
#define _UAPI_IOMMUFD_TEST_H
66

7-
#include <linux/types.h>
87
#include <linux/iommufd.h>
8+
#include <linux/types.h>
99

1010
enum {
1111
IOMMU_TEST_OP_ADD_RESERVED = 1,

drivers/iommu/iommufd/iova_bitmap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
* Copyright (c) 2022, Oracle and/or its affiliates.
44
* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved
55
*/
6+
#include <linux/highmem.h>
67
#include <linux/iova_bitmap.h>
78
#include <linux/mm.h>
89
#include <linux/slab.h>
9-
#include <linux/highmem.h>
1010

1111
#define BITS_PER_PAGE (PAGE_SIZE * BITS_PER_BYTE)
1212

0 commit comments

Comments
 (0)