Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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/err.h>
10#include <linux/errno.h>
11#include <linux/refcount.h>
12#include <linux/types.h>
13#include <linux/xarray.h>
14
15struct device;
16struct file;
17struct iommu_group;
18struct iommu_user_data;
19struct iommu_user_data_array;
20struct iommufd_access;
21struct iommufd_ctx;
22struct iommufd_device;
23struct iommufd_viommu_ops;
24struct page;
25
26enum iommufd_object_type {
27 IOMMUFD_OBJ_NONE,
28 IOMMUFD_OBJ_ANY = IOMMUFD_OBJ_NONE,
29 IOMMUFD_OBJ_DEVICE,
30 IOMMUFD_OBJ_HWPT_PAGING,
31 IOMMUFD_OBJ_HWPT_NESTED,
32 IOMMUFD_OBJ_IOAS,
33 IOMMUFD_OBJ_ACCESS,
34 IOMMUFD_OBJ_FAULT,
35 IOMMUFD_OBJ_VIOMMU,
36 IOMMUFD_OBJ_VDEVICE,
37#ifdef CONFIG_IOMMUFD_TEST
38 IOMMUFD_OBJ_SELFTEST,
39#endif
40 IOMMUFD_OBJ_MAX,
41};
42
43/* Base struct for all objects with a userspace ID handle. */
44struct iommufd_object {
45 refcount_t shortterm_users;
46 refcount_t users;
47 enum iommufd_object_type type;
48 unsigned int id;
49};
50
51struct iommufd_device *iommufd_device_bind(struct iommufd_ctx *ictx,
52 struct device *dev, u32 *id);
53void iommufd_device_unbind(struct iommufd_device *idev);
54
55int iommufd_device_attach(struct iommufd_device *idev, u32 *pt_id);
56int iommufd_device_replace(struct iommufd_device *idev, u32 *pt_id);
57void iommufd_device_detach(struct iommufd_device *idev);
58
59struct iommufd_ctx *iommufd_device_to_ictx(struct iommufd_device *idev);
60u32 iommufd_device_to_id(struct iommufd_device *idev);
61
62struct iommufd_access_ops {
63 u8 needs_pin_pages : 1;
64 void (*unmap)(void *data, unsigned long iova, unsigned long length);
65};
66
67enum {
68 IOMMUFD_ACCESS_RW_READ = 0,
69 IOMMUFD_ACCESS_RW_WRITE = 1 << 0,
70 /* Set if the caller is in a kthread then rw will use kthread_use_mm() */
71 IOMMUFD_ACCESS_RW_KTHREAD = 1 << 1,
72
73 /* Only for use by selftest */
74 __IOMMUFD_ACCESS_RW_SLOW_PATH = 1 << 2,
75};
76
77struct iommufd_access *
78iommufd_access_create(struct iommufd_ctx *ictx,
79 const struct iommufd_access_ops *ops, void *data, u32 *id);
80void iommufd_access_destroy(struct iommufd_access *access);
81int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id);
82int iommufd_access_replace(struct iommufd_access *access, u32 ioas_id);
83void iommufd_access_detach(struct iommufd_access *access);
84
85void iommufd_ctx_get(struct iommufd_ctx *ictx);
86
87struct iommufd_viommu {
88 struct iommufd_object obj;
89 struct iommufd_ctx *ictx;
90 struct iommu_device *iommu_dev;
91 struct iommufd_hwpt_paging *hwpt;
92
93 const struct iommufd_viommu_ops *ops;
94
95 struct xarray vdevs;
96
97 unsigned int type;
98};
99
100/**
101 * struct iommufd_viommu_ops - vIOMMU specific operations
102 * @destroy: Clean up all driver-specific parts of an iommufd_viommu. The memory
103 * of the vIOMMU will be free-ed by iommufd core after calling this op
104 * @alloc_domain_nested: Allocate a IOMMU_DOMAIN_NESTED on a vIOMMU that holds a
105 * nesting parent domain (IOMMU_DOMAIN_PAGING). @user_data
106 * must be defined in include/uapi/linux/iommufd.h.
107 * It must fully initialize the new iommu_domain before
108 * returning. Upon failure, ERR_PTR must be returned.
109 * @cache_invalidate: Flush hardware cache used by a vIOMMU. It can be used for
110 * any IOMMU hardware specific cache: TLB and device cache.
111 * The @array passes in the cache invalidation requests, in
112 * form of a driver data structure. A driver must update the
113 * array->entry_num to report the number of handled requests.
114 * The data structure of the array entry must be defined in
115 * include/uapi/linux/iommufd.h
116 */
117struct iommufd_viommu_ops {
118 void (*destroy)(struct iommufd_viommu *viommu);
119 struct iommu_domain *(*alloc_domain_nested)(
120 struct iommufd_viommu *viommu, u32 flags,
121 const struct iommu_user_data *user_data);
122 int (*cache_invalidate)(struct iommufd_viommu *viommu,
123 struct iommu_user_data_array *array);
124};
125
126#if IS_ENABLED(CONFIG_IOMMUFD)
127struct iommufd_ctx *iommufd_ctx_from_file(struct file *file);
128struct iommufd_ctx *iommufd_ctx_from_fd(int fd);
129void iommufd_ctx_put(struct iommufd_ctx *ictx);
130bool iommufd_ctx_has_group(struct iommufd_ctx *ictx, struct iommu_group *group);
131
132int iommufd_access_pin_pages(struct iommufd_access *access, unsigned long iova,
133 unsigned long length, struct page **out_pages,
134 unsigned int flags);
135void iommufd_access_unpin_pages(struct iommufd_access *access,
136 unsigned long iova, unsigned long length);
137int iommufd_access_rw(struct iommufd_access *access, unsigned long iova,
138 void *data, size_t len, unsigned int flags);
139int iommufd_vfio_compat_ioas_get_id(struct iommufd_ctx *ictx, u32 *out_ioas_id);
140int iommufd_vfio_compat_ioas_create(struct iommufd_ctx *ictx);
141int iommufd_vfio_compat_set_no_iommu(struct iommufd_ctx *ictx);
142#else /* !CONFIG_IOMMUFD */
143static inline struct iommufd_ctx *iommufd_ctx_from_file(struct file *file)
144{
145 return ERR_PTR(-EOPNOTSUPP);
146}
147
148static inline void iommufd_ctx_put(struct iommufd_ctx *ictx)
149{
150}
151
152static inline int iommufd_access_pin_pages(struct iommufd_access *access,
153 unsigned long iova,
154 unsigned long length,
155 struct page **out_pages,
156 unsigned int flags)
157{
158 return -EOPNOTSUPP;
159}
160
161static inline void iommufd_access_unpin_pages(struct iommufd_access *access,
162 unsigned long iova,
163 unsigned long length)
164{
165}
166
167static inline int iommufd_access_rw(struct iommufd_access *access, unsigned long iova,
168 void *data, size_t len, unsigned int flags)
169{
170 return -EOPNOTSUPP;
171}
172
173static inline int iommufd_vfio_compat_ioas_create(struct iommufd_ctx *ictx)
174{
175 return -EOPNOTSUPP;
176}
177
178static inline int iommufd_vfio_compat_set_no_iommu(struct iommufd_ctx *ictx)
179{
180 return -EOPNOTSUPP;
181}
182#endif /* CONFIG_IOMMUFD */
183
184#if IS_ENABLED(CONFIG_IOMMUFD_DRIVER_CORE)
185struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
186 size_t size,
187 enum iommufd_object_type type);
188struct device *iommufd_viommu_find_dev(struct iommufd_viommu *viommu,
189 unsigned long vdev_id);
190#else /* !CONFIG_IOMMUFD_DRIVER_CORE */
191static inline struct iommufd_object *
192_iommufd_object_alloc(struct iommufd_ctx *ictx, size_t size,
193 enum iommufd_object_type type)
194{
195 return ERR_PTR(-EOPNOTSUPP);
196}
197
198static inline struct device *
199iommufd_viommu_find_dev(struct iommufd_viommu *viommu, unsigned long vdev_id)
200{
201 return NULL;
202}
203#endif /* CONFIG_IOMMUFD_DRIVER_CORE */
204
205/*
206 * Helpers for IOMMU driver to allocate driver structures that will be freed by
207 * the iommufd core. The free op will be called prior to freeing the memory.
208 */
209#define iommufd_viommu_alloc(ictx, drv_struct, member, viommu_ops) \
210 ({ \
211 drv_struct *ret; \
212 \
213 static_assert(__same_type(struct iommufd_viommu, \
214 ((drv_struct *)NULL)->member)); \
215 static_assert(offsetof(drv_struct, member.obj) == 0); \
216 ret = (drv_struct *)_iommufd_object_alloc( \
217 ictx, sizeof(drv_struct), IOMMUFD_OBJ_VIOMMU); \
218 if (!IS_ERR(ret)) \
219 ret->member.ops = viommu_ops; \
220 ret; \
221 })
222#endif