diff mbox series

[1/2] iommu: Add ops->domain_alloc_nested()

Message ID 1-v1-c252ebdeb57b+329-iommu_paging_flags_jgg@nvidia.com (mailing list archive)
State New
Headers show
Series Rename ops->domain_alloc_user() to domain_alloc_paging_flags() | expand

Commit Message

Jason Gunthorpe Nov. 14, 2024, 7:55 p.m. UTC
It turns out all the drivers that are using this immediately call into
another function, so just make that function directly into the op. This
makes paging=NULL for domain_alloc_user and we can remove the argument in
the next patch.

The function mirrors the similar op in the viommu that allocates a nested
domain on top of the viommu's nesting parent. This version supports cases
where a viommu is not being used.

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
 drivers/iommu/intel/iommu.c          |  9 +++------
 drivers/iommu/intel/iommu.h          |  6 ++++--
 drivers/iommu/intel/nested.c         | 11 +++++++++--
 drivers/iommu/iommufd/hw_pagetable.c |  8 ++++----
 drivers/iommu/iommufd/selftest.c     |  7 ++++---
 include/linux/iommu.h                |  9 +++++----
 6 files changed, 29 insertions(+), 21 deletions(-)

Comments

Baolu Lu Nov. 15, 2024, 3:19 a.m. UTC | #1
On 11/15/24 03:55, Jason Gunthorpe wrote:
> It turns out all the drivers that are using this immediately call into
> another function, so just make that function directly into the op. This
> makes paging=NULL for domain_alloc_user and we can remove the argument in
> the next patch.
> 
> The function mirrors the similar op in the viommu that allocates a nested
> domain on top of the viommu's nesting parent. This version supports cases
> where a viommu is not being used.
> 
> Signed-off-by: Jason Gunthorpe<jgg@nvidia.com>
> ---
>   drivers/iommu/intel/iommu.c          |  9 +++------
>   drivers/iommu/intel/iommu.h          |  6 ++++--
>   drivers/iommu/intel/nested.c         | 11 +++++++++--
>   drivers/iommu/iommufd/hw_pagetable.c |  8 ++++----
>   drivers/iommu/iommufd/selftest.c     |  7 ++++---
>   include/linux/iommu.h                |  9 +++++----
>   6 files changed, 29 insertions(+), 21 deletions(-)
>

Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>

with below minor suggestion.

[...]

