Skip to content

Commit bed9e51

Browse files
committed
Merge branch 'vfio-no-iommu' into iommufd.git for-next
Shared branch with VFIO for the no-iommu support. Signed-off-by: Jason Gunthorpe <[email protected]>
2 parents fd9f2a9 + c9a397c commit bed9e51

File tree

10 files changed

+136
-35
lines changed

10 files changed

+136
-35
lines changed

drivers/iommu/iommufd/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ config IOMMUFD_VFIO_CONTAINER
2323
removed.
2424

2525
IOMMUFD VFIO container emulation is known to lack certain features
26-
of the native VFIO container, such as no-IOMMU support, peer-to-peer
26+
of the native VFIO container, such as peer-to-peer
2727
DMA mapping, PPC IOMMU support, as well as other potentially
2828
undiscovered gaps. This option is currently intended for the
2929
purpose of testing IOMMUFD with unmodified userspace supporting VFIO

drivers/iommu/iommufd/iommufd_private.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ struct iommufd_ctx {
1818
struct xarray objects;
1919

2020
u8 account_mode;
21+
/* Compatibility with VFIO no iommu */
22+
u8 no_iommu_mode;
2123
struct iommufd_ioas *vfio_ioas;
2224
};
2325

drivers/iommu/iommufd/vfio_compat.c

Lines changed: 86 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,39 +26,84 @@ static struct iommufd_ioas *get_compat_ioas(struct iommufd_ctx *ictx)
2626
}
2727

