diff options
| -rw-r--r-- | drivers/iommu/intel-iommu.c | 49 |
1 files changed, 39 insertions, 10 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 58cc2b75d7ae..d1f5caad04f9 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
| @@ -2543,22 +2543,46 @@ static bool device_has_rmrr(struct device *dev) | |||
| 2543 | return false; | 2543 | return false; |
| 2544 | } | 2544 | } |
| 2545 | 2545 | ||
| 2546 | /* | ||
| 2547 | * There are a couple cases where we need to restrict the functionality of | ||
| 2548 | * devices associated with RMRRs. The first is when evaluating a device for | ||
| 2549 | * identity mapping because problems exist when devices are moved in and out | ||
| 2550 | * of domains and their respective RMRR information is lost. This means that | ||
| 2551 | * a device with associated RMRRs will never be in a "passthrough" domain. | ||
| 2552 | * The second is use of the device through the IOMMU API. This interface | ||
| 2553 | * expects to have full control of the IOVA space for the device. We cannot | ||
| 2554 | * satisfy both the requirement that RMRR access is maintained and have an | ||
| 2555 | * unencumbered IOVA space. We also have no ability to quiesce the device's | ||
| 2556 | * use of the RMRR space or even inform the IOMMU API user of the restriction. | ||
| 2557 | * We therefore prevent devices associated with an RMRR from participating in | ||
| 2558 | * the IOMMU API, which eliminates them from device assignment. | ||
| 2559 | * | ||
| 2560 | * In both cases we assume that PCI USB devices with RMRRs have them largely | ||
| 2561 | * for historical reasons and that the RMRR space is not actively used post | ||
| 2562 | * boot. This exclusion may change if vendors begin to abuse it. | ||
| 2563 | */ | ||
| 2564 | static bool device_is_rmrr_locked(struct device *dev) | ||
| 2565 | { | ||
| 2566 | if (!device_has_rmrr(dev)) | ||
| 2567 | return false; | ||
| 2568 | |||
| 2569 | if (dev_is_pci(dev)) { | ||
| 2570 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 2571 | |||
| 2572 | if ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB) | ||
| 2573 | return false; | ||
| 2574 | } | ||
| 2575 | |||
| 2576 | return true; | ||
| 2577 | } | ||
| 2578 | |||
| 2546 | static int iommu_should_identity_map(struct device *dev, int startup) | 2579 | static int iommu_should_identity_map(struct device *dev, int startup) |
| 2547 | { | 2580 | { |
| 2548 | 2581 | ||
| 2549 | if (dev_is_pci(dev)) { | 2582 | if (dev_is_pci(dev)) { |
| 2550 | struct pci_dev *pdev = to_pci_dev(dev); | 2583 | struct pci_dev *pdev = to_pci_dev(dev); |
| 2551 | 2584 | ||
| 2552 | /* | 2585 | if (device_is_rmrr_locked(dev)) |
| 2553 | * We want to prevent any device associated with an RMRR from | ||
| 2554 | * getting placed into the SI Domain. This is done because | ||
| 2555 | * problems exist when devices are moved in and out of domains | ||
| 2556 | * and their respective RMRR info is lost. We exempt USB devices | ||
| 2557 | * from this process due to their usage of RMRRs that are known | ||
| 2558 | * to not be needed after BIOS hand-off to OS. | ||
| 2559 | */ | ||
| 2560 | if (device_has_rmrr(dev) && | ||
| 2561 | (pdev->class >> 8) != PCI_CLASS_SERIAL_USB) | ||
| 2562 | return 0; | 2586 | return 0; |
| 2563 | 2587 | ||
| 2564 | if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev)) | 2588 | if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev)) |
| @@ -4221,6 +4245,11 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, | |||
| 4221 | int addr_width; | 4245 | int addr_width; |
| 4222 | u8 bus, devfn; | 4246 | u8 bus, devfn; |
| 4223 | 4247 | ||
| 4248 | if (device_is_rmrr_locked(dev)) { | ||
| 4249 | dev_warn(dev, "Device is ineligible for IOMMU domain attach due to platform RMRR requirement. Contact your platform vendor.\n"); | ||
| 4250 | return -EPERM; | ||
| 4251 | } | ||
| 4252 | |||
| 4224 | /* normally dev is not mapped */ | 4253 | /* normally dev is not mapped */ |
| 4225 | if (unlikely(domain_context_mapped(dev))) { | 4254 | if (unlikely(domain_context_mapped(dev))) { |
| 4226 | struct dmar_domain *old_domain; | 4255 | struct dmar_domain *old_domain; |
