lkml.org 
[lkml]   [2023]   [Sep]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v4 10/17] iommufd: Support IOMMU_HWPT_ALLOC allocation with user data
    Date
    IOMMU_HWPT_ALLOC already supports iommu_domain allocation for usersapce.
    But it can only allocate a hw_pagetable that associates to a given IOAS,
    i.e. only a kernel-managed hw_pagetable of IOMMU_HWPT_TYPE_DEFAULT type.

    IOMMU drivers can now support user-managed hw_pagetables, for two-stage
    translation use cases, that require user data input from the user space.

    Extend the IOMMU_HWPT_ALLOC ioctl to accept non-default hwpt_type with a
    type specified user data. Also, update the @pt_id to accept hwpt_id too
    besides an ioas_id. Then, pass them to the downstream alloc_fn().

    Co-developed-by: Nicolin Chen <nicolinc@nvidia.com>
    Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
    Signed-off-by: Yi Liu <yi.l.liu@intel.com>
    ---
    drivers/iommu/iommufd/hw_pagetable.c | 19 ++++++++++++++++++-
    include/uapi/linux/iommufd.h | 23 +++++++++++++++++++++--
    2 files changed, 39 insertions(+), 3 deletions(-)

    diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c
    index 90fd65859e28..ab25de149ae6 100644
    --- a/drivers/iommu/iommufd/hw_pagetable.c
    +++ b/drivers/iommu/iommufd/hw_pagetable.c
    @@ -300,6 +300,7 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd)
    bool flag);
    struct iommufd_hw_pagetable *hwpt, *parent;
    struct iommu_hwpt_alloc *cmd = ucmd->cmd;
    + struct iommu_user_data *data = NULL;
    struct iommufd_object *pt_obj;
    struct iommufd_device *idev;
    struct iommufd_ioas *ioas;
    @@ -308,6 +309,11 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd)

    if (cmd->flags & ~IOMMU_HWPT_ALLOC_NEST_PARENT || cmd->__reserved)
    return -EOPNOTSUPP;
    + if (!cmd->data_len && cmd->hwpt_type != IOMMU_HWPT_TYPE_DEFAULT)
    + return -EINVAL;
    + if (cmd->flags & IOMMU_HWPT_ALLOC_NEST_PARENT &&
    + cmd->hwpt_type != IOMMU_HWPT_TYPE_DEFAULT)
    + return -EINVAL;

    idev = iommufd_get_device(ucmd, cmd->dev_id);
    if (IS_ERR(idev))
    @@ -340,9 +346,19 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd)
    goto out_put_pt;
    }

    + if (cmd->data_len) {
    + data = kzalloc(sizeof(*data), GFP_KERNEL);
    + if (!data) {
    + rc = -ENOMEM;
    + goto out_put_pt;
    + }
    + data->uptr = u64_to_user_ptr(cmd->data_uptr);
    + data->len = cmd->data_len;
    + }
    +
    mutex_lock(mutex);
    hwpt = alloc_fn(ucmd->ictx, pt_obj, idev, cmd->flags,
    - IOMMU_HWPT_TYPE_DEFAULT, NULL, false);
    + cmd->hwpt_type, data, false);
    if (IS_ERR(hwpt)) {
    rc = PTR_ERR(hwpt);
    goto out_unlock;
    @@ -359,6 +375,7 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd)
    iommufd_object_abort_and_destroy(ucmd->ictx, &hwpt->obj);
    out_unlock:
    mutex_unlock(mutex);
    + kfree(data);
    out_put_pt:
    iommufd_put_object(pt_obj);
    out_put_idev:
    diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
    index 3c8660fe9bb1..c46b1f772f20 100644
    --- a/include/uapi/linux/iommufd.h
    +++ b/include/uapi/linux/iommufd.h
    @@ -370,15 +370,31 @@ enum iommu_hwpt_type {
    * @size: sizeof(struct iommu_hwpt_alloc)
    * @flags: Combination of enum iommufd_hwpt_alloc_flags
    * @dev_id: The device to allocate this HWPT for
    - * @pt_id: The IOAS to connect this HWPT to
    + * @pt_id: The IOAS or HWPT to connect this HWPT to
    * @out_hwpt_id: The ID of the new HWPT
    * @__reserved: Must be 0
    + * @hwpt_type: One of enum iommu_hwpt_type
    + * @data_len: Length of the type specific data
    + * @data_uptr: User pointer to the type specific data
    *
    * Explicitly allocate a hardware page table object. This is the same object
    * type that is returned by iommufd_device_attach() and represents the
    * underlying iommu driver's iommu_domain kernel object.
    *
    - * A HWPT will be created with the IOVA mappings from the given IOAS.
    + * A kernel-managed HWPT will be created with the mappings from the given
    + * IOAS via the @pt_id. The @hwpt_type for this allocation can be set to
    + * either IOMMU_HWPT_TYPE_DEFAULT or a pre-defined type corresponding to
    + * an I/O page table type supported by the underlying IOMMU hardware.
    + *
    + * A user-managed HWPT will be created from a given parent HWPT via the
    + * @pt_id, in which the parent HWPT must be allocated previously via the
    + * same ioctl from a given IOAS (@pt_id). In this case, the @hwpt_type
    + * must be set to a pre-defined type corresponding to an I/O page table
    + * type supported by the underlying IOMMU hardware.
    + *
    + * If the @hwpt_type is set to IOMMU_HWPT_TYPE_DEFAULT, @data_len and
    + * @data_uptr should be zero. Otherwise, both @data_len and @data_uptr
    + * must be given.
    */
    struct iommu_hwpt_alloc {
    __u32 size;
    @@ -387,6 +403,9 @@ struct iommu_hwpt_alloc {
    __u32 pt_id;
    __u32 out_hwpt_id;
    __u32 __reserved;
    + __u32 hwpt_type;
    + __u32 data_len;
    + __aligned_u64 data_uptr;
    };
    #define IOMMU_HWPT_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_ALLOC)

    --
    2.34.1
    \
     
     \ /
      Last update: 2023-09-21 20:55    [W:2.379 / U:0.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site