VT-d: don't suppress invalidation address write when it is zero GFN zero is a valid address, and hence may need invalidation done for it just like for any other GFN. Signed-off-by: Jan Beulich --- The comment right before the respective dmar_writeq() confuses me: What "first" TLB reg does it talk about? Is it simply stale (albeit it has been there already in 3.2.x, i.e. it would then likely have been stale already at the time that code got added)? --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -414,7 +414,7 @@ static int flush_iotlb_reg(void *_iommu, { struct iommu *iommu = (struct iommu *) _iommu; int tlb_offset = ecap_iotlb_offset(iommu->ecap); - u64 val = 0, val_iva = 0; + u64 val = 0; unsigned long flags; /* @@ -435,7 +435,6 @@ static int flush_iotlb_reg(void *_iommu, switch ( type ) { case DMA_TLB_GLOBAL_FLUSH: - /* global flush doesn't need set IVA_REG */ val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT; break; case DMA_TLB_DSI_FLUSH: @@ -443,8 +442,6 @@ static int flush_iotlb_reg(void *_iommu, break; case DMA_TLB_PSI_FLUSH: val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did); - /* Note: always flush non-leaf currently */ - val_iva = size_order | addr; break; default: BUG(); @@ -457,8 +454,11 @@ static int flush_iotlb_reg(void *_iommu, spin_lock_irqsave(&iommu->register_lock, flags); /* Note: Only uses first TLB reg currently */ - if ( val_iva ) - dmar_writeq(iommu->reg, tlb_offset, val_iva); + if ( type == DMA_TLB_PSI_FLUSH ) + { + /* Note: always flush non-leaf currently. */ + dmar_writeq(iommu->reg, tlb_offset, size_order | addr); + } dmar_writeq(iommu->reg, tlb_offset + 8, val); /* Make sure hardware complete it */