History

iommufd: File descriptor, context, kconfig and makefiles

This is the basic infrastructure of a new miscdevice to hold the iommufd IOCTL API. It provides: - A miscdevice to create file descriptors to run the IOCTL interface over - A table based ioctl dispatch and centralized extendable pre-validation step - An xarray mapping userspace ID's to kernel objects. The design has multiple inter-related objects held within in a single IOMMUFD fd - A simple usage count to build a graph of object relations and protect against hostile userspace racing ioctls The only IOCTL provided in this patch is the generic 'destroy any object by handle' operation.

Jason Gunthorpe committed 3 years ago

Commit 2ff4bed1 parent 658234d10 files · +571 −1Browse files

Unified · Split

10 files
  1. Documentation/userspace-api/ioctl/ioctl-number.rst +1 −0
  2. MAINTAINERS +12 −0
  3. drivers/iommu/Kconfig +1 −0
  4. drivers/iommu/Makefile +1 −1
  5. drivers/iommu/iommufd/Kconfig +12 −0
  6. drivers/iommu/iommufd/Makefile +5 −0
  7. drivers/iommu/iommufd/iommufd_private.h +109 −0
  8. drivers/iommu/iommufd/main.c +344 −0
  9. include/linux/iommufd.h +31 −0
  10. include/uapi/linux/iommufd.h +55 −0
