@@ -101,6 +101,8 @@ struct kmem_cache *amd_iommu_irq_cache;
101
101
static void update_domain (struct protection_domain * domain );
102
102
static int protection_domain_init (struct protection_domain * domain );
103
103
static void detach_device (struct device * dev );
104
+ static void update_and_flush_device_table (struct protection_domain * domain ,
105
+ struct domain_pgtable * pgtable );
104
106
105
107
/****************************************************************************
106
108
*
@@ -1461,8 +1463,16 @@ static bool increase_address_space(struct protection_domain *domain,
1461
1463
1462
1464
* pte = PM_LEVEL_PDE (pgtable .mode , iommu_virt_to_phys (pgtable .root ));
1463
1465
1464
- root = amd_iommu_domain_encode_pgtable (pte , pgtable .mode + 1 );
1466
+ pgtable .root = pte ;
1467
+ pgtable .mode += 1 ;
1468
+ update_and_flush_device_table (domain , & pgtable );
1469
+ domain_flush_complete (domain );
1465
1470
1471
+ /*
1472
+ * Device Table needs to be updated and flushed before the new root can
1473
+ * be published.
1474
+ */
1475
+ root = amd_iommu_domain_encode_pgtable (pte , pgtable .mode );
1466
1476
atomic64_set (& domain -> pt_root , root );
1467
1477
1468
1478
ret = true;
@@ -1893,19 +1903,17 @@ static bool dma_ops_domain(struct protection_domain *domain)
1893
1903
}
1894
1904
1895
1905
static void set_dte_entry (u16 devid , struct protection_domain * domain ,
1906
+ struct domain_pgtable * pgtable ,
1896
1907
bool ats , bool ppr )
1897
1908
{
1898
- struct domain_pgtable pgtable ;
1899
1909
u64 pte_root = 0 ;
1900
1910
u64 flags = 0 ;
1901
1911
u32 old_domid ;
1902
1912
1903
- amd_iommu_domain_get_pgtable (domain , & pgtable );
1913
+ if (pgtable -> mode != PAGE_MODE_NONE )
1914
+ pte_root = iommu_virt_to_phys (pgtable -> root );
1904
1915
1905
- if (pgtable .mode != PAGE_MODE_NONE )
1906
- pte_root = iommu_virt_to_phys (pgtable .root );
1907
-
1908
- pte_root |= (pgtable .mode & DEV_ENTRY_MODE_MASK )
1916
+ pte_root |= (pgtable -> mode & DEV_ENTRY_MODE_MASK )
1909
1917
<< DEV_ENTRY_MODE_SHIFT ;
1910
1918
pte_root |= DTE_FLAG_IR | DTE_FLAG_IW | DTE_FLAG_V | DTE_FLAG_TV ;
1911
1919
@@ -1978,6 +1986,7 @@ static void clear_dte_entry(u16 devid)
1978
1986
static void do_attach (struct iommu_dev_data * dev_data ,
1979
1987
struct protection_domain * domain )
1980
1988
{
1989
+ struct domain_pgtable pgtable ;
1981
1990
struct amd_iommu * iommu ;
1982
1991
bool ats ;
1983
1992
@@ -1993,7 +2002,9 @@ static void do_attach(struct iommu_dev_data *dev_data,
1993
2002
domain -> dev_cnt += 1 ;
1994
2003
1995
2004
/* Update device table */
1996
- set_dte_entry (dev_data -> devid , domain , ats , dev_data -> iommu_v2 );
2005
+ amd_iommu_domain_get_pgtable (domain , & pgtable );
2006
+ set_dte_entry (dev_data -> devid , domain , & pgtable ,
2007
+ ats , dev_data -> iommu_v2 );
1997
2008
clone_aliases (dev_data -> pdev );
1998
2009
1999
2010
device_flush_dte (dev_data );
@@ -2304,22 +2315,34 @@ static int amd_iommu_domain_get_attr(struct iommu_domain *domain,
2304
2315
*
2305
2316
*****************************************************************************/
2306
2317
2307
- static void update_device_table (struct protection_domain * domain )
2318
+ static void update_device_table (struct protection_domain * domain ,
2319
+ struct domain_pgtable * pgtable )
2308
2320
{
2309
2321
struct iommu_dev_data * dev_data ;
2310
2322
2311
2323
list_for_each_entry (dev_data , & domain -> dev_list , list ) {
2312
- set_dte_entry (dev_data -> devid , domain , dev_data -> ats . enabled ,
2313
- dev_data -> iommu_v2 );
2324
+ set_dte_entry (dev_data -> devid , domain , pgtable ,
2325
+ dev_data -> ats . enabled , dev_data -> iommu_v2 );
2314
2326
clone_aliases (dev_data -> pdev );
2315
2327
}
2316
2328
}
2317
2329
2330
+ static void update_and_flush_device_table (struct protection_domain * domain ,
2331
+ struct domain_pgtable * pgtable )
2332
+ {
2333
+ update_device_table (domain , pgtable );
2334
+ domain_flush_devices (domain );
2335
+ }
2336
+
2318
2337
static void update_domain (struct protection_domain * domain )
2319
2338
{
2320
- update_device_table ( domain ) ;
2339
+ struct domain_pgtable pgtable ;
2321
2340
2322
- domain_flush_devices (domain );
2341
+ /* Update device table */
2342
+ amd_iommu_domain_get_pgtable (domain , & pgtable );
2343
+ update_and_flush_device_table (domain , & pgtable );
2344
+
2345
+ /* Flush domain TLB(s) and wait for completion */
2323
2346
domain_flush_tlb_pde (domain );
2324
2347
domain_flush_complete (domain );
2325
2348
}
0 commit comments