2012-01-05 20:41:54 +01:00
|
|
|
# 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 <olaf@aepfle.de>
|
|
|
|
|
2012-08-10 23:38:41 +02:00
|
|
|
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
|
2012-01-05 20:41:54 +01:00
|
|
|
@@ -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 );
|
2012-08-10 23:38:41 +02:00
|
|
|
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 *
|
2012-01-05 20:41:54 +01:00
|
|
|
* - 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.
|
2012-08-10 23:38:41 +02:00
|
|
|
@@ -2888,7 +2888,7 @@ int p2m_mem_paging_nominate(struct p2m_d
|
2012-01-05 20:41:54 +01:00
|
|
|
/* 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 )
|
2012-08-10 23:38:41 +02:00
|
|
|
@@ -2916,7 +2916,7 @@ int p2m_mem_paging_nominate(struct p2m_d
|
2012-01-05 20:41:54 +01:00
|
|
|
* 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
|
2012-08-10 23:38:41 +02:00
|
|
|
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
|
2012-01-05 20:41:54 +01:00
|
|
|
@@ -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;
|