Message ID | 20240412081516.31168-13-yi.l.liu@intel.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | iommufd support pasid attach/replace | expand |
> From: Liu, Yi L <yi.l.liu@intel.com> > Sent: Friday, April 12, 2024 4:15 PM > > From: Lu Baolu <baolu.lu@linux.intel.com> > > This allows the upper layers to set a nested type domain to a PASID of a > device if the PASID feature is supported by the IOMMU hardware. > > The set_dev_pasid callback for non-nested domain has already be there, so > this only needs to add it for nested domains. Note that the S2 domain with > dirty tracking capability is not supported yet as no user for now. S2 domain does support dirty tracking. Do you mean the specific check in intel_iommu_set_dev_pasid() i.e. pasid-granular dirty tracking is not supported yet? > +static int intel_nested_set_dev_pasid(struct iommu_domain *domain, > + struct device *dev, ioasid_t pasid, > + struct iommu_domain *old) > +{ > + struct device_domain_info *info = dev_iommu_priv_get(dev); > + struct dmar_domain *dmar_domain = to_dmar_domain(domain); > + struct intel_iommu *iommu = info->iommu; > + > + if (iommu->agaw < dmar_domain->s2_domain->agaw) > + return -EINVAL; > + this check is covered by prepare_domain_attach_device() already.
On 2024/4/17 17:25, Tian, Kevin wrote: >> From: Liu, Yi L <yi.l.liu@intel.com> >> Sent: Friday, April 12, 2024 4:15 PM >> >> From: Lu Baolu <baolu.lu@linux.intel.com> >> >> This allows the upper layers to set a nested type domain to a PASID of a >> device if the PASID feature is supported by the IOMMU hardware. >> >> The set_dev_pasid callback for non-nested domain has already be there, so >> this only needs to add it for nested domains. Note that the S2 domain with >> dirty tracking capability is not supported yet as no user for now. > > S2 domain does support dirty tracking. Do you mean the specific > check in intel_iommu_set_dev_pasid() i.e. pasid-granular dirty > tracking is not supported yet? yes. We may remove this check when real usage comes. e.g. SIOV. >> +static int intel_nested_set_dev_pasid(struct iommu_domain *domain, >> + struct device *dev, ioasid_t pasid, >> + struct iommu_domain *old) >> +{ >> + struct device_domain_info *info = dev_iommu_priv_get(dev); >> + struct dmar_domain *dmar_domain = to_dmar_domain(domain); >> + struct intel_iommu *iommu = info->iommu; >> + >> + if (iommu->agaw < dmar_domain->s2_domain->agaw) >> + return -EINVAL; >> + > > this check is covered by prepare_domain_attach_device() already. This was added to avoid modifying the s2_domain's agaw. I'm fine to remove it personally as the existing attach path also needs to update domain's agaw per device attachment. @Baolu, how about your opinion?
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 9e79ffdd47db..052b90917ced 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -319,6 +319,11 @@ static int domain_type_is_si(struct dmar_domain *domain) return domain->domain.type == IOMMU_DOMAIN_IDENTITY; } +static int domain_type_is_nested(struct dmar_domain *domain) +{ + return domain->domain.type == IOMMU_DOMAIN_NESTED; +} + static int domain_pfn_supported(struct dmar_domain *domain, unsigned long pfn) { int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; @@ -4626,9 +4631,9 @@ static void intel_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid, intel_drain_pasid_prq(dev, pasid); } -static int intel_iommu_set_dev_pasid(struct iommu_domain *domain, - struct device *dev, ioasid_t pasid, - struct iommu_domain *old) +int intel_iommu_set_dev_pasid(struct iommu_domain *domain, + struct device *dev, ioasid_t pasid, + struct iommu_domain *old) { struct device_domain_info *info = dev_iommu_priv_get(dev); struct dmar_domain *dmar_domain = to_dmar_domain(domain); @@ -4650,7 +4655,15 @@ static int intel_iommu_set_dev_pasid(struct iommu_domain *domain, if (old) intel_iommu_remove_dev_pasid(dev, pasid, old); - ret = prepare_domain_attach_device(domain, dev); + /* + * Nested type domain should adjust its parent domain according + * to iommu capability. + */ + if (domain_type_is_nested(dmar_domain)) + ret = prepare_domain_attach_device( + &dmar_domain->s2_domain->domain, dev); + else + ret = prepare_domain_attach_device(domain, dev); if (ret) return ret; @@ -4664,6 +4677,8 @@ static int intel_iommu_set_dev_pasid(struct iommu_domain *domain, if (domain_type_is_si(dmar_domain)) ret = intel_pasid_setup_pass_through(iommu, dev, pasid); + else if (domain_type_is_nested(dmar_domain)) + ret = intel_pasid_setup_nested(iommu, dev, pasid, dmar_domain); else if (dmar_domain->use_first_level) ret = domain_setup_first_level(iommu, dmar_domain, dev, pasid); diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h index 404d2476a877..3dfd183c9736 100644 --- a/drivers/iommu/intel/iommu.h +++ b/drivers/iommu/intel/iommu.h @@ -1082,6 +1082,9 @@ void device_block_translation(struct device *dev); int prepare_domain_attach_device(struct iommu_domain *domain, struct device *dev); void domain_update_iommu_cap(struct dmar_domain *domain); +int intel_iommu_set_dev_pasid(struct iommu_domain *domain, + struct device *dev, ioasid_t pasid, + struct iommu_domain *old); int dmar_ir_support(void); diff --git a/drivers/iommu/intel/nested.c b/drivers/iommu/intel/nested.c index a7d68f3d518a..7cb124cc0ca0 100644 --- a/drivers/iommu/intel/nested.c +++ b/drivers/iommu/intel/nested.c @@ -70,6 +70,20 @@ static int intel_nested_attach_dev(struct iommu_domain *domain, return 0; } +static int intel_nested_set_dev_pasid(struct iommu_domain *domain, + struct device *dev, ioasid_t pasid, + struct iommu_domain *old) +{ + struct device_domain_info *info = dev_iommu_priv_get(dev); + struct dmar_domain *dmar_domain = to_dmar_domain(domain); + struct intel_iommu *iommu = info->iommu; + + if (iommu->agaw < dmar_domain->s2_domain->agaw) + return -EINVAL; + + return intel_iommu_set_dev_pasid(domain, dev, pasid, old); +} + static void intel_nested_domain_free(struct iommu_domain *domain) { struct dmar_domain *dmar_domain = to_dmar_domain(domain); @@ -170,6 +184,7 @@ static int intel_nested_cache_invalidate_user(struct iommu_domain *domain, static const struct iommu_domain_ops intel_nested_domain_ops = { .attach_dev = intel_nested_attach_dev, + .set_dev_pasid = intel_nested_set_dev_pasid, .free = intel_nested_domain_free, .cache_invalidate_user = intel_nested_cache_invalidate_user, };