[RESEND PATCH v1 08/37] iommu/amd: Introduce per PCI segment alias_table

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

This will replace global alias table (amd_iommu_alias_table).

Co-developed-by: Vasant Hegde 
Signed-off-by: Vasant Hegde 
Signed-off-by: Suravee Suthikulpanit 
---
 drivers/iommu/amd/amd_iommu_types.h |  7 +
 drivers/iommu/amd/init.c| 41 ++---
 drivers/iommu/amd/iommu.c   | 41 ++---
 3 files changed, 64 insertions(+), 25 deletions(-)

diff --git a/drivers/iommu/amd/amd_iommu_types.h 
b/drivers/iommu/amd/amd_iommu_types.h
index 330bb346207a..f9776f188e36 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -572,6 +572,13 @@ struct amd_iommu_pci_seg {
 * will be copied to. It's only be used in kdump kernel.
 */
struct dev_table_entry *old_dev_tbl_cpy;
+
+   /*
+* The alias table is a driver specific data structure which contains 
the
+* mappings of the PCI device ids to the actual requestor ids on the 
IOMMU.
+* More than one device can share the same requestor id.
+*/
+   u16 *alias_table;
 };
 
 /*
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index af413738da01..fe31de6e764c 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -698,6 +698,31 @@ static inline void free_irq_lookup_table(struct 
amd_iommu_pci_seg *pci_seg)
pci_seg->irq_lookup_table = NULL;
 }
 
+static int __init alloc_alias_table(struct amd_iommu_pci_seg *pci_seg)
+{
+   int i;
+
+   pci_seg->alias_table = (void *)__get_free_pages(GFP_KERNEL,
+   
get_order(alias_table_size));
+   if (!pci_seg->alias_table)
+   return -ENOMEM;
+
+   /*
+* let all alias entries point to itself
+*/
+   for (i = 0; i <= amd_iommu_last_bdf; ++i)
+   pci_seg->alias_table[i] = i;
+
+   return 0;
+}
+
+static void __init free_alias_table(struct amd_iommu_pci_seg *pci_seg)
+{
+   free_pages((unsigned long)pci_seg->alias_table,
+  get_order(alias_table_size));
+   pci_seg->alias_table = NULL;
+}
+
 /*
  * Allocates the command buffer. This buffer is per AMD IOMMU. We can
  * write commands to that buffer later and the IOMMU will execute them
@@ -1266,6 +1291,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu 
*iommu,
u32 dev_i, ext_flags = 0;
bool alias = false;
struct ivhd_entry *e;
+   struct amd_iommu_pci_seg *pci_seg = iommu->pci_seg;
u32 ivhd_size;
int ret;
 
@@ -1347,7 +1373,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu 
*iommu,
devid_to = e->ext >> 8;
set_dev_entry_from_acpi(iommu, devid   , e->flags, 0);
set_dev_entry_from_acpi(iommu, devid_to, e->flags, 0);
-   amd_iommu_alias_table[devid] = devid_to;
+   pci_seg->alias_table[devid] = devid_to;
break;
case IVHD_DEV_ALIAS_RANGE:
 
@@ -1405,7 +1431,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu 
*iommu,
devid = e->devid;
for (dev_i = devid_start; dev_i <= devid; ++dev_i) {
if (alias) {
-   amd_iommu_alias_table[dev_i] = devid_to;
+   pci_seg->alias_table[dev_i] = devid_to;
set_dev_entry_from_acpi(iommu,
devid_to, flags, ext_flags);
}
@@ -1540,6 +1566,8 @@ static struct amd_iommu_pci_seg *__init 
alloc_pci_segment(u16 id)
 
if (alloc_dev_table(pci_seg))
return NULL;
+   if (alloc_alias_table(pci_seg))
+   return NULL;
if (alloc_rlookup_table(pci_seg))
return NULL;
 
@@ -1566,6 +1594,7 @@ static void __init free_pci_segment(void)
list_del(_seg->list);
free_irq_lookup_table(pci_seg);
free_rlookup_table(pci_seg);
+   free_alias_table(pci_seg);
free_dev_table(pci_seg);
kfree(pci_seg);
}
@@ -2838,7 +2867,7 @@ static void __init ivinfo_init(void *ivrs)
 static int __init early_amd_iommu_init(void)
 {
struct acpi_table_header *ivrs_base;
-   int i, remap_cache_sz, ret;
+   int remap_cache_sz, ret;
acpi_status status;
 
if (!amd_iommu_detected)
@@ -2909,12 +2938,6 @@ static int __init early_amd_iommu_init(void)
if (amd_iommu_pd_alloc_bitmap == NULL)
goto out;
 
-   /*
-* let all alias entries point to itself
-*/
-   for (i = 0; i <= amd_iommu_last_bdf; ++i)
-   amd_iommu_alias_table[i] = i;
-
/*
 * never allocate domain 0 because its used as the non-allocated and

[PATCH v1 08/37] iommu/amd: Introduce per PCI segment alias_table

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

This will replace global alias table (amd_iommu_alias_table).

Co-developed-by: Vasant Hegde 
Signed-off-by: Vasant Hegde 
Signed-off-by: Suravee Suthikulpanit 
---
 drivers/iommu/amd/amd_iommu_types.h |  7 +
 drivers/iommu/amd/init.c| 41 ++---
 drivers/iommu/amd/iommu.c   | 41 ++---
 3 files changed, 64 insertions(+), 25 deletions(-)

diff --git a/drivers/iommu/amd/amd_iommu_types.h 
b/drivers/iommu/amd/amd_iommu_types.h
index 330bb346207a..f9776f188e36 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -572,6 +572,13 @@ struct amd_iommu_pci_seg {
 * will be copied to. It's only be used in kdump kernel.
 */
