[RESEND PATCH v1 07/37] iommu/amd: Introduce per PCI segment old_dev_tbl_cpy

2022-04-04 Thread Vasant Hegde via iommu
From: Suravee Suthikulpanit 

It will remove global old_dev_tbl_cpy. Also update copy_device_table()
copy device table for all PCI segments.

Co-developed-by: Vasant Hegde 
Signed-off-by: Vasant Hegde 
Signed-off-by: Suravee Suthikulpanit 
---
 drivers/iommu/amd/amd_iommu_types.h |   6 ++
 drivers/iommu/amd/init.c| 109 
 2 files changed, 70 insertions(+), 45 deletions(-)

diff --git a/drivers/iommu/amd/amd_iommu_types.h 
b/drivers/iommu/amd/amd_iommu_types.h
index 7bf35e3a1ed6..330bb346207a 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -566,6 +566,12 @@ struct amd_iommu_pci_seg {
 * device id quickly.
 */
struct irq_remap_table **irq_lookup_table;
+
+   /*
+* Pointer to a device table which the content of old device table
+* will be copied to. It's only be used in kdump kernel.
+*/
+   struct dev_table_entry *old_dev_tbl_cpy;
 };
 
 /*
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 27785a558d9c..af413738da01 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -193,11 +193,6 @@ bool amd_iommu_force_isolation __read_mostly;
  * page table root pointer.
  */
 struct dev_table_entry *amd_iommu_dev_table;
-/*
- * Pointer to a device table which the content of old device table
- * will be copied to. It's only be used in kdump kernel.
- */
-static struct dev_table_entry *old_dev_tbl_cpy;
 
 /*
  * The alias table is a driver specific data structure which contains the
@@ -990,39 +985,27 @@ static int get_dev_entry_bit(u16 devid, u8 bit)
 }
 
 
-static bool copy_device_table(void)
+static bool __copy_device_table(struct amd_iommu *iommu)
 {
-   u64 int_ctl, int_tab_len, entry = 0, last_entry = 0;
+   u64 int_ctl, int_tab_len, entry = 0;
+   struct amd_iommu_pci_seg *pci_seg = iommu->pci_seg;
struct dev_table_entry *old_devtb = NULL;
u32 lo, hi, devid, old_devtb_size;
phys_addr_t old_devtb_phys;
-   struct amd_iommu *iommu;
u16 dom_id, dte_v, irq_v;
gfp_t gfp_flag;
u64 tmp;
 
-   if (!amd_iommu_pre_enabled)
-   return false;
-
-   pr_warn("Translation is already enabled - trying to copy translation 
structures\n");
-   for_each_iommu(iommu) {
-   /* All IOMMUs should use the same device table with the same 
size */
-   lo = readl(iommu->mmio_base + MMIO_DEV_TABLE_OFFSET);
-   hi = readl(iommu->mmio_base + MMIO_DEV_TABLE_OFFSET + 4);
-   entry = (((u64) hi) << 32) + lo;
-   if (last_entry && last_entry != entry) {
-   pr_err("IOMMU:%d should use the same dev table as 
others!\n",
-   iommu->index);
-   return false;
-   }
-   last_entry = entry;
+   /* Each IOMMU use separate device table with the same size */
+   lo = readl(iommu->mmio_base + MMIO_DEV_TABLE_OFFSET);
+   hi = readl(iommu->mmio_base + MMIO_DEV_TABLE_OFFSET + 4);
+   entry = (((u64) hi) << 32) + lo;
 
-   old_devtb_size = ((entry & ~PAGE_MASK) + 1) << 12;
-   if (old_devtb_size != dev_table_size) {
-   pr_err("The device table size of IOMMU:%d is not 
expected!\n",
-   iommu->index);
-   return false;
-   }
+   old_devtb_size = ((entry & ~PAGE_MASK) + 1) << 12;
+   if (old_devtb_size != dev_table_size) {
+   pr_err("The device table size of IOMMU:%d is not expected!\n",
+   iommu->index);
+   return false;
}
 
/*
@@ -1045,31 +1028,31 @@ static bool copy_device_table(void)
return false;
 
gfp_flag = GFP_KERNEL | __GFP_ZERO | GFP_DMA32;
-   old_dev_tbl_cpy = (void *)__get_free_pages(gfp_flag,
-   get_order(dev_table_size));
-   if (old_dev_tbl_cpy == NULL) {
+   pci_seg->old_dev_tbl_cpy = (void *)__get_free_pages(gfp_flag,
+   get_order(dev_table_size));
+   if (pci_seg->old_dev_tbl_cpy == NULL) {
pr_err("Failed to allocate memory for copying old device 
table!\n");
memunmap(old_devtb);
return false;
}
 
for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) {
-   old_dev_tbl_cpy[devid] = old_devtb[devid];
+   pci_seg->old_dev_tbl_cpy[devid] = old_devtb[devid];
dom_id = old_devtb[devid].data[1] & DEV_DOMID_MASK;
dte_v = old_devtb[devid].data[0] & DTE_FLAG_V;
 
if (dte_v && dom_id) {
-   old_dev_tbl_cpy[devid].data[0] = 
old_devtb[devid].data[0];
-   old_dev_tbl_cpy[devid].data[1] = 
old_devtb[devid].data[1];
+   

[PATCH v1 07/37] iommu/amd: Introduce per PCI segment old_dev_tbl_cpy

2022-04-04 Thread Vasant Hegde via iommu
From: Suravee Suthikulpanit 

It will remove global old_dev_tbl_cpy. Also update copy_device_table()
copy device table for all PCI segments.

Co-developed-by: Vasant Hegde 
Signed-off-by: Vasant Hegde 
Signed-off-by: Suravee Suthikulpanit 
---
 drivers/iommu/amd/amd_iommu_types.h |   6 ++
 drivers/iommu/amd/init.c| 109 
 2 files changed, 70 insertions(+), 45 deletions(-)

diff --git a/drivers/iommu/amd/amd_iommu_types.h 
b/drivers/iommu/amd/amd_iommu_types.h
index 7bf35e3a1ed6..330bb346207a 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -566,6 +566,12 @@ struct amd_iommu_pci_seg {
 * device id quickly.
 */
