Skip to content

Commit 139a57a

Browse files
jgunthorpejoergroedel
authored andcommitted
iommu/fsl: Use driver_managed_dma to allow VFIO to work
The FSL driver is mangling the iommu_groups to not have a group for its PCI bridge/controller (eg the thing passed to fsl_add_bridge()). Robin says this is so FSL could work with VFIO which would be blocked by having a probed driver on the platform_device in the same group. This is supported by comments from FSL: https://lore.kernel.org/all/C5ECD7A89D1DC44195F34B25E172658D459471@039-SN2MPN1-013.039d.mgd.msft.net .. PCIe devices share the same device group as the PCI controller. This becomes a problem while assigning the devices to the guest, as you are required to unbind all the PCIe devices including the controller from the host. PCIe controller can't be unbound from the host, so we simply delete the controller iommu_group. However, today, we use driver_managed_dma to allow PCI infrastructure devices that are 'security safe' to co-exist in groups and still allow VFIO to work. Set this flag for the fsl_pci_driver. Change fsl_pamu_device_group() so that it no longer removes the controller from any groups. For check_pci_ctl_endpt_part() mode this creates an extra group that contains only the controller. Otherwise force the controller's single group to be the group of all the PCI devices on the controller's hose. VFIO continues to work because of driver_managed_dma. Remove the iommu_group_remove_device() calls from fsl_pamu and lightly restructure its fsl_pamu_device_group() function. Signed-off-by: Jason Gunthorpe <[email protected]> Tested-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 7977a08 commit 139a57a

File tree

2 files changed

+24
-81
lines changed

2 files changed

+24
-81
lines changed

arch/powerpc/sysdev/fsl_pci.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,6 +1353,7 @@ static struct platform_driver fsl_pci_driver = {
13531353
.of_match_table = pci_ids,
13541354
},
13551355
.probe = fsl_pci_probe,
1356+
.driver_managed_dma = true,
13561357
};
13571358

13581359
static int __init fsl_pci_init(void)

drivers/iommu/fsl_pamu_domain.c

Lines changed: 23 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -334,17 +334,6 @@ int fsl_pamu_configure_l1_stash(struct iommu_domain *domain, u32 cpu)
334334
return ret;
335335
}
336336

337-
static struct iommu_group *get_device_iommu_group(struct device *dev)
338-
{
339-
struct iommu_group *group;
340-
341-
group = iommu_group_get(dev);
342-
if (!group)
343-
group = iommu_group_alloc();
344-
345-
return group;
346-
}
347-
348337
static bool check_pci_ctl_endpt_part(struct pci_controller *pci_ctl)
349338
{
350339
u32 version;
@@ -356,85 +345,38 @@ static bool check_pci_ctl_endpt_part(struct pci_controller *pci_ctl)
356345
return version >= 0x204;
357346
}
358347

359-
/* Get iommu group information from peer devices or devices on the parent bus */
360-
static struct iommu_group *get_shared_pci_device_group(struct pci_dev *pdev)
348+
static struct iommu_group *fsl_pamu_device_group(struct device *dev)
361349
{
362-
struct pci_dev *tmp;
363350
struct iommu_group *group;
364-
struct pci_bus *bus = pdev->bus;
351+
struct pci_dev *pdev;
365352

366353
/*
367-
* Traverese the pci bus device list to get
368-
* the shared iommu group.
354+
* For platform devices we allocate a separate group for each of the
355+
* devices.
369356
*/
370-
while (bus) {
371-
list_for_each_entry(tmp, &bus->devices, bus_list) {
372-
if (tmp == pdev)
373-
continue;
374-
group = iommu_group_get(&tmp->dev);
375-
if (group)
376-
return group;
377-
}
378-
379-
bus = bus->parent;
380-
}
381-
382-
return NULL;
383-
}
384-
385-
static struct iommu_group *get_pci_device_group(struct pci_dev *pdev)
386-
{
387-
struct pci_controller *pci_ctl;
388-
bool pci_endpt_partitioning;
389-
struct iommu_group *group = NULL;
390-
391-
pci_ctl = pci_bus_to_host(pdev->bus);
392-
pci_endpt_partitioning = check_pci_ctl_endpt_part(pci_ctl);
393-
/* We can partition PCIe devices so assign device group to the device */
394-
if (pci_endpt_partitioning) {
395-
group = pci_device_group(&pdev->dev);
396-
397-
/*
398-
* PCIe controller is not a paritionable entity
399-
* free the controller device iommu_group.
400-
*/
401-
if (pci_ctl->parent->iommu_group)
402-
iommu_group_remove_device(pci_ctl->parent);
403-
} else {
404-
/*
405-
* All devices connected to the controller will share the
406-
* PCI controllers device group. If this is the first
407-
* device to be probed for the pci controller, copy the
408-
* device group information from the PCI controller device
409-
* node and remove the PCI controller iommu group.
410-
* For subsequent devices, the iommu group information can
411-
* be obtained from sibling devices (i.e. from the bus_devices
412-
* link list).
413-
*/
414-
if (pci_ctl->parent->iommu_group) {
415-
group = get_device_iommu_group(pci_ctl->parent);
416-
iommu_group_remove_device(pci_ctl->parent);
417-
} else {
418-
group = get_shared_pci_device_group(pdev);
419-
}
420-
}
421-
422-
if (!group)
423-
group = ERR_PTR(-ENODEV);
424-
425-
return group;
426-
}
357+
if (!dev_is_pci(dev))
358+
return generic_device_group(dev);
427359

428-
static struct iommu_group *fsl_pamu_device_group(struct device *dev)
429-
{
430360
/*
431-
* For platform devices we allocate a separate group for
432-
* each of the devices.
361+
* We can partition PCIe devices so assign device group to the device
433362
*/
434-
if (!dev_is_pci(dev))
435-
return generic_device_group(dev);
363+
pdev = to_pci_dev(dev);
364+
if (check_pci_ctl_endpt_part(pci_bus_to_host(pdev->bus)))
365+
return pci_device_group(&pdev->dev);
436366

437-
return get_pci_device_group(to_pci_dev(dev));
367+
/*
368+
* All devices connected to the controller will share the same device
369+
* group.
370+
*
371+
* Due to ordering between fsl_pamu_init() and fsl_pci_init() it is
372+
* guaranteed that the pci_ctl->parent platform_device will have the
373+
* iommu driver bound and will already have a group set. So we just
374+
* re-use this group as the group for every device in the hose.
375+
*/
376+
group = iommu_group_get(pci_bus_to_host(pdev->bus)->parent);
377+
if (WARN_ON(!group))
378+
return ERR_PTR(-EINVAL);
379+
return group;
438380
}
439381

440382
static struct iommu_device *fsl_pamu_probe_device(struct device *dev)

0 commit comments

Comments
 (0)