Message ID | f70cdcc21df7cf07ae1da02aba8a5aa932718a25.1746757630.git.nicolinc@nvidia.com |
---|---|
State | New |
Headers | show |
Series | iommufd: Add vIOMMU infrastructure (Part-4 HW QUEUE) | expand |
On Thu, May 08, 2025 at 08:02:39PM -0700, Nicolin Chen wrote: > Repurpose the @__reserved field in the struct iommu_hw_info_arm_smmuv3, > to an HW implementation-defined field @impl. It would be nicer to have a tegra/cmdq specific struct and a way for iommu_hw_info to select it. 'impl' isn't going to scale very well if something else wants to use this. We have out_data_type but we could have an input sub_data_type too. 0 means what we have today, then a simple enum to select another info struct. > @@ -726,6 +726,7 @@ struct arm_smmu_impl_ops { > struct arm_smmu_domain *smmu_domain, struct iommufd_ctx *ictx, > unsigned int viommu_type, > const struct iommu_user_data *user_data); > + u32 (*hw_info)(struct arm_smmu_device *smmu, u32 *impl); > }; Then the dispatch here is just having a sub-struct enum # in arm_smmu_impl_ops for dispatching. Jason
On Thu, May 15, 2025 at 02:17:06PM -0300, Jason Gunthorpe wrote: > On Thu, May 08, 2025 at 08:02:39PM -0700, Nicolin Chen wrote: > > Repurpose the @__reserved field in the struct iommu_hw_info_arm_smmuv3, > > to an HW implementation-defined field @impl. > > It would be nicer to have a tegra/cmdq specific struct and a way for > iommu_hw_info to select it. 'impl' isn't going to scale very well if > something else wants to use this. > > We have out_data_type but we could have an input sub_data_type too. 0 > means what we have today, then a simple enum to select another info > struct. So, there will be two hw_info calls back to back right? Should the first call return out_data_type=CMDQV while returning the arm_smmu_v3 hw_info data? Otherwise, VMM wouldn't know what to set in the input sub_data_type of the 2nd ioctl? Thanks Nicolin
On Thu, May 15, 2025 at 11:52:05AM -0700, Nicolin Chen wrote: > On Thu, May 15, 2025 at 02:17:06PM -0300, Jason Gunthorpe wrote: > > On Thu, May 08, 2025 at 08:02:39PM -0700, Nicolin Chen wrote: > > > Repurpose the @__reserved field in the struct iommu_hw_info_arm_smmuv3, > > > to an HW implementation-defined field @impl. > > > > It would be nicer to have a tegra/cmdq specific struct and a way for > > iommu_hw_info to select it. 'impl' isn't going to scale very well if > > something else wants to use this. > > > > We have out_data_type but we could have an input sub_data_type too. 0 > > means what we have today, then a simple enum to select another info > > struct. > > So, there will be two hw_info calls back to back right? yes > Should the first call return out_data_type=CMDQV while returning > the arm_smmu_v3 hw_info data? Otherwise, VMM wouldn't know what > to set in the input sub_data_type of the 2nd ioctl? No, either set a flag in the smmu_v3 hw_info, as you were doing here, or just have the vmm probe it. Given the VMM is likely to be told to run in vCMDQ mode on the command line try-and-fail doesn't sound so bad. And I guess we don't need a "sub type" just a "requested type" where 0 means return the best one and non-zero means return a specific one or fail with EOPNOTSUPP. Jason
On Thu, May 15, 2025 at 04:23:29PM -0300, Jason Gunthorpe wrote: > On Thu, May 15, 2025 at 12:21:17PM -0700, Nicolin Chen wrote: > > On Thu, May 15, 2025 at 03:56:29PM -0300, Jason Gunthorpe wrote: > > > On Thu, May 15, 2025 at 11:52:05AM -0700, Nicolin Chen wrote: > > > > On Thu, May 15, 2025 at 02:17:06PM -0300, Jason Gunthorpe wrote: > > > > > On Thu, May 08, 2025 at 08:02:39PM -0700, Nicolin Chen wrote: > > > > Should the first call return out_data_type=CMDQV while returning > > > > the arm_smmu_v3 hw_info data? Otherwise, VMM wouldn't know what > > > > to set in the input sub_data_type of the 2nd ioctl? > > > > > > No, either set a flag in the smmu_v3 hw_info, as you were doing here, > > > or just have the vmm probe it. Given the VMM is likely to be told to > > > run in vCMDQ mode on the command line try-and-fail doesn't sound so > > > bad. > > > > > > And I guess we don't need a "sub type" just a "requested type" where 0 > > > means return the best one and non-zero means return a specific one or > > > fail with EOPNOTSUPP. > > > > OK. I think this would work: > > hw_info (req_type=0) => out_data_type=SMMU_V3, flags=HAS_CMDQV > > hw_info (req_type=CMDQV) => out_data_type=CMDQV, flags=0 > > Yeah > > > Or, would it be simpler by having a sub_data_uptr: > > hw_info => out_data_type=SMMU_V3, sub_data_type=CMDQV, > > data_uptr=iommu_hw_info_arm_smmuv3, > > sub_data_uptr=iommu_hw_info_tegra241_cmdqv > > ? > > I think the former is simpler to code, you can just add the req_type > to the signatures and if the driver comes back with a type != req_type > the core code will return EOPNOTSUPP OK. Maybe just turn the out_data_type to be bidirectional? Then we would only need to update the docs: /** * enum iommu_hw_info_type - IOMMU Hardware Info Types - * @IOMMU_HW_INFO_TYPE_NONE: Used by the drivers that do not report hardware - * info + * @IOMMU_HW_INFO_TYPE_NONE: (for output) used by the drivers that do not report + * hardware info + * @IOMMU_HW_INFO_TYPE_DEFAULT: (for input) Used to request the default type * @IOMMU_HW_INFO_TYPE_INTEL_VTD: Intel VT-d iommu info type * @IOMMU_HW_INFO_TYPE_ARM_SMMUV3: ARM SMMUv3 iommu info type + * @IOMMU_HW_INFO_TYPE_TEGRA241_CMDQV: Subtype of ARM SMMUv3 for Tegra241 CMDQV */ enum iommu_hw_info_type { IOMMU_HW_INFO_TYPE_NONE = 0, + IOMMU_HW_INFO_TYPE_DEFAULT = 0, IOMMU_HW_INFO_TYPE_INTEL_VTD = 1, IOMMU_HW_INFO_TYPE_ARM_SMMUV3 = 2, + IOMMU_HW_INFO_TYPE_TEGRA241_CMDQV =3, }; - * @out_data_type: Output the iommu hardware info type as defined in the enum - * iommu_hw_info_type. + * @data_type: Bidirectional property. + * Input the requested iommu hardware info type as defined in the + * enum iommu_hw_info_type. Requesting IOMMU_HW_INFO_TYPE_DEFAULT + * lets kernel pick the default type to output, otherwise kernel + * will validate the input type and may reject with -EOPNOTSUPP. + * Output the supported iommu hardware info type as defined in the + * same enum iommu_hw_info_type And similarly in the iommu API kdoc too. > Finally we end up with only one ioctl enum number space for the > types, which seems appealing. Yea. Avoiding a sub enum is nicer. Thanks Nicolin
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h index a5835af72417..bab7a9ce1283 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h @@ -726,6 +726,7 @@ struct arm_smmu_impl_ops { struct arm_smmu_domain *smmu_domain, struct iommufd_ctx *ictx, unsigned int viommu_type, const struct iommu_user_data *user_data); + u32 (*hw_info)(struct arm_smmu_device *smmu, u32 *impl); }; /* An SMMUv3 instance */ diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h index 001e2deb5a2d..28ab42a85268 100644 --- a/include/uapi/linux/iommufd.h +++ b/include/uapi/linux/iommufd.h @@ -554,7 +554,7 @@ struct iommu_hw_info_vtd { * (IOMMU_HW_INFO_TYPE_ARM_SMMUV3) * * @flags: Must be set to 0 - * @__reserved: Must be 0 + * @impl: Must be 0 * @idr: Implemented features for ARM SMMU Non-secure programming interface * @iidr: Information about the implementation and implementer of ARM SMMU, * and architecture version supported @@ -585,7 +585,7 @@ struct iommu_hw_info_vtd { */ struct iommu_hw_info_arm_smmuv3 { __u32 flags; - __u32 __reserved; + __u32 impl; __u32 idr[6]; __u32 iidr; __u32 aidr; diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c index b316d1df043f..8ea9a022e444 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c @@ -10,6 +10,7 @@ void *arm_smmu_hw_info(struct device *dev, u32 *length, u32 *type) { struct arm_smmu_master *master = dev_iommu_priv_get(dev); + struct arm_smmu_device *smmu = master->smmu; struct iommu_hw_info_arm_smmuv3 *info; u32 __iomem *base_idr; unsigned int i; @@ -18,15 +19,25 @@ void *arm_smmu_hw_info(struct device *dev, u32 *length, u32 *type) if (!info) return ERR_PTR(-ENOMEM); - base_idr = master->smmu->base + ARM_SMMU_IDR0; + base_idr = smmu->base + ARM_SMMU_IDR0; for (i = 0; i <= 5; i++) info->idr[i] = readl_relaxed(base_idr + i); - info->iidr = readl_relaxed(master->smmu->base + ARM_SMMU_IIDR); - info->aidr = readl_relaxed(master->smmu->base + ARM_SMMU_AIDR); + info->iidr = readl_relaxed(smmu->base + ARM_SMMU_IIDR); + info->aidr = readl_relaxed(smmu->base + ARM_SMMU_AIDR); *length = sizeof(*info); *type = IOMMU_HW_INFO_TYPE_ARM_SMMUV3; + if (smmu->impl_ops && smmu->impl_ops->hw_info) { + u32 flags, impl; + + flags = smmu->impl_ops->hw_info(smmu, &impl); + if (flags) { + info->impl = impl; + info->flags |= flags; + } + } + return info; }