Documentation/userspace-api/ioctl/ioctl-number.rst+1−0
@@ -105,6 +105,7 @@ Code Seq# Include File Comments · 104 unmodified lines
105'8' all SNP8023 advanced NIC card105'8' all SNP8023 advanced NIC card
106 <mailto:mcr@solidum.com>106 <mailto:mcr@solidum.com>
107';' 64-7F linux/vfio.h107';' 64-7F linux/vfio.h
108';' 80-FF linux/iommufd.h
108'=' 00-3f uapi/linux/ptp_clock.h <mailto:richardcochran@gmail.com>109'=' 00-3f uapi/linux/ptp_clock.h <mailto:richardcochran@gmail.com>
109'@' 00-0F linux/radeonfb.h conflict!110'@' 00-0F linux/radeonfb.h conflict!
110'@' 00-0F drivers/video/aty/aty128fb.c conflict!111'@' 00-0F drivers/video/aty/aty128fb.c conflict!
MAINTAINERS+12−0
@@ -10717,6 +10717,18 @@ F: drivers/iommu/dma-iommu.h · 10716 unmodified lines
10717F: drivers/iommu/iova.c10717F: drivers/iommu/iova.c
10718F: include/linux/iova.h10718F: include/linux/iova.h
10719 10719
10720IOMMUFD
10721M: Jason Gunthorpe <jgg@nvidia.com>
10722M: Kevin Tian <kevin.tian@intel.com>
10723L: iommu@lists.linux.dev
10724S: Maintained
10725T: git git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd.git
10726F: Documentation/userspace-api/iommufd.rst
10727F: drivers/iommu/iommufd/
10728F: include/linux/iommufd.h
10729F: include/uapi/linux/iommufd.h
10730F: tools/testing/selftests/iommu/
10731
10720IOMMU SUBSYSTEM10732IOMMU SUBSYSTEM
10721M: Joerg Roedel <joro@8bytes.org>10733M: Joerg Roedel <joro@8bytes.org>
10722M: Will Deacon <will@kernel.org>10734M: Will Deacon <will@kernel.org>
drivers/iommu/Kconfig+1−0
@@ -188,6 +188,7 @@ config MSM_IOMMU · 187 unmodified lines
188 188
189source "drivers/iommu/amd/Kconfig"189source "drivers/iommu/amd/Kconfig"
190source "drivers/iommu/intel/Kconfig"190source "drivers/iommu/intel/Kconfig"
191source "drivers/iommu/iommufd/Kconfig"
191 192
192config IRQ_REMAP193config IRQ_REMAP
193 bool "Support for Interrupt Remapping"194 bool "Support for Interrupt Remapping"
drivers/iommu/Makefile+1−1
@@ -1,5 +1,5 @@
1# SPDX-License-Identifier: GPL-2.01# SPDX-License-Identifier: GPL-2.0
2obj-y += amd/ intel/ arm/2obj-y += amd/ intel/ arm/ iommufd/
3obj-$(CONFIG_IOMMU_API) += iommu.o3obj-$(CONFIG_IOMMU_API) += iommu.o
4obj-$(CONFIG_IOMMU_API) += iommu-traces.o4obj-$(CONFIG_IOMMU_API) += iommu-traces.o
5obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o5obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o
drivers/iommu/iommufd/Kconfig+12−0
@@ -0,0 +1,12 @@
1# SPDX-License-Identifier: GPL-2.0-only
2config IOMMUFD
3 tristate "IOMMU Userspace API"
4 select INTERVAL_TREE
5 select INTERVAL_TREE_SPAN_ITER
6 select IOMMU_API
7 default n
8 help
9 Provides /dev/iommu, the user API to control the IOMMU subsystem as
10 it relates to managing IO page tables that point at user space memory.
11
12 If you don't know what to do here, say N.
drivers/iommu/iommufd/Makefile+5−0
@@ -0,0 +1,5 @@
1# SPDX-License-Identifier: GPL-2.0-only
2iommufd-y := \
3 main.o
4
5obj-$(CONFIG_IOMMUFD) += iommufd.o
drivers/iommu/iommufd/iommufd_private.h+109−0
@@ -0,0 +1,109 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES
3 */
4#ifndef __IOMMUFD_PRIVATE_H
5#define __IOMMUFD_PRIVATE_H
6
7#include <linux/rwsem.h>
8#include <linux/xarray.h>
9#include <linux/refcount.h>
10#include <linux/uaccess.h>
11
12struct iommufd_ctx {
13 struct file *file;
14 struct xarray objects;
15};
16
17struct iommufd_ucmd {
18 struct iommufd_ctx *ictx;
19 void __user *ubuffer;
20 u32 user_size;
21 void *cmd;
22};
23
24/* Copy the response in ucmd->cmd back to userspace. */
25static inline int iommufd_ucmd_respond(struct iommufd_ucmd *ucmd,
26 size_t cmd_len)
27{
28 if (copy_to_user(ucmd->ubuffer, ucmd->cmd,
29 min_t(size_t, ucmd->user_size, cmd_len)))
30 return -EFAULT;
31 return 0;
32}
33
34enum iommufd_object_type {
35 IOMMUFD_OBJ_NONE,
36 IOMMUFD_OBJ_ANY = IOMMUFD_OBJ_NONE,
37};
38
39/* Base struct for all objects with a userspace ID handle. */
40struct iommufd_object {
41 struct rw_semaphore destroy_rwsem;
42 refcount_t users;
43 enum iommufd_object_type type;
44 unsigned int id;
45};
46
47static inline bool iommufd_lock_obj(struct iommufd_object *obj)
48{
49 if (!down_read_trylock(&obj->destroy_rwsem))
50 return false;
51 if (!refcount_inc_not_zero(&obj->users)) {
52 up_read(&obj->destroy_rwsem);
53 return false;
54 }
55 return true;
56}
57
58struct iommufd_object *iommufd_get_object(struct iommufd_ctx *ictx, u32 id,
59 enum iommufd_object_type type);
60static inline void iommufd_put_object(struct iommufd_object *obj)
61{
62 refcount_dec(&obj->users);
63 up_read(&obj->destroy_rwsem);
64}
65
66/**
67 * iommufd_ref_to_users() - Switch from destroy_rwsem to users refcount
68 * protection
69 * @obj - Object to release
70 *
71 * Objects have two refcount protections (destroy_rwsem and the refcount_t
72 * users). Holding either of these will prevent the object from being destroyed.
73 *
74 * Depending on the use case, one protection or the other is appropriate. In
75 * most cases references are being protected by the destroy_rwsem. This allows
76 * orderly destruction of the object because iommufd_object_destroy_user() will
77 * wait for it to become unlocked. However, as a rwsem, it cannot be held across
78 * a system call return. So cases that have longer term needs must switch
79 * to the weaker users refcount_t.
80 *
81 * With users protection iommufd_object_destroy_user() will return false,
82 * refusing to destroy the object, causing -EBUSY to userspace.
83 */
84static inline void iommufd_ref_to_users(struct iommufd_object *obj)
85{
86 up_read(&obj->destroy_rwsem);
87 /* iommufd_lock_obj() obtains users as well */
88}
89void iommufd_object_abort(struct iommufd_ctx *ictx, struct iommufd_object *obj);
90void iommufd_object_abort_and_destroy(struct iommufd_ctx *ictx,
91 struct iommufd_object *obj);
92void iommufd_object_finalize(struct iommufd_ctx *ictx,
93 struct iommufd_object *obj);
94bool iommufd_object_destroy_user(struct iommufd_ctx *ictx,
95 struct iommufd_object *obj);
96struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
97 size_t size,
98 enum iommufd_object_type type);
99
100#define iommufd_object_alloc(ictx, ptr, type) \
101 container_of(_iommufd_object_alloc( \
102 ictx, \
103 sizeof(*(ptr)) + BUILD_BUG_ON_ZERO( \
104 offsetof(typeof(*(ptr)), \
105 obj) != 0), \
106 type), \
107 typeof(*(ptr)), obj)
108
109#endif
drivers/iommu/iommufd/main.c+344−0
@@ -0,0 +1,344 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/* Copyright (C) 2021 Intel Corporation
3 * Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES
4 *
5 * iommufd provides control over the IOMMU HW objects created by IOMMU kernel
6 * drivers. IOMMU HW objects revolve around IO page tables that map incoming DMA
7 * addresses (IOVA) to CPU addresses.
8 */
9#define pr_fmt(fmt) "iommufd: " fmt
10
11#include <linux/file.h>
12#include <linux/fs.h>
13#include <linux/module.h>
14#include <linux/slab.h>
15#include <linux/miscdevice.h>
16#include <linux/mutex.h>
17#include <linux/bug.h>
18#include <uapi/linux/iommufd.h>
19#include <linux/iommufd.h>
20
21#include "iommufd_private.h"
22
23struct iommufd_object_ops {
24 void (*destroy)(struct iommufd_object *obj);
25};
26static const struct iommufd_object_ops iommufd_object_ops[];
27
28struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
29 size_t size,
30 enum iommufd_object_type type)
31{
32 struct iommufd_object *obj;
33 int rc;
34
35 obj = kzalloc(size, GFP_KERNEL_ACCOUNT);
36 if (!obj)
37 return ERR_PTR(-ENOMEM);
38 obj->type = type;
39 init_rwsem(&obj->destroy_rwsem);
40 refcount_set(&obj->users, 1);
41
42 /*
43 * Reserve an ID in the xarray but do not publish the pointer yet since
44 * the caller hasn't initialized it yet. Once the pointer is published
45 * in the xarray and visible to other threads we can't reliably destroy
46 * it anymore, so the caller must complete all errorable operations
47 * before calling iommufd_object_finalize().
48 */
49 rc = xa_alloc(&ictx->objects, &obj->id, XA_ZERO_ENTRY,
50 xa_limit_32b, GFP_KERNEL_ACCOUNT);
51 if (rc)
52 goto out_free;
53 return obj;
54out_free:
55 kfree(obj);
56 return ERR_PTR(rc);
57}
58
59/*
60 * Allow concurrent access to the object.
61 *
62 * Once another thread can see the object pointer it can prevent object
63 * destruction. Expect for special kernel-only objects there is no in-kernel way
64 * to reliably destroy a single object. Thus all APIs that are creating objects
65 * must use iommufd_object_abort() to handle their errors and only call
66 * iommufd_object_finalize() once object creation cannot fail.
67 */
68void iommufd_object_finalize(struct iommufd_ctx *ictx,
69 struct iommufd_object *obj)
70{
71 void *old;
72
73 old = xa_store(&ictx->objects, obj->id, obj, GFP_KERNEL);
74 /* obj->id was returned from xa_alloc() so the xa_store() cannot fail */
75 WARN_ON(old);
76}
77
78/* Undo _iommufd_object_alloc() if iommufd_object_finalize() was not called */
79void iommufd_object_abort(struct iommufd_ctx *ictx, struct iommufd_object *obj)
80{
81 void *old;
82
83 old = xa_erase(&ictx->objects, obj->id);
84 WARN_ON(old);
85 kfree(obj);
86}
87
88/*
89 * Abort an object that has been fully initialized and needs destroy, but has
90 * not been finalized.
91 */
92void iommufd_object_abort_and_destroy(struct iommufd_ctx *ictx,
93 struct iommufd_object *obj)
94{
95 iommufd_object_ops[obj->type].destroy(obj);
96 iommufd_object_abort(ictx, obj);
97}
98
99struct iommufd_object *iommufd_get_object(struct iommufd_ctx *ictx, u32 id,
100 enum iommufd_object_type type)
101{
102 struct iommufd_object *obj;
103
104 xa_lock(&ictx->objects);
105 obj = xa_load(&ictx->objects, id);
106 if (!obj || (type != IOMMUFD_OBJ_ANY && obj->type != type) ||
107 !iommufd_lock_obj(obj))
108 obj = ERR_PTR(-ENOENT);
109 xa_unlock(&ictx->objects);
110 return obj;
111}
112
113/*
114 * The caller holds a users refcount and wants to destroy the object. Returns
115 * true if the object was destroyed. In all cases the caller no longer has a
116 * reference on obj.
117 */
118bool iommufd_object_destroy_user(struct iommufd_ctx *ictx,
119 struct iommufd_object *obj)
120{
121 /*
122 * The purpose of the destroy_rwsem is to ensure deterministic
123 * destruction of objects used by external drivers and destroyed by this
124 * function. Any temporary increment of the refcount must hold the read
125 * side of this, such as during ioctl execution.
126 */
127 down_write(&obj->destroy_rwsem);
128 xa_lock(&ictx->objects);
129 refcount_dec(&obj->users);
130 if (!refcount_dec_if_one(&obj->users)) {
131 xa_unlock(&ictx->objects);
132 up_write(&obj->destroy_rwsem);
133 return false;
134 }
135 __xa_erase(&ictx->objects, obj->id);
136 xa_unlock(&ictx->objects);
137 up_write(&obj->destroy_rwsem);
138
139 iommufd_object_ops[obj->type].destroy(obj);
140 kfree(obj);
141 return true;
142}
143
144static int iommufd_destroy(struct iommufd_ucmd *ucmd)
145{
146 struct iommu_destroy *cmd = ucmd->cmd;
147 struct iommufd_object *obj;
148
149 obj = iommufd_get_object(ucmd->ictx, cmd->id, IOMMUFD_OBJ_ANY);
150 if (IS_ERR(obj))
151 return PTR_ERR(obj);
152 iommufd_ref_to_users(obj);
153 /* See iommufd_ref_to_users() */
154 if (!iommufd_object_destroy_user(ucmd->ictx, obj))
155 return -EBUSY;
156 return 0;
157}
158
159static int iommufd_fops_open(struct inode *inode, struct file *filp)
160{
161 struct iommufd_ctx *ictx;
162
163 ictx = kzalloc(sizeof(*ictx), GFP_KERNEL_ACCOUNT);
164 if (!ictx)
165 return -ENOMEM;
166
167 xa_init_flags(&ictx->objects, XA_FLAGS_ALLOC1 | XA_FLAGS_ACCOUNT);
168 ictx->file = filp;
169 filp->private_data = ictx;
170 return 0;
171}
172
173static int iommufd_fops_release(struct inode *inode, struct file *filp)
174{
175 struct iommufd_ctx *ictx = filp->private_data;
176 struct iommufd_object *obj;
177
178 /*
179 * The objects in the xarray form a graph of "users" counts, and we have
180 * to destroy them in a depth first manner. Leaf objects will reduce the
181 * users count of interior objects when they are destroyed.
182 *
183 * Repeatedly destroying all the "1 users" leaf objects will progress
184 * until the entire list is destroyed. If this can't progress then there
185 * is some bug related to object refcounting.
186 */
187 while (!xa_empty(&ictx->objects)) {
188 unsigned int destroyed = 0;
189 unsigned long index;
190
191 xa_for_each(&ictx->objects, index, obj) {
192 if (!refcount_dec_if_one(&obj->users))
193 continue;
194 destroyed++;
195 xa_erase(&ictx->objects, index);
196 iommufd_object_ops[obj->type].destroy(obj);
197 kfree(obj);
198 }
199 /* Bug related to users refcount */
200 if (WARN_ON(!destroyed))
201 break;
202 }
203 kfree(ictx);
204 return 0;
205}
206
207union ucmd_buffer {
208 struct iommu_destroy destroy;
209};
210
211struct iommufd_ioctl_op {
212 unsigned int size;
213 unsigned int min_size;
214 unsigned int ioctl_num;
215 int (*execute)(struct iommufd_ucmd *ucmd);
216};
217
218#define IOCTL_OP(_ioctl, _fn, _struct, _last) \
219 [_IOC_NR(_ioctl) - IOMMUFD_CMD_BASE] = { \
220 .size = sizeof(_struct) + \
221 BUILD_BUG_ON_ZERO(sizeof(union ucmd_buffer) < \
222 sizeof(_struct)), \
223 .min_size = offsetofend(_struct, _last), \
224 .ioctl_num = _ioctl, \
225 .execute = _fn, \
226 }
227static const struct iommufd_ioctl_op iommufd_ioctl_ops[] = {
228 IOCTL_OP(IOMMU_DESTROY, iommufd_destroy, struct iommu_destroy, id),
229};
230
231static long iommufd_fops_ioctl(struct file *filp, unsigned int cmd,
232 unsigned long arg)
233{
234 const struct iommufd_ioctl_op *op;
235 struct iommufd_ucmd ucmd = {};
236 union ucmd_buffer buf;
237 unsigned int nr;
238 int ret;
239
240 ucmd.ictx = filp->private_data;
241 ucmd.ubuffer = (void __user *)arg;
242 ret = get_user(ucmd.user_size, (u32 __user *)ucmd.ubuffer);
243 if (ret)
244 return ret;
245
246 nr = _IOC_NR(cmd);
247 if (nr < IOMMUFD_CMD_BASE ||
248 (nr - IOMMUFD_CMD_BASE) >= ARRAY_SIZE(iommufd_ioctl_ops))
249 return -ENOIOCTLCMD;
250 op = &iommufd_ioctl_ops[nr - IOMMUFD_CMD_BASE];
251 if (op->ioctl_num != cmd)
252 return -ENOIOCTLCMD;
253 if (ucmd.user_size < op->min_size)
254 return -EINVAL;
255
256 ucmd.cmd = &buf;
257 ret = copy_struct_from_user(ucmd.cmd, op->size, ucmd.ubuffer,
258 ucmd.user_size);
259 if (ret)
260 return ret;
261 ret = op->execute(&ucmd);
262 return ret;
263}
264
265static const struct file_operations iommufd_fops = {
266 .owner = THIS_MODULE,
267 .open = iommufd_fops_open,
268 .release = iommufd_fops_release,
269 .unlocked_ioctl = iommufd_fops_ioctl,
270};
271
272/**
273 * iommufd_ctx_get - Get a context reference
274 * @ictx: Context to get
275 *
276 * The caller must already hold a valid reference to ictx.
277 */
278void iommufd_ctx_get(struct iommufd_ctx *ictx)
279{
280 get_file(ictx->file);
281}
282EXPORT_SYMBOL_NS_GPL(iommufd_ctx_get, IOMMUFD);
283
284/**
285 * iommufd_ctx_from_file - Acquires a reference to the iommufd context
286 * @file: File to obtain the reference from
287 *
288 * Returns a pointer to the iommufd_ctx, otherwise ERR_PTR. The struct file
289 * remains owned by the caller and the caller must still do fput. On success
290 * the caller is responsible to call iommufd_ctx_put().
291 */
292struct iommufd_ctx *iommufd_ctx_from_file(struct file *file)
293{
294 struct iommufd_ctx *ictx;
295
296 if (file->f_op != &iommufd_fops)
297 return ERR_PTR(-EBADFD);
298 ictx = file->private_data;
299 iommufd_ctx_get(ictx);
300 return ictx;
301}
302EXPORT_SYMBOL_NS_GPL(iommufd_ctx_from_file, IOMMUFD);
303
304/**
305 * iommufd_ctx_put - Put back a reference
306 * @ictx: Context to put back
307 */
308void iommufd_ctx_put(struct iommufd_ctx *ictx)
309{
310 fput(ictx->file);
311}
312EXPORT_SYMBOL_NS_GPL(iommufd_ctx_put, IOMMUFD);
313
314static const struct iommufd_object_ops iommufd_object_ops[] = {
315};
316
317static struct miscdevice iommu_misc_dev = {
318 .minor = MISC_DYNAMIC_MINOR,
319 .name = "iommu",
320 .fops = &iommufd_fops,
321 .nodename = "iommu",
322 .mode = 0660,
323};
324
325static int __init iommufd_init(void)
326{
327 int ret;
328
329 ret = misc_register(&iommu_misc_dev);
330 if (ret)
331 return ret;
332 return 0;
333}
334
335static void __exit iommufd_exit(void)
336{
337 misc_deregister(&iommu_misc_dev);
338}
339
340module_init(iommufd_init);
341module_exit(iommufd_exit);
342
343MODULE_DESCRIPTION("I/O Address Space Management for passthrough devices");
344MODULE_LICENSE("GPL");
include/linux/iommufd.h+31−0
@@ -0,0 +1,31 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright (C) 2021 Intel Corporation
4 * Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES
5 */
6#ifndef __LINUX_IOMMUFD_H
7#define __LINUX_IOMMUFD_H
8
9#include <linux/types.h>
10#include <linux/errno.h>
11#include <linux/err.h>
12
13struct iommufd_ctx;
14struct file;
15
16void iommufd_ctx_get(struct iommufd_ctx *ictx);
17
18#if IS_ENABLED(CONFIG_IOMMUFD)
19struct iommufd_ctx *iommufd_ctx_from_file(struct file *file);
20void iommufd_ctx_put(struct iommufd_ctx *ictx);
21#else /* !CONFIG_IOMMUFD */
22static inline struct iommufd_ctx *iommufd_ctx_from_file(struct file *file)
23{
24 return ERR_PTR(-EOPNOTSUPP);
25}
26
27static inline void iommufd_ctx_put(struct iommufd_ctx *ictx)
28{
29}
30#endif /* CONFIG_IOMMUFD */
31#endif
include/uapi/linux/iommufd.h+55−0
@@ -0,0 +1,55 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2/* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES.
3 */
4#ifndef _UAPI_IOMMUFD_H
5#define _UAPI_IOMMUFD_H
6
7#include <linux/types.h>
8#include <linux/ioctl.h>
9
10#define IOMMUFD_TYPE (';')
11
12/**
13 * DOC: General ioctl format
14 *
15 * The ioctl interface follows a general format to allow for extensibility. Each
16 * ioctl is passed in a structure pointer as the argument providing the size of
17 * the structure in the first u32. The kernel checks that any structure space
18 * beyond what it understands is 0. This allows userspace to use the backward
19 * compatible portion while consistently using the newer, larger, structures.
20 *
21 * ioctls use a standard meaning for common errnos:
22 *
23 * - ENOTTY: The IOCTL number itself is not supported at all
24 * - E2BIG: The IOCTL number is supported, but the provided structure has
25 * non-zero in a part the kernel does not understand.
26 * - EOPNOTSUPP: The IOCTL number is supported, and the structure is
27 * understood, however a known field has a value the kernel does not
28 * understand or support.
29 * - EINVAL: Everything about the IOCTL was understood, but a field is not
30 * correct.
31 * - ENOENT: An ID or IOVA provided does not exist.
32 * - ENOMEM: Out of memory.
33 * - EOVERFLOW: Mathematics overflowed.
34 *
35 * As well as additional errnos, within specific ioctls.
36 */
37enum {
38 IOMMUFD_CMD_BASE = 0x80,
39 IOMMUFD_CMD_DESTROY = IOMMUFD_CMD_BASE,
40};
41
42/**
43 * struct iommu_destroy - ioctl(IOMMU_DESTROY)
44 * @size: sizeof(struct iommu_destroy)
45 * @id: iommufd object ID to destroy. Can by any destroyable object type.
46 *
47 * Destroy any object held within iommufd.
48 */
49struct iommu_destroy {
50 __u32 size;
51 __u32 id;
52};
53#define IOMMU_DESTROY _IO(IOMMUFD_TYPE, IOMMUFD_CMD_DESTROY)
54
55#endif