Hi Jason,
Some nits below.
On 2022/10/26 2:12, Jason Gunthorpe wrote:
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.
Signed-off-by: Yi Liu yi.l.liu@intel.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com
[---8<---]
+struct iommufd_ioctl_op {
- unsigned int size;
- unsigned int min_size;
- unsigned int ioctl_num;
- int (*execute)(struct iommufd_ucmd *ucmd);
+};
+#define IOCTL_OP(_ioctl, _fn, _struct, _last) \
- [_IOC_NR(_ioctl) - IOMMUFD_CMD_BASE] = { \
.size = sizeof(_struct) + \
BUILD_BUG_ON_ZERO(sizeof(union ucmd_buffer) < \
sizeof(_struct)), \
.min_size = offsetofend(_struct, _last), \
.ioctl_num = _ioctl, \
.execute = _fn, \
- }
+static struct iommufd_ioctl_op iommufd_ioctl_ops[] = {
How about making the ops "static const"?
- IOCTL_OP(IOMMU_DESTROY, iommufd_destroy, struct iommu_destroy, id),
+};
+static long iommufd_fops_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
+{
- struct iommufd_ucmd ucmd = {};
- struct iommufd_ioctl_op *op;
- union ucmd_buffer buf;
- unsigned int nr;
- int ret;
- ucmd.ictx = filp->private_data;
- ucmd.ubuffer = (void __user *)arg;
- ret = get_user(ucmd.user_size, (u32 __user *)ucmd.ubuffer);
- if (ret)
return ret;
- nr = _IOC_NR(cmd);
- if (nr < IOMMUFD_CMD_BASE ||
(nr - IOMMUFD_CMD_BASE) >= ARRAY_SIZE(iommufd_ioctl_ops))
return -ENOIOCTLCMD;
- op = &iommufd_ioctl_ops[nr - IOMMUFD_CMD_BASE];
- if (op->ioctl_num != cmd)
return -ENOIOCTLCMD;
- if (ucmd.user_size < op->min_size)
return -EOPNOTSUPP;
- ucmd.cmd = &buf;
- ret = copy_struct_from_user(ucmd.cmd, op->size, ucmd.ubuffer,
ucmd.user_size);
- if (ret)
return ret;
- ret = op->execute(&ucmd);
- return ret;
+}
+static const struct file_operations iommufd_fops = {
- .owner = THIS_MODULE,
- .open = iommufd_fops_open,
- .release = iommufd_fops_release,
- .unlocked_ioctl = iommufd_fops_ioctl,
+};
[---8<---]
+static int __init iommufd_init(void) +{
- int ret;
- ret = misc_register(&iommu_misc_dev);
- if (ret) {
pr_err("Failed to register misc device\n");
return ret;
- }
- return 0;
+}
+static void __exit iommufd_exit(void) +{
- misc_deregister(&iommu_misc_dev);
+}
+module_init(iommufd_init); +module_exit(iommufd_exit);
+MODULE_DESCRIPTION("I/O Address Space Management for passthrough devices"); +MODULE_LICENSE("GPL");
Could above be "GPL v2"?
diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h new file mode 100644 index 00000000000000..d1817472c27373 --- /dev/null +++ b/include/linux/iommufd.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/*
- Copyright (C) 2021 Intel Corporation
- Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES
- */
+#ifndef __LINUX_IOMMUFD_H +#define __LINUX_IOMMUFD_H
+#include <linux/types.h> +#include <linux/errno.h> +#include <linux/err.h>
+struct iommufd_ctx; +struct file;
+void iommufd_ctx_get(struct iommufd_ctx *ictx);
+#if IS_ENABLED(CONFIG_IOMMUFD) +struct iommufd_ctx *iommufd_ctx_from_file(struct file *file); +void iommufd_ctx_put(struct iommufd_ctx *ictx); +#else /* !CONFIG_IOMMUFD */ +static inline struct iommufd_ctx *iommufd_ctx_from_file(struct file *file) +{
- return ERR_PTR(-EOPNOTSUPP);
+}
+static inline void iommufd_ctx_put(struct iommufd_ctx *ictx) +{ +} +#endif /* CONFIG_IOMMUFD */ +#endif diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h new file mode 100644 index 00000000000000..b77b7eb0aeb13c --- /dev/null +++ b/include/uapi/linux/iommufd.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES.
- */
+#ifndef _UAPI_IOMMUFD_H +#define _UAPI_IOMMUFD_H
+#include <linux/types.h> +#include <linux/ioctl.h>
+#define IOMMUFD_TYPE (';')
+/**
- DOC: General ioctl format
- The ioctl mechanims follows a general format to allow for extensibility. Each
^^^^^^^^^ mechanism?
- ioctl is passed in a structure pointer as the argument providing the size of
- the structure in the first u32. The kernel checks that any structure space
- beyond what it understands is 0. This allows userspace to use the backward
- compatible portion while consistently using the newer, larger, structures.
- ioctls use a standard meaning for common errnos:
- ENOTTY: The IOCTL number itself is not supported at all
- E2BIG: The IOCTL number is supported, but the provided structure has
- non-zero in a part the kernel does not understand.
- EOPNOTSUPP: The IOCTL number is supported, and the structure is
- understood, however a known field has a value the kernel does not
- understand or support.
- EINVAL: Everything about the IOCTL was understood, but a field is not
- correct.
- ENOENT: An ID or IOVA provided does not exist.
- ENOMEM: Out of memory.
- EOVERFLOW: Mathematics oveflowed.
- As well as additional errnos, within specific ioctls.
- */
+enum {
- IOMMUFD_CMD_BASE = 0x80,
- IOMMUFD_CMD_DESTROY = IOMMUFD_CMD_BASE,
+};
+/**
- struct iommu_destroy - ioctl(IOMMU_DESTROY)
- @size: sizeof(struct iommu_destroy)
- @id: iommufd object ID to destroy. Can by any destroyable object type.
- Destroy any object held within iommufd.
- */
+struct iommu_destroy {
- __u32 size;
- __u32 id;
+}; +#define IOMMU_DESTROY _IO(IOMMUFD_TYPE, IOMMUFD_CMD_DESTROY)
+#endif
Best regards, baolu