diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index 2b7099e09852..a223387eec5c 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -2769,6 +2769,14 @@ static struct iommu_domain *amd_iommu_domain_alloc_paging_v2(struct device *dev, return &domain->domain; } +static inline bool is_nest_parent_supported(u32 flags) +{ + /* Only allow nest parent when these features are supported */ + return check_feature(FEATURE_GT) && + check_feature(FEATURE_GIOSUP) && + check_feature2(FEATURE_GCR3TRPMODE); +} + static struct iommu_domain * amd_iommu_domain_alloc_paging_flags(struct device *dev, u32 flags, const struct iommu_user_data *user_data) @@ -2776,16 +2784,28 @@ amd_iommu_domain_alloc_paging_flags(struct device *dev, u32 flags, { struct amd_iommu *iommu = get_amd_iommu_from_dev(dev); const u32 supported_flags = IOMMU_HWPT_ALLOC_DIRTY_TRACKING | - IOMMU_HWPT_ALLOC_PASID; + IOMMU_HWPT_ALLOC_PASID | + IOMMU_HWPT_ALLOC_NEST_PARENT; if ((flags & ~supported_flags) || user_data) return ERR_PTR(-EOPNOTSUPP); switch (flags & supported_flags) { case IOMMU_HWPT_ALLOC_DIRTY_TRACKING: - /* Allocate domain with v1 page table for dirty tracking */ - if (!amd_iommu_hd_support(iommu)) + case IOMMU_HWPT_ALLOC_NEST_PARENT: + case IOMMU_HWPT_ALLOC_DIRTY_TRACKING | IOMMU_HWPT_ALLOC_NEST_PARENT: + /* + * Allocate domain with v1 page table for dirty tracking + * and/or Nest parent. + */ + if ((flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING) && + !amd_iommu_hd_support(iommu)) break; + + if ((flags & IOMMU_HWPT_ALLOC_NEST_PARENT) && + !is_nest_parent_supported(flags)) + break; + return amd_iommu_domain_alloc_paging_v1(dev, flags); case IOMMU_HWPT_ALLOC_PASID: /* Allocate domain with v2 page table if IOMMU supports PASID. */