Skip to content

Commit

Permalink
iommu/vt-d: Exclude devices using RMRRs from IOMMU API domains
Browse files Browse the repository at this point in the history
The user of the IOMMU API domain expects to have full control of
the IOVA space for the domain.  RMRRs are fundamentally incompatible
with that idea.  We can neither map the RMRR into the IOMMU API
domain, nor can we guarantee that the device won't continue DMA with
the area described by the RMRR as part of the new domain.  Therefore
we must prevent such devices from being used by the IOMMU API.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: stable@vger.kernel.org
Signed-off-by: Joerg Roedel <jroedel@suse.de>
  • Loading branch information
Alex Williamson authored and Joerg Roedel committed Jul 29, 2014
1 parent 161f693 commit c875d2c
Showing 1 changed file with 39 additions and 10 deletions.
49 changes: 39 additions & 10 deletions drivers/iommu/intel-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2543,22 +2543,46 @@ static bool device_has_rmrr(struct device *dev)
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)
{

if (dev_is_pci(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;

if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
Expand Down Expand Up @@ -4221,6 +4245,11 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
int addr_width;
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 */
if (unlikely(domain_context_mapped(dev))) {
struct dmar_domain *old_domain;
Expand Down

0 comments on commit c875d2c

Please sign in to comment.