Commit db78436b authored by Linus Torvalds's avatar Linus Torvalds

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
parents 54d7e819 79805c1b
...@@ -3578,6 +3578,7 @@ int iommu_replace_group_handle(struct iommu_group *group, ...@@ -3578,6 +3578,7 @@ int iommu_replace_group_handle(struct iommu_group *group,
ret = xa_reserve(&group->pasid_array, IOMMU_NO_PASID, GFP_KERNEL); ret = xa_reserve(&group->pasid_array, IOMMU_NO_PASID, GFP_KERNEL);
if (ret) if (ret)
goto err_unlock; goto err_unlock;
handle->domain = new_domain;
} }
ret = __iommu_group_set_domain(group, new_domain); ret = __iommu_group_set_domain(group, new_domain);
......
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES /* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES
*/ */
#include <linux/iommu.h>
#include <linux/iommufd.h> #include <linux/iommufd.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/iommu.h>
#include <uapi/linux/iommufd.h> #include <uapi/linux/iommufd.h>
#include "../iommu-priv.h"
#include "../iommu-priv.h"
#include "io_pagetable.h" #include "io_pagetable.h"
#include "iommufd_private.h" #include "iommufd_private.h"
...@@ -327,8 +327,9 @@ static int iommufd_group_setup_msi(struct iommufd_group *igroup, ...@@ -327,8 +327,9 @@ static int iommufd_group_setup_msi(struct iommufd_group *igroup,
return 0; return 0;
} }
static int iommufd_hwpt_paging_attach(struct iommufd_hwpt_paging *hwpt_paging, static int
struct iommufd_device *idev) iommufd_device_attach_reserved_iova(struct iommufd_device *idev,
struct iommufd_hwpt_paging *hwpt_paging)
{ {
int rc; int rc;
...@@ -354,6 +355,7 @@ static int iommufd_hwpt_paging_attach(struct iommufd_hwpt_paging *hwpt_paging, ...@@ -354,6 +355,7 @@ static int iommufd_hwpt_paging_attach(struct iommufd_hwpt_paging *hwpt_paging,
int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt, int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
struct iommufd_device *idev) struct iommufd_device *idev)
{ {
struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt);
int rc; int rc;
mutex_lock(&idev->igroup->lock); mutex_lock(&idev->igroup->lock);
...@@ -363,8 +365,8 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt, ...@@ -363,8 +365,8 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
goto err_unlock; goto err_unlock;
} }
if (hwpt_is_paging(hwpt)) { if (hwpt_paging) {
rc = iommufd_hwpt_paging_attach(to_hwpt_paging(hwpt), idev); rc = iommufd_device_attach_reserved_iova(idev, hwpt_paging);
if (rc) if (rc)
goto err_unlock; goto err_unlock;
} }
...@@ -387,9 +389,8 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt, ...@@ -387,9 +389,8 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
mutex_unlock(&idev->igroup->lock); mutex_unlock(&idev->igroup->lock);
return 0; return 0;
err_unresv: err_unresv:
if (hwpt_is_paging(hwpt)) if (hwpt_paging)
iopt_remove_reserved_iova(&to_hwpt_paging(hwpt)->ioas->iopt, iopt_remove_reserved_iova(&hwpt_paging->ioas->iopt, idev->dev);
idev->dev);
err_unlock: err_unlock:
mutex_unlock(&idev->igroup->lock); mutex_unlock(&idev->igroup->lock);
return rc; return rc;
...@@ -399,6 +400,7 @@ struct iommufd_hw_pagetable * ...@@ -399,6 +400,7 @@ struct iommufd_hw_pagetable *
iommufd_hw_pagetable_detach(struct iommufd_device *idev) iommufd_hw_pagetable_detach(struct iommufd_device *idev)
{ {
struct iommufd_hw_pagetable *hwpt = idev->igroup->hwpt; struct iommufd_hw_pagetable *hwpt = idev->igroup->hwpt;
struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt);
mutex_lock(&idev->igroup->lock); mutex_lock(&idev->igroup->lock);
list_del(&idev->group_item); list_del(&idev->group_item);
...@@ -406,9 +408,8 @@ iommufd_hw_pagetable_detach(struct iommufd_device *idev) ...@@ -406,9 +408,8 @@ iommufd_hw_pagetable_detach(struct iommufd_device *idev)
iommufd_hwpt_detach_device(hwpt, idev); iommufd_hwpt_detach_device(hwpt, idev);
idev->igroup->hwpt = NULL; idev->igroup->hwpt = NULL;
} }
if (hwpt_is_paging(hwpt)) if (hwpt_paging)
iopt_remove_reserved_iova(&to_hwpt_paging(hwpt)->ioas->iopt, iopt_remove_reserved_iova(&hwpt_paging->ioas->iopt, idev->dev);
idev->dev);
mutex_unlock(&idev->igroup->lock); mutex_unlock(&idev->igroup->lock);
/* Caller must destroy hwpt */ /* Caller must destroy hwpt */
...@@ -440,17 +441,17 @@ iommufd_group_remove_reserved_iova(struct iommufd_group *igroup, ...@@ -440,17 +441,17 @@ iommufd_group_remove_reserved_iova(struct iommufd_group *igroup,
} }
static int static int
iommufd_group_do_replace_paging(struct iommufd_group *igroup, iommufd_group_do_replace_reserved_iova(struct iommufd_group *igroup,
struct iommufd_hwpt_paging *hwpt_paging) struct iommufd_hwpt_paging *hwpt_paging)
{ {
struct iommufd_hw_pagetable *old_hwpt = igroup->hwpt; struct iommufd_hwpt_paging *old_hwpt_paging;
struct iommufd_device *cur; struct iommufd_device *cur;
int rc; int rc;
lockdep_assert_held(&igroup->lock); lockdep_assert_held(&igroup->lock);
if (!hwpt_is_paging(old_hwpt) || old_hwpt_paging = find_hwpt_paging(igroup->hwpt);
hwpt_paging->ioas != to_hwpt_paging(old_hwpt)->ioas) { if (!old_hwpt_paging || hwpt_paging->ioas != old_hwpt_paging->ioas) {
list_for_each_entry(cur, &igroup->device_list, group_item) { list_for_each_entry(cur, &igroup->device_list, group_item) {
rc = iopt_table_enforce_dev_resv_regions( rc = iopt_table_enforce_dev_resv_regions(
&hwpt_paging->ioas->iopt, cur->dev, NULL); &hwpt_paging->ioas->iopt, cur->dev, NULL);
...@@ -473,6 +474,8 @@ static struct iommufd_hw_pagetable * ...@@ -473,6 +474,8 @@ static struct iommufd_hw_pagetable *
iommufd_device_do_replace(struct iommufd_device *idev, iommufd_device_do_replace(struct iommufd_device *idev,
struct iommufd_hw_pagetable *hwpt) struct iommufd_hw_pagetable *hwpt)
{ {
struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt);
struct iommufd_hwpt_paging *old_hwpt_paging;
struct iommufd_group *igroup = idev->igroup; struct iommufd_group *igroup = idev->igroup;
struct iommufd_hw_pagetable *old_hwpt; struct iommufd_hw_pagetable *old_hwpt;
unsigned int num_devices; unsigned int num_devices;
...@@ -491,9 +494,8 @@ iommufd_device_do_replace(struct iommufd_device *idev, ...@@ -491,9 +494,8 @@ iommufd_device_do_replace(struct iommufd_device *idev,
} }
old_hwpt = igroup->hwpt; old_hwpt = igroup->hwpt;
if (hwpt_is_paging(hwpt)) { if (hwpt_paging) {
rc = iommufd_group_do_replace_paging(igroup, rc = iommufd_group_do_replace_reserved_iova(igroup, hwpt_paging);
to_hwpt_paging(hwpt));
if (rc) if (rc)
goto err_unlock; goto err_unlock;
} }
...@@ -502,11 +504,10 @@ iommufd_device_do_replace(struct iommufd_device *idev, ...@@ -502,11 +504,10 @@ iommufd_device_do_replace(struct iommufd_device *idev,
if (rc) if (rc)
goto err_unresv; goto err_unresv;
if (hwpt_is_paging(old_hwpt) && old_hwpt_paging = find_hwpt_paging(old_hwpt);
(!hwpt_is_paging(hwpt) || if (old_hwpt_paging &&
to_hwpt_paging(hwpt)->ioas != to_hwpt_paging(old_hwpt)->ioas)) (!hwpt_paging || hwpt_paging->ioas != old_hwpt_paging->ioas))
iommufd_group_remove_reserved_iova(igroup, iommufd_group_remove_reserved_iova(igroup, old_hwpt_paging);
to_hwpt_paging(old_hwpt));
igroup->hwpt = hwpt; igroup->hwpt = hwpt;
...@@ -524,9 +525,8 @@ iommufd_device_do_replace(struct iommufd_device *idev, ...@@ -524,9 +525,8 @@ iommufd_device_do_replace(struct iommufd_device *idev,
/* Caller must destroy old_hwpt */ /* Caller must destroy old_hwpt */
return old_hwpt; return old_hwpt;
err_unresv: err_unresv:
if (hwpt_is_paging(hwpt)) if (hwpt_paging)
iommufd_group_remove_reserved_iova(igroup, iommufd_group_remove_reserved_iova(igroup, hwpt_paging);
to_hwpt_paging(hwpt));
err_unlock: err_unlock:
mutex_unlock(&idev->igroup->lock); mutex_unlock(&idev->igroup->lock);
return ERR_PTR(rc); return ERR_PTR(rc);
......
...@@ -3,14 +3,14 @@ ...@@ -3,14 +3,14 @@
*/ */
#define pr_fmt(fmt) "iommufd: " fmt #define pr_fmt(fmt) "iommufd: " fmt
#include <linux/anon_inodes.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/iommufd.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/iommufd.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/anon_inodes.h>
#include <uapi/linux/iommufd.h> #include <uapi/linux/iommufd.h>
#include "../iommu-priv.h" #include "../iommu-priv.h"
...@@ -161,7 +161,6 @@ static int __fault_domain_replace_dev(struct iommufd_device *idev, ...@@ -161,7 +161,6 @@ static int __fault_domain_replace_dev(struct iommufd_device *idev,
if (!handle) if (!handle)
return -ENOMEM; return -ENOMEM;
handle->handle.domain = hwpt->domain;
handle->idev = idev; handle->idev = idev;
ret = iommu_replace_group_handle(idev->igroup->group, ret = iommu_replace_group_handle(idev->igroup->group,
hwpt->domain, &handle->handle); hwpt->domain, &handle->handle);
......
...@@ -225,7 +225,8 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx, ...@@ -225,7 +225,8 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx,
if ((flags & ~IOMMU_HWPT_FAULT_ID_VALID) || if ((flags & ~IOMMU_HWPT_FAULT_ID_VALID) ||
!user_data->len || !ops->domain_alloc_user) !user_data->len || !ops->domain_alloc_user)
return ERR_PTR(-EOPNOTSUPP); return ERR_PTR(-EOPNOTSUPP);
if (parent->auto_domain || !parent->nest_parent) if (parent->auto_domain || !parent->nest_parent ||
parent->common.domain->owner != ops)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
hwpt_nested = __iommufd_object_alloc( hwpt_nested = __iommufd_object_alloc(
......
...@@ -8,17 +8,17 @@ ...@@ -8,17 +8,17 @@
* The datastructure uses the iopt_pages to optimize the storage of the PFNs * The datastructure uses the iopt_pages to optimize the storage of the PFNs
* between the domains and xarray. * between the domains and xarray.
*/ */
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/iommu.h>
#include <linux/iommufd.h> #include <linux/iommufd.h>
#include <linux/lockdep.h> #include <linux/lockdep.h>
#include <linux/iommu.h>
#include <linux/sched/mm.h> #include <linux/sched/mm.h>
#include <linux/err.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/errno.h>
#include <uapi/linux/iommufd.h> #include <uapi/linux/iommufd.h>
#include "io_pagetable.h"
#include "double_span.h" #include "double_span.h"
#include "io_pagetable.h"
struct iopt_pages_list { struct iopt_pages_list {
struct iopt_pages *pages; struct iopt_pages *pages;
...@@ -112,6 +112,7 @@ static int iopt_alloc_iova(struct io_pagetable *iopt, unsigned long *iova, ...@@ -112,6 +112,7 @@ static int iopt_alloc_iova(struct io_pagetable *iopt, unsigned long *iova,
unsigned long page_offset = uptr % PAGE_SIZE; unsigned long page_offset = uptr % PAGE_SIZE;
struct interval_tree_double_span_iter used_span; struct interval_tree_double_span_iter used_span;
struct interval_tree_span_iter allowed_span; struct interval_tree_span_iter allowed_span;
unsigned long max_alignment = PAGE_SIZE;
unsigned long iova_alignment; unsigned long iova_alignment;
lockdep_assert_held(&iopt->iova_rwsem); lockdep_assert_held(&iopt->iova_rwsem);
...@@ -131,6 +132,13 @@ static int iopt_alloc_iova(struct io_pagetable *iopt, unsigned long *iova, ...@@ -131,6 +132,13 @@ static int iopt_alloc_iova(struct io_pagetable *iopt, unsigned long *iova,
roundup_pow_of_two(length), roundup_pow_of_two(length),
1UL << __ffs64(uptr)); 1UL << __ffs64(uptr));
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
max_alignment = HPAGE_SIZE;
#endif
/* Protect against ALIGN() overflow */
if (iova_alignment >= max_alignment)
iova_alignment = max_alignment;
if (iova_alignment < iopt->iova_alignment) if (iova_alignment < iopt->iova_alignment)
return -EINVAL; return -EINVAL;
......
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
#define __IO_PAGETABLE_H #define __IO_PAGETABLE_H
#include <linux/interval_tree.h> #include <linux/interval_tree.h>
#include <linux/mutex.h>
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/mutex.h>
#include <linux/xarray.h> #include <linux/xarray.h>
#include "iommufd_private.h" #include "iommufd_private.h"
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES * Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES
*/ */
#include <linux/interval_tree.h> #include <linux/interval_tree.h>
#include <linux/iommufd.h>
#include <linux/iommu.h> #include <linux/iommu.h>
#include <linux/iommufd.h>
#include <uapi/linux/iommufd.h> #include <uapi/linux/iommufd.h>
#include "io_pagetable.h" #include "io_pagetable.h"
......
...@@ -4,13 +4,14 @@ ...@@ -4,13 +4,14 @@
#ifndef __IOMMUFD_PRIVATE_H #ifndef __IOMMUFD_PRIVATE_H
#define __IOMMUFD_PRIVATE_H #define __IOMMUFD_PRIVATE_H
#include <linux/rwsem.h>
#include <linux/xarray.h>
#include <linux/refcount.h>
#include <linux/uaccess.h>
#include <linux/iommu.h> #include <linux/iommu.h>
#include <linux/iova_bitmap.h> #include <linux/iova_bitmap.h>
#include <linux/refcount.h>
#include <linux/rwsem.h>
#include <linux/uaccess.h>
#include <linux/xarray.h>
#include <uapi/linux/iommufd.h> #include <uapi/linux/iommufd.h>
#include "../iommu-priv.h" #include "../iommu-priv.h"
struct iommu_domain; struct iommu_domain;
...@@ -324,6 +325,25 @@ to_hwpt_paging(struct iommufd_hw_pagetable *hwpt) ...@@ -324,6 +325,25 @@ to_hwpt_paging(struct iommufd_hw_pagetable *hwpt)
return container_of(hwpt, struct iommufd_hwpt_paging, common); return container_of(hwpt, struct iommufd_hwpt_paging, common);
} }
static inline struct iommufd_hwpt_nested *
to_hwpt_nested(struct iommufd_hw_pagetable *hwpt)
{
return container_of(hwpt, struct iommufd_hwpt_nested, common);
}
static inline struct iommufd_hwpt_paging *
find_hwpt_paging(struct iommufd_hw_pagetable *hwpt)
{
switch (hwpt->obj.type) {
case IOMMUFD_OBJ_HWPT_PAGING:
return to_hwpt_paging(hwpt);
case IOMMUFD_OBJ_HWPT_NESTED:
return to_hwpt_nested(hwpt)->parent;
default:
return NULL;
}
}
static inline struct iommufd_hwpt_paging * static inline struct iommufd_hwpt_paging *
iommufd_get_hwpt_paging(struct iommufd_ucmd *ucmd, u32 id) iommufd_get_hwpt_paging(struct iommufd_ucmd *ucmd, u32 id)
{ {
...@@ -490,8 +510,10 @@ static inline int iommufd_hwpt_attach_device(struct iommufd_hw_pagetable *hwpt, ...@@ -490,8 +510,10 @@ static inline int iommufd_hwpt_attach_device(struct iommufd_hw_pagetable *hwpt,
static inline void iommufd_hwpt_detach_device(struct iommufd_hw_pagetable *hwpt, static inline void iommufd_hwpt_detach_device(struct iommufd_hw_pagetable *hwpt,
struct iommufd_device *idev) struct iommufd_device *idev)
{ {
if (hwpt->fault) if (hwpt->fault) {
iommufd_fault_domain_detach_dev(hwpt, idev); iommufd_fault_domain_detach_dev(hwpt, idev);
return;
}
iommu_detach_group(hwpt->domain, idev->igroup->group); iommu_detach_group(hwpt->domain, idev->igroup->group);
} }
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
#ifndef _UAPI_IOMMUFD_TEST_H #ifndef _UAPI_IOMMUFD_TEST_H
#define _UAPI_IOMMUFD_TEST_H #define _UAPI_IOMMUFD_TEST_H
#include <linux/types.h>
#include <linux/iommufd.h> #include <linux/iommufd.h>
#include <linux/types.h>
enum { enum {
IOMMU_TEST_OP_ADD_RESERVED = 1, IOMMU_TEST_OP_ADD_RESERVED = 1,
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
* Copyright (c) 2022, Oracle and/or its affiliates. * Copyright (c) 2022, Oracle and/or its affiliates.
* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved
*/ */
#include <linux/highmem.h>
#include <linux/iova_bitmap.h> #include <linux/iova_bitmap.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/highmem.h>
#define BITS_PER_PAGE (PAGE_SIZE * BITS_PER_BYTE) #define BITS_PER_PAGE (PAGE_SIZE * BITS_PER_BYTE)
......
...@@ -8,15 +8,15 @@ ...@@ -8,15 +8,15 @@
*/ */
#define pr_fmt(fmt) "iommufd: " fmt #define pr_fmt(fmt) "iommufd: " fmt
#include <linux/bug.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/module.h> #include <linux/iommufd.h>
#include <linux/slab.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/bug.h> #include <linux/slab.h>
#include <uapi/linux/iommufd.h> #include <uapi/linux/iommufd.h>
#include <linux/iommufd.h>
#include "io_pagetable.h" #include "io_pagetable.h"
#include "iommufd_private.h" #include "iommufd_private.h"
......
...@@ -45,16 +45,16 @@ ...@@ -45,16 +45,16 @@
* last_iova + 1 can overflow. An iopt_pages index will always be much less than * last_iova + 1 can overflow. An iopt_pages index will always be much less than
* ULONG_MAX so last_index + 1 cannot overflow. * ULONG_MAX so last_index + 1 cannot overflow.
*/ */
#include <linux/highmem.h>
#include <linux/iommu.h>
#include <linux/iommufd.h>
#include <linux/kthread.h>
#include <linux/overflow.h> #include <linux/overflow.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/iommu.h>
#include <linux/sched/mm.h> #include <linux/sched/mm.h>
#include <linux/highmem.h>
#include <linux/kthread.h>
#include <linux/iommufd.h>
#include "io_pagetable.h"
#include "double_span.h" #include "double_span.h"
#include "io_pagetable.h"
#ifndef CONFIG_IOMMUFD_TEST #ifndef CONFIG_IOMMUFD_TEST
#define TEMP_MEMORY_LIMIT 65536 #define TEMP_MEMORY_LIMIT 65536
......
...@@ -3,14 +3,14 @@ ...@@ -3,14 +3,14 @@
* *
* Kernel side components to support tools/testing/selftests/iommu * Kernel side components to support tools/testing/selftests/iommu
*/ */
#include <linux/slab.h>
#include <linux/iommu.h>
#include <linux/xarray.h>
#include <linux/file.h>
#include <linux/debugfs.h>
#include <linux/anon_inodes.h> #include <linux/anon_inodes.h>
#include <linux/debugfs.h>
#include <linux/fault-inject.h> #include <linux/fault-inject.h>
#include <linux/file.h>
#include <linux/iommu.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/xarray.h>
#include <uapi/linux/iommufd.h> #include <uapi/linux/iommufd.h>
#include "../iommu-priv.h" #include "../iommu-priv.h"
...@@ -1343,7 +1343,7 @@ static int iommufd_test_dirty(struct iommufd_ucmd *ucmd, unsigned int mockpt_id, ...@@ -1343,7 +1343,7 @@ static int iommufd_test_dirty(struct iommufd_ucmd *ucmd, unsigned int mockpt_id,
unsigned long page_size, void __user *uptr, unsigned long page_size, void __user *uptr,
u32 flags) u32 flags)
{ {
unsigned long bitmap_size, i, max; unsigned long i, max;
struct iommu_test_cmd *cmd = ucmd->cmd; struct iommu_test_cmd *cmd = ucmd->cmd;
struct iommufd_hw_pagetable *hwpt; struct iommufd_hw_pagetable *hwpt;
struct mock_iommu_domain *mock; struct mock_iommu_domain *mock;
...@@ -1364,15 +1364,14 @@ static int iommufd_test_dirty(struct iommufd_ucmd *ucmd, unsigned int mockpt_id, ...@@ -1364,15 +1364,14 @@ static int iommufd_test_dirty(struct iommufd_ucmd *ucmd, unsigned int mockpt_id,
} }
max = length / page_size; max = length / page_size;
bitmap_size = DIV_ROUND_UP(max, BITS_PER_BYTE); tmp = kvzalloc(DIV_ROUND_UP(max, BITS_PER_LONG) * sizeof(unsigned long),
GFP_KERNEL_ACCOUNT);
tmp = kvzalloc(bitmap_size, GFP_KERNEL_ACCOUNT);
if (!tmp) { if (!tmp) {
rc = -ENOMEM; rc = -ENOMEM;
goto out_put; goto out_put;
} }
if (copy_from_user(tmp, uptr, bitmap_size)) { if (copy_from_user(tmp, uptr,DIV_ROUND_UP(max, BITS_PER_BYTE))) {
rc = -EFAULT; rc = -EFAULT;
goto out_free; goto out_free;
} }
......
...@@ -6,17 +6,17 @@ ...@@ -6,17 +6,17 @@
#ifndef __LINUX_IOMMUFD_H #ifndef __LINUX_IOMMUFD_H
#define __LINUX_IOMMUFD_H #define __LINUX_IOMMUFD_H
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/errno.h>
#include <linux/types.h>
struct device; struct device;
struct iommufd_device;
struct page;
struct iommufd_ctx;
struct iommufd_access;
struct file; struct file;
struct iommu_group; struct iommu_group;
struct iommufd_access;
struct iommufd_ctx;
struct iommufd_device;
struct page;
struct iommufd_device *iommufd_device_bind(struct iommufd_ctx *ictx, struct iommufd_device *iommufd_device_bind(struct iommufd_ctx *ictx,
struct device *dev, u32 *id); struct device *dev, u32 *id);
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
#ifndef _UAPI_IOMMUFD_H #ifndef _UAPI_IOMMUFD_H
#define _UAPI_IOMMUFD_H #define _UAPI_IOMMUFD_H
#include <linux/types.h>
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/types.h>
#define IOMMUFD_TYPE (';') #define IOMMUFD_TYPE (';')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment