Lines Matching +full:dte +full:- +full:mode
1 // SPDX-License-Identifier: GPL-2.0-only
6 #define dev_fmt(fmt) "AMD-Vi: " fmt
22 * Validate guest DTE to make sure that configuration for host (v1)
27 u32 gpt_level = FIELD_GET(DTE_GPT_LEVEL_MASK, gdte->dte[2]); in validate_gdte_nested()
29 /* Must be zero: Mode, Host-TPR */ in validate_gdte_nested()
30 if (FIELD_GET(DTE_MODE_MASK, gdte->dte[0]) != 0 || in validate_gdte_nested()
31 FIELD_GET(DTE_HOST_TRP, gdte->dte[0]) != 0) in validate_gdte_nested()
32 return -EINVAL; in validate_gdte_nested()
34 /* GCR3 TRP must be non-zero if V, GV is set */ in validate_gdte_nested()
35 if (FIELD_GET(DTE_FLAG_V, gdte->dte[0]) == 1 && in validate_gdte_nested()
36 FIELD_GET(DTE_FLAG_GV, gdte->dte[0]) == 1 && in validate_gdte_nested()
37 FIELD_GET(DTE_GCR3_14_12, gdte->dte[0]) == 0 && in validate_gdte_nested()
38 FIELD_GET(DTE_GCR3_30_15, gdte->dte[1]) == 0 && in validate_gdte_nested()
39 FIELD_GET(DTE_GCR3_51_31, gdte->dte[1]) == 0) in validate_gdte_nested()
40 return -EINVAL; in validate_gdte_nested()
42 /* Valid Guest Paging Mode values are 0 and 1 */ in validate_gdte_nested()
45 return -EINVAL; in validate_gdte_nested()
48 if (FIELD_GET(DTE_GLX, gdte->dte[0]) == 3) in validate_gdte_nested()
49 return -EINVAL; in validate_gdte_nested()
53 * the Guest Paging Mode in validate_gdte_nested()
57 return -EOPNOTSUPP; in validate_gdte_nested()
74 return ERR_PTR(-ENOMEM); in gdom_info_load_or_alloc_locked()
85 refcount_set(&elm->users, 0); in gdom_info_load_or_alloc_locked()
102 if (user_data->type != IOMMU_HWPT_DATA_AMD_GUEST) in amd_iommu_alloc_domain_nested()
103 return ERR_PTR(-EOPNOTSUPP); in amd_iommu_alloc_domain_nested()
107 return ERR_PTR(-ENOMEM); in amd_iommu_alloc_domain_nested()
109 ret = iommu_copy_struct_from_user(&ndom->gdte, user_data, in amd_iommu_alloc_domain_nested()
111 dte); in amd_iommu_alloc_domain_nested()
115 ret = validate_gdte_nested(&ndom->gdte); in amd_iommu_alloc_domain_nested()
119 ndom->gdom_id = FIELD_GET(DTE_DOMID_MASK, ndom->gdte.dte[1]); in amd_iommu_alloc_domain_nested()
120 ndom->domain.ops = &nested_domain_ops; in amd_iommu_alloc_domain_nested()
121 ndom->domain.type = IOMMU_DOMAIN_NESTED; in amd_iommu_alloc_domain_nested()
122 ndom->viommu = aviommu; in amd_iommu_alloc_domain_nested()
125 * Normally, when a guest has multiple pass-through devices, in amd_iommu_alloc_domain_nested()
126 * the IOMMU driver setup DTEs with the same stage-2 table and in amd_iommu_alloc_domain_nested()
128 * if the guest setup different stage-1 tables with same PASID, in amd_iommu_alloc_domain_nested()
139 xa_lock(&aviommu->gdomid_array); in amd_iommu_alloc_domain_nested()
141 gdom_info = gdom_info_load_or_alloc_locked(&aviommu->gdomid_array, ndom->gdom_id); in amd_iommu_alloc_domain_nested()
143 xa_unlock(&aviommu->gdomid_array); in amd_iommu_alloc_domain_nested()
149 if (refcount_inc_not_zero(&gdom_info->users)) { in amd_iommu_alloc_domain_nested()
150 ndom->gdom_info = gdom_info; in amd_iommu_alloc_domain_nested()
151 xa_unlock(&aviommu->gdomid_array); in amd_iommu_alloc_domain_nested()
154 __func__, ndom->gdom_id, gdom_info->hdom_id); in amd_iommu_alloc_domain_nested()
156 return &ndom->domain; in amd_iommu_alloc_domain_nested()
160 gdom_info->hdom_id = amd_iommu_pdom_id_alloc(); in amd_iommu_alloc_domain_nested()
161 if (gdom_info->hdom_id <= 0) { in amd_iommu_alloc_domain_nested()
162 __xa_cmpxchg(&aviommu->gdomid_array, in amd_iommu_alloc_domain_nested()
163 ndom->gdom_id, gdom_info, NULL, GFP_ATOMIC); in amd_iommu_alloc_domain_nested()
164 xa_unlock(&aviommu->gdomid_array); in amd_iommu_alloc_domain_nested()
165 ret = -ENOSPC; in amd_iommu_alloc_domain_nested()
169 ndom->gdom_info = gdom_info; in amd_iommu_alloc_domain_nested()
170 refcount_set(&gdom_info->users, 1); in amd_iommu_alloc_domain_nested()
172 xa_unlock(&aviommu->gdomid_array); in amd_iommu_alloc_domain_nested()
175 __func__, ndom->gdom_id, gdom_info->hdom_id); in amd_iommu_alloc_domain_nested()
177 return &ndom->domain; in amd_iommu_alloc_domain_nested()
191 struct iommu_hwpt_amd_guest *gdte = &ndom->gdte; in set_dte_nested()
199 if (WARN_ON(!ndom->viommu || !ndom->viommu->parent)) in set_dte_nested()
202 parent = ndom->viommu->parent; in set_dte_nested()
206 pt_iommu_amdv1_hw_info(&parent->amdv1, &pt_info); in set_dte_nested()
209 * Use domain ID from nested domain to program DTE. in set_dte_nested()
212 amd_iommu_set_dte_v1(dev_data, parent, ndom->gdom_info->hdom_id, in set_dte_nested()
216 new->data[0] |= DTE_FLAG_GV; in set_dte_nested()
219 new->data[0] |= gdte->dte[0] & DTE_FLAG_PPR; in set_dte_nested()
222 new->data[0] |= gdte->dte[0] & (DTE_GLX | DTE_FLAG_GIOV); in set_dte_nested()
225 new->data[0] |= gdte->dte[0] & DTE_GCR3_14_12; in set_dte_nested()
226 new->data[1] |= gdte->dte[1] & (DTE_GCR3_30_15 | DTE_GCR3_51_31); in set_dte_nested()
228 /* Guest paging mode */ in set_dte_nested()
229 new->data[2] |= gdte->dte[2] & DTE_GPT_LEVEL_MASK; in set_dte_nested()
244 if (WARN_ON(dev_data->pasid_enabled)) in nested_attach_device()
245 return -EINVAL; in nested_attach_device()
247 mutex_lock(&dev_data->mutex); in nested_attach_device()
253 mutex_unlock(&dev_data->mutex); in nested_attach_device()
262 struct amd_iommu_viommu *aviommu = ndom->viommu; in nested_domain_free()
264 xa_lock(&aviommu->gdomid_array); in nested_domain_free()
266 if (!refcount_dec_and_test(&ndom->gdom_info->users)) { in nested_domain_free()
267 xa_unlock(&aviommu->gdomid_array); in nested_domain_free()
275 curr = __xa_cmpxchg(&aviommu->gdomid_array, ndom->gdom_id, in nested_domain_free()
276 ndom->gdom_info, NULL, GFP_ATOMIC); in nested_domain_free()
278 xa_unlock(&aviommu->gdomid_array); in nested_domain_free()
284 __func__, ndom->gdom_id, curr->hdom_id); in nested_domain_free()
286 amd_iommu_pdom_id_free(ndom->gdom_info->hdom_id); in nested_domain_free()