diff options
-rw-r--r-- | drivers/iommu/iommu.c | 163 |
1 files changed, 96 insertions, 67 deletions
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index d2d242fcaa3d..b59826aa5531 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/notifier.h> | 30 | #include <linux/notifier.h> |
31 | #include <linux/err.h> | 31 | #include <linux/err.h> |
32 | #include <linux/pci.h> | 32 | #include <linux/pci.h> |
33 | #include <linux/bitops.h> | ||
33 | #include <trace/events/iommu.h> | 34 | #include <trace/events/iommu.h> |
34 | 35 | ||
35 | static struct kset *iommu_group_kset; | 36 | static struct kset *iommu_group_kset; |
@@ -519,6 +520,9 @@ int iommu_group_id(struct iommu_group *group) | |||
519 | } | 520 | } |
520 | EXPORT_SYMBOL_GPL(iommu_group_id); | 521 | EXPORT_SYMBOL_GPL(iommu_group_id); |
521 | 522 | ||
523 | static struct iommu_group *get_pci_alias_group(struct pci_dev *pdev, | ||
524 | unsigned long *devfns); | ||
525 | |||
522 | /* | 526 | /* |
523 | * To consider a PCI device isolated, we require ACS to support Source | 527 | * To consider a PCI device isolated, we require ACS to support Source |
524 | * Validation, Request Redirection, Completer Redirection, and Upstream | 528 | * Validation, Request Redirection, Completer Redirection, and Upstream |
@@ -529,6 +533,86 @@ EXPORT_SYMBOL_GPL(iommu_group_id); | |||
529 | */ | 533 | */ |
530 | #define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF) | 534 | #define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF) |
531 | 535 | ||
536 | /* | ||
537 | * For multifunction devices which are not isolated from each other, find | ||
538 | * all the other non-isolated functions and look for existing groups. For | ||
539 | * each function, we also need to look for aliases to or from other devices | ||
540 | * that may already have a group. | ||
541 | */ | ||
542 | static struct iommu_group *get_pci_function_alias_group(struct pci_dev *pdev, | ||
543 | unsigned long *devfns) | ||
544 | { | ||
545 | struct pci_dev *tmp = NULL; | ||
546 | struct iommu_group *group; | ||
547 | |||
548 | if (!pdev->multifunction || pci_acs_enabled(pdev, REQ_ACS_FLAGS)) | ||
549 | return NULL; | ||
550 | |||
551 | for_each_pci_dev(tmp) { | ||
552 | if (tmp == pdev || tmp->bus != pdev->bus || | ||
553 | PCI_SLOT(tmp->devfn) != PCI_SLOT(pdev->devfn) || | ||
554 | pci_acs_enabled(tmp, REQ_ACS_FLAGS)) | ||
555 | continue; | ||
556 | |||
557 | group = get_pci_alias_group(tmp, devfns); | ||
558 | if (group) { | ||
559 | pci_dev_put(tmp); | ||
560 | return group; | ||
561 | } | ||
562 | } | ||
563 | |||
564 | return NULL; | ||
565 | } | ||
566 | |||
567 | /* | ||
568 | * Look for aliases to or from the given device for exisiting groups. The | ||
569 | * dma_alias_devfn only supports aliases on the same bus, therefore the search | ||
570 | * space is quite small (especially since we're really only looking at pcie | ||
571 | * device, and therefore only expect multiple slots on the root complex or | ||
572 | * downstream switch ports). It's conceivable though that a pair of | ||
573 | * multifunction devices could have aliases between them that would cause a | ||
574 | * loop. To prevent this, we use a bitmap to track where we've been. | ||
575 | */ | ||
576 | static struct iommu_group *get_pci_alias_group(struct pci_dev *pdev, | ||
577 | unsigned long *devfns) | ||
578 | { | ||
579 | struct pci_dev *tmp = NULL; | ||
580 | struct iommu_group *group; | ||
581 | |||
582 | if (test_and_set_bit(pdev->devfn & 0xff, devfns)) | ||
583 | return NULL; | ||
584 | |||
585 | group = iommu_group_get(&pdev->dev); | ||
586 | if (group) | ||
587 | return group; | ||
588 | |||
589 | for_each_pci_dev(tmp) { | ||
590 | if (tmp == pdev || tmp->bus != pdev->bus) | ||
591 | continue; | ||
592 | |||
593 | /* We alias them or they alias us */ | ||
594 | if (((pdev->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN) && | ||
595 | pdev->dma_alias_devfn == tmp->devfn) || | ||
596 | ((tmp->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN) && | ||
597 | tmp->dma_alias_devfn == pdev->devfn)) { | ||
598 | |||
599 | group = get_pci_alias_group(tmp, devfns); | ||
600 | if (group) { | ||
601 | pci_dev_put(tmp); | ||
602 | return group; | ||
603 | } | ||
604 | |||
605 | group = get_pci_function_alias_group(tmp, devfns); | ||
606 | if (group) { | ||
607 | pci_dev_put(tmp); | ||
608 | return group; | ||
609 | } | ||
610 | } | ||
611 | } | ||
612 | |||
613 | return NULL; | ||
614 | } | ||
615 | |||
532 | struct group_for_pci_data { | 616 | struct group_for_pci_data { |
533 | struct pci_dev *pdev; | 617 | struct pci_dev *pdev; |
534 | struct iommu_group *group; | 618 | struct iommu_group *group; |
@@ -557,7 +641,7 @@ static struct iommu_group *iommu_group_get_for_pci_dev(struct pci_dev *pdev) | |||
557 | struct group_for_pci_data data; | 641 | struct group_for_pci_data data; |
558 | struct pci_bus *bus; | 642 | struct pci_bus *bus; |
559 | struct iommu_group *group = NULL; | 643 | struct iommu_group *group = NULL; |
560 | struct pci_dev *tmp; | 644 | u64 devfns[4] = { 0 }; |
561 | 645 | ||
562 | /* | 646 | /* |
563 | * Find the upstream DMA alias for the device. A device must not | 647 | * Find the upstream DMA alias for the device. A device must not |
@@ -591,76 +675,21 @@ static struct iommu_group *iommu_group_get_for_pci_dev(struct pci_dev *pdev) | |||
591 | } | 675 | } |
592 | 676 | ||
593 | /* | 677 | /* |
594 | * Next we need to consider DMA alias quirks. If one device aliases | 678 | * Look for existing groups on device aliases. If we alias another |
595 | * to another, they should be grouped together. It's theoretically | 679 | * device or another device aliases us, use the same group. |
596 | * possible that aliases could create chains of devices where each | ||
597 | * device aliases another device. If we then factor in multifunction | ||
598 | * ACS grouping requirements, each alias could incorporate a new slot | ||
599 | * with multiple functions, each with aliases. This is all extremely | ||
600 | * unlikely as DMA alias quirks are typically only used for PCIe | ||
601 | * devices where we usually have a single slot per bus. Furthermore, | ||
602 | * the alias quirk is usually to another function within the slot | ||
603 | * (and ACS multifunction is not supported) or to a different slot | ||
604 | * that doesn't physically exist. The likely scenario is therefore | ||
605 | * that everything on the bus gets grouped together. To reduce the | ||
606 | * problem space, share the IOMMU group for all devices on the bus | ||
607 | * if a DMA alias quirk is present on the bus. | ||
608 | */ | ||
609 | tmp = NULL; | ||
610 | for_each_pci_dev(tmp) { | ||
611 | if (tmp->bus != pdev->bus || | ||
612 | !(tmp->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN)) | ||
613 | continue; | ||
614 | |||
615 | pci_dev_put(tmp); | ||
616 | tmp = NULL; | ||
617 | |||
618 | /* We have an alias quirk, search for an existing group */ | ||
619 | for_each_pci_dev(tmp) { | ||
620 | struct iommu_group *group_tmp; | ||
621 | |||
622 | if (tmp->bus != pdev->bus) | ||
623 | continue; | ||
624 | |||
625 | group_tmp = iommu_group_get(&tmp->dev); | ||
626 | if (!group) { | ||
627 | group = group_tmp; | ||
628 | continue; | ||
629 | } | ||
630 | |||
631 | if (group_tmp) { | ||
632 | WARN_ON(group != group_tmp); | ||
633 | iommu_group_put(group_tmp); | ||
634 | } | ||
635 | } | ||
636 | |||
637 | return group ? group : iommu_group_alloc(); | ||
638 | } | ||
639 | |||
640 | /* | ||
641 | * Non-multifunction devices or multifunction devices supporting | ||
642 | * ACS get their own group. | ||
643 | */ | 680 | */ |
644 | if (!pdev->multifunction || pci_acs_enabled(pdev, REQ_ACS_FLAGS)) | 681 | group = get_pci_alias_group(pdev, (unsigned long *)devfns); |
645 | return iommu_group_alloc(); | 682 | if (group) |
683 | return group; | ||
646 | 684 | ||
647 | /* | 685 | /* |
648 | * Multifunction devices not supporting ACS share a group with other | 686 | * Look for existing groups on non-isolated functions on the same |
649 | * similar devices in the same slot. | 687 | * slot and aliases of those funcions, if any. No need to clear |
688 | * the search bitmap, the tested devfns are still valid. | ||
650 | */ | 689 | */ |
651 | tmp = NULL; | 690 | group = get_pci_function_alias_group(pdev, (unsigned long *)devfns); |
652 | for_each_pci_dev(tmp) { | 691 | if (group) |
653 | if (tmp == pdev || tmp->bus != pdev->bus || | 692 | return group; |
654 | PCI_SLOT(tmp->devfn) != PCI_SLOT(pdev->devfn) || | ||
655 | pci_acs_enabled(tmp, REQ_ACS_FLAGS)) | ||
656 | continue; | ||
657 | |||
658 | group = iommu_group_get(&tmp->dev); | ||
659 | if (group) { | ||
660 | pci_dev_put(tmp); | ||
661 | return group; | ||
662 | } | ||
663 | } | ||
664 | 693 | ||
665 | /* No shared group found, allocate new */ | 694 | /* No shared group found, allocate new */ |
666 | return iommu_group_alloc(); | 695 | return iommu_group_alloc(); |