diff options
author | Gary R Hook <gary.hook@amd.com> | 2017-12-20 09:47:08 -0700 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2017-12-20 09:47:08 -0700 |
commit | ff18c4e598de13af6503d6adb66f3ad768b6a53e (patch) | |
tree | 43b81ef7179015b5793c6ffefd936af281ac7b11 /drivers/iommu/amd_iommu.c | |
parent | f9fc049ef1e05da3e3d2a45d098ec89b89bf687e (diff) | |
download | linux-ff18c4e598de13af6503d6adb66f3ad768b6a53e.tar.bz2 |
iommu/amd: Set the device table entry PPR bit for IOMMU V2 devices
The AMD IOMMU specification Rev 3.00 (December 2016) introduces a
new Enhanced PPR Handling Support (EPHSup) bit in the MMIO register
offset 0030h (IOMMU Extended Feature Register).
When EPHSup=1, the IOMMU hardware requires the PPR bit of the
device table entry (DTE) to be set in order to support PPR for a
particular endpoint device.
Please see https://support.amd.com/TechDocs/48882_IOMMU.pdf for
this revision of the AMD IOMMU specification.
Signed-off-by: Gary R Hook <gary.hook@amd.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Diffstat (limited to 'drivers/iommu/amd_iommu.c')
-rw-r--r-- | drivers/iommu/amd_iommu.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 6af7ae6eac5e..0c71442e331c 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -1817,7 +1817,8 @@ static bool dma_ops_domain(struct protection_domain *domain) return domain->flags & PD_DMA_OPS_MASK; } -static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats) +static void set_dte_entry(u16 devid, struct protection_domain *domain, + bool ats, bool ppr) { u64 pte_root = 0; u64 flags = 0; @@ -1834,6 +1835,13 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats) if (ats) flags |= DTE_FLAG_IOTLB; + if (ppr) { + struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; + + if (iommu_feature(iommu, FEATURE_EPHSUP)) + pte_root |= 1ULL << DEV_ENTRY_PPR; + } + if (domain->flags & PD_IOMMUV2_MASK) { u64 gcr3 = iommu_virt_to_phys(domain->gcr3_tbl); u64 glx = domain->glx; @@ -1896,9 +1904,9 @@ static void do_attach(struct iommu_dev_data *dev_data, domain->dev_cnt += 1; /* Update device table */ - set_dte_entry(dev_data->devid, domain, ats); + set_dte_entry(dev_data->devid, domain, ats, dev_data->iommu_v2); if (alias != dev_data->devid) - set_dte_entry(alias, domain, ats); + set_dte_entry(alias, domain, ats, dev_data->iommu_v2); device_flush_dte(dev_data); } @@ -2277,13 +2285,15 @@ static void update_device_table(struct protection_domain *domain) struct iommu_dev_data *dev_data; list_for_each_entry(dev_data, &domain->dev_list, list) { - set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled); + set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled, + dev_data->iommu_v2); if (dev_data->devid == dev_data->alias) continue; /* There is an alias, update device table entry for it */ - set_dte_entry(dev_data->alias, domain, dev_data->ats.enabled); + set_dte_entry(dev_data->alias, domain, dev_data->ats.enabled, + dev_data->iommu_v2); } } |