From: Nicolin Chen <[email protected]> Install the mmap'd host VINTF page0 as a RAM-device MemoryRegion backing the guest's virtual VINTF Page 0 aperture (guest MMIO offset 0x30000) when VINTF is enabled, and remove it on VINTF disable or reset. This eliminates QEMU trapping for hot-path CONS/PROD index updates via that aperture.
After this patch, the two VCMDQ Page 0 apertures use different access paths: the direct aperture (0x10000) remains QEMU-trapped, while the VINTF aperture (0x30000) is a guest-direct RAM mapping. The direct aperture is intentionally kept trapped (not aliased to the host VINTF mmap) so that writes to an unallocated VCMDQ remain well-defined. The CMDQV architecture allows software to program a VCMDQ through the direct aperture without first allocating it to a VINTF; aliasing would route those writes to unallocated logical slots in the VINTF page, where the hardware silently drops them. Signed-off-by: Nicolin Chen <[email protected]> Tested-by: Nicolin Chen <[email protected]> Co-developed-by: Shameer Kolothum <[email protected]> Signed-off-by: Shameer Kolothum <[email protected]> --- hw/arm/tegra241-cmdqv.h | 1 + hw/arm/tegra241-cmdqv.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/hw/arm/tegra241-cmdqv.h b/hw/arm/tegra241-cmdqv.h index 84499b840d..01cd6af97d 100644 --- a/hw/arm/tegra241-cmdqv.h +++ b/hw/arm/tegra241-cmdqv.h @@ -49,6 +49,7 @@ typedef struct Tegra241CMDQV { IOMMUFDVeventq *veventq; IOMMUFDHWqueue *vcmdq[TEGRA241_CMDQV_MAX_CMDQ]; void *vintf_page0; + MemoryRegion *mr_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 63fe0ac681..7264b4bfa9 100644 --- a/hw/arm/tegra241-cmdqv.c +++ b/hw/arm/tegra241-cmdqv.c @@ -26,6 +26,40 @@ static void tegra241_cmdqv_reset_vcmdq_cache(Tegra241CMDQV *cmdqv, int index) cmdqv->vcmdq_gerrorn[index] = 0; } +static void tegra241_cmdqv_guest_unmap_vintf_page0(Tegra241CMDQV *cmdqv) +{ + if (!cmdqv->mr_vintf_page0) { + return; + } + + memory_region_del_subregion(&cmdqv->mmio_cmdqv, cmdqv->mr_vintf_page0); + object_unparent(OBJECT(cmdqv->mr_vintf_page0)); + g_free(cmdqv->mr_vintf_page0); + cmdqv->mr_vintf_page0 = NULL; +} + +static void tegra241_cmdqv_guest_map_vintf_page0(Tegra241CMDQV *cmdqv) +{ + char *name; + + if (cmdqv->mr_vintf_page0) { + return; + } + + name = g_strdup_printf("%s vintf-page0", + memory_region_name(&cmdqv->mmio_cmdqv)); + cmdqv->mr_vintf_page0 = g_malloc0(sizeof(*cmdqv->mr_vintf_page0)); + memory_region_init_ram_device_ptr(cmdqv->mr_vintf_page0, + memory_region_owner(&cmdqv->mmio_cmdqv), + name, VINTF_PAGE_SIZE, + cmdqv->vintf_page0); + memory_region_set_skip_iommu_map(cmdqv->mr_vintf_page0, true); + memory_region_add_subregion_overlap(&cmdqv->mmio_cmdqv, + CMDQV_VINTF_PAGE0_BASE, + cmdqv->mr_vintf_page0, 1); + g_free(name); +} + static void tegra241_cmdqv_free_vcmdq(Tegra241CMDQV *cmdqv, int index) { IOMMUFDViommu *viommu = cmdqv->s_accel->viommu; @@ -430,7 +464,9 @@ static void tegra241_cmdqv_config_vintf_write(Tegra241CMDQV *cmdqv, * enabled need their hw_queue allocated now. */ tegra241_cmdqv_setup_all_vcmdq(cmdqv, errp); + tegra241_cmdqv_guest_map_vintf_page0(cmdqv); } else { + tegra241_cmdqv_guest_unmap_vintf_page0(cmdqv); tegra241_cmdqv_free_all_vcmdq(cmdqv); cmdqv->vintf_status &= ~R_VINTF0_STATUS_ENABLE_OK_MASK; } @@ -772,6 +808,7 @@ static void tegra241_cmdqv_reset(SMMUv3State *s) return; } + tegra241_cmdqv_guest_unmap_vintf_page0(cmdqv); tegra241_cmdqv_free_all_vcmdq(cmdqv); } -- 2.43.0
