Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

iommu/amd: Refactor logic to program the host page table in DTE

Introduce the amd_iommu_set_dte_v1() helper function to configure
IOMMU host (v1) page table into DTE. This will be used later
when attaching nested doamin.

Also, remove obsolete warning when SNP is enabled and domain id
is zero since this check is no longer applicable.

Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>

authored by

Suravee Suthikulpanit and committed by
Joerg Roedel
93eee2a4 4e1b09d9

+82 -73
+4
drivers/iommu/amd/amd_iommu.h
··· 190 190 struct dev_table_entry *get_dev_table(struct amd_iommu *iommu); 191 191 struct iommu_dev_data *search_dev_data(struct amd_iommu *iommu, u16 devid); 192 192 193 + void amd_iommu_set_dte_v1(struct iommu_dev_data *dev_data, 194 + struct protection_domain *domain, u16 domid, 195 + struct pt_iommu_amdv1_hw_info *pt_info, 196 + struct dev_table_entry *new); 193 197 void amd_iommu_update_dte(struct amd_iommu *iommu, 194 198 struct iommu_dev_data *dev_data, 195 199 struct dev_table_entry *new);
+1
drivers/iommu/amd/amd_iommu_types.h
··· 357 357 #define DTE_FLAG_HAD (3ULL << 7) 358 358 #define DTE_MODE_MASK GENMASK_ULL(11, 9) 359 359 #define DTE_HOST_TRP GENMASK_ULL(51, 12) 360 + #define DTE_FLAG_PPR BIT_ULL(52) 360 361 #define DTE_FLAG_GIOV BIT_ULL(54) 361 362 #define DTE_FLAG_GV BIT_ULL(55) 362 363 #define DTE_GLX GENMASK_ULL(57, 56)
+77 -73
drivers/iommu/amd/iommu.c
··· 2072 2072 * Note: 2073 2073 * The old value for GCR3 table and GPT have been cleared from caller. 2074 2074 */ 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) 2078 2077 { 2079 2078 struct gcr3_tbl_info *gcr3_info = &dev_data->gcr3_info; 2080 - u64 gcr3; 2079 + u64 gcr3 = iommu_virt_to_phys(gcr3_info->gcr3_tbl); 2081 2080 2082 - if (!gcr3_info->gcr3_tbl) 2083 - return; 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; 2084 2088 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); 2090 - 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); 2099 2093 2100 2094 /* Guest page table can only support 4 and 5 levels */ 2101 2095 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); 2103 2097 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; 2105 2151 } 2106 2152 2107 2153 static void set_dte_entry(struct amd_iommu *iommu, 2108 2154 struct iommu_dev_data *dev_data, 2109 2155 phys_addr_t top_paddr, unsigned int top_level) 2110 2156 { 2111 - u16 domid; 2112 2157 u32 old_domid; 2113 2158 struct dev_table_entry new = {}; 2114 2159 struct protection_domain *domain = dev_data->domain; 2115 2160 struct gcr3_tbl_info *gcr3_info = &dev_data->gcr3_info; 2116 2161 struct dev_table_entry *dte = &get_dev_table(iommu)[dev_data->devid]; 2117 - struct pt_iommu_amdv1_hw_info pt_info; 2118 2162 2119 2163 amd_iommu_make_clear_dte(dev_data, &new); 2120 2164 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 - 2167 2165 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); 2171 2175 2172 2176 amd_iommu_update_dte(iommu, dev_data, &new); 2173 2177