@@ -2072,102 +2072,106 @@ int amd_iommu_clear_gcr3(struct iommu_dev_data *dev_data, ioasid_t pasid)
20722072 * Note:
20732073 * The old value for GCR3 table and GPT have been cleared from caller.
20742074 */
2075- static void set_dte_gcr3_table (struct amd_iommu * iommu ,
2076- struct iommu_dev_data * dev_data ,
2077- struct dev_table_entry * target )
2075+ static void set_dte_gcr3_table (struct iommu_dev_data * dev_data ,
2076+ struct dev_table_entry * new )
20782077{
20792078 struct gcr3_tbl_info * gcr3_info = & dev_data -> gcr3_info ;
2080- u64 gcr3 ;
2079+ u64 gcr3 = iommu_virt_to_phys ( gcr3_info -> gcr3_tbl ) ;
20812080
2082- if (!gcr3_info -> gcr3_tbl )
2083- return ;
2084-
2085- pr_debug ("%s: devid=%#x, glx=%#x, gcr3_tbl=%#llx\n" ,
2086- __func__ , dev_data -> devid , gcr3_info -> glx ,
2087- (unsigned long long )gcr3_info -> gcr3_tbl );
2088-
2089- gcr3 = iommu_virt_to_phys (gcr3_info -> gcr3_tbl );
2081+ new -> data [0 ] |= DTE_FLAG_TV |
2082+ (dev_data -> ppr ? DTE_FLAG_PPR : 0 ) |
2083+ (pdom_is_v2_pgtbl_mode (dev_data -> domain ) ? DTE_FLAG_GIOV : 0 ) |
2084+ DTE_FLAG_GV |
2085+ FIELD_PREP (DTE_GLX , gcr3_info -> glx ) |
2086+ FIELD_PREP (DTE_GCR3_14_12 , gcr3 >> 12 ) |
2087+ DTE_FLAG_IR | DTE_FLAG_IW ;
20902088
2091- target -> data [0 ] |= DTE_FLAG_GV |
2092- FIELD_PREP (DTE_GLX , gcr3_info -> glx ) |
2093- FIELD_PREP (DTE_GCR3_14_12 , gcr3 >> 12 );
2094- if (pdom_is_v2_pgtbl_mode (dev_data -> domain ))
2095- target -> data [0 ] |= DTE_FLAG_GIOV ;
2096-
2097- target -> data [1 ] |= FIELD_PREP (DTE_GCR3_30_15 , gcr3 >> 15 ) |
2098- FIELD_PREP (DTE_GCR3_51_31 , gcr3 >> 31 );
2089+ new -> data [1 ] |= FIELD_PREP (DTE_DOMID_MASK , dev_data -> gcr3_info .domid ) |
2090+ FIELD_PREP (DTE_GCR3_30_15 , gcr3 >> 15 ) |
2091+ (dev_data -> ats_enabled ? DTE_FLAG_IOTLB : 0 ) |
2092+ FIELD_PREP (DTE_GCR3_51_31 , gcr3 >> 31 );
20992093
21002094 /* Guest page table can only support 4 and 5 levels */
21012095 if (amd_iommu_gpt_level == PAGE_MODE_5_LEVEL )
2102- target -> data [2 ] |= FIELD_PREP (DTE_GPT_LEVEL_MASK , GUEST_PGTABLE_5_LEVEL );
2096+ new -> data [2 ] |= FIELD_PREP (DTE_GPT_LEVEL_MASK , GUEST_PGTABLE_5_LEVEL );
21032097 else
2104- target -> data [2 ] |= FIELD_PREP (DTE_GPT_LEVEL_MASK , GUEST_PGTABLE_4_LEVEL );
2098+ new -> data [2 ] |= FIELD_PREP (DTE_GPT_LEVEL_MASK , GUEST_PGTABLE_4_LEVEL );
2099+ }
2100+
2101+ void amd_iommu_set_dte_v1 (struct iommu_dev_data * dev_data ,
2102+ struct protection_domain * domain , u16 domid ,
2103+ struct pt_iommu_amdv1_hw_info * pt_info ,
2104+ struct dev_table_entry * new )
2105+ {
2106+ u64 host_pt_root = __sme_set (pt_info -> host_pt_root );
2107+
2108+ /* Note Dirty tracking is used for v1 table only for now */
2109+ new -> data [0 ] |= DTE_FLAG_TV |
2110+ FIELD_PREP (DTE_MODE_MASK , pt_info -> mode ) |
2111+ (domain -> dirty_tracking ? DTE_FLAG_HAD : 0 ) |
2112+ FIELD_PREP (DTE_HOST_TRP , host_pt_root >> 12 ) |
2113+ DTE_FLAG_IR | DTE_FLAG_IW ;
2114+
2115+ new -> data [1 ] |= FIELD_PREP (DTE_DOMID_MASK , domid ) |
2116+ (dev_data -> ats_enabled ? DTE_FLAG_IOTLB : 0 );
2117+ }
2118+
2119+ static void set_dte_v1 (struct iommu_dev_data * dev_data ,
2120+ struct protection_domain * domain , u16 domid ,
2121+ phys_addr_t top_paddr , unsigned int top_level ,
2122+ struct dev_table_entry * new )
2123+ {
2124+ struct pt_iommu_amdv1_hw_info pt_info ;
2125+
2126+ /*
2127+ * When updating the IO pagetable, the new top and level
2128+ * are provided as parameters. For other operations i.e.
2129+ * device attach, retrieve the current pagetable info
2130+ * via the IOMMU PT API.
2131+ */
2132+ if (top_paddr ) {
2133+ pt_info .host_pt_root = top_paddr ;
2134+ pt_info .mode = top_level + 1 ;
2135+ } else {
2136+ WARN_ON (top_paddr || top_level );
2137+ pt_iommu_amdv1_hw_info (& domain -> amdv1 , & pt_info );
2138+ }
2139+
2140+ amd_iommu_set_dte_v1 (dev_data , domain , domid , & pt_info , new );
2141+ }
2142+
2143+ static void set_dte_passthrough (struct iommu_dev_data * dev_data ,
2144+ struct protection_domain * domain ,
2145+ struct dev_table_entry * new )
2146+ {
2147+ new -> data [0 ] |= DTE_FLAG_TV | DTE_FLAG_IR | DTE_FLAG_IW ;
2148+
2149+ new -> data [1 ] |= FIELD_PREP (DTE_DOMID_MASK , domain -> id ) |
2150+ (dev_data -> ats_enabled ) ? DTE_FLAG_IOTLB : 0 ;
21052151}
21062152
21072153static void set_dte_entry (struct amd_iommu * iommu ,
21082154 struct iommu_dev_data * dev_data ,
21092155 phys_addr_t top_paddr , unsigned int top_level )
21102156{
2111- u16 domid ;
21122157 u32 old_domid ;
21132158 struct dev_table_entry new = {};
21142159 struct protection_domain * domain = dev_data -> domain ;
21152160 struct gcr3_tbl_info * gcr3_info = & dev_data -> gcr3_info ;
21162161 struct dev_table_entry * dte = & get_dev_table (iommu )[dev_data -> devid ];
2117- struct pt_iommu_amdv1_hw_info pt_info ;
21182162
21192163 amd_iommu_make_clear_dte (dev_data , & new );
21202164
2121- if (gcr3_info && gcr3_info -> gcr3_tbl )
2122- domid = dev_data -> gcr3_info .domid ;
2123- else {
2124- domid = domain -> id ;
2125-
2126- if (domain -> domain .type & __IOMMU_DOMAIN_PAGING ) {
2127- /*
2128- * When updating the IO pagetable, the new top and level
2129- * are provided as parameters. For other operations i.e.
2130- * device attach, retrieve the current pagetable info
2131- * via the IOMMU PT API.
2132- */
2133- if (top_paddr ) {
2134- pt_info .host_pt_root = top_paddr ;
2135- pt_info .mode = top_level + 1 ;
2136- } else {
2137- WARN_ON (top_paddr || top_level );
2138- pt_iommu_amdv1_hw_info (& domain -> amdv1 ,
2139- & pt_info );
2140- }
2141-
2142- new .data [0 ] |= __sme_set (pt_info .host_pt_root ) |
2143- (pt_info .mode & DEV_ENTRY_MODE_MASK )
2144- << DEV_ENTRY_MODE_SHIFT ;
2145- }
2146- }
2147-
2148- new .data [0 ] |= DTE_FLAG_IR | DTE_FLAG_IW ;
2149-
2150- /*
2151- * When SNP is enabled, we can only support TV=1 with non-zero domain ID.
2152- * This is prevented by the SNP-enable and IOMMU_DOMAIN_IDENTITY check in
2153- * do_iommu_domain_alloc().
2154- */
2155- WARN_ON (amd_iommu_snp_en && (domid == 0 ));
2156- new .data [0 ] |= DTE_FLAG_TV ;
2157-
2158- if (dev_data -> ppr )
2159- new .data [0 ] |= 1ULL << DEV_ENTRY_PPR ;
2160-
2161- if (domain -> dirty_tracking )
2162- new .data [0 ] |= DTE_FLAG_HAD ;
2163-
2164- if (dev_data -> ats_enabled )
2165- new .data [1 ] |= DTE_FLAG_IOTLB ;
2166-
21672165 old_domid = READ_ONCE (dte -> data [1 ]) & DTE_DOMID_MASK ;
2168- new .data [1 ] |= domid ;
2169-
2170- set_dte_gcr3_table (iommu , dev_data , & new );
2166+ if (gcr3_info -> gcr3_tbl )
2167+ set_dte_gcr3_table (dev_data , & new );
2168+ else if (domain -> domain .type == IOMMU_DOMAIN_IDENTITY )
2169+ set_dte_passthrough (dev_data , domain , & new );
2170+ else if ((domain -> domain .type & __IOMMU_DOMAIN_PAGING ) &&
2171+ domain -> pd_mode == PD_MODE_V1 )
2172+ set_dte_v1 (dev_data , domain , domain -> id , top_paddr , top_level , & new );
2173+ else
2174+ WARN_ON (true);
21712175
21722176 amd_iommu_update_dte (iommu , dev_data , & new );
21732177
0 commit comments