@@ -75,6 +75,9 @@ struct kmem_cache *amd_iommu_irq_cache;
7575
7676static 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