From: David Woodhouse <dwmw@xxxxxxxxxxxx> commit d76b42e92780c3587c1a998a3a943b501c137553 upstream. My virtual IOMMU implementation is whining that the guest is reading a register that doesn't exist. Only read the VCCAP_REG if the corresponding capability is set in ECAP_REG to indicate that it actually exists. Fixes: 3375303e8287 ("iommu/vt-d: Add custom allocator for IOASID") Signed-off-by: David Woodhouse <dwmw@xxxxxxxxxxxx> Reviewed-by: Liu Yi L <yi.l.liu@xxxxxxxxx> Cc: stable@xxxxxxxxxxxxxxx # v5.7+ Acked-by: Lu Baolu <baolu.lu@xxxxxxxxxxxxxxx> Link: https://lore.kernel.org/r/de32b150ffaa752e0cff8571b17dfb1213fbe71c.camel@xxxxxxxxxxxxx Signed-off-by: Will Deacon <will@xxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/iommu/intel/dmar.c | 3 ++- drivers/iommu/intel/iommu.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) --- a/drivers/iommu/intel/dmar.c +++ b/drivers/iommu/intel/dmar.c @@ -964,7 +964,8 @@ static int map_iommu(struct intel_iommu warn_invalid_dmar(phys_addr, " returns all ones"); goto unmap; } - iommu->vccap = dmar_readq(iommu->reg + DMAR_VCCAP_REG); + if (ecap_vcs(iommu->ecap)) + iommu->vccap = dmar_readq(iommu->reg + DMAR_VCCAP_REG); /* the registers might be more than one page */ map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap), --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1798,7 +1798,7 @@ static void free_dmar_iommu(struct intel if (ecap_prs(iommu->ecap)) intel_svm_finish_prq(iommu); } - if (ecap_vcs(iommu->ecap) && vccap_pasid(iommu->vccap)) + if (vccap_pasid(iommu->vccap)) ioasid_unregister_allocator(&iommu->pasid_allocator); #endif @@ -3177,7 +3177,7 @@ static void register_pasid_allocator(str * is active. All vIOMMU allocators will eventually be calling the same * host allocator. */ - if (!ecap_vcs(iommu->ecap) || !vccap_pasid(iommu->vccap)) + if (!vccap_pasid(iommu->vccap)) return; pr_info("Register custom PASID allocator\n");