Skip to content

Commit

Permalink
iommu: Add ops->domain_alloc_nested()
Browse files Browse the repository at this point in the history
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.

Link: https://patch.msgid.link/r/1-v1-c252ebdeb57b+329-iommu_paging_flags_jgg@nvidia.com
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
  • Loading branch information
Jason Gunthorpe committed Nov 22, 2024
1 parent 2d76228 commit 64214c2
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 21 deletions.
9 changes: 3 additions & 6 deletions drivers/iommu/intel/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
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
8 changes: 4 additions & 4 deletions drivers/iommu/iommufd/hw_pagetable.c
Original file line number Diff line number Diff line change
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
7 changes: 4 additions & 3 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 Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down
9 changes: 5 additions & 4 deletions include/linux/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 64214c2

Please sign in to comment.