struct dev_table_entry *old_dev_tbl_cpy;
+
+   /*
+* The alias table is a driver specific data structure which contains 
the
+* mappings of the PCI device ids to the actual requestor ids on the 
IOMMU.
+* More than one device can share the same requestor id.
+*/
+   u16 *alias_table;
 };
 
 /*
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index af413738da01..fe31de6e764c 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -698,6 +698,31 @@ static inline void free_irq_lookup_table(struct 
amd_iommu_pci_seg *pci_seg)
pci_seg->irq_lookup_table = NULL;
 }
 
+static int __init alloc_alias_table(struct amd_iommu_pci_seg *pci_seg)
+{
+   int i;
+
+   pci_seg->alias_table = (void *)__get_free_pages(GFP_KERNEL,
+   
get_order(alias_table_size));
+   if (!pci_seg->alias_table)
+   return -ENOMEM;
+
+   /*
+* let all alias entries point to itself
+*/
+   for (i = 0; i <= amd_iommu_last_bdf; ++i)
+   pci_seg->alias_table[i] = i;
+
+   return 0;
+}
+
+static void __init free_alias_table(struct amd_iommu_pci_seg *pci_seg)
+{
+   free_pages((unsigned long)pci_seg->alias_table,
+  get_order(alias_table_size));
+   pci_seg->alias_table = NULL;
+}
+
 /*
  * Allocates the command buffer. This buffer is per AMD IOMMU. We can
  * write commands to that buffer later and the IOMMU will execute them
@@ -1266,6 +1291,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu 
*iommu,
u32 dev_i, ext_flags = 0;
bool alias = false;
struct ivhd_entry *e;
+   struct amd_iommu_pci_seg *pci_seg = iommu->pci_seg;
u32 ivhd_size;
int ret;
 
@@ -1347,7 +1373,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu 
*iommu,
devid_to = e->ext >> 8;
set_dev_entry_from_acpi(iommu, devid   , e->flags, 0);
set_dev_entry_from_acpi(iommu, devid_to, e->flags, 0);
-   amd_iommu_alias_table[devid] = devid_to;
+   pci_seg->alias_table[devid] = devid_to;
break;
case IVHD_DEV_ALIAS_RANGE:
 
@@ -1405,7 +1431,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu 
*iommu,
devid = e->devid;
for (dev_i = devid_start; dev_i <= devid; ++dev_i) {
if (alias) {
-   amd_iommu_alias_table[dev_i] = devid_to;
+   pci_seg->alias_table[dev_i] = devid_to;
set_dev_entry_from_acpi(iommu,
devid_to, flags, ext_flags);
}
@@ -1540,6 +1566,8 @@ static struct amd_iommu_pci_seg *__init 
alloc_pci_segment(u16 id)
 
if (alloc_dev_table(pci_seg))
return NULL;
+   if (alloc_alias_table(pci_seg))
+   return NULL;
if (alloc_rlookup_table(pci_seg))
return NULL;
 
@@ -1566,6 +1594,7 @@ static void __init free_pci_segment(void)
list_del(_seg->list);
free_irq_lookup_table(pci_seg);
free_rlookup_table(pci_seg);
+   free_alias_table(pci_seg);
free_dev_table(pci_seg);
kfree(pci_seg);
}
@@ -2838,7 +2867,7 @@ static void __init ivinfo_init(void *ivrs)
 static int __init early_amd_iommu_init(void)
 {
struct acpi_table_header *ivrs_base;
-   int i, remap_cache_sz, ret;
+   int remap_cache_sz, ret;
acpi_status status;
 
if (!amd_iommu_detected)
@@ -2909,12 +2938,6 @@ static int __init early_amd_iommu_init(void)
if (amd_iommu_pd_alloc_bitmap == NULL)
goto out;
 
-   /*
-* let all alias entries point to itself
-*/
-   for (i = 0; i <= amd_iommu_last_bdf; ++i)
-   amd_iommu_alias_table[i] = i;
-
/*
 * never allocate domain 0 because its used as the non-allocated and