From: Jan Beulich Date: Thu, 13 Aug 2015 12:44:21 +0000 (+0200) Subject: x86/p2m: clear_identity_p2m_entry() must cope with 'relaxed' RDM mode X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~2624^2~4 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=adc5b2e05ec781db974216857f98a1ac1d74111b;p=xen.git x86/p2m: clear_identity_p2m_entry() must cope with 'relaxed' RDM mode Tearing down a 1:1 mapping that was never established isn't really nice (and in fact hits an ASSERT() in p2m_remove_page()). Convert from a wrapper macro to a proper function which then can take care of the situation. Also take the opportunity to remove the 'page_order' parameter of clear_identity_p2m_entry(), to make it match set_identity_p2m_entry(). Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper Release-acked-by: Wei Liu --- diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index 7aafaccc76..8fa918b827 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -1019,6 +1019,38 @@ int clear_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn) return rc; } +int clear_identity_p2m_entry(struct domain *d, unsigned long gfn) +{ + p2m_type_t p2mt; + p2m_access_t a; + mfn_t mfn; + struct p2m_domain *p2m = p2m_get_hostp2m(d); + int ret; + + if ( !paging_mode_translate(d) ) + return 0; + + gfn_lock(p2m, gfn, 0); + + mfn = p2m->get_entry(p2m, gfn, &p2mt, &a, 0, NULL, NULL); + if ( p2mt == p2m_mmio_direct && mfn_x(mfn) == gfn ) + { + ret = p2m_set_entry(p2m, gfn, _mfn(INVALID_MFN), PAGE_ORDER_4K, + p2m_invalid, p2m->default_access); + gfn_unlock(p2m, gfn, 0); + } + else + { + gfn_unlock(p2m, gfn, 0); + printk(XENLOG_G_WARNING + "non-identity map d%d:%lx not cleared (mapped to %lx)\n", + d->domain_id, gfn, mfn_x(mfn)); + ret = 0; + } + + return ret; +} + /* Returns: 0 for success, -errno for failure */ int set_shared_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn) { diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index 1dffc40058..836aed5960 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -1839,7 +1839,7 @@ static int rmrr_identity_mapping(struct domain *d, bool_t map, while ( base_pfn < end_pfn ) { - if ( clear_identity_p2m_entry(d, base_pfn, 0) ) + if ( clear_identity_p2m_entry(d, base_pfn) ) ret = -ENXIO; base_pfn++; } diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h index f4871787dc..5e99ac61ca 100644 --- a/xen/include/asm-x86/p2m.h +++ b/xen/include/asm-x86/p2m.h @@ -563,9 +563,7 @@ int clear_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn); /* Set identity addresses in the p2m table (for pass-through) */ int set_identity_p2m_entry(struct domain *d, unsigned long gfn, p2m_access_t p2ma, unsigned int flag); - -#define clear_identity_p2m_entry(d, gfn, page_order) \ - guest_physmap_remove_page(d, gfn, gfn, page_order) +int clear_identity_p2m_entry(struct domain *d, unsigned long gfn); /* Add foreign mapping to the guest's p2m table. */ int p2m_add_foreign(struct domain *tdom, unsigned long fgfn,