2828
/**
29-
* iommufd_vfio_compat_ioas_id - Return the IOAS ID that vfio should use
29+
* iommufd_vfio_compat_ioas_get_id - Ensure a compat IOAS exists
30+
* @ictx: Context to operate on
31+
* @out_ioas_id: The IOAS ID of the compatibility IOAS
32+
*
33+
* Return the ID of the current compatibility IOAS. The ID can be passed into
34+
* other functions that take an ioas_id.
35+
*/
36+
int iommufd_vfio_compat_ioas_get_id(struct iommufd_ctx *ictx, u32 *out_ioas_id)
37+
{
38+
struct iommufd_ioas *ioas;
39+
40+
ioas = get_compat_ioas(ictx);
41+
if (IS_ERR(ioas))
42+
return PTR_ERR(ioas);
43+
*out_ioas_id = ioas->obj.id;
44+
iommufd_put_object(&ioas->obj);
45+
return 0;
46+
}
47+
EXPORT_SYMBOL_NS_GPL(iommufd_vfio_compat_ioas_get_id, IOMMUFD_VFIO);
48+
49+
/**
50+
* iommufd_vfio_compat_set_no_iommu - Called when a no-iommu device is attached
51+
* @ictx: Context to operate on
52+
*
53+
* This allows selecting the VFIO_NOIOMMU_IOMMU and blocks normal types.
54+
*/
55+
int iommufd_vfio_compat_set_no_iommu(struct iommufd_ctx *ictx)
56+
{
57+
int ret;
58+
59+
xa_lock(&ictx->objects);
60+
if (!ictx->vfio_ioas) {
61+
ictx->no_iommu_mode = 1;
62+
ret = 0;
63+
} else {
64+
ret = -EINVAL;
65+
}
66+
xa_unlock(&ictx->objects);
67+
return ret;
68+
}
69+
EXPORT_SYMBOL_NS_GPL(iommufd_vfio_compat_set_no_iommu, IOMMUFD_VFIO);
70+
71+
/**
72+
* iommufd_vfio_compat_ioas_create - Ensure the compat IOAS is created
3073
* @ictx: Context to operate on
31-
* @out_ioas_id: The ioas_id the caller should use
3274
*
3375
* The compatibility IOAS is the IOAS that the vfio compatibility ioctls operate
3476
* on since they do not have an IOAS ID input in their ABI. Only attaching a
35-
* group should cause a default creation of the internal ioas, this returns the
36-
* existing ioas if it has already been assigned somehow.
77+
* group should cause a default creation of the internal ioas, this does nothing
78+
* if an existing ioas has already been assigned somehow.
3779
*/
38-
int iommufd_vfio_compat_ioas_id(struct iommufd_ctx *ictx, u32 *out_ioas_id)
80+
int iommufd_vfio_compat_ioas_create(struct iommufd_ctx *ictx)
3981
{
4082
struct iommufd_ioas *ioas = NULL;
41-
struct iommufd_ioas *out_ioas;
83+
int ret;
4284

4385
ioas = iommufd_ioas_alloc(ictx);
4486
if (IS_ERR(ioas))
4587
return PTR_ERR(ioas);
4688

4789
xa_lock(&ictx->objects);
48-
if (ictx->vfio_ioas && iommufd_lock_obj(&ictx->vfio_ioas->obj))
49-
out_ioas = ictx->vfio_ioas;
50-
else {
51-
out_ioas = ioas;
52-
ictx->vfio_ioas = ioas;
90+
/*
91+
* VFIO won't allow attaching a container to both iommu and no iommu
92+
* operation
93+
*/
94+
if (ictx->no_iommu_mode) {
95+
ret = -EINVAL;
96+
goto out_abort;
5397
}
54-
xa_unlock(&ictx->objects);
5598

56-
*out_ioas_id = out_ioas->obj.id;
57-
if (out_ioas != ioas) {
58-
iommufd_put_object(&out_ioas->obj);
59-
iommufd_object_abort(ictx, &ioas->obj);
60-
return 0;
99+
if (ictx->vfio_ioas && iommufd_lock_obj(&ictx->vfio_ioas->obj)) {
100+
ret = 0;
101+
iommufd_put_object(&ictx->vfio_ioas->obj);
102+
goto out_abort;
61103
}
104+
ictx->vfio_ioas = ioas;
105+
xa_unlock(&ictx->objects);
106+
62107
/*
63108
* An automatically created compat IOAS is treated as a userspace
64109
* created object. Userspace can learn the ID via IOMMU_VFIO_IOAS_GET,
@@ -67,8 +112,13 @@ int iommufd_vfio_compat_ioas_id(struct iommufd_ctx *ictx, u32 *out_ioas_id)
67112
*/
68113
iommufd_object_finalize(ictx, &ioas->obj);
69114
return 0;
115+
116+
out_abort:
117+
xa_unlock(&ictx->objects);
118+
iommufd_object_abort(ictx, &ioas->obj);
119+
return ret;
70120
}
71-
EXPORT_SYMBOL_NS_GPL(iommufd_vfio_compat_ioas_id, IOMMUFD_VFIO);
121+
EXPORT_SYMBOL_NS_GPL(iommufd_vfio_compat_ioas_create, IOMMUFD_VFIO);
72122

73123
int iommufd_vfio_ioas(struct iommufd_ucmd *ucmd)
74124
{
@@ -235,6 +285,9 @@ static int iommufd_vfio_check_extension(struct iommufd_ctx *ictx,
235285
case VFIO_UNMAP_ALL:
236286
return 1;
237287

288+
case VFIO_NOIOMMU_IOMMU:
289+
return IS_ENABLED(CONFIG_VFIO_NOIOMMU);
290+
238291
case VFIO_DMA_CC_IOMMU:
239292
return iommufd_vfio_cc_iommu(ictx);
240293

@@ -261,10 +314,24 @@ static int iommufd_vfio_check_extension(struct iommufd_ctx *ictx,
261314

262315
static int iommufd_vfio_set_iommu(struct iommufd_ctx *ictx, unsigned long type)
263316
{
317+
bool no_iommu_mode = READ_ONCE(ictx->no_iommu_mode);
264318
struct iommufd_ioas *ioas = NULL;
265319
int rc = 0;
266320

267-
if (type != VFIO_TYPE1_IOMMU && type != VFIO_TYPE1v2_IOMMU)
321+
/*
322+
* Emulation for NOIOMMU is imperfect in that VFIO blocks almost all
323+
* other ioctls. We let them keep working but they mostly fail since no
324+
* IOAS should exist.
325+
*/
326+
if (IS_ENABLED(CONFIG_VFIO_NOIOMMU) && type == VFIO_NOIOMMU_IOMMU &&
327+
no_iommu_mode) {
328+
if (!capable(CAP_SYS_RAWIO))
329+
return -EPERM;
330+
return 0;
331+
}
332+
333+
if ((type != VFIO_TYPE1_IOMMU && type != VFIO_TYPE1v2_IOMMU) ||
334+
no_iommu_mode)
268335
return -EINVAL;
269336

270337
/* VFIO fails the set_iommu if there is no group */

drivers/vfio/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ config VFIO_IOMMU_SPAPR_TCE
3232
tristate
3333
depends on SPAPR_TCE_IOMMU
3434
default VFIO
35+
endif
3536

3637
config VFIO_NOIOMMU
3738
bool "VFIO No-IOMMU support"
@@ -46,7 +47,6 @@ config VFIO_NOIOMMU
4647
this mode since there is no IOMMU to provide DMA translation.
4748

4849
If you don't know what to do here, say N.
49-
endif
5050

5151
config VFIO_VIRQFD
5252
bool

drivers/vfio/container.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,6 @@ static struct vfio {
2929
struct mutex iommu_drivers_lock;
3030
} vfio;
3131

32-
#ifdef CONFIG_VFIO_NOIOMMU
33-
bool vfio_noiommu __read_mostly;
34-
module_param_named(enable_unsafe_noiommu_mode,
35-
vfio_noiommu, bool, S_IRUGO | S_IWUSR);
36-
MODULE_PARM_DESC(enable_unsafe_noiommu_mode, "Enable UNSAFE, no-IOMMU mode. This mode provides no device isolation, no DMA translation, no host kernel protection, cannot be used for device assignment to virtual machines, requires RAWIO permissions, and will taint the kernel. If you do not know what this is for, step away. (default: false)");
37-
#endif
38-
3932
static void *vfio_noiommu_open(unsigned long arg)
4033
{
4134
if (arg != VFIO_NOIOMMU_IOMMU)

drivers/vfio/group.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,12 @@ static int vfio_group_ioctl_set_container(struct vfio_group *group,
133133

134134
iommufd = iommufd_ctx_from_file(f.file);
135135
if (!IS_ERR(iommufd)) {
136-
u32 ioas_id;
136+
if (IS_ENABLED(CONFIG_VFIO_NOIOMMU) &&
137+
group->type == VFIO_NO_IOMMU)
138+
ret = iommufd_vfio_compat_set_no_iommu(iommufd);
139+
else
140+
ret = iommufd_vfio_compat_ioas_create(iommufd);
137141

138-
ret = iommufd_vfio_compat_ioas_id(iommufd, &ioas_id);
139142
if (ret) {
140143
iommufd_ctx_put(group->iommufd);
141144
goto out_unlock;

drivers/vfio/iommufd.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,20 @@ int vfio_iommufd_bind(struct vfio_device *vdev, struct iommufd_ctx *ictx)
1818

1919
lockdep_assert_held(&vdev->dev_set->lock);
2020

21+
if (vfio_device_is_noiommu(vdev)) {
22+
if (!capable(CAP_SYS_RAWIO))
23+
return -EPERM;
24+
25+
/*
26+
* Require no compat ioas to be assigned to proceed. The basic
27+
* statement is that the user cannot have done something that
28+
* implies they expected translation to exist
29+
*/
30+
if (!iommufd_vfio_compat_ioas_get_id(ictx, &ioas_id))
31+
return -EPERM;
32+
return 0;
33+
}
34+
2135
/*
2236
* If the driver doesn't provide this op then it means the device does
2337
* not do DMA at all. So nothing to do.
@@ -29,7 +43,7 @@ int vfio_iommufd_bind(struct vfio_device *vdev, struct iommufd_ctx *ictx)
2943
if (ret)
3044
return ret;
3145

32-
ret = iommufd_vfio_compat_ioas_id(ictx, &ioas_id);
46+
ret = iommufd_vfio_compat_ioas_get_id(ictx, &ioas_id);
3347
if (ret)
3448
goto err_unbind;
3549
ret = vdev->ops->attach_ioas(vdev, &ioas_id);
@@ -52,6 +66,9 @@ void vfio_iommufd_unbind(struct vfio_device *vdev)
5266
{
5367
lockdep_assert_held(&vdev->dev_set->lock);
5468

69+
if (vfio_device_is_noiommu(vdev))
70+
return;
71+
5572
if (vdev->ops->unbind_iommufd)
5673
vdev->ops->unbind_iommufd(vdev);
5774
}

drivers/vfio/vfio.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
#include <linux/device.h>
1111
#include <linux/cdev.h>
1212
#include <linux/module.h>
13+
#include <linux/vfio.h>
1314

1415
struct iommufd_ctx;
1516
struct iommu_group;
16-
struct vfio_device;
1717
struct vfio_container;
1818

1919
void vfio_device_put_registration(struct vfio_device *device);
@@ -88,6 +88,12 @@ bool vfio_device_has_container(struct vfio_device *device);
8888
int __init vfio_group_init(void);
8989
void vfio_group_cleanup(void);
9090

91+
static inline bool vfio_device_is_noiommu(struct vfio_device *vdev)
92+
{
93+
return IS_ENABLED(CONFIG_VFIO_NOIOMMU) &&
94+
vdev->group->type == VFIO_NO_IOMMU;
95+
}
96+
9197
#if IS_ENABLED(CONFIG_VFIO_CONTAINER)
9298
/* events for the backend driver notify callback */
9399
enum vfio_iommu_notify_type {

drivers/vfio/vfio_main.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ static struct vfio {
4545
struct ida device_ida;
4646
} vfio;
4747

48+
#ifdef CONFIG_VFIO_NOIOMMU
49+
bool vfio_noiommu __read_mostly;
50+
module_param_named(enable_unsafe_noiommu_mode,
51+
vfio_noiommu, bool, S_IRUGO | S_IWUSR);
52+
MODULE_PARM_DESC(enable_unsafe_noiommu_mode, "Enable UNSAFE, no-IOMMU mode. This mode provides no device isolation, no DMA translation, no host kernel protection, cannot be used for device assignment to virtual machines, requires RAWIO permissions, and will taint the kernel. If you do not know what this is for, step away. (default: false)");
53+
#endif
54+
4855
static DEFINE_XARRAY(vfio_device_set_xa);
4956

5057
int vfio_assign_device_set(struct vfio_device *device, void *set_id)

include/linux/iommufd.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ void iommufd_access_unpin_pages(struct iommufd_access *access,
5757
unsigned long iova, unsigned long length);
5858
int iommufd_access_rw(struct iommufd_access *access, unsigned long iova,
5959
void *data, size_t len, unsigned int flags);
60-
int iommufd_vfio_compat_ioas_id(struct iommufd_ctx *ictx, u32 *out_ioas_id);
60+
int iommufd_vfio_compat_ioas_get_id(struct iommufd_ctx *ictx, u32 *out_ioas_id);
61+
int iommufd_vfio_compat_ioas_create(struct iommufd_ctx *ictx);
62+
int iommufd_vfio_compat_set_no_iommu(struct iommufd_ctx *ictx);
6163
#else /* !CONFIG_IOMMUFD */
6264
static inline struct iommufd_ctx *iommufd_ctx_from_file(struct file *file)
6365
{
@@ -89,8 +91,12 @@ static inline int iommufd_access_rw(struct iommufd_access *access, unsigned long
8991
return -EOPNOTSUPP;
9092
}
9193

92-
static inline int iommufd_vfio_compat_ioas_id(struct iommufd_ctx *ictx,
93-
u32 *out_ioas_id)
94+
static inline int iommufd_vfio_compat_ioas_create(struct iommufd_ctx *ictx)
95+
{
96+
return -EOPNOTSUPP;
97+
}
98+
99+
static inline int iommufd_vfio_compat_set_no_iommu(struct iommufd_ctx *ictx)
94100
{
95101
return -EOPNOTSUPP;
96102
}

0 commit comments

Comments
 (0)