aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGary R Hook <gary.hook@amd.com>2017-12-20 11:47:08 -0500
committerAlex Williamson <alex.williamson@redhat.com>2017-12-20 11:47:08 -0500
commitff18c4e598de13af6503d6adb66f3ad768b6a53e (patch)
tree43b81ef7179015b5793c6ffefd936af281ac7b11
parentf9fc049ef1e05da3e3d2a45d098ec89b89bf687e (diff)
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>
-rw-r--r--drivers/iommu/amd_iommu.c20
-rw-r--r--drivers/iommu/amd_iommu_types.h2
2 files changed, 17 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)
1817 return domain->flags & PD_DMA_OPS_MASK; 1817 return domain->flags & PD_DMA_OPS_MASK;
1818} 1818}
1819 1819
1820static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats) 1820static void set_dte_entry(u16 devid, struct protection_domain *domain,
1821 bool ats, bool ppr)
1821{ 1822{
1822 u64 pte_root = 0; 1823 u64 pte_root = 0;
1823 u64 flags = 0; 1824 u64 flags = 0;
@@ -1834,6 +1835,13 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
1834 if (ats) 1835 if (ats)
1835 flags |= DTE_FLAG_IOTLB; 1836 flags |= DTE_FLAG_IOTLB;
1836 1837
1838 if (ppr) {
1839 struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
1840
1841 if (iommu_feature(iommu, FEATURE_EPHSUP))
1842 pte_root |= 1ULL << DEV_ENTRY_PPR;
1843 }
1844
1837 if (domain->flags & PD_IOMMUV2_MASK) { 1845 if (domain->flags & PD_IOMMUV2_MASK) {
1838 u64 gcr3 = iommu_virt_to_phys(domain->gcr3_tbl); 1846 u64 gcr3 = iommu_virt_to_phys(domain->gcr3_tbl);
1839 u64 glx = domain->glx; 1847 u64 glx = domain->glx;
@@ -1896,9 +1904,9 @@ static void do_attach(struct iommu_dev_data *dev_data,
1896 domain->dev_cnt += 1; 1904 domain->dev_cnt += 1;
1897 1905
1898 /* Update device table */ 1906 /* Update device table */
1899 set_dte_entry(dev_data->devid, domain, ats); 1907 set_dte_entry(dev_data->devid, domain, ats, dev_data->iommu_v2);
1900 if (alias != dev_data->devid) 1908 if (alias != dev_data->devid)
1901 set_dte_entry(alias, domain, ats); 1909 set_dte_entry(alias, domain, ats, dev_data->iommu_v2);
1902 1910
1903 device_flush_dte(dev_data); 1911 device_flush_dte(dev_data);
1904} 1912}
@@ -2277,13 +2285,15 @@ static void update_device_table(struct protection_domain *domain)
2277 struct iommu_dev_data *dev_data; 2285 struct iommu_dev_data *dev_data;
2278 2286
2279 list_for_each_entry(dev_data, &domain->dev_list, list) { 2287 list_for_each_entry(dev_data, &domain->dev_list, list) {
2280 set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled); 2288 set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled,
2289 dev_data->iommu_v2);
2281 2290
2282 if (dev_data->devid == dev_data->alias) 2291 if (dev_data->devid == dev_data->alias)
2283 continue; 2292 continue;
2284 2293
2285 /* There is an alias, update device table entry for it */ 2294 /* There is an alias, update device table entry for it */
2286 set_dte_entry(dev_data->alias, domain, dev_data->ats.enabled); 2295 set_dte_entry(dev_data->alias, domain, dev_data->ats.enabled,
2296 dev_data->iommu_v2);
2287 } 2297 }
2288} 2298}
2289 2299
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index f6b24c7d8b70..6a877ebd058b 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -98,6 +98,7 @@
98#define FEATURE_HE (1ULL<<8) 98#define FEATURE_HE (1ULL<<8)
99#define FEATURE_PC (1ULL<<9) 99#define FEATURE_PC (1ULL<<9)
100#define FEATURE_GAM_VAPIC (1ULL<<21) 100#define FEATURE_GAM_VAPIC (1ULL<<21)
101#define FEATURE_EPHSUP (1ULL<<50)
101 102
102#define FEATURE_PASID_SHIFT 32 103#define FEATURE_PASID_SHIFT 32
103#define FEATURE_PASID_MASK (0x1fULL << FEATURE_PASID_SHIFT) 104#define FEATURE_PASID_MASK (0x1fULL << FEATURE_PASID_SHIFT)
@@ -192,6 +193,7 @@
192/* macros and definitions for device table entries */ 193/* macros and definitions for device table entries */
193#define DEV_ENTRY_VALID 0x00 194#define DEV_ENTRY_VALID 0x00
194#define DEV_ENTRY_TRANSLATION 0x01 195#define DEV_ENTRY_TRANSLATION 0x01
196#define DEV_ENTRY_PPR 0x34
195#define DEV_ENTRY_IR 0x3d 197#define DEV_ENTRY_IR 0x3d
196#define DEV_ENTRY_IW 0x3e 198#define DEV_ENTRY_IW 0x3e
197#define DEV_ENTRY_NO_PAGE_FAULT 0x62 199#define DEV_ENTRY_NO_PAGE_FAULT 0x62