diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index 8c31bf808d..8d225d2d6c 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -1990,11 +1990,17 @@ int xenmem_add_to_physmap_one( { gmfn = idx; mfn = get_gfn_unshare(d, gmfn, &p2mt); - /* If the page is still shared, exit early */ - if ( p2m_is_shared(p2mt) ) + /* + * The entry at the destination gfn will be created as type p2m_ram_rw. + * Only allow moving source gfns with read/write or logdirty RAM types + * to avoid unexpected p2m type changes as a result of the operation. + * Note that for logdirty source type we rely on p2m_add_page() marking + * the destination gfn as dirty. + */ + if ( p2mt != p2m_ram_rw && p2mt != p2m_ram_logdirty ) { put_gfn(d, gmfn); - return -ENOMEM; + return p2m_is_shared(p2mt) ? -ENOMEM : -EACCES; } page = get_page_from_mfn(mfn, d); if ( unlikely(!page) )