Commit b7a0855e authored by Jason Gunthorpe's avatar Jason Gunthorpe Committed by Joerg Roedel
Browse files

iommu: Add new flag to explictly request PASID capable domain



Introduce new flag (IOMMU_HWPT_ALLOC_PASID) to domain_alloc_users() ops.
If IOMMU supports PASID it will allocate domain. Otherwise return error.
In error path check for -EOPNOTSUPP and try to allocate non-PASID
domain so that DMA-API mode work fine for drivers which does not support
PASID as well.

Also modify __iommu_group_alloc_default_domain() to call
iommu_paging_domain_alloc_flags() with appropriate flag when allocating
paging domain.

Signed-off-by: default avatarJason Gunthorpe <jgg@ziepe.ca>
Co-developed-by: default avatarVasant Hegde <vasant.hegde@amd.com>
Signed-off-by: default avatarVasant Hegde <vasant.hegde@amd.com>
Reviewed-by: default avatarLu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: default avatarKevin Tian <kevin.tian@intel.com>
Link: https://lore.kernel.org/r/20241028093810.5901-4-vasant.hegde@amd.com


Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 20858d4e
Loading
Loading
Loading
Loading
+45 −11
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <trace/events/iommu.h>
#include <linux/sched/mm.h>
#include <linux/msi.h>
#include <uapi/linux/iommufd.h>

#include "dma-iommu.h"
#include "iommu-priv.h"
@@ -99,6 +100,9 @@ static int __iommu_attach_device(struct iommu_domain *domain,
				 struct device *dev);
static int __iommu_attach_group(struct iommu_domain *domain,
				struct iommu_group *group);
static struct iommu_domain *__iommu_paging_domain_alloc_flags(struct device *dev,
						       unsigned int type,
						       unsigned int flags);

enum {
	IOMMU_SET_DOMAIN_MUST_SUCCEED = 1 << 0,
@@ -1585,8 +1589,30 @@ EXPORT_SYMBOL_GPL(fsl_mc_device_group);
static struct iommu_domain *
__iommu_group_alloc_default_domain(struct iommu_group *group, int req_type)
{
	struct device *dev = iommu_group_first_dev(group);
	struct iommu_domain *dom;

	if (group->default_domain && group->default_domain->type == req_type)
		return group->default_domain;

	/*
	 * When allocating the DMA API domain assume that the driver is going to
	 * use PASID and make sure the RID's domain is PASID compatible.
	 */
	if (req_type & __IOMMU_DOMAIN_PAGING) {
		dom = __iommu_paging_domain_alloc_flags(dev, req_type,
			   dev->iommu->max_pasids ? IOMMU_HWPT_ALLOC_PASID : 0);

		/*
		 * If driver does not support PASID feature then
		 * try to allocate non-PASID domain
		 */
		if (PTR_ERR(dom) == -EOPNOTSUPP)
			dom = __iommu_paging_domain_alloc_flags(dev, req_type, 0);

		return dom;
	}

	return __iommu_group_domain_alloc(group, req_type);
}

@@ -1961,15 +1987,8 @@ __iommu_group_domain_alloc(struct iommu_group *group, unsigned int type)
	return __iommu_domain_alloc(dev_iommu_ops(dev), dev, type);
}

/**
 * iommu_paging_domain_alloc_flags() - Allocate a paging domain
 * @dev: device for which the domain is allocated
 * @flags: Enum of iommufd_hwpt_alloc_flags
 *
 * Allocate a paging domain which will be managed by a kernel driver. Return
 * allocated domain if successful, or an ERR pointer for failure.
 */
struct iommu_domain *iommu_paging_domain_alloc_flags(struct device *dev,
static struct iommu_domain *
__iommu_paging_domain_alloc_flags(struct device *dev, unsigned int type,
				  unsigned int flags)
{
	const struct iommu_ops *ops;
@@ -1994,9 +2013,24 @@ struct iommu_domain *iommu_paging_domain_alloc_flags(struct device *dev,
	if (!domain)
		return ERR_PTR(-ENOMEM);

	iommu_domain_init(domain, IOMMU_DOMAIN_UNMANAGED, ops);
	iommu_domain_init(domain, type, ops);
	return domain;
}

/**
 * iommu_paging_domain_alloc_flags() - Allocate a paging domain
 * @dev: device for which the domain is allocated
 * @flags: Bitmap of iommufd_hwpt_alloc_flags
 *
 * Allocate a paging domain which will be managed by a kernel driver. Return
 * allocated domain if successful, or an ERR pointer for failure.
 */
struct iommu_domain *iommu_paging_domain_alloc_flags(struct device *dev,
						     unsigned int flags)
{
	return __iommu_paging_domain_alloc_flags(dev,
					 IOMMU_DOMAIN_UNMANAGED, flags);
}
EXPORT_SYMBOL_GPL(iommu_paging_domain_alloc_flags);

void iommu_domain_free(struct iommu_domain *domain)
+8 −0
Original line number Diff line number Diff line
@@ -359,11 +359,19 @@ struct iommu_vfio_ioas {
 *                                   enforced on device attachment
 * @IOMMU_HWPT_FAULT_ID_VALID: The fault_id field of hwpt allocation data is
 *                             valid.
 * @IOMMU_HWPT_ALLOC_PASID: Requests a domain that can be used with PASID. The
 *                          domain can be attached to any PASID on the device.
 *                          Any domain attached to the non-PASID part of the
 *                          device must also be flaged, otherwise attaching a
 *                          PASID will blocked.
 *                          If IOMMU does not support PASID it will return
 *                          error (-EOPNOTSUPP).
 */
enum iommufd_hwpt_alloc_flags {
	IOMMU_HWPT_ALLOC_NEST_PARENT = 1 << 0,
	IOMMU_HWPT_ALLOC_DIRTY_TRACKING = 1 << 1,
	IOMMU_HWPT_FAULT_ID_VALID = 1 << 2,
	IOMMU_HWPT_ALLOC_PASID = 1 << 3,
};

/**