|
@@ -2543,22 +2543,46 @@ static bool device_has_rmrr(struct device *dev)
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * There are a couple cases where we need to restrict the functionality of
|
|
|
|
+ * devices associated with RMRRs. The first is when evaluating a device for
|
|
|
|
+ * identity mapping because problems exist when devices are moved in and out
|
|
|
|
+ * of domains and their respective RMRR information is lost. This means that
|
|
|
|
+ * a device with associated RMRRs will never be in a "passthrough" domain.
|
|
|
|
+ * The second is use of the device through the IOMMU API. This interface
|
|
|
|
+ * expects to have full control of the IOVA space for the device. We cannot
|
|
|
|
+ * satisfy both the requirement that RMRR access is maintained and have an
|
|
|
|
+ * unencumbered IOVA space. We also have no ability to quiesce the device's
|
|
|
|
+ * use of the RMRR space or even inform the IOMMU API user of the restriction.
|
|
|
|
+ * We therefore prevent devices associated with an RMRR from participating in
|
|
|
|
+ * the IOMMU API, which eliminates them from device assignment.
|
|
|
|
+ *
|
|
|
|
+ * In both cases we assume that PCI USB devices with RMRRs have them largely
|
|
|
|
+ * for historical reasons and that the RMRR space is not actively used post
|
|
|
|
+ * boot. This exclusion may change if vendors begin to abuse it.
|
|
|
|
+ */
|
|
|
|
+static bool device_is_rmrr_locked(struct device *dev)
|
|
|
|
+{
|
|
|
|
+ if (!device_has_rmrr(dev))
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ if (dev_is_pci(dev)) {
|
|
|
|
+ struct pci_dev *pdev = to_pci_dev(dev);
|
|
|
|
+
|
|
|
|
+ if ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
static int iommu_should_identity_map(struct device *dev, int startup)
|
|
static int iommu_should_identity_map(struct device *dev, int startup)
|
|
{
|
|
{
|
|
|
|
|
|
if (dev_is_pci(dev)) {
|
|
if (dev_is_pci(dev)) {
|
|
struct pci_dev *pdev = to_pci_dev(dev);
|
|
struct pci_dev *pdev = to_pci_dev(dev);
|
|
|
|
|
|
- /*
|
|
|
|
- * We want to prevent any device associated with an RMRR from
|
|
|
|
- * getting placed into the SI Domain. This is done because
|
|
|
|
- * problems exist when devices are moved in and out of domains
|
|
|
|
- * and their respective RMRR info is lost. We exempt USB devices
|
|
|
|
- * from this process due to their usage of RMRRs that are known
|
|
|
|
- * to not be needed after BIOS hand-off to OS.
|
|
|
|
- */
|
|
|
|
- if (device_has_rmrr(dev) &&
|
|
|
|
- (pdev->class >> 8) != PCI_CLASS_SERIAL_USB)
|
|
|
|
|
|
+ if (device_is_rmrr_locked(dev))
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
|
|
if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
|
|
@@ -4221,6 +4245,11 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
|
|
int addr_width;
|
|
int addr_width;
|
|
u8 bus, devfn;
|
|
u8 bus, devfn;
|
|
|
|
|
|
|
|
+ if (device_is_rmrr_locked(dev)) {
|
|
|
|
+ dev_warn(dev, "Device is ineligible for IOMMU domain attach due to platform RMRR requirement. Contact your platform vendor.\n");
|
|
|
|
+ return -EPERM;
|
|
|
|
+ }
|
|
|
|
+
|
|
/* normally dev is not mapped */
|
|
/* normally dev is not mapped */
|
|
if (unlikely(domain_context_mapped(dev))) {
|
|
if (unlikely(domain_context_mapped(dev))) {
|
|
struct dmar_domain *old_domain;
|
|
struct dmar_domain *old_domain;
|