From: Quan Xu Date: Tue, 20 Jun 2017 14:51:32 +0000 (+0200) Subject: IOMMU: handle IOMMU mapping and unmapping failures X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=7b3712a59bd3f1f1e2b5979df19bf111e0d9fa78;p=xen.git IOMMU: handle IOMMU mapping and unmapping failures Treat IOMMU mapping and unmapping failures as a fatal to the DomU If IOMMU mapping and unmapping failed, crash the DomU and propagate the error up to the call trees. No spamming of the log can occur. For DomU, we avoid logging any message for already dying domains. For Dom0, that'll still be more verbose than we'd really like, but it at least wouldn't outright flood the console. Signed-off-by: Quan Xu Reviewed-by: Kevin Tian Reviewed-by: Jan Beulich master commit: 834c97baebb3743c54bcae228e984ae1b9692e6a master date: 2016-06-14 15:10:57 +0200 --- diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c index f2841de27f..5af95ce0a0 100644 --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -200,21 +200,47 @@ int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn, unsigned int flags) { const struct domain_iommu *hd = dom_iommu(d); + int rc; if ( !iommu_enabled || !hd->platform_ops ) return 0; - return hd->platform_ops->map_page(d, gfn, mfn, flags); + rc = hd->platform_ops->map_page(d, gfn, mfn, flags); + if ( unlikely(rc) ) + { + if ( !d->is_shutting_down && printk_ratelimit() ) + printk(XENLOG_ERR + "d%d: IOMMU mapping gfn %#lx to mfn %#lx failed: %d\n", + d->domain_id, gfn, mfn, rc); + + if ( !is_hardware_domain(d) ) + domain_crash(d); + } + + return rc; } int iommu_unmap_page(struct domain *d, unsigned long gfn) { const struct domain_iommu *hd = dom_iommu(d); + int rc; if ( !iommu_enabled || !hd->platform_ops ) return 0; - return hd->platform_ops->unmap_page(d, gfn); + rc = hd->platform_ops->unmap_page(d, gfn); + if ( unlikely(rc) ) + { + if ( !d->is_shutting_down && printk_ratelimit() ) + printk(XENLOG_ERR + "d%d: IOMMU unmapping gfn %#lx failed: %d\n", + d->domain_id, gfn, rc); + + if ( !is_hardware_domain(d) ) + domain_crash(d); + } + + return rc; } static void iommu_free_pagetables(unsigned long unused)