Skip to content

Commit

Permalink
Merge tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/jgg/iommufd

Pull more iommufd updates from Jason Gunthorpe:
 "Change the driver callback op domain_alloc_user() into two ops:
  domain_alloc_paging_flags() and domain_alloc_nesting() that better
  describe what the ops are expected to do.

  There will be per-driver cleanup based on this going into the next
  cycle via the driver trees"

* tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd:
  iommu: Rename ops->domain_alloc_user() to domain_alloc_paging_flags()
  iommu: Add ops->domain_alloc_nested()
  • Loading branch information
Linus Torvalds committed Nov 27, 2024
2 parents 9ad55a6 + d537647 commit 64e6fc2
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 55 deletions.
9 changes: 4 additions & 5 deletions drivers/iommu/amd/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2407,9 +2407,8 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned int type)
}

static struct iommu_domain *
amd_iommu_domain_alloc_user(struct device *dev, u32 flags,
struct iommu_domain *parent,
const struct iommu_user_data *user_data)
amd_iommu_domain_alloc_paging_flags(struct device *dev, u32 flags,
const struct iommu_user_data *user_data)

{
unsigned int type = IOMMU_DOMAIN_UNMANAGED;
Expand All @@ -2420,7 +2419,7 @@ amd_iommu_domain_alloc_user(struct device *dev, u32 flags,
if (dev)
iommu = get_amd_iommu_from_dev(dev);

if ((flags & ~supported_flags) || parent || user_data)
if ((flags & ~supported_flags) || user_data)
return ERR_PTR(-EOPNOTSUPP);

/* Allocate domain with v2 page table if IOMMU supports PASID. */
Expand Down Expand Up @@ -2884,7 +2883,7 @@ const struct iommu_ops amd_iommu_ops = {
.release_domain = &release_domain,
.identity_domain = &identity_domain.domain,
.domain_alloc = amd_iommu_domain_alloc,
.domain_alloc_user = amd_iommu_domain_alloc_user,
.domain_alloc_paging_flags = amd_iommu_domain_alloc_paging_flags,
.domain_alloc_sva = amd_iommu_domain_alloc_sva,
.probe_device = amd_iommu_probe_device,
.release_device = amd_iommu_release_device,
Expand Down
9 changes: 4 additions & 5 deletions drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -3132,9 +3132,8 @@ static struct iommu_domain arm_smmu_blocked_domain = {
};

static struct iommu_domain *
arm_smmu_domain_alloc_user(struct device *dev, u32 flags,
struct iommu_domain *parent,
const struct iommu_user_data *user_data)
arm_smmu_domain_alloc_paging_flags(struct device *dev, u32 flags,
const struct iommu_user_data *user_data)
{
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
Expand All @@ -3145,7 +3144,7 @@ arm_smmu_domain_alloc_user(struct device *dev, u32 flags,

if (flags & ~PAGING_FLAGS)
return ERR_PTR(-EOPNOTSUPP);
if (parent || user_data)
if (user_data)
return ERR_PTR(-EOPNOTSUPP);

if (flags & IOMMU_HWPT_ALLOC_PASID)
Expand Down Expand Up @@ -3546,7 +3545,7 @@ static struct iommu_ops arm_smmu_ops = {
.hw_info = arm_smmu_hw_info,
.domain_alloc_paging = arm_smmu_domain_alloc_paging,
.domain_alloc_sva = arm_smmu_sva_domain_alloc,
.domain_alloc_user = arm_smmu_domain_alloc_user,
.domain_alloc_paging_flags = arm_smmu_domain_alloc_paging_flags,
.probe_device = arm_smmu_probe_device,
.release_device = arm_smmu_release_device,
.device_group = arm_smmu_device_group,
Expand Down
15 changes: 4 additions & 11 deletions drivers/iommu/intel/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -3328,9 +3328,8 @@ static struct dmar_domain *paging_domain_alloc(struct device *dev, bool first_st
}

static struct iommu_domain *
intel_iommu_domain_alloc_user(struct device *dev, u32 flags,
struct iommu_domain *parent,
const struct iommu_user_data *user_data)
intel_iommu_domain_alloc_paging_flags(struct device *dev, u32 flags,
const struct iommu_user_data *user_data)
{
struct device_domain_info *info = dev_iommu_priv_get(dev);
bool dirty_tracking = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
Expand All @@ -3340,13 +3339,6 @@ 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 (flags &
(~(IOMMU_HWPT_ALLOC_NEST_PARENT | IOMMU_HWPT_ALLOC_DIRTY_TRACKING
| IOMMU_HWPT_FAULT_ID_VALID)))
Expand Down Expand Up @@ -4472,9 +4464,10 @@ const struct iommu_ops intel_iommu_ops = {
.identity_domain = &identity_domain,
.capable = intel_iommu_capable,
.hw_info = intel_iommu_hw_info,
.domain_alloc_user = intel_iommu_domain_alloc_user,
.domain_alloc_paging_flags = intel_iommu_domain_alloc_paging_flags,
.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,
Expand Down
6 changes: 4 additions & 2 deletions drivers/iommu/intel/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
11 changes: 9 additions & 2 deletions drivers/iommu/intel/nested.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions drivers/iommu/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1987,8 +1987,8 @@ __iommu_paging_domain_alloc_flags(struct device *dev, unsigned int type,

if (ops->domain_alloc_paging && !flags)
domain = ops->domain_alloc_paging(dev);
else if (ops->domain_alloc_user)
domain = ops->domain_alloc_user(dev, flags, NULL, NULL);
else if (ops->domain_alloc_paging_flags)
domain = ops->domain_alloc_paging_flags(dev, flags, NULL);
else if (ops->domain_alloc && !flags)
domain = ops->domain_alloc(IOMMU_DOMAIN_UNMANAGED);
else
Expand Down
16 changes: 8 additions & 8 deletions drivers/iommu/iommufd/hw_pagetable.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,

lockdep_assert_held(&ioas->mutex);

if ((flags || user_data) && !ops->domain_alloc_user)
if ((flags || user_data) && !ops->domain_alloc_paging_flags)
return ERR_PTR(-EOPNOTSUPP);
if (flags & ~valid_flags)
return ERR_PTR(-EOPNOTSUPP);
Expand All @@ -139,9 +139,9 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
hwpt_paging->ioas = ioas;
hwpt_paging->nest_parent = flags & IOMMU_HWPT_ALLOC_NEST_PARENT;

if (ops->domain_alloc_user) {
hwpt->domain = ops->domain_alloc_user(idev->dev, flags, NULL,
user_data);
if (ops->domain_alloc_paging_flags) {
hwpt->domain = ops->domain_alloc_paging_flags(idev->dev, flags,
user_data);
if (IS_ERR(hwpt->domain)) {
rc = PTR_ERR(hwpt->domain);
hwpt->domain = NULL;
Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand Down
15 changes: 6 additions & 9 deletions drivers/iommu/iommufd/selftest.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -379,9 +379,8 @@ mock_domain_alloc_nested(struct iommu_domain *parent, u32 flags,
}

static struct iommu_domain *
mock_domain_alloc_user(struct device *dev, u32 flags,
struct iommu_domain *parent,
const struct iommu_user_data *user_data)
mock_domain_alloc_paging_flags(struct device *dev, u32 flags,
const struct iommu_user_data *user_data)
{
bool has_dirty_flag = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
Expand All @@ -390,9 +389,6 @@ mock_domain_alloc_user(struct device *dev, u32 flags,
MOCK_FLAGS_DEVICE_NO_DIRTY;
struct iommu_domain *domain;

if (parent)
return mock_domain_alloc_nested(parent, flags, user_data);

if (user_data)
return ERR_PTR(-EOPNOTSUPP);
if ((flags & ~PAGING_FLAGS) || (has_dirty_flag && no_dirty_ops))
Expand Down Expand Up @@ -718,7 +714,8 @@ static const struct iommu_ops mock_ops = {
.pgsize_bitmap = MOCK_IO_PAGE_SIZE,
.hw_info = mock_domain_hw_info,
.domain_alloc_paging = mock_domain_alloc_paging,
.domain_alloc_user = mock_domain_alloc_user,
.domain_alloc_paging_flags = mock_domain_alloc_paging_flags,
.domain_alloc_nested = mock_domain_alloc_nested,
.capable = mock_domain_capable,
.device_group = generic_device_group,
.probe_device = mock_probe_device,
Expand Down
27 changes: 16 additions & 11 deletions include/linux/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -557,17 +557,19 @@ iommu_copy_struct_from_full_user_array(void *kdst, size_t kdst_entry_size,
* @domain_alloc: allocate and return an iommu domain if success. Otherwise
* NULL is returned. The domain is not fully initialized until
* 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
* new domain must support __IOMMU_DOMAIN_PAGING.
* Upon failure, ERR_PTR must be returned.
* @domain_alloc_paging_flags: Allocate an iommu domain corresponding to the
* input parameters as defined in
* include/uapi/linux/iommufd.h. 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.
* UNMANAGED, DMA, and DMA_FQ domain types. This is the
* same as invoking domain_alloc_paging_flags() with
* @flags=0, @user_data=NULL. A driver should implement
* only one of the two ops.
* @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
Expand Down Expand Up @@ -616,12 +618,15 @@ struct iommu_ops {

/* Domain allocation and freeing by the iommu driver */
struct iommu_domain *(*domain_alloc)(unsigned iommu_domain_type);
struct iommu_domain *(*domain_alloc_user)(
struct device *dev, u32 flags, struct iommu_domain *parent,
struct iommu_domain *(*domain_alloc_paging_flags)(
struct device *dev, u32 flags,
const struct iommu_user_data *user_data);
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);
Expand Down

0 comments on commit 64e6fc2

Please sign in to comment.