Hi Shameer, On 5/19/26 12:37 PM, Shameer Kolothum wrote: > Install an event handler on the CMDQV vEVENTQ fd to read and propagate > host received CMDQV errors to the guest. > > The handler runs in QEMU's main loop, using a non-blocking fd registered > via qemu_set_fd_handler(). > > Reviewed-by: Nicolin Chen <[email protected]> > Signed-off-by: Shameer Kolothum <[email protected]> > --- > hw/arm/tegra241-cmdqv.c | 60 +++++++++++++++++++++++++++++++++++++++++ > hw/arm/trace-events | 1 + > 2 files changed, 61 insertions(+) > > diff --git a/hw/arm/tegra241-cmdqv.c b/hw/arm/tegra241-cmdqv.c > index 853c548e58..0bba2c1801 100644 > --- a/hw/arm/tegra241-cmdqv.c > +++ b/hw/arm/tegra241-cmdqv.c > @@ -14,6 +14,7 @@ > > #include "hw/arm/smmuv3.h" > #include "hw/arm/smmuv3-common.h" > +#include "hw/core/irq.h" > #include "smmuv3-accel.h" > #include "tegra241-cmdqv.h" > #include "trace.h" > @@ -736,6 +737,48 @@ out: > trace_tegra241_cmdqv_write_mmio(offset, value, size); > } > > +static void tegra241_cmdqv_event_read(void *opaque) > +{ > + Tegra241CMDQV *cmdqv = opaque; > + IOMMUFDVeventq *veventq = cmdqv->veventq; > + struct { > + struct iommufd_vevent_header hdr; > + struct iommu_vevent_tegra241_cmdqv vevent; > + } buf; > + Error *local_err = NULL; > + > + if (!smmuv3_accel_event_read_validate(veventq, > + IOMMU_VEVENTQ_TYPE_TEGRA241_CMDQV, > + &buf, sizeof(buf), &local_err)) { > + warn_report_err_once(local_err); > + return; > + } > + > + if (buf.vevent.lvcmdq_err_map[0] || buf.vevent.lvcmdq_err_map[1]) { > + cmdqv->vintf_cmdq_err_map[0] = > + extract64(buf.vevent.lvcmdq_err_map[0], 0, 32); > + cmdqv->vintf_cmdq_err_map[1] = > + extract64(buf.vevent.lvcmdq_err_map[0], 32, 32); > + cmdqv->vintf_cmdq_err_map[2] = > + extract64(buf.vevent.lvcmdq_err_map[1], 0, 32); > + cmdqv->vintf_cmdq_err_map[3] = > + extract64(buf.vevent.lvcmdq_err_map[1], 32, 32); > + /* > + * CMDQV_CMDQ_ERR_MAP and VINTF0_LVCMDQ_ERR_MAP are distinct > + * registers (different MMIO offsets). With only VINTF0 exposed > + * they carry the same data, so mirror. > + */ > + for (int i = 0; i < 4; i++) { > + cmdqv->cmdq_err_map[i] = cmdqv->vintf_cmdq_err_map[i]; > + } > + cmdqv->vi_err_map[0] |= 0x1; > + qemu_irq_pulse(cmdqv->irq); I don't see SMMU_CMDQV_VI_ERR_MAP_0 updated anywhere. If I understand correctly, if you get an error on any VCMDQ you should update it. Also the triggering of the irq should depnd on SMMU_CMDQ_VI_INT_MASK0, no? > + trace_tegra241_cmdqv_err_map( > + cmdqv->vintf_cmdq_err_map[3], cmdqv->vintf_cmdq_err_map[2], > + cmdqv->vintf_cmdq_err_map[1], cmdqv->vintf_cmdq_err_map[0]); > + } > +} > + > static void tegra241_cmdqv_free_viommu(SMMUv3State *s) > { > SMMUv3AccelState *accel = s->s_accel; > @@ -747,6 +790,7 @@ static void tegra241_cmdqv_free_viommu(SMMUv3State *s) > return; > } > if (veventq) { > + qemu_set_fd_handler(veventq->veventq_fd, NULL, NULL, NULL); > close(veventq->veventq_fd); > iommufd_backend_free_id(viommu->iommufd, veventq->veventq_id); > g_free(veventq); > @@ -762,6 +806,7 @@ tegra241_cmdqv_alloc_viommu(SMMUv3State *s, > HostIOMMUDeviceIOMMUFD *idev, > Tegra241CMDQV *cmdqv = s->s_accel->cmdqv; > uint32_t viommu_id, veventq_id, veventq_fd; > IOMMUFDVeventq *veventq; > + int flags; > > if (!iommufd_backend_alloc_viommu(idev->iommufd, idev->devid, > IOMMU_VIOMMU_TYPE_TEGRA241_CMDQV, > @@ -780,14 +825,29 @@ tegra241_cmdqv_alloc_viommu(SMMUv3State *s, > HostIOMMUDeviceIOMMUFD *idev, > goto free_viommu; > } > > + flags = fcntl(veventq_fd, F_GETFL); > + if (flags < 0) { > + error_setg(errp, "Failed to get flags for vEVENTQ fd"); > + goto free_veventq; > + } > + if (fcntl(veventq_fd, F_SETFL, O_NONBLOCK | flags) < 0) { > + error_setg(errp, "Failed to set O_NONBLOCK on vEVENTQ fd"); > + goto free_veventq; > + } > + > veventq = g_new(IOMMUFDVeventq, 1); > veventq->veventq_id = veventq_id; > veventq->veventq_fd = veventq_fd; > cmdqv->veventq = veventq; > > + /* Set up event handler for veventq fd */ > + qemu_set_fd_handler(veventq_fd, tegra241_cmdqv_event_read, NULL, cmdqv); > *out_viommu_id = viommu_id; > return true; > > +free_veventq: > + close(veventq_fd); > + iommufd_backend_free_id(idev->iommufd, veventq_id); > free_viommu: > iommufd_backend_free_id(idev->iommufd, viommu_id); > return false; > diff --git a/hw/arm/trace-events b/hw/arm/trace-events > index c4262bb2be..5afbceee83 100644 > --- a/hw/arm/trace-events > +++ b/hw/arm/trace-events > @@ -75,6 +75,7 @@ smmuv3_accel_install_ste(uint32_t vsid, const char * type, > uint32_t hwpt_id) "vS > # tegra241-cmdqv > tegra241_cmdqv_read_mmio(uint64_t offset, uint64_t val, unsigned size) > "offset: 0x%"PRIx64" val: 0x%"PRIx64" size: 0x%x" > tegra241_cmdqv_write_mmio(uint64_t offset, uint64_t val, unsigned size) > "offset: 0x%"PRIx64" val: 0x%"PRIx64" size: 0x%x" > +tegra241_cmdqv_err_map(uint32_t map3, uint32_t map2, uint32_t map1, uint32_t > map0) "hw irq received. error (hex) maps: %04X:%04X:%04X:%04X" > tegra241_cmdqv_read_vcmdq_page0(int index, uint64_t offset0, uint64_t val) > "vcmdq[%d] page0 offset0: 0x%"PRIx64" val: 0x%"PRIx64 > tegra241_cmdqv_read_vcmdq_page1(int index, uint64_t offset0, uint64_t val) > "vcmdq[%d] page1 offset0: 0x%"PRIx64" val: 0x%"PRIx64 > tegra241_cmdqv_write_vcmdq_page0(int index, uint64_t offset0, uint64_t val) > "vcmdq[%d] page0 offset0: 0x%"PRIx64" val: 0x%"PRIx64 Thanks
Eric
