Re: [PATCH] iommu/amd - Set the device table entry PPR bit for IOMMU V2 devices

2017-12-20 Thread Gary R Hook

Please ignore; sent to the wrong list. Mea culpa.

On 12/20/2017 10:57 AM, Gary R Hook wrote:

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 
---
  drivers/iommu/amd_iommu.c   |   20 +++-
  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 cb78933ef53f..5f3da95ff6a0 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1818,7 +1818,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;
@@ -1835,6 +1836,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;
@@ -1897,9 +1905,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);

  }
@@ -2278,13 +2286,15 @@ static void update_device_table(struct 
protection_domain *domain)
struct iommu_dev_data *dev_data;
  
  	list_for_each_entry(dev_data, >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);
}
  }
  
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 @@
  #define FEATURE_HE(1ULL<<8)
  #define FEATURE_PC(1ULL<<9)
  #define FEATURE_GAM_VAPIC (1ULL<<21)
+#define FEATURE_EPHSUP (1ULL<<50)
  
  #define FEATURE_PASID_SHIFT	32

  #define FEATURE_PASID_MASK(0x1fULL << FEATURE_PASID_SHIFT)
@@ -192,6 +193,7 @@
  /* macros and definitions for device table entries */
  #define DEV_ENTRY_VALID 0x00
  #define DEV_ENTRY_TRANSLATION   0x01
+#define DEV_ENTRY_PPR   0x34
  #define DEV_ENTRY_IR0x3d
  #define DEV_ENTRY_IW0x3e
  #define DEV_ENTRY_NO_PAGE_FAULT   0x62





[PATCH] iommu/amd - Set the device table entry PPR bit for IOMMU V2 devices

2017-12-20 Thread Gary R Hook
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 
---
 drivers/iommu/amd_iommu.c   |   20 +++-
 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 cb78933ef53f..5f3da95ff6a0 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1818,7 +1818,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;
@@ -1835,6 +1836,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;
@@ -1897,9 +1905,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);
 }
@@ -2278,13 +2286,15 @@ static void update_device_table(struct 
protection_domain *domain)
struct iommu_dev_data *dev_data;
 
list_for_each_entry(dev_data, >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);
}
 }
 
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 @@
 #define FEATURE_HE (1ULL<<8)
 #define FEATURE_PC (1ULL<<9)
 #define FEATURE_GAM_VAPIC  (1ULL<<21)
+#define FEATURE_EPHSUP (1ULL<<50)
 
 #define FEATURE_PASID_SHIFT32
 #define FEATURE_PASID_MASK (0x1fULL << FEATURE_PASID_SHIFT)
@@ -192,6 +193,7 @@
 /* macros and definitions for device table entries */
 #define DEV_ENTRY_VALID 0x00
 #define DEV_ENTRY_TRANSLATION   0x01
+#define DEV_ENTRY_PPR   0x34
 #define DEV_ENTRY_IR0x3d
 #define DEV_ENTRY_IW0x3e
 #define DEV_ENTRY_NO_PAGE_FAULT0x62