Skip to content

Commit e8e1aac

Browse files
ssuthiku-amdjoergroedel
authored andcommitted
iommu/amd: Refactor helper function for setting / clearing GCR3
Refactor GCR3 helper functions in preparation to use per device GCR3 table. * Add new function update_gcr3 to update per device GCR3 table * Remove per domain default GCR3 setup during v2 page table allocation. Subsequent patch will add support to setup default gcr3 while attaching device to domain. * Remove amd_iommu_domain_update() from V2 page table path as device detach path will take care of updating the domain. * Consolidate GCR3 table related code in one place so that its easy to maintain. * Rename functions to reflect its usage. 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 bf8aff2 commit e8e1aac

File tree

3 files changed

+61
-83
lines changed

3 files changed

+61
-83
lines changed

drivers/iommu/amd/amd_iommu.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ bool amd_iommu_v2_supported(void);
4444
int amd_iommu_pdev_enable_cap_pri(struct pci_dev *pdev);
4545
void amd_iommu_pdev_disable_cap_pri(struct pci_dev *pdev);
4646

47+
/* GCR3 setup */
48+
int amd_iommu_set_gcr3(struct iommu_dev_data *dev_data,
49+
ioasid_t pasid, unsigned long gcr3);
50+
int amd_iommu_clear_gcr3(struct iommu_dev_data *dev_data, ioasid_t pasid);
51+
4752
int amd_iommu_flush_page(struct iommu_domain *dom, u32 pasid, u64 address);
4853
/*
4954
* This function flushes all internal caches of
@@ -61,9 +66,6 @@ void amd_iommu_dev_flush_pasid_all(struct iommu_dev_data *dev_data,
6166
ioasid_t pasid);
6267

6368
int amd_iommu_flush_tlb(struct iommu_domain *dom, u32 pasid);
64-
int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, u32 pasid,
65-
unsigned long cr3);
66-
int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, u32 pasid);
6769

6870
#ifdef CONFIG_IRQ_REMAP
6971
int amd_iommu_create_irq_domain(struct amd_iommu *iommu);

drivers/iommu/amd/io_pgtable_v2.c

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -350,38 +350,26 @@ static const struct iommu_flush_ops v2_flush_ops = {
350350

351351
static void v2_free_pgtable(struct io_pgtable *iop)
352352
{
353-
struct protection_domain *pdom;
354353
struct amd_io_pgtable *pgtable = container_of(iop, struct amd_io_pgtable, iop);
355354

356-
pdom = container_of(pgtable, struct protection_domain, iop);
357-
if (!(pdom->flags & PD_IOMMUV2_MASK))
355+
if (!pgtable || !pgtable->pgd)
358356
return;
359357

360-
/* Clear gcr3 entry */
361-
amd_iommu_domain_clear_gcr3(&pdom->domain, 0);
362-
363-
/* Make changes visible to IOMMUs */
364-
amd_iommu_domain_update(pdom);
365-
366358
/* Free page table */
367359
free_pgtable(pgtable->pgd, get_pgtable_level());
360+
pgtable->pgd = NULL;
368361
}
369362

