> -----Original Message----- > From: Eric Auger <eric.au...@redhat.com> > Sent: 05 September 2025 10:28 > To: qemu-...@nongnu.org; qemu-devel@nongnu.org; Shameer Kolothum > <skolothum...@nvidia.com> > Cc: peter.mayd...@linaro.org; Jason Gunthorpe <j...@nvidia.com>; Nicolin > Chen <nicol...@nvidia.com>; ddut...@redhat.com; berra...@redhat.com; > Nathan Chen <nath...@nvidia.com>; Matt Ochs <mo...@nvidia.com>; > smost...@google.com; linux...@huawei.com; wangzh...@hisilicon.com; > jiangkun...@huawei.com; jonathan.came...@huawei.com; > zhangfei....@linaro.org; zhenzhong.d...@intel.com; > shameerkolot...@gmail.com > Subject: Re: [RFC PATCH v3 08/15] hw/arm/smmuv3-accel: Add > set/unset_iommu_device callback > > External email: Use caution opening links or attachments > > > Hi Shameer, > > On 7/14/25 5:59 PM, Shameer Kolothum wrote: > > From: Nicolin Chen <nicol...@nvidia.com> > > > > Implement a set_iommu_device callback: > > -If found an existing viommu reuse that. > > (Devices behind the same physical SMMU should share an S2 HWPT) > I failed to see where this is done below?
Right. I think this is from the previous series. I need to update this. At present, we only allocate a viommu if one is not allocated already. And during the viommu allocation a S2 hwpt_id is passed which is a nested parent HWPT allocated by vfio/iommufd. All the devices that gets attached to this accel smmuv3/viommu will share that parent S2. > > -Else, > > Allocate a viommu with the nested parent S2 hwpt allocated by VFIO. > > Allocate bypass and abort hwpt. > > -And add the dev to viommu device list > > > > Also add an unset_iommu_device to unwind/cleanup above. > > > > Signed-off-by: Nicolin Chen <nicol...@nvidia.com> > > Signed-off-by: Shameer Kolothum > <shameerali.kolothum.th...@huawei.com> > > --- > > hw/arm/smmuv3-accel.c | 154 > +++++++++++++++++++++++++++++++++++++++ > > hw/arm/smmuv3-accel.h | 20 +++++ > > hw/arm/trace-events | 4 + > > include/system/iommufd.h | 6 ++ > > 4 files changed, 184 insertions(+) > > > > diff --git a/hw/arm/smmuv3-accel.c b/hw/arm/smmuv3-accel.c index > > 66cd4f5ece..fe90d48675 100644 > > --- a/hw/arm/smmuv3-accel.c > > +++ b/hw/arm/smmuv3-accel.c > > @@ -7,6 +7,7 @@ > > */ > > > > #include "qemu/osdep.h" > > +#include "trace.h" > > #include "qemu/error-report.h" > > > > #include "hw/arm/smmuv3.h" > > @@ -17,6 +18,9 @@ > > > > #include "smmuv3-accel.h" > > > > +#define SMMU_STE_VALID (1ULL << 0) > > +#define SMMU_STE_CFG_BYPASS (1ULL << 3) > > + > > static SMMUv3AccelDevice *smmuv3_accel_get_dev(SMMUState *bs, > SMMUPciBus *sbus, > > PCIBus *bus, int > > devfn) { @@ -39,6 +43,154 @@ static SMMUv3AccelDevice > > *smmuv3_accel_get_dev(SMMUState *bs, SMMUPciBus *sbus, > > return accel_dev; > > } > > > > +static bool > > +smmuv3_accel_dev_alloc_viommu(SMMUv3AccelDevice *accel_dev, > > + HostIOMMUDeviceIOMMUFD *idev, Error > > +**errp) { > > + struct iommu_hwpt_arm_smmuv3 bypass_data = { > > + .ste = { SMMU_STE_CFG_BYPASS | SMMU_STE_VALID, 0x0ULL }, > > + }; > > + struct iommu_hwpt_arm_smmuv3 abort_data = { > > + .ste = { SMMU_STE_VALID, 0x0ULL }, > > + }; > > + SMMUDevice *sdev = &accel_dev->sdev; > > + SMMUState *bs = sdev->smmu; > > + SMMUv3State *s = ARM_SMMUV3(bs); > > + SMMUv3AccelState *s_accel = s->s_accel; > > + uint32_t s2_hwpt_id = idev->hwpt_id; > > + SMMUS2Hwpt *s2_hwpt; > > + SMMUViommu *viommu; > > + uint32_t viommu_id; > > + > > + if (s_accel->viommu) { > > + accel_dev->viommu = s_accel->viommu; > > + return true; > > + } > > + > > + if (!iommufd_backend_alloc_viommu(idev->iommufd, idev->devid, > > + IOMMU_VIOMMU_TYPE_ARM_SMMUV3, > > + s2_hwpt_id, &viommu_id, errp)) { > > + return false; > > + } > > + > > + viommu = g_new0(SMMUViommu, 1); > > + viommu->core.viommu_id = viommu_id; > > + viommu->core.s2_hwpt_id = s2_hwpt_id; > > + viommu->core.iommufd = idev->iommufd; > > + > > + if (!iommufd_backend_alloc_hwpt(idev->iommufd, idev->devid, > > + viommu->core.viommu_id, 0, > > + IOMMU_HWPT_DATA_ARM_SMMUV3, > > + sizeof(abort_data), &abort_data, > > + &viommu->abort_hwpt_id, errp)) { > > + goto free_viommu; > > + } > > + > > + if (!iommufd_backend_alloc_hwpt(idev->iommufd, idev->devid, > > + viommu->core.viommu_id, 0, > > + IOMMU_HWPT_DATA_ARM_SMMUV3, > > + sizeof(bypass_data), &bypass_data, > > + &viommu->bypass_hwpt_id, errp)) { > > + goto free_abort_hwpt; > > + } > > + > > + s2_hwpt = g_new(SMMUS2Hwpt, 1); > > + s2_hwpt->iommufd = idev->iommufd; > > + s2_hwpt->hwpt_id = s2_hwpt_id; > > + > > + viommu->iommufd = idev->iommufd; > > + viommu->s2_hwpt = s2_hwpt; > > + > > + s_accel->viommu = viommu; > > + accel_dev->viommu = viommu; > > + return true; > > + > > +free_abort_hwpt: > > + iommufd_backend_free_id(idev->iommufd, viommu->abort_hwpt_id); > > +free_viommu: > > + iommufd_backend_free_id(idev->iommufd, viommu->core.viommu_id); > > + g_free(viommu); > > + return false; > > +} > > + > > +static bool smmuv3_accel_set_iommu_device(PCIBus *bus, void *opaque, > int devfn, > > + HostIOMMUDevice *hiod, > > +Error **errp) { > > + HostIOMMUDeviceIOMMUFD *idev = > HOST_IOMMU_DEVICE_IOMMUFD(hiod); > > + SMMUState *bs = opaque; > > + SMMUv3State *s = ARM_SMMUV3(bs); > > + SMMUv3AccelState *s_accel = s->s_accel; > > + SMMUPciBus *sbus = smmu_get_sbus(bs, bus); > > + SMMUv3AccelDevice *accel_dev = smmuv3_accel_get_dev(bs, sbus, bus, > devfn); > > + SMMUDevice *sdev = &accel_dev->sdev; > > + > > + if (!idev) { > > + return true; > > + } > > + > > + if (accel_dev->idev) { > > + if (accel_dev->idev != idev) { > > + error_report("Device 0x%x already has an associated > > + idev", > would not use "idev" as end-user will not easily understand what the beast is Ok. > > + smmu_get_sid(sdev)); > > + return false; > if this is considered as an error why don't we set errp? > > + } else { > > + return true; > > + } > > + } > > + > > + if (!smmuv3_accel_dev_alloc_viommu(accel_dev, idev, errp)) { > > + error_report("Device 0x%x: Unable to alloc viommu", > smmu_get_sid(sdev)); > > + return false; > same here > > + } > > + > > + accel_dev->idev = idev; > > + QLIST_INSERT_HEAD(&s_accel->viommu->device_list, accel_dev, next); > > + trace_smmuv3_accel_set_iommu_device(devfn, smmu_get_sid(sdev)); > > + return true; > > +} > > + > > +static void smmuv3_accel_unset_iommu_device(PCIBus *bus, void > *opaque, > > + int devfn) { > > + SMMUState *bs = opaque; > > + SMMUv3State *s = ARM_SMMUV3(bs); > > + SMMUPciBus *sbus = g_hash_table_lookup(bs- > >smmu_pcibus_by_busptr, bus); > > + SMMUv3AccelDevice *accel_dev; > > + SMMUViommu *viommu; > > + SMMUDevice *sdev; > > + > > + if (!sbus) { > > + return; > > + } > > + > > + sdev = sbus->pbdev[devfn]; > > + if (!sdev) { > > + return; > > + } > > + > > + accel_dev = container_of(sdev, SMMUv3AccelDevice, sdev); > > + if (!host_iommu_device_iommufd_attach_hwpt(accel_dev->idev, > > + accel_dev->idev->hwpt_id, > > + NULL)) { > > + error_report("Unable to attach dev to the default HW > > + pagetable"); > also trace smmu_get_sid(sdev) to be consistent with other traces? Ok. Thanks, Shameer