diff options
author | Gary R Hook <gary.hook@amd.com> | 2017-12-20 11:47:08 -0500 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2017-12-20 11:47:08 -0500 |
commit | ff18c4e598de13af6503d6adb66f3ad768b6a53e (patch) | |
tree | 43b81ef7179015b5793c6ffefd936af281ac7b11 | |
parent | f9fc049ef1e05da3e3d2a45d098ec89b89bf687e (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.c | 20 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_types.h | 2 |
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 | ||
1820 | static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats) | 1820 | static 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 |