370363
static struct io_pgtable *v2_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
371364
{
372365
struct amd_io_pgtable *pgtable = io_pgtable_cfg_to_data(cfg);
373366
struct protection_domain *pdom = (struct protection_domain *)cookie;
374-
int ret;
375367
int ias = IOMMU_IN_ADDR_BIT_SIZE;
376368

377369
pgtable->pgd = alloc_pgtable_page(pdom->nid, GFP_ATOMIC);
378370
if (!pgtable->pgd)
379371
return NULL;
380372

381-
ret = amd_iommu_domain_set_gcr3(&pdom->domain, 0, iommu_virt_to_phys(pgtable->pgd));
382-
if (ret)
383-
goto err_free_pgd;
384-
385373
if (get_pgtable_level() == PAGE_MODE_5_LEVEL)
386374
ias = 57;
387375

@@ -395,11 +383,6 @@ static struct io_pgtable *v2_alloc_pgtable(struct io_pgtable_cfg *cfg, void *coo
395383
cfg->tlb = &v2_flush_ops;
396384

397385
return &pgtable->iop;
398-
399-
err_free_pgd:
400-
free_pgtable_page(pgtable->pgd);
401-
402-
return NULL;
403386
}
404387

405388
struct io_pgtable_init_fns io_pgtable_amd_iommu_v2_init_fns = {

drivers/iommu/amd/iommu.c

Lines changed: 54 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,10 +1714,13 @@ static int setup_gcr3_table(struct protection_domain *domain, int pasids)
17141714
return 0;
17151715
}
17161716

1717-
static u64 *__get_gcr3_pte(u64 *root, int level, u32 pasid, bool alloc)
1717+
static u64 *__get_gcr3_pte(struct gcr3_tbl_info *gcr3_info,
1718+
ioasid_t pasid, bool alloc)
17181719
{
17191720
int index;
17201721
u64 *pte;
1722+
u64 *root = gcr3_info->gcr3_tbl;
1723+
int level = gcr3_info->glx;
17211724

17221725
while (true) {
17231726

@@ -1746,6 +1749,56 @@ static u64 *__get_gcr3_pte(u64 *root, int level, u32 pasid, bool alloc)
17461749
return pte;
17471750
}
17481751

1752+
static int update_gcr3(struct iommu_dev_data *dev_data,
1753+
ioasid_t pasid, unsigned long gcr3, bool set)
1754+
{
1755+
struct gcr3_tbl_info *gcr3_info = &dev_data->gcr3_info;
1756+
u64 *pte;
1757+
1758+
pte = __get_gcr3_pte(gcr3_info, pasid, true);
1759+
if (pte == NULL)
1760+
return -ENOMEM;
1761+
1762+
if (set)
1763+
*pte = (gcr3 & PAGE_MASK) | GCR3_VALID;
1764+
else
1765+
*pte = 0;
1766+
1767+
amd_iommu_dev_flush_pasid_all(dev_data, pasid);
1768+
return 0;
1769+
}
1770+
1771+
int amd_iommu_set_gcr3(struct iommu_dev_data *dev_data, ioasid_t pasid,
1772+
unsigned long gcr3)
1773+
{
1774+
struct gcr3_tbl_info *gcr3_info = &dev_data->gcr3_info;
1775+
int ret;
1776+
1777+
iommu_group_mutex_assert(dev_data->dev);
1778+
1779+
ret = update_gcr3(dev_data, pasid, gcr3, true);
1780+
if (ret)
1781+
return ret;
1782+
1783+
gcr3_info->pasid_cnt++;
1784+
return ret;
1785+
}
1786+
1787+
int amd_iommu_clear_gcr3(struct iommu_dev_data *dev_data, ioasid_t pasid)
1788+
{
1789+
struct gcr3_tbl_info *gcr3_info = &dev_data->gcr3_info;
1790+
int ret;
1791+
1792+
iommu_group_mutex_assert(dev_data->dev);
1793+
1794+
ret = update_gcr3(dev_data, pasid, 0, false);
1795+
if (ret)
1796+
return ret;
1797+
1798+
gcr3_info->pasid_cnt--;
1799+
return ret;
1800+
}
1801+
17491802
static void set_dte_entry(struct amd_iommu *iommu,
17501803
struct iommu_dev_data *dev_data)
17511804
{
@@ -2769,66 +2822,6 @@ int amd_iommu_flush_tlb(struct iommu_domain *dom, u32 pasid)
27692822
return ret;
27702823
}
27712824

2772-
static int __set_gcr3(struct protection_domain *domain, u32 pasid,
2773-
unsigned long cr3)
2774-
{
2775-
u64 *pte;
2776-
2777-
if (domain->iop.mode != PAGE_MODE_NONE)
2778-
return -EINVAL;
2779-
2780-
pte = __get_gcr3_pte(domain->gcr3_tbl, domain->glx, pasid, true);
2781-
if (pte == NULL)
2782-
return -ENOMEM;
2783-
2784-
*pte = (cr3 & PAGE_MASK) | GCR3_VALID;
2785-
2786-
return __amd_iommu_flush_tlb(domain, pasid);
2787-
}
2788-
2789-
static int __clear_gcr3(struct protection_domain *domain, u32 pasid)
2790-
{
2791-
u64 *pte;
2792-
2793-
if (domain->iop.mode != PAGE_MODE_NONE)
2794-
return -EINVAL;
2795-
2796-
pte = __get_gcr3_pte(domain->gcr3_tbl, domain->glx, pasid, false);
2797-
if (pte == NULL)
2798-
return 0;
2799-
2800-
*pte = 0;
2801-
2802-
return __amd_iommu_flush_tlb(domain, pasid);
2803-
}
2804-
2805-
int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, u32 pasid,
2806-
unsigned long cr3)
2807-
{
2808-
struct protection_domain *domain = to_pdomain(dom);
2809-
unsigned long flags;
2810-
int ret;
2811-
2812-
spin_lock_irqsave(&domain->lock, flags);
2813-
ret = __set_gcr3(domain, pasid, cr3);
2814-
spin_unlock_irqrestore(&domain->lock, flags);
2815-
2816-
return ret;
2817-
}
2818-
2819-
int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, u32 pasid)
2820-
{
2821-
struct protection_domain *domain = to_pdomain(dom);
2822-
unsigned long flags;
2823-
int ret;
2824-
2825-
spin_lock_irqsave(&domain->lock, flags);
2826-
ret = __clear_gcr3(domain, pasid);
2827-
spin_unlock_irqrestore(&domain->lock, flags);
2828-
2829-
return ret;
2830-
}
2831-
28322825
int amd_iommu_complete_ppr(struct pci_dev *pdev, u32 pasid,
28332826
int status, int tag)
28342827
{

0 commit comments

Comments
 (0)