[RESEND PATCH v1 09/37] iommu/amd: Introduce per PCI segment unity map list

2022-04-04 Thread Vasant Hegde via iommu
Newer AMD systems can support multiple PCI segments. In order to support
multiple PCI segments IVMD table in IVRS structure is enhanced to
include pci segment id. Update ivmd_header structure to include "pci_seg".

Also introduce per PCI segment unity map list. It will replace global
amd_iommu_unity_map list.

Note that we have used "reserved" field in IVMD table to include "pci_seg
id" which was set to zero. It will take care of backward compatibility
(new kernel will work fine on older systems).

Co-developed-by: Suravee Suthikulpanit 
Signed-off-by: Suravee Suthikulpanit 
Signed-off-by: Vasant Hegde 
---
 drivers/iommu/amd/amd_iommu_types.h | 13 +++--
 drivers/iommu/amd/init.c| 30 +++--
 drivers/iommu/amd/iommu.c   |  8 +++-
 3 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/drivers/iommu/amd/amd_iommu_types.h 
b/drivers/iommu/amd/amd_iommu_types.h
index f9776f188e36..c4c9c35e2bf7 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -579,6 +579,13 @@ struct amd_iommu_pci_seg {
 * More than one device can share the same requestor id.
 */
u16 *alias_table;
+
+   /*
+* A list of required unity mappings we find in ACPI. It is not locked
+* because as runtime it is only read. It is created at ACPI table
+* parsing time.
+*/
+   struct list_head unity_map;
 };
 
 /*
@@ -805,12 +812,6 @@ struct unity_map_entry {
int prot;
 };
 
-/*
- * List of all unity mappings. It is not locked because as runtime it is only
- * read. It is created at ACPI table parsing time.
- */
-extern struct list_head amd_iommu_unity_map;
-
 /*
  * Data structures for device handling
  */
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index fe31de6e764c..d613e20ea013 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -142,7 +142,8 @@ struct ivmd_header {
u16 length;
u16 devid;
u16 aux;
-   u64 resv;
+   u16 pci_seg;
+   u8  resv[6];
u64 range_start;
u64 range_length;
 } __attribute__((packed));
@@ -162,8 +163,6 @@ static int amd_iommu_target_ivhd_type;
 
 u16 amd_iommu_last_bdf;/* largest PCI device id we have
   to handle */
-LIST_HEAD(amd_iommu_unity_map);/* a list of required unity 
mappings
-  we find in ACPI */
 
 LIST_HEAD(amd_iommu_pci_seg_list); /* list of all PCI segments */
 LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the
@@ -1562,6 +1561,7 @@ static struct amd_iommu_pci_seg *__init 
alloc_pci_segment(u16 id)
 
pci_seg->id = id;
init_llist_head(&pci_seg->dev_data_list);
+   INIT_LIST_HEAD(&pci_seg->unity_map);
list_add_tail(&pci_seg->list, &amd_iommu_pci_seg_list);
 
