Re: [PATCH v6 06/24] iommu/amd: Map vIOMMU VF and VF Control MMIO BARs

From: Vasant Hegde

Date: Mon Oct 19 2026 - 14:00:49 EST




On 9/30/2026 2:53 PM, Suravee Suthikulpanit wrote:
> Enable hardware vIOMMU on an IOMMU by locating its PCI vendor-specific
> capability (VSC), reading the VF and VF Control BAR addresses, and
> mapping them for host access (256MB VF, 4MB VF Control).
>
> VF Control covers the first 4K of guest IOMMU MMIO (control registers,
> trapped by QEMU). VF MMIO covers the third 4K (virtualized by the
> IOMMU). Per-guest bases use the Guest ID from the previous patch.
>
> Reject a VSC VF or VF Control BAR that is disabled or decodes to
> physical address zero before mapping MMIO.
>
> Set AMD_IOMMU_FLAG_VIOMMU_EN after the VF BARs are mapped. Export
> MMIO map helpers. Call amd_viommu_uninit() from IOMMU teardown
> before free_iommu_buffers() so MMIO and the command buffer remain.
>
> Release the reserved MMIO region if ioremap() fails so VF/VFCTRL map
> errors do not leak request_mem_region() for the life of the machine.
>
> Skip the host release in iommu_unmap_mmio_space() when mmio_base is
> NULL, so a failed ioremap() is not released twice.
>
> Signed-off-by: Vasant Hegde <vasant.hegde@xxxxxxx>
> Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx>
> ---
> drivers/iommu/amd/amd_iommu.h | 2 +
> drivers/iommu/amd/amd_iommu_types.h | 31 +++++++++
> drivers/iommu/amd/amd_viommu.h | 6 ++
> drivers/iommu/amd/init.c | 25 ++++++--
> drivers/iommu/amd/viommu.c | 98 +++++++++++++++++++++++++++++
> 5 files changed, 157 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h


.../...

> +
> + pr_debug("device:%s, vsc offset:%04x\n",
> + pci_name(iommu->dev), vsc);
> +
> + /* Setting up VF and VF_CNTL MMIOs */
> + pci_read_config_dword(iommu->dev, vsc + MMIO_VSC_VF_BAR_LO_OFFSET, &lo);
> + pci_read_config_dword(iommu->dev, vsc + MMIO_VSC_VF_BAR_HI_OFFSET, &hi);
> + vf_phys = hi;
> + vf_phys = (vf_phys << 32) | lo;
> + if (!(vf_phys & 1)) {
> + pr_err(FW_BUG "vf_phys disabled\n");
> + return -EINVAL;
> + }
> + vf_phys &= ~1ULL;
> + if (!vf_phys) {
> + pr_err(FW_BUG "vf_phys address is zero\n");
> + return -EINVAL;
> + }
> +
> + pci_read_config_dword(iommu->dev, vsc + MMIO_VSC_VF_CNTL_BAR_LO_OFFSET, &lo);
> + pci_read_config_dword(iommu->dev, vsc + MMIO_VSC_VF_CNTL_BAR_HI_OFFSET, &hi);
> + vf_cntl_phys = hi;
> + vf_cntl_phys = (vf_cntl_phys << 32) | lo;

AI suggests, w should use mask with GENMASK_ULL(63, 28) and GENMASK_ULL(63, 22)
as other bits are reserved in these two registers.

-Vasant