struct irq_remap_table **irq_lookup_table;
+
+   /*
+* Pointer to a device table which the content of old device table
+* will be copied to. It's only be used in kdump kernel.
+*/
+   struct dev_table_entry *old_dev_tbl_cpy;
 };
 
 /*
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 27785a558d9c..af413738da01 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -193,11 +193,6 @@ bool amd_iommu_force_isolation __read_mostly;
  * page table root pointer.
  */
 struct dev_table_entry *amd_iommu_dev_table;
-/*
- * Pointer to a device table which the content of old device table
- * will be copied to. It's only be used in kdump kernel.
- */
-static struct dev_table_entry *old_dev_tbl_cpy;
 
 /*
  * The alias table is a driver specific data structure which contains the
@@ -990,39 +985,27 @@ static int get_dev_entry_bit(u16 devid, u8 bit)
 }
 
 
-static bool copy_device_table(void)
+static bool __copy_device_table(struct amd_iommu *iommu)
 {
-   u64 int_ctl, int_tab_len, entry = 0, last_entry = 0;
+   u64 int_ctl, int_tab_len, entry = 0;
+   struct amd_iommu_pci_seg *pci_seg = iommu->pci_seg;
struct dev_table_entry *old_devtb = NULL;
u32 lo, hi, devid, old_devtb_size;
phys_addr_t old_devtb_phys;
-   struct amd_iommu *iommu;
u16 dom_id, dte_v, irq_v;
gfp_t gfp_flag;
u64 tmp;
 
-   if (!amd_iommu_pre_enabled)
-   return false;
-
-   pr_warn("Translation is already enabled - trying to copy translation 
structures\n");
-   for_each_iommu(iommu) {
-   /* All IOMMUs should use the same device table with the same 
size */
-   lo = readl(iommu->mmio_base + MMIO_DEV_TABLE_OFFSET);
-   hi = readl(iommu->mmio_base + MMIO_DEV_TABLE_OFFSET + 4);
-   entry = (((u64) hi) << 32) + lo;
-   if (last_entry && last_entry != entry) {
-   pr_err("IOMMU:%d should use the same dev table as 
others!\n",
-   iommu->index);
-   return false;
-   }
-   last_entry = entry;
+   /* Each IOMMU use separate device table with the same size */
+   lo = readl(iommu->mmio_base + MMIO_DEV_TABLE_OFFSET);
+   hi = readl(iommu->mmio_base + MMIO_DEV_TABLE_OFFSET + 4);
+   entry = (((u64) hi) << 32) + lo;
 
-   old_devtb_size = ((entry & ~PAGE_MASK) + 1) << 12;
-   if (old_devtb_size != dev_table_size) {
-   pr_err("The device table size of IOMMU:%d is not 
expected!\n",
-   iommu->index);
-   return false;
-   }
+   old_devtb_size = ((entry & ~PAGE_MASK) + 1) << 12;
+   if (old_devtb_size != dev_table_size) {
+   pr_err("The device table size of IOMMU:%d is not expected!\n",
+   iommu->index);
+   return false;
}
 
/*
@@ -1045,31 +1028,31 @@ static bool copy_device_table(void)
return false;
 
gfp_flag = GFP_KERNEL | __GFP_ZERO | GFP_DMA32;
-   old_dev_tbl_cpy = (void *)__get_free_pages(gfp_flag,
-   get_order(dev_table_size));
-   if (old_dev_tbl_cpy == NULL) {
+   pci_seg->old_dev_tbl_cpy = (void *)__get_free_pages(gfp_flag,
+   get_order(dev_table_size));
+   if (pci_seg->old_dev_tbl_cpy == NULL) {
pr_err("Failed to allocate memory for copying old device 
table!\n");
memunmap(old_devtb);
return false;
}
 
for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) {
-   old_dev_tbl_cpy[devid] = old_devtb[devid];
+   pci_seg->old_dev_tbl_cpy[devid] = old_devtb[devid];
dom_id = old_devtb[devid].data[1] & DEV_DOMID_MASK;
dte_v = old_devtb[devid].data[0] & DTE_FLAG_V;
 
if (dte_v && dom_id) {
-   old_dev_tbl_cpy[devid].data[0] = 
old_devtb[devid].data[0];
-   old_dev_tbl_cpy[devid].data[1] = 
old_devtb[devid].data[1];
+