On Sat, 26 Oct 2024 at 07:50, Nicolin Chen <nicolinc@xxxxxxxxxx> wrote: > > Now a vIOMMU holds a shareable nesting parent HWPT. So, it can act like > that nesting parent HWPT to allocate a nested HWPT. > > Support that in the IOMMU_HWPT_ALLOC ioctl handler, and update its kdoc. > > Also, add an iommufd_hwpt_nested_alloc_for_viommu helper to allocate a > nested HWPT for a vIOMMU object. Since a vIOMMU object holds the parent > hwpt's refcount already, increase the refcount of the vIOMMU only. > > Signed-off-by: Nicolin Chen <nicolinc@xxxxxxxxxx> > --- > drivers/iommu/iommufd/iommufd_private.h | 1 + > include/uapi/linux/iommufd.h | 14 ++--- > drivers/iommu/iommufd/hw_pagetable.c | 71 ++++++++++++++++++++++++- > 3 files changed, 79 insertions(+), 7 deletions(-) > > diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h > index 9adf8d616796..8c9ab35eaea5 100644 > --- a/drivers/iommu/iommufd/iommufd_private.h > +++ b/drivers/iommu/iommufd/iommufd_private.h > @@ -288,6 +288,7 @@ struct iommufd_hwpt_paging { > struct iommufd_hwpt_nested { > struct iommufd_hw_pagetable common; > struct iommufd_hwpt_paging *parent; > + struct iommufd_viommu *viommu; > }; > > static inline bool hwpt_is_paging(struct iommufd_hw_pagetable *hwpt) > diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h > index 3d320d069654..717659b9fdce 100644 > --- a/include/uapi/linux/iommufd.h > +++ b/include/uapi/linux/iommufd.h > @@ -430,7 +430,7 @@ enum iommu_hwpt_data_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 or HWPT to connect this HWPT to > + * @pt_id: The IOAS or HWPT or vIOMMU to connect this HWPT to > * @out_hwpt_id: The ID of the new HWPT > * @__reserved: Must be 0 > * @data_type: One of enum iommu_hwpt_data_type > @@ -449,11 +449,13 @@ enum iommu_hwpt_data_type { > * IOMMU_HWPT_DATA_NONE. The HWPT can be allocated as a parent HWPT for a > * nesting configuration by passing IOMMU_HWPT_ALLOC_NEST_PARENT via @flags. > * > - * A user-managed nested HWPT will be created from a given parent HWPT via > - * @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 @data_type > - * must be set to a pre-defined type corresponding to an I/O page table > - * type supported by the underlying IOMMU hardware. > + * A user-managed nested HWPT will be created from a given vIOMMU (wrapping a > + * parent HWPT) or a parent HWPT via @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 @data_type must be set to a pre-defined type corresponding to an > + * I/O page table type supported by the underlying IOMMU hardware. The device > + * via @dev_id and the vIOMMU via @pt_id must be associated to the same IOMMU > + * instance. > * > * If the @data_type is set to IOMMU_HWPT_DATA_NONE, @data_len and > * @data_uptr should be zero. Otherwise, both @data_len and @data_uptr > diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c > index d06bf6e6c19f..1df5d40c93df 100644 > --- a/drivers/iommu/iommufd/hw_pagetable.c > +++ b/drivers/iommu/iommufd/hw_pagetable.c > @@ -57,7 +57,10 @@ void iommufd_hwpt_nested_destroy(struct iommufd_object *obj) > container_of(obj, struct iommufd_hwpt_nested, common.obj); > > __iommufd_hwpt_destroy(&hwpt_nested->common); > - refcount_dec(&hwpt_nested->parent->common.obj.users); > + if (hwpt_nested->viommu) > + refcount_dec(&hwpt_nested->viommu->obj.users); > + else > + refcount_dec(&hwpt_nested->parent->common.obj.users); > } > > void iommufd_hwpt_nested_abort(struct iommufd_object *obj) > @@ -260,6 +263,56 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx, > return ERR_PTR(rc); > } > > +/** > + * iommufd_viommu_alloc_hwpt_nested() - Get a hwpt_nested for a vIOMMU > + * @viommu: vIOMMU ojbect to associate the hwpt_nested/domain with > + * @user_data: user_data pointer. Must be valid > + * > + * Allocate a new IOMMU_DOMAIN_NESTED for a vIOMMU and return it as a NESTED > + * hw_pagetable. > + */ > +static struct iommufd_hwpt_nested * > +iommufd_viommu_alloc_hwpt_nested(struct iommufd_viommu *viommu, u32 flags, > + const struct iommu_user_data *user_data) > +{ > + struct iommufd_hwpt_nested *hwpt_nested; > + struct iommufd_hw_pagetable *hwpt; > + int rc; > + > + if (flags) > + return ERR_PTR(-EOPNOTSUPP); This check should be removed. When a user page fault is required, IOMMU_HWPT_FAULT_ID_VALID is set. if (cmd->flags & IOMMU_HWPT_FAULT_ID_VALID) { By the way, has qemu changed compared with v3? I still got a hardware error in this version, in check Thanks