# HG changeset patch # Parent 4019436855ff3d44228c8eb3e78a9133a9caf870 xenpaging: map gfn before nomination If the gfn is mapped before nomination, all special cases in do_mmu_update() for paged gfns can be removed. If a gfn is actually in any of the paging states the caller has to try again. Bump interface age. Signed-off-by: Olaf Hering Index: xen-4.1.3-testing/tools/xenpaging/xenpaging.c =================================================================== --- xen-4.1.3-testing.orig/tools/xenpaging/xenpaging.c +++ xen-4.1.3-testing/tools/xenpaging/xenpaging.c @@ -573,7 +573,7 @@ static int xenpaging_evict_page(xenpagin DECLARE_DOMCTL; - /* Map page */ + /* Map page to get a handle */ gfn = victim->gfn; ret = -EFAULT; page = xc_map_foreign_pages(xch, paging->mem_event.domain_id, @@ -584,16 +584,21 @@ static int xenpaging_evict_page(xenpagin goto out; } + /* Nominate the page */ + ret = xc_mem_paging_nominate(xch, paging->mem_event.domain_id, gfn); + if ( ret != 0 ) + goto out; + /* Copy page */ ret = write_page(fd, page, i); if ( ret != 0 ) { PERROR("Error copying page %lx", victim->gfn); - munmap(page, PAGE_SIZE); goto out; } munmap(page, PAGE_SIZE); + page = NULL; /* Tell Xen to evict page */ ret = xc_mem_paging_evict(xch, paging->mem_event.domain_id, @@ -612,6 +617,8 @@ static int xenpaging_evict_page(xenpagin paging->num_paged_out++; out: + if (page) + munmap(page, PAGE_SIZE); return ret; } @@ -735,14 +742,11 @@ static int evict_victim(xenpaging_t *pag ret = -EINTR; goto out; } - ret = xc_mem_paging_nominate(xch, paging->mem_event.domain_id, victim->gfn); - if ( ret == 0 ) - ret = xenpaging_evict_page(paging, victim, fd, i); - else + ret = xenpaging_evict_page(paging, victim, fd, i); + if ( ret && j++ % 1000 == 0 ) { - if ( j++ % 1000 == 0 ) - if ( xenpaging_mem_paging_flush_ioemu_cache(paging) ) - PERROR("Error flushing ioemu cache"); + if ( xenpaging_mem_paging_flush_ioemu_cache(paging) ) + PERROR("Error flushing ioemu cache"); } } while ( ret ); 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 @@ -2854,7 +2854,7 @@ set_shared_p2m_entry(struct p2m_domain * * - the gfn is backed by a mfn * - the p2mt of the gfn is pageable * - the mfn is not used for IO - * - the mfn has exactly one user and has no special meaning + * - the mfn has exactly two users (guest+pager) and has no special meaning * * Once the p2mt is changed the page is readonly for the guest. On success the * pager can write the page contents to disk and later evict the page. @@ -2888,7 +2888,7 @@ int p2m_mem_paging_nominate(struct p2m_d /* Check page count and type */ page = mfn_to_page(mfn); if ( (page->count_info & (PGC_count_mask | PGC_allocated)) != - (1 | PGC_allocated) ) + (2 | PGC_allocated) ) goto out; if ( (page->u.inuse.type_info & PGT_type_mask) != PGT_none ) @@ -2916,7 +2916,7 @@ int p2m_mem_paging_nominate(struct p2m_d * freed: * - the gfn is backed by a mfn * - the gfn was nominated - * - the mfn has still exactly one user and has no special meaning + * - the mfn has still exactly one user (the guest) and has no special meaning * * After successful nomination some other process could have mapped the page. In * this case eviction can not be done. If the gfn was populated before the pager Index: xen-4.1.3-testing/xen/include/public/mem_event.h =================================================================== --- xen-4.1.3-testing.orig/xen/include/public/mem_event.h +++ xen-4.1.3-testing/xen/include/public/mem_event.h @@ -49,7 +49,7 @@ #define MEM_EVENT_REASON_INT3 5 /* int3 was hit: gla/gfn are RIP */ #define MEM_EVENT_REASON_SINGLESTEP 6 /* single step was invoked: gla/gfn are RIP */ -#define MEM_EVENT_PAGING_AGE 1UL /* Number distinguish the mem_paging <-> pager interface */ +#define MEM_EVENT_PAGING_AGE 2UL /* Number distinguish the mem_paging <-> pager interface */ typedef struct mem_event_shared_page { uint32_t port;