From: Jan Beulich Date: Tue, 20 Apr 2021 10:02:35 +0000 (+0200) Subject: VT-d: re-order register restoring in vtd_resume() X-Git-Tag: archive/raspbian/4.14.2+25-gb6a8c4f72d-2+rpi1^2~47^2~31 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=732cf387c9bb343ac89ddd4a2e713880d62d2b5f;p=xen.git VT-d: re-order register restoring in vtd_resume() For one FECTL must be written last - the interrupt shouldn't be unmasked without first having written the data and address needed to actually deliver it. In the common case (when dma_msi_set_affinity() doesn't end up bailing early) this happens from init_vtd_hw(), but for this to actually have the intended effect we shouldn't subsequently overwrite what was written there - this is only benign when old and new settings match. Instead we should restore the registers ahead of calling init_vtd_hw(), just for the unlikely case of dma_msi_set_affinity() bailing early. In the moved code drop some stray casts as well. Signed-off-by: Jan Beulich Reviewed-by: Kevin Tian master commit: 95e07f8c0e64889ee56015c7f99bdf5309e9e8ef master date: 2021-03-30 14:39:54 +0200 --- diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index db1171ce0c..cf49118035 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -2615,6 +2615,21 @@ static void vtd_resume(void) if ( !iommu_enabled ) return; + for_each_drhd_unit ( drhd ) + { + iommu = drhd->iommu; + i = iommu->index; + + spin_lock_irqsave(&iommu->register_lock, flags); + dmar_writel(iommu->reg, DMAR_FEDATA_REG, + iommu_state[i][DMAR_FEDATA_REG]); + dmar_writel(iommu->reg, DMAR_FEADDR_REG, + iommu_state[i][DMAR_FEADDR_REG]); + dmar_writel(iommu->reg, DMAR_FEUADDR_REG, + iommu_state[i][DMAR_FEUADDR_REG]); + spin_unlock_irqrestore(&iommu->register_lock, flags); + } + if ( init_vtd_hw(true) != 0 && force_iommu ) panic("IOMMU setup failed, crash Xen for security purpose\n"); @@ -2626,12 +2641,6 @@ static void vtd_resume(void) spin_lock_irqsave(&iommu->register_lock, flags); dmar_writel(iommu->reg, DMAR_FECTL_REG, (u32) iommu_state[i][DMAR_FECTL_REG]); - dmar_writel(iommu->reg, DMAR_FEDATA_REG, - (u32) iommu_state[i][DMAR_FEDATA_REG]); - dmar_writel(iommu->reg, DMAR_FEADDR_REG, - (u32) iommu_state[i][DMAR_FEADDR_REG]); - dmar_writel(iommu->reg, DMAR_FEUADDR_REG, - (u32) iommu_state[i][DMAR_FEUADDR_REG]); spin_unlock_irqrestore(&iommu->register_lock, flags); iommu_enable_translation(drhd);