Hi Shameer, On 5/19/26 12:36 PM, Shameer Kolothum wrote: > From: Nicolin Chen <[email protected]> > > The CMDQ-V CMDQ pages provide a VM wide view of all VCMDQs, while the s/CMDQ pages/VCMDQ pages - yeah that's all very confusing ;-) - > VINTF pages expose a logical view local to a given VINTF. Although real > hardware may support multiple VINTFs, the kernel currently exposes a > single VINTF per VM. > > The kernel provides an mmap offset for the VINTF Page0 region during for the host VINTF page0 allocated for the VM
Actually is the whole host passthrough principle is not really explained anywhere. At least that's my feeling. It would be nice to have a summary for it, in the coverletter and in individual patch. Or maybe we can link to another doc. Reading the kernel uapi does not really provide the full picture, at least that's my own feeling. when a VM allocates a VIOMMU for the CMDQV, the kernel allocates this and this resource that is then given for exclusive usage of the VM ... How does it guarantee security between VMs, etc... Furthermore, what is not straightforward in this description is the sequence that will be executed - viommu_alloc done on which trap event? - hw_queue_alloc on which trap event? - mmap on guest VINT enable > vIOMMU allocation. However, the logical-to-physical association between > VCMDQs and a VINTF is only established after HW_QUEUE allocation. Prior > to that, the mapped Page0 does not back any real VCMDQ state. > > When VINTF is enabled, mmap the kernel provided Page0 region and set > ENABLE_OK only if the mmap succeeds. Unmap it when VINTF is disabled. > This prepares the VINTF mapping in advance of subsequent patches that > add VCMDQ allocation support. > > Signed-off-by: Nicolin Chen <[email protected]> > Co-developed-by: Shameer Kolothum <[email protected]> > Signed-off-by: Shameer Kolothum <[email protected]> Thanks Eric > --- > hw/arm/tegra241-cmdqv.h | 3 +++ > hw/arm/tegra241-cmdqv.c | 50 ++++++++++++++++++++++++++++++++++++++--- > 2 files changed, 50 insertions(+), 3 deletions(-) > > diff --git a/hw/arm/tegra241-cmdqv.h b/hw/arm/tegra241-cmdqv.h > index 6b21a407af..f0b031b4dc 100644 > --- a/hw/arm/tegra241-cmdqv.h > +++ b/hw/arm/tegra241-cmdqv.h > @@ -37,12 +37,15 @@ > #define CMDQV_VINTF_PAGE1_BASE 0x40000 > #define CMDQV_VCMDQ_STRIDE 0x80 > > +#define VINTF_PAGE_SIZE 0x10000 > + > typedef struct Tegra241CMDQV { > struct iommu_viommu_tegra241_cmdqv cmdqv_data; > SMMUv3AccelState *s_accel; > MemoryRegion mmio_cmdqv; > qemu_irq irq; > IOMMUFDVeventq *veventq; > + void *vintf_page0; > > /* CMDQ-V Config page register cache */ > uint32_t config; > diff --git a/hw/arm/tegra241-cmdqv.c b/hw/arm/tegra241-cmdqv.c > index 5d2d9d2e26..4d9f094b2a 100644 > --- a/hw/arm/tegra241-cmdqv.c > +++ b/hw/arm/tegra241-cmdqv.c > @@ -9,6 +9,8 @@ > > #include "qemu/osdep.h" > #include "qemu/log.h" > +#include "qemu/error-report.h" > +#include "qapi/error.h" > > #include "hw/arm/smmuv3.h" > #include "hw/arm/smmuv3-common.h" > @@ -228,8 +230,42 @@ static void > tegra241_cmdqv_write_vcmdq_page1_64(Tegra241CMDQV *cmdqv, > trace_tegra241_cmdqv_write_vcmdq_page1(index, offset0, value); > } > > +static bool > +tegra241_cmdqv_munmap_vintf_page0(Tegra241CMDQV *cmdqv, Error **errp) > +{ > + if (!cmdqv->vintf_page0) { > + return true; > + } > + > + if (munmap(cmdqv->vintf_page0, VINTF_PAGE_SIZE) < 0) { > + error_setg_errno(errp, errno, "Failed to unmap VINTF page0"); > + return false; > + } > + cmdqv->vintf_page0 = NULL; > + return true; > +} > + > +static bool tegra241_cmdqv_mmap_vintf_page0(Tegra241CMDQV *cmdqv, Error > **errp) > +{ > + IOMMUFDViommu *viommu = cmdqv->s_accel->viommu; > + > + if (cmdqv->vintf_page0) { > + return true; > + } > + > + if (!iommufd_backend_viommu_mmap(viommu->iommufd, viommu->viommu_id, > + VINTF_PAGE_SIZE, > + cmdqv->cmdqv_data.out_vintf_mmap_offset, > + &cmdqv->vintf_page0, errp)) { > + return false; > + } > + > + return true; > +} > + > static void tegra241_cmdqv_config_vintf_write(Tegra241CMDQV *cmdqv, > - hwaddr offset, uint64_t value) > + hwaddr offset, uint64_t value, > + Error **errp) > { > int i; > > @@ -244,8 +280,11 @@ static void > tegra241_cmdqv_config_vintf_write(Tegra241CMDQV *cmdqv, > > cmdqv->vintf_config = value; > if (value & R_VINTF0_CONFIG_ENABLE_MASK) { > - cmdqv->vintf_status |= R_VINTF0_STATUS_ENABLE_OK_MASK; > + if (tegra241_cmdqv_mmap_vintf_page0(cmdqv, errp)) { > + cmdqv->vintf_status |= R_VINTF0_STATUS_ENABLE_OK_MASK; > + } > } else { > + tegra241_cmdqv_munmap_vintf_page0(cmdqv, errp); > cmdqv->vintf_status &= ~R_VINTF0_STATUS_ENABLE_OK_MASK; > } > break; > @@ -347,6 +386,7 @@ out: > static void tegra241_cmdqv_writel_mmio(Tegra241CMDQV *cmdqv, hwaddr offset, > uint32_t value) > { > + Error *local_err = NULL; > int index; > > switch (offset) { > @@ -365,7 +405,7 @@ static void tegra241_cmdqv_writel_mmio(Tegra241CMDQV > *cmdqv, hwaddr offset, > cmdqv->cmdq_alloc_map[(offset - A_CMDQ_ALLOC_MAP_0) / 4] = value; > break; > case A_VINTF0_CONFIG ... A_VINTF0_LVCMDQ_ERR_MAP_3: > - tegra241_cmdqv_config_vintf_write(cmdqv, offset, value); > + tegra241_cmdqv_config_vintf_write(cmdqv, offset, value, &local_err); > break; > case A_VI_VCMDQ0_CONS_INDX ... A_VI_VCMDQ1_GERRORN: > /* > @@ -398,6 +438,10 @@ static void tegra241_cmdqv_writel_mmio(Tegra241CMDQV > *cmdqv, hwaddr offset, > qemu_log_mask(LOG_UNIMP, "%s unhandled write access at 0x%" PRIx64 > "\n", > __func__, offset); > } > + > + if (local_err) { > + error_report_err(local_err); > + } > } > > /*
