From: Nicolin Chen <[email protected]> The CMDQ-V CMDQ pages provide a VM wide view of all VCMDQs, while the 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 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]> --- 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); + } } /* -- 2.43.0
