* [PATCH v2 1/2] iommu/amd: Allocate page table using numa locality info
2023-03-21 9:23 [PATCH v2 0/2] Allocate IOMMU irq/page table using numa locality info Vasant Hegde
@ 2023-03-21 9:23 ` Vasant Hegde
2023-03-21 9:23 ` [PATCH v2 2/2] iommu/amd: Allocate IOMMU irqs " Vasant Hegde
2023-03-22 14:44 ` [PATCH v2 0/2] Allocate IOMMU irq/page table " Joerg Roedel
2 siblings, 0 replies; 4+ messages in thread
From: Vasant Hegde @ 2023-03-21 9:23 UTC (permalink / raw)
To: iommu, joro; +Cc: suravee.suthikulpanit, aik, baolu.lu, Vasant Hegde
Introduce 'struct protection_domain->nid' variable. It will contain
IOMMU NUMA node ID. And allocate page table pages using IOMMU numa
locality info. This optimizes page table walk by IOMMU.
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
---
drivers/iommu/amd/amd_iommu.h | 8 ++++++++
drivers/iommu/amd/amd_iommu_types.h | 1 +
drivers/iommu/amd/io_pgtable.c | 4 ++--
drivers/iommu/amd/io_pgtable_v2.c | 16 ++++++----------
drivers/iommu/amd/iommu.c | 6 ++++++
5 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
index c160a332ce33..20a142b54498 100644
--- a/drivers/iommu/amd/amd_iommu.h
+++ b/drivers/iommu/amd/amd_iommu.h
@@ -122,6 +122,14 @@ static inline int get_pci_sbdf_id(struct pci_dev *pdev)
return PCI_SEG_DEVID_TO_SBDF(seg, devid);
}
+static inline void *alloc_pgtable_page(int nid, gfp_t gfp)
+{
+ struct page *page;
+
+ page = alloc_pages_node(nid, gfp | __GFP_ZERO, 0);
+ return page ? page_address(page) : NULL;
+}
+
extern bool translation_pre_enabled(struct amd_iommu *iommu);
extern bool amd_iommu_is_attach_deferred(struct device *dev);
extern int __init add_special_device(u8 type, u8 id, u32 *devid,
diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h
index 3d684190b4d5..e5cfdeaaad48 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -549,6 +549,7 @@ struct protection_domain {
spinlock_t lock; /* mostly used to lock the page table*/
u16 id; /* the domain id written to the device table */
int glx; /* Number of levels for GCR3 table */
+ int nid; /* Node ID */
u64 *gcr3_tbl; /* Guest CR3 table */
unsigned long flags; /* flags to find out type of domain */
unsigned dev_cnt; /* devices assigned to this domain */
diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c
index ace0e9b8b913..1b67116882be 100644
--- a/drivers/iommu/amd/io_pgtable.c
+++ b/drivers/iommu/amd/io_pgtable.c
@@ -156,7 +156,7 @@ static bool increase_address_space(struct protection_domain *domain,
bool ret = true;
u64 *pte;
- pte = (void *)get_zeroed_page(gfp);
+ pte = alloc_pgtable_page(domain->nid, gfp);
if (!pte)
return false;
@@ -250,7 +250,7 @@ static u64 *alloc_pte(struct protection_domain *domain,
if (!IOMMU_PTE_PRESENT(__pte) ||
pte_level == PAGE_MODE_NONE) {
- page = (u64 *)get_zeroed_page(gfp);
+ page = alloc_pgtable_page(domain->nid, gfp);
if (!page)
return NULL;
diff --git a/drivers/iommu/amd/io_pgtable_v2.c b/drivers/iommu/amd/io_pgtable_v2.c
index 8638ddf6fb3b..9f8b423f7630 100644
--- a/drivers/iommu/amd/io_pgtable_v2.c
+++ b/drivers/iommu/amd/io_pgtable_v2.c
@@ -46,11 +46,6 @@ static inline bool is_large_pte(u64 pte)
return (pte & IOMMU_PAGE_PSE);
}
-static inline void *alloc_pgtable_page(void)
-{
- return (void *)get_zeroed_page(GFP_KERNEL);
-}
-
static inline u64 set_pgtable_attr(u64 *page)
{
u64 prot;
@@ -138,8 +133,8 @@ static void free_pgtable(u64 *pt, int level)
}
/* Allocate page table */
-static u64 *v2_alloc_pte(u64 *pgd, unsigned long iova,
- unsigned long pg_size, bool *updated)
+static u64 *v2_alloc_pte(int nid, u64 *pgd, unsigned long iova,
+ unsigned long pg_size, gfp_t gfp, bool *updated)
{
u64 *pte, *page;
int level, end_level;
@@ -162,7 +157,7 @@ static u64 *v2_alloc_pte(u64 *pgd, unsigned long iova,
}
if (!IOMMU_PTE_PRESENT(__pte)) {
- page = alloc_pgtable_page();
+ page = alloc_pgtable_page(nid, gfp);
if (!page)
return NULL;
@@ -262,7 +257,8 @@ static int iommu_v2_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
while (mapped_size < size) {
map_size = get_alloc_page_size(pgsize);
- pte = v2_alloc_pte(pdom->iop.pgd, iova, map_size, &updated);
+ pte = v2_alloc_pte(pdom->nid, pdom->iop.pgd,
+ iova, map_size, gfp, &updated);
if (!pte) {
ret = -EINVAL;
goto out;
@@ -384,7 +380,7 @@ static struct io_pgtable *v2_alloc_pgtable(struct io_pgtable_cfg *cfg, void *coo
struct protection_domain *pdom = (struct protection_domain *)cookie;
int ret;
- pgtable->pgd = alloc_pgtable_page();
+ pgtable->pgd = alloc_pgtable_page(pdom->nid, GFP_ATOMIC);
if (!pgtable->pgd)
return NULL;
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 5a505ba5467e..5452d0dd6569 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -1662,6 +1662,10 @@ static void do_attach(struct iommu_dev_data *dev_data,
dev_data->domain = domain;
list_add(&dev_data->list, &domain->dev_list);
+ /* Update NUMA Node ID */
+ if (domain->nid == NUMA_NO_NODE)
+ domain->nid = dev_to_node(dev_data->dev);
+
/* Do reference counting */
domain->dev_iommu[iommu->index] += 1;
domain->dev_cnt += 1;
@@ -2097,6 +2101,8 @@ static struct protection_domain *protection_domain_alloc(unsigned int type)
if (type == IOMMU_DOMAIN_IDENTITY)
return domain;
+ domain->nid = NUMA_NO_NODE;
+
pgtbl_ops = alloc_io_pgtable_ops(pgtable, &domain->iop.pgtbl_cfg, domain);
if (!pgtbl_ops) {
domain_id_free(domain->id);
--
2.31.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH v2 2/2] iommu/amd: Allocate IOMMU irqs using numa locality info
2023-03-21 9:23 [PATCH v2 0/2] Allocate IOMMU irq/page table using numa locality info Vasant Hegde
2023-03-21 9:23 ` [PATCH v2 1/2] iommu/amd: Allocate page " Vasant Hegde
@ 2023-03-21 9:23 ` Vasant Hegde
2023-03-22 14:44 ` [PATCH v2 0/2] Allocate IOMMU irq/page table " Joerg Roedel
2 siblings, 0 replies; 4+ messages in thread
From: Vasant Hegde @ 2023-03-21 9:23 UTC (permalink / raw)
To: iommu, joro; +Cc: suravee.suthikulpanit, aik, baolu.lu, Vasant Hegde
Use numa information to allocate irq resources and also to set
irq affinity. This optimizes the IOMMU interrupt handling.
Reviewed-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Reviewed-by: Alexey Kardashevskiy <aik@amd.com>
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
---
drivers/iommu/amd/init.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 19a46b9f7357..141eca29c951 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -2383,6 +2383,7 @@ static int iommu_setup_intcapxt(struct amd_iommu *iommu)
struct irq_domain *domain;
struct irq_alloc_info info;
int irq, ret;
+ int node = dev_to_node(&iommu->dev->dev);
domain = iommu_get_irqdomain();
if (!domain)
@@ -2392,7 +2393,7 @@ static int iommu_setup_intcapxt(struct amd_iommu *iommu)
info.type = X86_IRQ_ALLOC_TYPE_AMDVI;
info.data = iommu;
- irq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, &info);
+ irq = irq_domain_alloc_irqs(domain, 1, node, &info);
if (irq < 0) {
irq_domain_remove(domain);
return irq;
--
2.31.1
^ permalink raw reply related [flat|nested] 4+ messages in thread