Skip to content

Commit cf70873

Browse files
ssuthiku-amdjoergroedel
authored andcommitted
iommu/amd: Refactor GCR3 table helper functions
To use the new per-device struct gcr3_tbl_info. Use GFP_KERNEL flag instead of GFP_ATOMIC for GCR3 table allocation. Also modify set_dte_entry() to use new per device GCR3 table. Also in free_gcr3_table() path replace BUG_ON with WARN_ON_ONCE(). Signed-off-by: Suravee Suthikulpanit <[email protected]> Co-developed-by: Vasant Hegde <[email protected]> Signed-off-by: Vasant Hegde <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent fb575d1 commit cf70873

File tree

1 file changed

+31
-22
lines changed

1 file changed

+31
-22
lines changed

drivers/iommu/amd/iommu.c

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ struct kmem_cache *amd_iommu_irq_cache;
7575

7676
static void detach_device(struct device *dev);
7777

78+
static void set_dte_entry(struct amd_iommu *iommu,
79+
struct iommu_dev_data *dev_data);
80+
7881
/****************************************************************************
7982
*
8083
* Helper functions
@@ -1666,16 +1669,19 @@ static void free_gcr3_tbl_level2(u64 *tbl)
16661669
}
16671670
}
16681671

1669-
static void free_gcr3_table(struct protection_domain *domain)
1672+
static void free_gcr3_table(struct gcr3_tbl_info *gcr3_info)
16701673
{
1671-
if (domain->glx == 2)
1672-
free_gcr3_tbl_level2(domain->gcr3_tbl);
1673-
else if (domain->glx == 1)
1674-
free_gcr3_tbl_level1(domain->gcr3_tbl);
1674+
if (gcr3_info->glx == 2)
1675+
free_gcr3_tbl_level2(gcr3_info->gcr3_tbl);
1676+
else if (gcr3_info->glx == 1)
1677+
free_gcr3_tbl_level1(gcr3_info->gcr3_tbl);
16751678
else
1676-
BUG_ON(domain->glx != 0);
1679+
WARN_ON_ONCE(gcr3_info->glx != 0);
1680+
1681+
gcr3_info->glx = 0;
16771682

1678-
free_page((unsigned long)domain->gcr3_tbl);
1683+
free_page((unsigned long)gcr3_info->gcr3_tbl);
1684+
gcr3_info->gcr3_tbl = NULL;
16791685
}
16801686

16811687
/*
@@ -1694,22 +1700,23 @@ static int get_gcr3_levels(int pasids)
16941700
return levels ? (DIV_ROUND_UP(levels, 9) - 1) : levels;
16951701
}
16961702

1697-
/* Note: This function expects iommu_domain->lock to be held prior calling the function. */
1698-
static int setup_gcr3_table(struct protection_domain *domain, int pasids)
1703+
static int setup_gcr3_table(struct gcr3_tbl_info *gcr3_info,
1704+
struct amd_iommu *iommu, int pasids)
16991705
{
17001706
int levels = get_gcr3_levels(pasids);
1707+
int nid = iommu ? dev_to_node(&iommu->dev->dev) : NUMA_NO_NODE;
17011708

17021709
if (levels > amd_iommu_max_glx_val)
17031710
return -EINVAL;
17041711

1705-
domain->gcr3_tbl = alloc_pgtable_page(domain->nid, GFP_ATOMIC);
1706-
if (domain->gcr3_tbl == NULL)
1707-
return -ENOMEM;
1712+
if (gcr3_info->gcr3_tbl)
1713+
return -EBUSY;
17081714

1709-
domain->glx = levels;
1710-
domain->flags |= PD_IOMMUV2_MASK;
1715+
gcr3_info->gcr3_tbl = alloc_pgtable_page(nid, GFP_KERNEL);
1716+
if (gcr3_info->gcr3_tbl == NULL)
1717+
return -ENOMEM;
17111718

1712-
amd_iommu_domain_update(domain);
1719+
gcr3_info->glx = levels;
17131720

17141721
return 0;
17151722
}
@@ -1808,6 +1815,7 @@ static void set_dte_entry(struct amd_iommu *iommu,
18081815
u16 devid = dev_data->devid;
18091816
struct protection_domain *domain = dev_data->domain;
18101817
struct dev_table_entry *dev_table = get_dev_table(iommu);
1818+
struct gcr3_tbl_info *gcr3_info = &dev_data->gcr3_info;
18111819

18121820
if (domain->iop.mode != PAGE_MODE_NONE)
18131821
pte_root = iommu_virt_to_phys(domain->iop.root);
@@ -1835,9 +1843,9 @@ static void set_dte_entry(struct amd_iommu *iommu,
18351843
if (domain->dirty_tracking)
18361844
pte_root |= DTE_FLAG_HAD;
18371845

1838-
if (domain->flags & PD_IOMMUV2_MASK) {
1839-
u64 gcr3 = iommu_virt_to_phys(domain->gcr3_tbl);
1840-
u64 glx = domain->glx;
1846+
if (gcr3_info && gcr3_info->gcr3_tbl) {
1847+
u64 gcr3 = iommu_virt_to_phys(gcr3_info->gcr3_tbl);
1848+
u64 glx = gcr3_info->glx;
18411849
u64 tmp;
18421850

18431851
pte_root |= DTE_FLAG_GV;
@@ -1865,7 +1873,8 @@ static void set_dte_entry(struct amd_iommu *iommu,
18651873
((u64)GUEST_PGTABLE_5_LEVEL << DTE_GPT_LEVEL_SHIFT);
18661874
}
18671875

1868-
if (domain->flags & PD_GIOV_MASK)
1876+
/* GIOV is supported with V2 page table mode only */
1877+
if (pdom_is_v2_pgtbl_mode(domain))
18691878
pte_root |= DTE_FLAG_GIOV;
18701879
}
18711880

@@ -1922,14 +1931,14 @@ static int do_attach(struct iommu_dev_data *dev_data,
19221931
/* Init GCR3 table and update device table */
19231932
if (domain->pd_mode == PD_MODE_V2) {
19241933
/* By default, setup GCR3 table to support single PASID */
1925-
ret = setup_gcr3_table(dev_data->domain, 1);
1934+
ret = setup_gcr3_table(&dev_data->gcr3_info, iommu, 1);
19261935
if (ret)
19271936
return ret;
19281937

19291938
ret = update_gcr3(dev_data, 0,
19301939
iommu_virt_to_phys(domain->iop.pgd), true);
19311940
if (ret) {
1932-
free_gcr3_table(dev_data->domain);
1941+
free_gcr3_table(&dev_data->gcr3_info);
19331942
return ret;
19341943
}
19351944
}
@@ -1951,7 +1960,7 @@ static void do_detach(struct iommu_dev_data *dev_data)
19511960
/* Clear GCR3 table */
19521961
if (domain->pd_mode == PD_MODE_V2) {
19531962
update_gcr3(dev_data, 0, 0, false);
1954-
free_gcr3_table(dev_data->domain);
1963+
free_gcr3_table(&dev_data->gcr3_info);
19551964
}
19561965

19571966
/* Update data structures */

0 commit comments

Comments
 (0)