> diff --git a/drivers/iommu/intel/nested.c b/drivers/iommu/intel/nested.c
> index 42c4533a6ea21d..aba92c00b42740 100644
> --- a/drivers/iommu/intel/nested.c
> +++ b/drivers/iommu/intel/nested.c
> @@ -186,14 +186,21 @@ static const struct iommu_domain_ops intel_nested_domain_ops = {
>   	.cache_invalidate_user	= intel_nested_cache_invalidate_user,
>   };
>   
> -struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *parent,
> -					       const struct iommu_user_data *user_data)
> +struct iommu_domain *
> +intel_iommu_domain_alloc_nested(struct device *dev, struct iommu_domain *parent,
> +				u32 flags,
> +				const struct iommu_user_data *user_data)
>   {
> +	struct device_domain_info *info = dev_iommu_priv_get(dev);
>   	struct dmar_domain *s2_domain = to_dmar_domain(parent);
> +	struct intel_iommu *iommu = info->iommu;
>   	struct iommu_hwpt_vtd_s1 vtd;
>   	struct dmar_domain *domain;
>   	int ret;
>   
> +	if (!nested_supported(iommu) || flags)
> +		return ERR_PTR(-EOPNOTSUPP);

How about making it like

         if (!nested_supported(iommu) || (flags & 
~IOMMU_HWPT_FAULT_ID_VALID))
                 return ERR_PTR(-EOPNOTSUPP);

         if ((flags & IOMMU_HWPT_FAULT_ID_VALID) && !info->pri_supported)
                 return ERR_PTR(-EOPNOTSUPP);

?

--
baolu
Jason Gunthorpe Nov. 15, 2024, 2:48 p.m. UTC | #2
On Fri, Nov 15, 2024 at 11:19:03AM +0800, Baolu Lu wrote:

> > diff --git a/drivers/iommu/intel/nested.c b/drivers/iommu/intel/nested.c
> > index 42c4533a6ea21d..aba92c00b42740 100644
> > --- a/drivers/iommu/intel/nested.c
> > +++ b/drivers/iommu/intel/nested.c
> > @@ -186,14 +186,21 @@ static const struct iommu_domain_ops intel_nested_domain_ops = {
> >   	.cache_invalidate_user	= intel_nested_cache_invalidate_user,
> >   };
> > -struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *parent,
> > -					       const struct iommu_user_data *user_data)
> > +struct iommu_domain *
> > +intel_iommu_domain_alloc_nested(struct device *dev, struct iommu_domain *parent,
> > +				u32 flags,
> > +				const struct iommu_user_data *user_data)
> >   {
> > +	struct device_domain_info *info = dev_iommu_priv_get(dev);
> >   	struct dmar_domain *s2_domain = to_dmar_domain(parent);
> > +	struct intel_iommu *iommu = info->iommu;
> >   	struct iommu_hwpt_vtd_s1 vtd;
> >   	struct dmar_domain *domain;
> >   	int ret;
> > +	if (!nested_supported(iommu) || flags)
> > +		return ERR_PTR(-EOPNOTSUPP);
> 
> How about making it like
> 
>         if (!nested_supported(iommu) || (flags &
> ~IOMMU_HWPT_FAULT_ID_VALID))
>                 return ERR_PTR(-EOPNOTSUPP);
> 
>         if ((flags & IOMMU_HWPT_FAULT_ID_VALID) && !info->pri_supported)
>                 return ERR_PTR(-EOPNOTSUPP);

I think that is possibly a good idea for a followup, but right now it
was left like this:

+       hwpt->domain = ops->domain_alloc_nested(
+               idev->dev, parent->common.domain,
+               flags & ~IOMMU_HWPT_FAULT_ID_VALID, user_data);

So you'd also want to remove the FAUlT_ID_VALID masking there to move
it to the driver.

I'm also wondering if we should put the pri_supported concept into
core code flags and have less boilerplate in drivers.

Thanks,
Jason
diff mbox series

Patch

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 527f6f89d8a1f5..6f11a075114f7a 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -3340,12 +3340,8 @@  intel_iommu_domain_alloc_user(struct device *dev, u32 flags,
 	struct iommu_domain *domain;
 	bool first_stage;
 
-	/* Must be NESTING domain */
-	if (parent) {
-		if (!nested_supported(iommu) || flags)
-			return ERR_PTR(-EOPNOTSUPP);
-		return intel_nested_domain_alloc(parent, user_data);
-	}
+	if (parent)
+		return ERR_PTR(-EOPNOTSUPP);
 
 	if (flags &
 	    (~(IOMMU_HWPT_ALLOC_NEST_PARENT | IOMMU_HWPT_ALLOC_DIRTY_TRACKING
@@ -4475,6 +4471,7 @@  const struct iommu_ops intel_iommu_ops = {
 	.domain_alloc_user	= intel_iommu_domain_alloc_user,
 	.domain_alloc_sva	= intel_svm_domain_alloc,
 	.domain_alloc_paging	= intel_iommu_domain_alloc_paging,
+	.domain_alloc_nested	= intel_iommu_domain_alloc_nested,
 	.probe_device		= intel_iommu_probe_device,
 	.release_device		= intel_iommu_release_device,
 	.get_resv_regions	= intel_iommu_get_resv_regions,
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index 2cca094c259dc1..6ea7bbe26b19d5 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -1265,8 +1265,10 @@  int __domain_setup_first_level(struct intel_iommu *iommu,
 int dmar_ir_support(void);
 
 void iommu_flush_write_buffer(struct intel_iommu *iommu);
-struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *parent,
-					       const struct iommu_user_data *user_data);
+struct iommu_domain *
+intel_iommu_domain_alloc_nested(struct device *dev, struct iommu_domain *parent,
+				u32 flags,
+				const struct iommu_user_data *user_data);
 struct device *device_rbtree_find(struct intel_iommu *iommu, u16 rid);
 
 enum cache_tag_type {
diff --git a/drivers/iommu/intel/nested.c b/drivers/iommu/intel/nested.c
index 42c4533a6ea21d..aba92c00b42740 100644
--- a/drivers/iommu/intel/nested.c
+++ b/drivers/iommu/intel/nested.c
@@ -186,14 +186,21 @@  static const struct iommu_domain_ops intel_nested_domain_ops = {
 	.cache_invalidate_user	= intel_nested_cache_invalidate_user,
 };
 
-struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *parent,
-					       const struct iommu_user_data *user_data)
+struct iommu_domain *
+intel_iommu_domain_alloc_nested(struct device *dev, struct iommu_domain *parent,
+				u32 flags,
+				const struct iommu_user_data *user_data)
 {
+	struct device_domain_info *info = dev_iommu_priv_get(dev);
 	struct dmar_domain *s2_domain = to_dmar_domain(parent);
+	struct intel_iommu *iommu = info->iommu;
 	struct iommu_hwpt_vtd_s1 vtd;
 	struct dmar_domain *domain;
 	int ret;
 
+	if (!nested_supported(iommu) || flags)
+		return ERR_PTR(-EOPNOTSUPP);
+
 	/* Must be nested domain */
 	if (user_data->type != IOMMU_HWPT_DATA_VTD_S1)
 		return ERR_PTR(-EOPNOTSUPP);
diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c
index 9236e8ca9aa864..ec3c64a8c79633 100644
--- a/drivers/iommu/iommufd/hw_pagetable.c
+++ b/drivers/iommu/iommufd/hw_pagetable.c
@@ -227,7 +227,7 @@  iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx,
 	int rc;
 
 	if ((flags & ~IOMMU_HWPT_FAULT_ID_VALID) ||
-	    !user_data->len || !ops->domain_alloc_user)
+	    !user_data->len || !ops->domain_alloc_nested)
 		return ERR_PTR(-EOPNOTSUPP);
 	if (parent->auto_domain || !parent->nest_parent ||
 	    parent->common.domain->owner != ops)
@@ -242,9 +242,9 @@  iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx,
 	refcount_inc(&parent->common.obj.users);
 	hwpt_nested->parent = parent;
 
-	hwpt->domain = ops->domain_alloc_user(idev->dev,
-					      flags & ~IOMMU_HWPT_FAULT_ID_VALID,
-					      parent->common.domain, user_data);
+	hwpt->domain = ops->domain_alloc_nested(
+		idev->dev, parent->common.domain,
+		flags & ~IOMMU_HWPT_FAULT_ID_VALID, user_data);
 	if (IS_ERR(hwpt->domain)) {
 		rc = PTR_ERR(hwpt->domain);
 		hwpt->domain = NULL;
diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c
index 2f9de177dffc79..c58083c3660aee 100644
--- a/drivers/iommu/iommufd/selftest.c
+++ b/drivers/iommu/iommufd/selftest.c
@@ -356,8 +356,8 @@  __mock_domain_alloc_nested(const struct iommu_user_data *user_data)
 }
 
 static struct iommu_domain *
-mock_domain_alloc_nested(struct iommu_domain *parent, u32 flags,
-			 const struct iommu_user_data *user_data)
+mock_domain_alloc_nested(struct device *dev, struct iommu_domain *parent,
+			 u32 flags, const struct iommu_user_data *user_data)
 {
 	struct mock_iommu_domain_nested *mock_nested;
 	struct mock_iommu_domain *mock_parent;
@@ -391,7 +391,7 @@  mock_domain_alloc_user(struct device *dev, u32 flags,
 	struct iommu_domain *domain;
 
 	if (parent)
-		return mock_domain_alloc_nested(parent, flags, user_data);
+		return ERR_PTR(-EOPNOTSUPP);
 
 	if (user_data)
 		return ERR_PTR(-EOPNOTSUPP);
@@ -719,6 +719,7 @@  static const struct iommu_ops mock_ops = {
 	.hw_info = mock_domain_hw_info,
 	.domain_alloc_paging = mock_domain_alloc_paging,
 	.domain_alloc_user = mock_domain_alloc_user,
+	.domain_alloc_nested = mock_domain_alloc_nested,
 	.capable = mock_domain_capable,
 	.device_group = generic_device_group,
 	.probe_device = mock_probe_device,
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index d6aaaec3caf462..0472cc1245192d 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -559,15 +559,13 @@  iommu_copy_struct_from_full_user_array(void *kdst, size_t kdst_entry_size,
  *                the caller iommu_domain_alloc() returns.
  * @domain_alloc_user: Allocate an iommu domain corresponding to the input
  *                     parameters as defined in include/uapi/linux/iommufd.h.
- *                     Upon success, if the @user_data is valid and the @parent
- *                     points to a kernel-managed domain, the new domain must be
- *                     IOMMU_DOMAIN_NESTED type; otherwise, the @parent must be
- *                     NULL while the @user_data can be optionally provided, the
+ *                     The @user_data can be optionally provided, the
  *                     new domain must support __IOMMU_DOMAIN_PAGING.
  *                     Upon failure, ERR_PTR must be returned.
  * @domain_alloc_paging: Allocate an iommu_domain that can be used for
  *                       UNMANAGED, DMA, and DMA_FQ domain types.
  * @domain_alloc_sva: Allocate an iommu_domain for Shared Virtual Addressing.
+ * @domain_alloc_nested: Allocate an iommu_domain for nested translation.
  * @probe_device: Add device to iommu driver handling
  * @release_device: Remove device from iommu driver handling
  * @probe_finalize: Do final setup work after the device is added to an IOMMU
@@ -622,6 +620,9 @@  struct iommu_ops {
 	struct iommu_domain *(*domain_alloc_paging)(struct device *dev);
 	struct iommu_domain *(*domain_alloc_sva)(struct device *dev,
 						 struct mm_struct *mm);
+	struct iommu_domain *(*domain_alloc_nested)(
+		struct device *dev, struct iommu_domain *parent, u32 flags,
+		const struct iommu_user_data *user_data);
 
 	struct iommu_device *(*probe_device)(struct device *dev);
 	void (*release_device)(struct device *dev);