From: David Woodhouse dwmw@amazon.co.uk
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@amazon.co.uk Reviewed-by: Liu Yi L yi.l.liu@intel.com Cc: stable@vger.kernel.org # v5.7+ Acked-by: Lu Baolu baolu.lu@linux.intel.com Link: https://lore.kernel.org/r/de32b150ffaa752e0cff8571b17dfb1213fbe71c.camel@inf... Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- 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");