# HG changeset patch # Parent 00989d5f44b59ba7f3a467342a14b9c7621fa926 xenpaging: restore p2mt if gfn is needed before evict In the rare case that a gfn is needed by a guest or a foreign domain between nominate and evict, restore the p2mt and skip sending a request. A request is not needed because the pager will notice the evict failure. Signed-off-by: Olaf Hering --- xen/arch/x86/mm/p2m.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) Index: xen-4.1.3-testing/xen/arch/x86/mm/p2m.c =================================================================== --- xen-4.1.3-testing.orig/xen/arch/x86/mm/p2m.c +++ xen-4.1.3-testing/xen/arch/x86/mm/p2m.c @@ -3038,6 +3038,7 @@ void p2m_mem_paging_populate(struct p2m_ p2m_type_t p2mt; p2m_access_t a; mfn_t mfn; + int restored = 0; struct domain *d = p2m->domain; /* Check that there's space on the ring for this request */ @@ -3053,23 +3054,25 @@ void p2m_mem_paging_populate(struct p2m_ /* Allow only nominated or evicted pages to enter page-in path */ if ( p2m_do_populate(p2mt) ) { - /* Evict will fail now, tag this request for pager */ - if ( p2mt == p2m_ram_paging_out ) - req.flags |= MEM_EVENT_FLAG_EVICT_FAIL; - - set_p2m_entry(p2m, gfn, mfn, 0, p2m_ram_paging_in_start, a); + /* Restore page state if gfn was requested before evict */ + if ( p2mt == p2m_ram_paging_out && mfn_valid(mfn) ) { + set_p2m_entry(p2m, gfn, mfn, 0, p2m_ram_rw, a); + restored = 1; + } else { + set_p2m_entry(p2m, gfn, mfn, 0, p2m_ram_paging_in_start, a); + } audit_p2m(p2m, 1); } p2m_unlock(p2m); /* Pause domain if request came from guest and gfn has paging type */ - if ( p2m_is_paging(p2mt) && v->domain == d ) + if ( !restored && p2m_is_paging(p2mt) && v->domain == d ) { vcpu_pause_nosync(v); req.flags |= MEM_EVENT_FLAG_VCPU_PAUSED; } /* No need to inform pager if the gfn is not in the page-out path */ - else if ( !p2m_do_populate(p2mt) ) + else if ( restored || !p2m_do_populate(p2mt) ) { /* gfn is already on its way back and vcpu is not paused */ mem_event_put_req_producers(&d->mem_event->paging);