hw/arm/tegra241-cmdqv: Implement CMDQV vIOMMU alloc/free
Replace the stub implementation with real vIOMMU allocation for Tegra241 CMDQV. Allocate a matching vEVENTQ together with the vIOMMU, since it is specific to the Tegra241 CMDQV vIOMMU and used to receive CMDQV events. Free both objects on teardown. Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Tested-by: Nicolin Chen <nicolinc@nvidia.com> Tested-by: Eric Auger <eric.auger@redhat.com> Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com> Message-id: 20260609112552.378999-14-skolothumtho@nvidia.com Co-developed-by: Shameer Kolothum <skolothumtho@nvidia.com> Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Nicolin Chen committed
Jun 9, 2026 at 12:25 UTC
43763a1ab76fb618119bb76b0e4a93b599b40f13
2 files changed
+48
-1
hw/arm/tegra241-cmdqv.c
+47
-1
@@ -10,6 +10,7 @@
10
#include "qemu/osdep.h"
11
12
#include "hw/arm/smmuv3.h"
13
+#include "hw/arm/smmuv3-common.h"
14
#include "smmuv3-accel.h"
15
#include "tegra241-cmdqv.h"
16
@@ -26,13 +27,58 @@ static void tegra241_cmdqv_write_mmio(void *opaque, hwaddr offset,
27
28
static void tegra241_cmdqv_free_viommu(SMMUv3State *s)
29
{
30
+ SMMUv3AccelState *accel = s->s_accel;
31
+ IOMMUFDViommu *viommu = accel->viommu;
32
+ Tegra241CMDQV *cmdqv = accel->cmdqv;
33
+ IOMMUFDVeventq *veventq = cmdqv->veventq;
34
+
35
+ if (!viommu) {
36
+ return;
37
+ }
38
+ if (veventq) {
39
+ close(veventq->veventq_fd);
40
+ iommufd_backend_free_id(viommu->iommufd, veventq->veventq_id);
41
+ g_free(veventq);
42
+ cmdqv->veventq = NULL;
43
+ }
44
+ iommufd_backend_free_id(viommu->iommufd, viommu->viommu_id);
45
}
46
47
static bool
48
tegra241_cmdqv_alloc_viommu(SMMUv3State *s, HostIOMMUDeviceIOMMUFD *idev,
49
uint32_t *out_viommu_id, Error **errp)
50
{
35
- error_setg(errp, "NVIDIA Tegra241 CMDQV is unsupported");
51
+ Tegra241CMDQV *cmdqv = s->s_accel->cmdqv;
52
+ uint32_t viommu_id, veventq_id, veventq_fd;
53
+ IOMMUFDVeventq *veventq;
54
+
55
+ if (!iommufd_backend_alloc_viommu(idev->iommufd, idev->devid,
56
+ IOMMU_VIOMMU_TYPE_TEGRA241_CMDQV,
57
+ idev->hwpt_id, cmdqv->cmdqv_data,
58
+ sizeof(*cmdqv->cmdqv_data), &viommu_id,
59
+ errp)) {
60
+ return false;
61
+ }
62
+
63
+ if (!iommufd_backend_alloc_veventq(idev->iommufd, viommu_id,
64
+ IOMMU_VEVENTQ_TYPE_TEGRA241_CMDQV,
65
+ 1 << SMMU_EVENTQS, &veventq_id,
66
+ &veventq_fd,
67
+ errp)) {
68
+ error_append_hint(errp, "Tegra241 CMDQV: failed to alloc veventq");
69
+ goto free_viommu;
70
+ }
71
+
72
+ veventq = g_new(IOMMUFDVeventq, 1);
73
+ veventq->veventq_id = veventq_id;
74
+ veventq->veventq_fd = veventq_fd;
75
+ cmdqv->veventq = veventq;
76
+
77
+ *out_viommu_id = viommu_id;
78
+ return true;
79
+
80
+free_viommu:
81
+ iommufd_backend_free_id(idev->iommufd, viommu_id);
82
return false;
83
}
84
hw/arm/tegra241-cmdqv.h
+1
@@ -32,6 +32,7 @@ typedef struct Tegra241CMDQV {
32
SMMUv3AccelState *s_accel;
33
MemoryRegion mmio_cmdqv;
34
qemu_irq irq;
35
+ IOMMUFDVeventq *veventq;
36
} Tegra241CMDQV;
37
38
const SMMUv3AccelCmdqvOps *tegra241_cmdqv_get_ops(void);