Skip to content

Commit 0d571dc

Browse files
hegdevasantjoergroedel
authored andcommitted
iommu/amd: Allocate page table using numa locality info
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> Link: https://lore.kernel.org/r/20230321092348.6127-2-vasant.hegde@amd.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent e8d018d commit 0d571dc

5 files changed

Lines changed: 23 additions & 12 deletions

File tree

drivers/iommu/amd/amd_iommu.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@ static inline int get_pci_sbdf_id(struct pci_dev *pdev)
122122
return PCI_SEG_DEVID_TO_SBDF(seg, devid);
123123
}
124124

125+
static inline void *alloc_pgtable_page(int nid, gfp_t gfp)
126+
{
127+
struct page *page;
128+
129+
page = alloc_pages_node(nid, gfp | __GFP_ZERO, 0);
130+
return page ? page_address(page) : NULL;
131+
}
132+
125133
extern bool translation_pre_enabled(struct amd_iommu *iommu);
126134
extern bool amd_iommu_is_attach_deferred(struct device *dev);
127135
extern int __init add_special_device(u8 type, u8 id, u32 *devid,

drivers/iommu/amd/amd_iommu_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ struct protection_domain {
549549
spinlock_t lock; /* mostly used to lock the page table*/
550550
u16 id; /* the domain id written to the device table */
551551
int glx; /* Number of levels for GCR3 table */
552+
int nid; /* Node ID */
552553
u64 *gcr3_tbl; /* Guest CR3 table */
553554
unsigned long flags; /* flags to find out type of domain */
554555
unsigned dev_cnt; /* devices assigned to this domain */

drivers/iommu/amd/io_pgtable.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ static bool increase_address_space(struct protection_domain *domain,
156156
bool ret = true;
157157
u64 *pte;
158158

159-
pte = (void *)get_zeroed_page(gfp);
159+
pte = alloc_pgtable_page(domain->nid, gfp);
160160
if (!pte)
161161
return false;
162162

@@ -250,7 +250,7 @@ static u64 *alloc_pte(struct protection_domain *domain,
250250

251251
if (!IOMMU_PTE_PRESENT(__pte) ||
252252
pte_level == PAGE_MODE_NONE) {
253-
page = (u64 *)get_zeroed_page(gfp);
253+
page = alloc_pgtable_page(domain->nid, gfp);
254254

255255
if (!page)
256256
return NULL;

drivers/iommu/amd/io_pgtable_v2.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,6 @@ static inline bool is_large_pte(u64 pte)
4646
return (pte & IOMMU_PAGE_PSE);
4747
}
4848

49-
static inline void *alloc_pgtable_page(void)
50-
{
51-
return (void *)get_zeroed_page(GFP_KERNEL);
52-
}
53-
5449
static inline u64 set_pgtable_attr(u64 *page)
5550
{
5651
u64 prot;
@@ -138,8 +133,8 @@ static void free_pgtable(u64 *pt, int level)
138133
}
139134

140135
/* Allocate page table */
141-
static u64 *v2_alloc_pte(u64 *pgd, unsigned long iova,
142-
unsigned long pg_size, bool *updated)
136+
static u64 *v2_alloc_pte(int nid, u64 *pgd, unsigned long iova,
137+
unsigned long pg_size, gfp_t gfp, bool *updated)
143138
{
144139
u64 *pte, *page;
145140
int level, end_level;
@@ -162,7 +157,7 @@ static u64 *v2_alloc_pte(u64 *pgd, unsigned long iova,
162157
}
163158

164159
if (!IOMMU_PTE_PRESENT(__pte)) {
165-
page = alloc_pgtable_page();
160+
page = alloc_pgtable_page(nid, gfp);
166161
if (!page)
167162
return NULL;
168163

@@ -262,7 +257,8 @@ static int iommu_v2_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
262257

263258
while (mapped_size < size) {
264259
map_size = get_alloc_page_size(pgsize);
265-
pte = v2_alloc_pte(pdom->iop.pgd, iova, map_size, &updated);
260+
pte = v2_alloc_pte(pdom->nid, pdom->iop.pgd,
261+
iova, map_size, gfp, &updated);
266262
if (!pte) {
267263
ret = -EINVAL;
268264
goto out;
@@ -384,7 +380,7 @@ static struct io_pgtable *v2_alloc_pgtable(struct io_pgtable_cfg *cfg, void *coo
384380
struct protection_domain *pdom = (struct protection_domain *)cookie;
385381
int ret;
386382

387-
pgtable->pgd = alloc_pgtable_page();
383+
pgtable->pgd = alloc_pgtable_page(pdom->nid, GFP_ATOMIC);
388384
if (!pgtable->pgd)
389385
return NULL;
390386

drivers/iommu/amd/iommu.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,6 +1662,10 @@ static void do_attach(struct iommu_dev_data *dev_data,
16621662
dev_data->domain = domain;
16631663
list_add(&dev_data->list, &domain->dev_list);
16641664

1665+
/* Update NUMA Node ID */
1666+
if (domain->nid == NUMA_NO_NODE)
1667+
domain->nid = dev_to_node(dev_data->dev);
1668+
16651669
/* Do reference counting */
16661670
domain->dev_iommu[iommu->index] += 1;
16671671
domain->dev_cnt += 1;
@@ -2097,6 +2101,8 @@ static struct protection_domain *protection_domain_alloc(unsigned int type)
20972101
if (type == IOMMU_DOMAIN_IDENTITY)
20982102
return domain;
20992103

2104+
domain->nid = NUMA_NO_NODE;
2105+
21002106
pgtbl_ops = alloc_io_pgtable_ops(pgtable, &domain->iop.pgtbl_cfg, domain);
21012107
if (!pgtbl_ops) {
21022108
domain_id_free(domain->id);

0 commit comments

Comments
 (0)