Skip to content

Commit c9e8701

Browse files
hegdevasantjoergroedel
authored andcommitted
iommu/amd: Setup GCR3 table in advance if domain is SVA capable
SVA can be supported if domain is in passthrough mode or paging domain with v2 page table. Current code sets up GCR3 table for domain with v2 page table only. Setup GCR3 table for all SVA capable domains. - Move GCR3 init/destroy to separate function. - Change default GCR3 table to use MAX supported PASIDs. Ideally it should use 1 level PASID table as its using PASID zero only. But we don't have support to extend PASID table yet. We will fix this later. - When domain is configured with passthrough mode, allocate default GCR3 table only if device is SVA capable. Note that in attach_device() path it will not know whether device will use SVA or not. If device is attached to passthrough domain and if it doesn't use SVA then GCR3 table will never be used. We will endup wasting memory allocated for GCR3 table. This is done to avoid DTE update when attaching PASID to device. 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 a0c47f2 commit c9e8701

File tree

1 file changed

+71
-15
lines changed

1 file changed

+71
-15
lines changed

drivers/iommu/amd/iommu.c

Lines changed: 71 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,21 @@ static inline bool pdom_is_v2_pgtbl_mode(struct protection_domain *pdom)
8989
return (pdom && (pdom->pd_mode == PD_MODE_V2));
9090
}
9191

92+
static inline bool pdom_is_in_pt_mode(struct protection_domain *pdom)
93+
{
94+
return (pdom->domain.type == IOMMU_DOMAIN_IDENTITY);
95+
}
96+
97+
/*
98+
* We cannot support PASID w/ existing v1 page table in the same domain
99+
* since it will be nested. However, existing domain w/ v2 page table
100+
* or passthrough mode can be used for PASID.
101+
*/
102+
static inline bool pdom_is_sva_capable(struct protection_domain *pdom)
103+
{
104+
return pdom_is_v2_pgtbl_mode(pdom) || pdom_is_in_pt_mode(pdom);
105+
}
106+
92107
static inline int get_acpihid_device_id(struct device *dev,
93108
struct acpihid_map_entry **entry)
94109
{
@@ -1964,6 +1979,58 @@ void amd_iommu_dev_update_dte(struct iommu_dev_data *dev_data, bool set)
19641979
iommu_completion_wait(iommu);
19651980
}
19661981

1982+
/*
1983+
* If domain is SVA capable then initialize GCR3 table. Also if domain is
1984+
* in v2 page table mode then update GCR3[0].
1985+
*/
1986+
static int init_gcr3_table(struct iommu_dev_data *dev_data,
1987+
struct protection_domain *pdom)
1988+
{
1989+
struct amd_iommu *iommu = get_amd_iommu_from_dev_data(dev_data);
1990+
int max_pasids = dev_data->max_pasids;
1991+
int ret = 0;
1992+
1993+
/*
1994+
* If domain is in pt mode then setup GCR3 table only if device
1995+
* is PASID capable
1996+
*/
1997+
if (pdom_is_in_pt_mode(pdom) && !pdev_pasid_supported(dev_data))
1998+
return ret;
1999+
2000+
/*
2001+
* By default, setup GCR3 table to support MAX PASIDs
2002+
* supported by the device/IOMMU.
2003+
*/
2004+
ret = setup_gcr3_table(&dev_data->gcr3_info, iommu,
2005+
max_pasids > 0 ? max_pasids : 1);
2006+
if (ret)
2007+
return ret;
2008+
2009+
/* Setup GCR3[0] only if domain is setup with v2 page table mode */
2010+
if (!pdom_is_v2_pgtbl_mode(pdom))
2011+
return ret;
2012+
2013+
ret = update_gcr3(dev_data, 0, iommu_virt_to_phys(pdom->iop.pgd), true);
2014+
if (ret)
2015+
free_gcr3_table(&dev_data->gcr3_info);
2016+
2017+
return ret;
2018+
}
2019+
2020+
static void destroy_gcr3_table(struct iommu_dev_data *dev_data,
2021+
struct protection_domain *pdom)
2022+
{
2023+
struct gcr3_tbl_info *gcr3_info = &dev_data->gcr3_info;
2024+
2025+
if (pdom_is_v2_pgtbl_mode(pdom))
2026+
update_gcr3(dev_data, 0, 0, false);
2027+
2028+
if (gcr3_info->gcr3_tbl == NULL)
2029+
return;
2030+
2031+
free_gcr3_table(gcr3_info);
2032+
}
2033+
19672034
static int do_attach(struct iommu_dev_data *dev_data,
19682035
struct protection_domain *domain)
19692036
{
@@ -1982,19 +2049,10 @@ static int do_attach(struct iommu_dev_data *dev_data,
19822049
domain->dev_iommu[iommu->index] += 1;
19832050
domain->dev_cnt += 1;
19842051

1985-
/* Init GCR3 table and update device table */
1986-
if (domain->pd_mode == PD_MODE_V2) {
1987-
/* By default, setup GCR3 table to support single PASID */
1988-
ret = setup_gcr3_table(&dev_data->gcr3_info, iommu, 1);
2052+
if (pdom_is_sva_capable(domain)) {
2053+
ret = init_gcr3_table(dev_data, domain);
19892054
if (ret)
19902055
return ret;
1991-
1992-
ret = update_gcr3(dev_data, 0,
1993-
iommu_virt_to_phys(domain->iop.pgd), true);
1994-
if (ret) {
1995-
free_gcr3_table(&dev_data->gcr3_info);
1996-
return ret;
1997-
}
19982056
}
19992057

20002058
/* Update device table */
@@ -2009,10 +2067,8 @@ static void do_detach(struct iommu_dev_data *dev_data)
20092067
struct amd_iommu *iommu = get_amd_iommu_from_dev_data(dev_data);
20102068

20112069
/* Clear GCR3 table */
2012-
if (domain->pd_mode == PD_MODE_V2) {
2013-
update_gcr3(dev_data, 0, 0, false);
2014-
free_gcr3_table(&dev_data->gcr3_info);
2015-
}
2070+
if (pdom_is_sva_capable(domain))
2071+
destroy_gcr3_table(dev_data, domain);
20162072

20172073
/* Update data structures */
20182074
dev_data->domain = NULL;

0 commit comments

Comments
 (0)