if (alloc_dev_table(pci_seg))
@@ -2397,10 +2397,13 @@ static int iommu_init_irq(struct amd_iommu *iommu)
 static void __init free_unity_maps(void)
 {
struct unity_map_entry *entry, *next;
+   struct amd_iommu_pci_seg *p, *pci_seg;
 
-   list_for_each_entry_safe(entry, next, &amd_iommu_unity_map, list) {
-   list_del(&entry->list);
-   kfree(entry);
+   for_each_pci_segment_safe(pci_seg, p) {
+   list_for_each_entry_safe(entry, next, &pci_seg->unity_map, 
list) {
+   list_del(&entry->list);
+   kfree(entry);
+   }
}
 }
 
@@ -2408,8 +2411,13 @@ static void __init free_unity_maps(void)
 static int __init init_unity_map_range(struct ivmd_header *m)
 {
struct unity_map_entry *e = NULL;
+   struct amd_iommu_pci_seg *pci_seg;
char *s;
 
+   pci_seg = get_pci_segment(m->pci_seg);
+   if (pci_seg == NULL)
+   return -ENOMEM;
+
e = kzalloc(sizeof(*e), GFP_KERNEL);
if (e == NULL)
return -ENOMEM;
@@ -2447,14 +2455,16 @@ static int __init init_unity_map_range(struct 
ivmd_header *m)
if (m->flags & IVMD_FLAG_EXCL_RANGE)
e->prot = (IVMD_FLAG_IW | IVMD_FLAG_IR) >> 1;
 
-   DUMP_printk("%s devid_start: %02x:%02x.%x devid_end: %02x:%02x.%x"
-   " range_start: %016llx range_end: %016llx flags: %x\n", s,
+   DUMP_printk("%s devid_start: %04x:%02x:%02x.%x devid_end: "
+   "%04x:%02x:%02x.%x range_start: %016llx range_end: %016llx"
+   " flags: %x\n", s, m->pci_seg,
PCI_BUS_NUM(e->devid_start), PCI_SLOT(e->devid_start),
-   PCI_FUNC(e->devid_start), PCI_BUS_NUM(e->devid_end),
+   PCI_FUNC(e->devid_start), m->pci_seg,
+   PCI_BUS_NUM(e->devid_end),
PCI_SLOT(e->devid_end), PCI_FUNC(e->devid_end),
e->address_start, e->address_end, m->flags);
 
-   list_add_tail(&e->li

[PATCH v1 09/37] iommu/amd: Introduce per PCI segment unity map list

2022-04-04 Thread Vasant Hegde via iommu
Newer AMD systems can support multiple PCI segments. In order to support
multiple PCI segments IVMD table in IVRS structure is enhanced to
include pci segment id. Update ivmd_header structure to include "pci_seg".

Also introduce per PCI segment unity map list. It will replace global
amd_iommu_unity_map list.

Note that we have used "reserved" field in IVMD table to include "pci_seg
id" which was set to zero. It will take care of backward compatibility
(new kernel will work fine on older systems).

Co-developed-by: Suravee Suthikulpanit 
Signed-off-by: Suravee Suthikulpanit 
Signed-off-by: Vasant Hegde 
---
 drivers/iommu/amd/amd_iommu_types.h | 13 +++--
 drivers/iommu/amd/init.c| 30 +++--
 drivers/iommu/amd/iommu.c   |  8 +++-
 3 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/drivers/iommu/amd/amd_iommu_types.h 
b/drivers/iommu/amd/amd_iommu_types.h
index f9776f188e36..c4c9c35e2bf7 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -579,6 +579,13 @@ struct amd_iommu_pci_seg {
 * More than one device can share the same requestor id.
 */
u16 *alias_table;
+
+   /*
+* A list of required unity mappings we find in ACPI. It is not locked
+* because as runtime it is only read. It is created at ACPI table
+* parsing time.
+*/
+   struct list_head unity_map;
 };
 
 /*
@@ -805,12 +812,6 @@ struct unity_map_entry {
int prot;
 };
 
-/*
- * List of all unity mappings. It is not locked because as runtime it is only
- * read. It is created at ACPI table parsing time.
- */
-extern struct list_head amd_iommu_unity_map;
-
 /*
  * Data structures for device handling
  */
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index fe31de6e764c..d613e20ea013 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -142,7 +142,8 @@ struct ivmd_header {
u16 length;
u16 devid;
u16 aux;
-   u64 resv;
+   u16 pci_seg;
+   u8  resv[6];
u64 range_start;
u64 range_length;
 } __attribute__((packed));
@@ -162,8 +163,6 @@ static int amd_iommu_target_ivhd_type;
 
 u16 amd_iommu_last_bdf;/* largest PCI device id we have
   to handle */
-LIST_HEAD(amd_iommu_unity_map);/* a list of required unity 
mappings
-  we find in ACPI */
 
 LIST_HEAD(amd_iommu_pci_seg_list); /* list of all PCI segments */
 LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the
@@ -1562,6 +1561,7 @@ static struct amd_iommu_pci_seg *__init 
alloc_pci_segment(u16 id)
 
pci_seg->id = id;
init_llist_head(&pci_seg->dev_data_list);
+   INIT_LIST_HEAD(&pci_seg->unity_map);
list_add_tail(&pci_seg->list, &amd_iommu_pci_seg_list);
 
if (alloc_dev_table(pci_seg))
@@ -2397,10 +2397,13 @@ static int iommu_init_irq(struct amd_iommu *iommu)
 static void __init free_unity_maps(void)
 {
struct unity_map_entry *entry, *next;
+   struct amd_iommu_pci_seg *p, *pci_seg;
 
-   list_for_each_entry_safe(entry, next, &amd_iommu_unity_map, list) {
-   list_del(&entry->list);
-   kfree(entry);
+   for_each_pci_segment_safe(pci_seg, p) {
+   list_for_each_entry_safe(entry, next, &pci_seg->unity_map, 
list) {
+   list_del(&entry->list);
+   kfree(entry);
+   }
}
 }
 
@@ -2408,8 +2411,13 @@ static void __init free_unity_maps(void)
 static int __init init_unity_map_range(struct ivmd_header *m)
 {
struct unity_map_entry *e = NULL;
+   struct amd_iommu_pci_seg *pci_seg;
char *s;
 
+   pci_seg = get_pci_segment(m->pci_seg);
+   if (pci_seg == NULL)
+   return -ENOMEM;
+
e = kzalloc(sizeof(*e), GFP_KERNEL);
if (e == NULL)
return -ENOMEM;
@@ -2447,14 +2455,16 @@ static int __init init_unity_map_range(struct 
ivmd_header *m)
if (m->flags & IVMD_FLAG_EXCL_RANGE)
e->prot = (IVMD_FLAG_IW | IVMD_FLAG_IR) >> 1;
 
-   DUMP_printk("%s devid_start: %02x:%02x.%x devid_end: %02x:%02x.%x"
-   " range_start: %016llx range_end: %016llx flags: %x\n", s,
+   DUMP_printk("%s devid_start: %04x:%02x:%02x.%x devid_end: "
+   "%04x:%02x:%02x.%x range_start: %016llx range_end: %016llx"
+   " flags: %x\n", s, m->pci_seg,
PCI_BUS_NUM(e->devid_start), PCI_SLOT(e->devid_start),
-   PCI_FUNC(e->devid_start), PCI_BUS_NUM(e->devid_end),
+   PCI_FUNC(e->devid_start), m->pci_seg,
+   PCI_BUS_NUM(e->devid_end),
PCI_SLOT(e->devid_end), PCI_FUNC(e->devid_end),
e->address_start, e->address_end, m->flags);
 
-   list_add_tail(&e->li