Skip to content

Commit 16ab8a5

Browse files
committed
vfio/noiommu: Don't use iommu_present() to track fake groups
Using iommu_present() to determine whether an IOMMU group is real or fake has some problems. First, apparently Power systems don't register an IOMMU on the device bus, so the groups and containers get marked as noiommu and then won't bind to their actual IOMMU driver. Second, I expect we'll run into the same issue as we try to support vGPUs through vfio, since they're likely to emulate this behavior of creating an IOMMU group on a virtual device and then providing a vfio IOMMU backend tailored to the sort of isolation they provide, which won't necessarily be fully compatible with the IOMMU API. The solution here is to use the existing iommudata interface to IOMMU groups, which allows us to easily identify the fake groups we've created for noiommu purposes. The iommudata we set is purely arbitrary since we're only comparing the address, so we use the address of the noiommu switch itself. Reported-by: Alexey Kardashevskiy <[email protected]> Reviewed-by: Alexey Kardashevskiy <[email protected]> Tested-by: Alexey Kardashevskiy <[email protected]> Tested-by: Anatoly Burakov <[email protected]> Tested-by: Santosh Shukla <[email protected]> Fixes: 03a76b6 ("vfio: Include No-IOMMU mode") Signed-off-by: Alex Williamson <[email protected]>
1 parent 92e963f commit 16ab8a5

File tree

1 file changed

+10
-14
lines changed

1 file changed

+10
-14
lines changed

drivers/vfio/vfio.c

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ struct iommu_group *vfio_iommu_group_get(struct device *dev)
123123
/*
124124
* With noiommu enabled, an IOMMU group will be created for a device
125125
* that doesn't already have one and doesn't have an iommu_ops on their
126-
* bus. We use iommu_present() again in the main code to detect these
127-
* fake groups.
126+
* bus. We set iommudata simply to be able to identify these groups
127+
* as special use and for reclamation later.
128128
*/
129129
if (group || !noiommu || iommu_present(dev->bus))
130130
return group;
@@ -134,6 +134,7 @@ struct iommu_group *vfio_iommu_group_get(struct device *dev)
134134
return NULL;
135135

136136
iommu_group_set_name(group, "vfio-noiommu");
137+
iommu_group_set_iommudata(group, &noiommu, NULL);
137138
ret = iommu_group_add_device(group, dev);
138139
iommu_group_put(group);
139140
if (ret)
@@ -158,7 +159,7 @@ EXPORT_SYMBOL_GPL(vfio_iommu_group_get);
158159
void vfio_iommu_group_put(struct iommu_group *group, struct device *dev)
159160
{
160161
#ifdef CONFIG_VFIO_NOIOMMU
161-
if (!iommu_present(dev->bus))
162+
if (iommu_group_get_iommudata(group) == &noiommu)
162163
iommu_group_remove_device(dev);
163164
#endif
164165

@@ -190,16 +191,10 @@ static long vfio_noiommu_ioctl(void *iommu_data,
190191
return -ENOTTY;
191192
}
192193

193-
static int vfio_iommu_present(struct device *dev, void *unused)
194-
{
195-
return iommu_present(dev->bus) ? 1 : 0;
196-
}
197-
198194
static int vfio_noiommu_attach_group(void *iommu_data,
199195
struct iommu_group *iommu_group)
200196
{
201-
return iommu_group_for_each_dev(iommu_group, NULL,
202-
vfio_iommu_present) ? -EINVAL : 0;
197+
return iommu_group_get_iommudata(iommu_group) == &noiommu ? 0 : -EINVAL;
203198
}
204199

205200
static void vfio_noiommu_detach_group(void *iommu_data,
@@ -323,8 +318,7 @@ static void vfio_group_unlock_and_free(struct vfio_group *group)
323318
/**
324319
* Group objects - create, release, get, put, search
325320
*/
326-
static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group,
327-
bool iommu_present)
321+
static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
328322
{
329323
struct vfio_group *group, *tmp;
330324
struct device *dev;
@@ -342,7 +336,9 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group,
342336
atomic_set(&group->container_users, 0);
343337
atomic_set(&group->opened, 0);
344338
group->iommu_group = iommu_group;
345-
group->noiommu = !iommu_present;
339+
#ifdef CONFIG_VFIO_NOIOMMU
340+
group->noiommu = (iommu_group_get_iommudata(iommu_group) == &noiommu);
341+
#endif
346342

347343
group->nb.notifier_call = vfio_iommu_group_notifier;
348344

@@ -767,7 +763,7 @@ int vfio_add_group_dev(struct device *dev,
767763

768764
group = vfio_group_get_from_iommu(iommu_group);
769765
if (!group) {
770-
group = vfio_create_group(iommu_group, iommu_present(dev->bus));
766+
group = vfio_create_group(iommu_group);
771767
if (IS_ERR(group)) {
772768
iommu_group_put(iommu_group);
773769
return PTR_ERR(group);

0 commit comments

Comments
 (0)