* [PATCH 01/12] xenpaging: remove domain_id and mfn from struct xenpaging_victim
2011-01-10 16:43 [PATCH 00/12] xenpaging changes for xen-unstable Olaf Hering
@ 2011-01-10 16:43 ` Olaf Hering
2011-01-10 16:43 ` [PATCH 02/12] xenpaging: specify policy mru_size at runtime Olaf Hering
` (11 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Olaf Hering @ 2011-01-10 16:43 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: xen-unstable.xenpaging.no_domain_id.patch --]
[-- Type: text/plain, Size: 6856 bytes --]
Remove unused member 'mfn' from struct xenpaging_victim.
xenpaging operates on a single guest, so it needs only a single domain_id.
Remove domain_id from struct xenpaging_victim and use the one from
paging->mem_event where needed. Its not used in the policy.
This saves 4MB runtime data with a 1GB pagefile.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
tools/xenpaging/policy.h | 7 +++----
tools/xenpaging/policy_default.c | 10 +++-------
tools/xenpaging/xenpaging.c | 26 ++++++++++++--------------
tools/xenpaging/xenpaging.h | 4 ----
4 files changed, 18 insertions(+), 29 deletions(-)
--- xen-unstable.hg-4.1.22694.orig/tools/xenpaging/policy.h
+++ xen-unstable.hg-4.1.22694/tools/xenpaging/policy.h
@@ -29,10 +29,9 @@
int policy_init(xenpaging_t *paging);
-int policy_choose_victim(xenpaging_t *paging, domid_t domain_id,
- xenpaging_victim_t *victim);
-void policy_notify_paged_out(domid_t domain_id, unsigned long gfn);
-void policy_notify_paged_in(domid_t domain_id, unsigned long gfn);
+int policy_choose_victim(xenpaging_t *paging, xenpaging_victim_t *victim);
+void policy_notify_paged_out(unsigned long gfn);
+void policy_notify_paged_in(unsigned long gfn);
#endif // __XEN_PAGING_POLICY_H__
--- xen-unstable.hg-4.1.22694.orig/tools/xenpaging/policy_default.c
+++ xen-unstable.hg-4.1.22694/tools/xenpaging/policy_default.c
@@ -67,16 +67,12 @@ int policy_init(xenpaging_t *paging)
return rc;
}
-int policy_choose_victim(xenpaging_t *paging, domid_t domain_id,
- xenpaging_victim_t *victim)
+int policy_choose_victim(xenpaging_t *paging, xenpaging_victim_t *victim)
{
xc_interface *xch = paging->xc_handle;
unsigned long wrap = current_gfn;
ASSERT(victim != NULL);
- /* Domain to pick on */
- victim->domain_id = domain_id;
-
do
{
current_gfn++;
@@ -96,13 +92,13 @@ int policy_choose_victim(xenpaging_t *pa
return 0;
}
-void policy_notify_paged_out(domid_t domain_id, unsigned long gfn)
+void policy_notify_paged_out(unsigned long gfn)
{
set_bit(gfn, bitmap);
clear_bit(gfn, unconsumed);
}
-void policy_notify_paged_in(domid_t domain_id, unsigned long gfn)
+void policy_notify_paged_in(unsigned long gfn)
{
unsigned long old_gfn = mru[i_mru & (MRU_SIZE - 1)];
--- xen-unstable.hg-4.1.22694.orig/tools/xenpaging/xenpaging.c
+++ xen-unstable.hg-4.1.22694/tools/xenpaging/xenpaging.c
@@ -171,7 +171,7 @@ xenpaging_t *xenpaging_init(domid_t doma
goto err;
}
- rc = xc_get_platform_info(xch, domain_id,
+ rc = xc_get_platform_info(xch, paging->mem_event.domain_id,
paging->platform_info);
if ( rc != 1 )
{
@@ -187,7 +187,7 @@ xenpaging_t *xenpaging_init(domid_t doma
goto err;
}
- rc = xc_domain_getinfolist(xch, domain_id, 1,
+ rc = xc_domain_getinfolist(xch, paging->mem_event.domain_id, 1,
paging->domain_info);
if ( rc != 1 )
{
@@ -348,7 +348,7 @@ int xenpaging_evict_page(xenpaging_t *pa
/* Map page */
gfn = victim->gfn;
ret = -EFAULT;
- page = xc_map_foreign_pages(xch, victim->domain_id,
+ page = xc_map_foreign_pages(xch, paging->mem_event.domain_id,
PROT_READ | PROT_WRITE, &gfn, 1);
if ( page == NULL )
{
@@ -380,7 +380,7 @@ int xenpaging_evict_page(xenpaging_t *pa
}
/* Notify policy of page being paged out */
- policy_notify_paged_out(paging->mem_event.domain_id, victim->gfn);
+ policy_notify_paged_out(victim->gfn);
out:
return ret;
@@ -397,7 +397,7 @@ static int xenpaging_resume_page(xenpagi
/* Notify policy of page being paged in */
if ( notify_policy )
- policy_notify_paged_in(paging->mem_event.domain_id, rsp->gfn);
+ policy_notify_paged_in(rsp->gfn);
/* Tell Xen page is ready */
ret = xc_mem_paging_resume(paging->xc_handle, paging->mem_event.domain_id,
@@ -464,7 +464,7 @@ static int xenpaging_populate_page(xenpa
return ret;
}
-static int evict_victim(xenpaging_t *paging, domid_t domain_id,
+static int evict_victim(xenpaging_t *paging,
xenpaging_victim_t *victim, int fd, int i)
{
xc_interface *xch = paging->xc_handle;
@@ -473,7 +473,7 @@ static int evict_victim(xenpaging_t *pag
do
{
- ret = policy_choose_victim(paging, domain_id, victim);
+ ret = policy_choose_victim(paging, victim);
if ( ret != 0 )
{
if ( ret != -ENOSPC )
@@ -486,14 +486,13 @@ static int evict_victim(xenpaging_t *pag
ret = -EINTR;
goto out;
}
- ret = xc_mem_paging_nominate(xch,
- paging->mem_event.domain_id, victim->gfn);
+ 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
{
if ( j++ % 1000 == 0 )
- if ( xc_mem_paging_flush_ioemu_cache(domain_id) )
+ if ( xc_mem_paging_flush_ioemu_cache(paging->mem_event.domain_id) )
ERROR("Error flushing ioemu cache");
}
}
@@ -578,7 +577,7 @@ int main(int argc, char *argv[])
memset(victims, 0, sizeof(xenpaging_victim_t) * num_pages);
for ( i = 0; i < num_pages; i++ )
{
- rc = evict_victim(paging, domain_id, &victims[i], fd, i);
+ rc = evict_victim(paging, &victims[i], fd, i);
if ( rc == -ENOSPC )
break;
if ( rc == -EINTR )
@@ -619,8 +618,7 @@ int main(int argc, char *argv[])
/* Find where in the paging file to read from */
for ( i = 0; i < num_pages; i++ )
{
- if ( (victims[i].domain_id == paging->mem_event.domain_id) &&
- (victims[i].gfn == req.gfn) )
+ if ( victims[i].gfn == req.gfn )
break;
}
@@ -652,7 +650,7 @@ int main(int argc, char *argv[])
}
/* Evict a new page to replace the one we just paged in */
- evict_victim(paging, domain_id, &victims[i], fd, i);
+ evict_victim(paging, &victims[i], fd, i);
}
else
{
--- xen-unstable.hg-4.1.22694.orig/tools/xenpaging/xenpaging.h
+++ xen-unstable.hg-4.1.22694/tools/xenpaging/xenpaging.h
@@ -49,12 +49,8 @@ typedef struct xenpaging {
typedef struct xenpaging_victim {
- /* the domain to evict a page from */
- domid_t domain_id;
/* the gfn of the page to evict */
unsigned long gfn;
- /* the mfn of evicted page */
- unsigned long mfn;
} xenpaging_victim_t;
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 02/12] xenpaging: specify policy mru_size at runtime
2011-01-10 16:43 [PATCH 00/12] xenpaging changes for xen-unstable Olaf Hering
2011-01-10 16:43 ` [PATCH 01/12] xenpaging: remove domain_id and mfn from struct xenpaging_victim Olaf Hering
@ 2011-01-10 16:43 ` Olaf Hering
2011-01-10 16:43 ` [PATCH 03/12] xenpaging: mkdir /var/lib/xen/xenpaging during make install Olaf Hering
` (10 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Olaf Hering @ 2011-01-10 16:43 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: xen-unstable.xenpaging.runtime_mru_size.patch --]
[-- Type: text/plain, Size: 3213 bytes --]
The environment variable XENPAGING_POLICY_MRU_SIZE will change the
mru_size in the policy at runtime.
Specifying the mru_size at runtime allows the admin to keep more pages in
memory so guests can make more progress. Its also good for development to
reduce the value to put more pressure on the paging related code paths.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
Note: some work is still required to actually get the value into the
environment of the process. Maybe it will become an config option
at some point.
tools/xenpaging/policy_default.c | 23 ++++++++++++++++++-----
tools/xenpaging/xenpaging.c | 8 ++++++++
tools/xenpaging/xenpaging.h | 1 +
3 files changed, 27 insertions(+), 5 deletions(-)
--- xen-unstable.hg-4.1.22571.orig/tools/xenpaging/policy_default.c
+++ xen-unstable.hg-4.1.22571/tools/xenpaging/policy_default.c
@@ -26,11 +26,12 @@
#include "policy.h"
-#define MRU_SIZE (1024 * 16)
+#define DEFAULT_MRU_SIZE (1024 * 16)
-static unsigned long mru[MRU_SIZE];
+static unsigned long *mru;
static unsigned int i_mru;
+static unsigned int mru_size;
static unsigned long *bitmap;
static unsigned long *unconsumed;
static unsigned long current_gfn;
@@ -57,7 +58,19 @@ int policy_init(xenpaging_t *paging)
max_pages = paging->domain_info->max_pages;
/* Initialise MRU list of paged in pages */
- for ( i = 0; i < MRU_SIZE; i++ )
+ if ( paging->policy_mru_size > 0 )
+ mru_size = paging->policy_mru_size;
+ else
+ mru_size = DEFAULT_MRU_SIZE;
+
+ mru = malloc(sizeof(*mru) * mru_size);
+ if ( mru == NULL )
+ {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ for ( i = 0; i < mru_size; i++ )
mru[i] = INVALID_MFN;
/* Don't page out page 0 */
@@ -100,12 +113,12 @@ void policy_notify_paged_out(unsigned lo
void policy_notify_paged_in(unsigned long gfn)
{
- unsigned long old_gfn = mru[i_mru & (MRU_SIZE - 1)];
+ unsigned long old_gfn = mru[i_mru & (mru_size - 1)];
if ( old_gfn != INVALID_MFN )
clear_bit(old_gfn, bitmap);
- mru[i_mru & (MRU_SIZE - 1)] = gfn;
+ mru[i_mru & (mru_size - 1)] = gfn;
i_mru++;
}
--- xen-unstable.hg-4.1.22571.orig/tools/xenpaging/xenpaging.c
+++ xen-unstable.hg-4.1.22571/tools/xenpaging/xenpaging.c
@@ -78,6 +78,7 @@ xenpaging_t *xenpaging_init(domid_t doma
xenpaging_t *paging;
xc_interface *xch;
xentoollog_logger *dbg = NULL;
+ char *p;
int rc;
if ( getenv("XENPAGING_DEBUG") )
@@ -92,6 +93,13 @@ xenpaging_t *xenpaging_init(domid_t doma
paging = malloc(sizeof(xenpaging_t));
memset(paging, 0, sizeof(xenpaging_t));
+ p = getenv("XENPAGING_POLICY_MRU_SIZE");
+ if ( p && *p )
+ {
+ paging->policy_mru_size = atoi(p);
+ DPRINTF("Setting policy mru_size to %d\n", paging->policy_mru_size);
+ }
+
/* Open connection to xen */
paging->xc_handle = xch;
--- xen-unstable.hg-4.1.22571.orig/tools/xenpaging/xenpaging.h
+++ xen-unstable.hg-4.1.22571/tools/xenpaging/xenpaging.h
@@ -45,6 +45,7 @@ typedef struct xenpaging {
unsigned long *bitmap;
mem_event_t mem_event;
+ int policy_mru_size;
} xenpaging_t;
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 03/12] xenpaging: mkdir /var/lib/xen/xenpaging during make install
2011-01-10 16:43 [PATCH 00/12] xenpaging changes for xen-unstable Olaf Hering
2011-01-10 16:43 ` [PATCH 01/12] xenpaging: remove domain_id and mfn from struct xenpaging_victim Olaf Hering
2011-01-10 16:43 ` [PATCH 02/12] xenpaging: specify policy mru_size at runtime Olaf Hering
@ 2011-01-10 16:43 ` Olaf Hering
2011-01-10 16:43 ` [PATCH 04/12] xenpaging: print page-in/page-out progress Olaf Hering
` (9 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Olaf Hering @ 2011-01-10 16:43 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: xen-unstable.xenpaging.make_install.patch --]
[-- Type: text/plain, Size: 561 bytes --]
pagefiles go to /var/lib/xen/xenpaging directory,
create this directory during make install
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
tools/xenpaging/Makefile | 1 +
1 file changed, 1 insertion(+)
--- xen-unstable.hg-4.1.22571.orig/tools/xenpaging/Makefile
+++ xen-unstable.hg-4.1.22571/tools/xenpaging/Makefile
@@ -27,6 +27,7 @@ xenpaging: $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
install: all
+ $(INSTALL_DIR) $(DESTDIR)/var/lib/xen/xenpaging
$(INSTALL_DIR) $(DESTDIR)$(SBINDIR)
$(INSTALL_PROG) $(IBINS) $(DESTDIR)$(SBINDIR)
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 04/12] xenpaging: print page-in/page-out progress
2011-01-10 16:43 [PATCH 00/12] xenpaging changes for xen-unstable Olaf Hering
` (2 preceding siblings ...)
2011-01-10 16:43 ` [PATCH 03/12] xenpaging: mkdir /var/lib/xen/xenpaging during make install Olaf Hering
@ 2011-01-10 16:43 ` Olaf Hering
2011-01-10 16:43 ` [PATCH 05/12] xenpaging: make three functions static Olaf Hering
` (8 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Olaf Hering @ 2011-01-10 16:43 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: xen-unstable.xenpaging.print-pageout-pagein-progress.patch --]
[-- Type: text/plain, Size: 978 bytes --]
Now that DPRINTF is triggered only when the environment variable
XENPAGING_DEBUG is found, make such a debug session actually useful by
printing the entire page-out/page-in process. The 'Got event from Xen'
message alone is not helpful.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
tools/xenpaging/xenpaging.c | 2 ++
1 file changed, 2 insertions(+)
--- xen-unstable.hg-4.1.22571.orig/tools/xenpaging/xenpaging.c
+++ xen-unstable.hg-4.1.22571/tools/xenpaging/xenpaging.c
@@ -387,6 +387,7 @@ int xenpaging_evict_page(xenpaging_t *pa
goto out;
}
+ DPRINTF("evict_page > gfn %lx pageslot %d\n", victim->gfn, i);
/* Notify policy of page being paged out */
policy_notify_paged_out(victim->gfn);
@@ -427,6 +428,7 @@ static int xenpaging_populate_page(xenpa
unsigned char oom = 0;
_gfn = *gfn;
+ DPRINTF("populate_page < gfn %lx pageslot %d\n", _gfn, i);
do
{
/* Tell Xen to allocate a page for the domain */
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 05/12] xenpaging: make three functions static
2011-01-10 16:43 [PATCH 00/12] xenpaging changes for xen-unstable Olaf Hering
` (3 preceding siblings ...)
2011-01-10 16:43 ` [PATCH 04/12] xenpaging: print page-in/page-out progress Olaf Hering
@ 2011-01-10 16:43 ` Olaf Hering
2011-01-11 18:36 ` Ian Jackson
2011-01-10 16:43 ` [PATCH 06/12] xenpaging: update machine_to_phys_mapping[] during page deallocation Olaf Hering
` (7 subsequent siblings)
12 siblings, 1 reply; 19+ messages in thread
From: Olaf Hering @ 2011-01-10 16:43 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: xen-unstable.xenpaging.static_functions.patch --]
[-- Type: text/plain, Size: 1134 bytes --]
xenpaging_init(), xenpaging_teardown() and xenpaging_evict_page() are
only used in file scope, so they can be marked static.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
tools/xenpaging/xenpaging.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- xen-unstable.hg-4.1.22697.orig/tools/xenpaging/xenpaging.c
+++ xen-unstable.hg-4.1.22697/tools/xenpaging/xenpaging.c
@@ -73,7 +73,7 @@ static void *init_page(void)
return NULL;
}
-xenpaging_t *xenpaging_init(domid_t domain_id)
+static xenpaging_t *xenpaging_init(domid_t domain_id)
{
xenpaging_t *paging;
xc_interface *xch;
@@ -251,7 +251,7 @@ xenpaging_t *xenpaging_init(domid_t doma
return NULL;
}
-int xenpaging_teardown(xenpaging_t *paging)
+static int xenpaging_teardown(xenpaging_t *paging)
{
int rc;
xc_interface *xch;
@@ -343,7 +343,7 @@ static int put_response(mem_event_t *mem
return 0;
}
-int xenpaging_evict_page(xenpaging_t *paging,
+static int xenpaging_evict_page(xenpaging_t *paging,
xenpaging_victim_t *victim, int fd, int i)
{
xc_interface *xch = paging->xc_handle;
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 06/12] xenpaging: update machine_to_phys_mapping[] during page deallocation
2011-01-10 16:43 [PATCH 00/12] xenpaging changes for xen-unstable Olaf Hering
` (4 preceding siblings ...)
2011-01-10 16:43 ` [PATCH 05/12] xenpaging: make three functions static Olaf Hering
@ 2011-01-10 16:43 ` Olaf Hering
2011-01-11 10:37 ` Keir Fraser
2011-01-10 16:43 ` [PATCH 07/12] xenpaging: update machine_to_phys_mapping[] during page-in Olaf Hering
` (6 subsequent siblings)
12 siblings, 1 reply; 19+ messages in thread
From: Olaf Hering @ 2011-01-10 16:43 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: xen-unstable.xenpaging.machine_to_phys_mapping.free_domheap_pages.patch --]
[-- Type: text/plain, Size: 2029 bytes --]
The machine_to_phys_mapping[] array needs updating during page
deallocation. If that page is allocated again, a call to
get_gpfn_from_mfn() will still return an old gfn from another guest.
This will cause trouble because this gfn number has no or different
meaning in the context of the current guest.
This happens when the entire guest ram is paged-out before
xen_vga_populate_vram() runs. Then XENMEM_populate_physmap is called
with gfn 0xff000. A new page is allocated with alloc_domheap_pages.
This new page does not have a gfn yet. However, in
guest_physmap_add_entry() the passed mfn maps still to an old gfn
(perhaps from another old guest). This old gfn is in paged-out state in
this guests context and has no mfn anymore. As a result, the ASSERT()
triggers because p2m_is_ram() is true for p2m_ram_paging* types.
If the machine_to_phys_mapping[] array is updated properly, both loops
in guest_physmap_add_entry() turn into no-ops for the new page and the
mfn/gfn mapping will be done at the end of the function.
If XENMEM_add_to_physmap is used with XENMAPSPACE_gmfn,
get_gpfn_from_mfn() will return an appearently valid gfn. As a result,
guest_physmap_remove_page() is called. The ASSERT in p2m_remove_page
triggers because the passed mfn does not match the old mfn for the
passed gfn.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
xen/common/page_alloc.c | 6 ++++++
1 file changed, 6 insertions(+)
--- xen-unstable.hg-4.1.22571.orig/xen/common/page_alloc.c
+++ xen-unstable.hg-4.1.22571/xen/common/page_alloc.c
@@ -1200,9 +1200,15 @@ void free_domheap_pages(struct page_info
{
int i, drop_dom_ref;
struct domain *d = page_get_owner(pg);
+ unsigned long mfn;
ASSERT(!in_irq());
+ /* this page is not a gfn anymore */
+ mfn = page_to_mfn(pg);
+ for ( i = 0; i < (1 << order); i++ )
+ set_gpfn_from_mfn(mfn + i, INVALID_M2P_ENTRY);
+
if ( unlikely(is_xen_heap_page(pg)) )
{
/* NB. May recursively lock from relinquish_memory(). */
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 06/12] xenpaging: update machine_to_phys_mapping[] during page deallocation
2011-01-10 16:43 ` [PATCH 06/12] xenpaging: update machine_to_phys_mapping[] during page deallocation Olaf Hering
@ 2011-01-11 10:37 ` Keir Fraser
2011-01-11 11:00 ` Olaf Hering
0 siblings, 1 reply; 19+ messages in thread
From: Keir Fraser @ 2011-01-11 10:37 UTC (permalink / raw)
To: Olaf Hering, xen-devel
Could we do this in free_heap_pages() instead? That definitely catches
everything that gets placed in Xen's free pool.
-- Keir
On 10/01/2011 16:43, "Olaf Hering" <olaf@aepfle.de> wrote:
> The machine_to_phys_mapping[] array needs updating during page
> deallocation. If that page is allocated again, a call to
> get_gpfn_from_mfn() will still return an old gfn from another guest.
> This will cause trouble because this gfn number has no or different
> meaning in the context of the current guest.
>
> This happens when the entire guest ram is paged-out before
> xen_vga_populate_vram() runs. Then XENMEM_populate_physmap is called
> with gfn 0xff000. A new page is allocated with alloc_domheap_pages.
> This new page does not have a gfn yet. However, in
> guest_physmap_add_entry() the passed mfn maps still to an old gfn
> (perhaps from another old guest). This old gfn is in paged-out state in
> this guests context and has no mfn anymore. As a result, the ASSERT()
> triggers because p2m_is_ram() is true for p2m_ram_paging* types.
> If the machine_to_phys_mapping[] array is updated properly, both loops
> in guest_physmap_add_entry() turn into no-ops for the new page and the
> mfn/gfn mapping will be done at the end of the function.
>
> If XENMEM_add_to_physmap is used with XENMAPSPACE_gmfn,
> get_gpfn_from_mfn() will return an appearently valid gfn. As a result,
> guest_physmap_remove_page() is called. The ASSERT in p2m_remove_page
> triggers because the passed mfn does not match the old mfn for the
> passed gfn.
>
>
> Signed-off-by: Olaf Hering <olaf@aepfle.de>
>
> ---
> xen/common/page_alloc.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> --- xen-unstable.hg-4.1.22571.orig/xen/common/page_alloc.c
> +++ xen-unstable.hg-4.1.22571/xen/common/page_alloc.c
> @@ -1200,9 +1200,15 @@ void free_domheap_pages(struct page_info
> {
> int i, drop_dom_ref;
> struct domain *d = page_get_owner(pg);
> + unsigned long mfn;
>
> ASSERT(!in_irq());
>
> + /* this page is not a gfn anymore */
> + mfn = page_to_mfn(pg);
> + for ( i = 0; i < (1 << order); i++ )
> + set_gpfn_from_mfn(mfn + i, INVALID_M2P_ENTRY);
> +
> if ( unlikely(is_xen_heap_page(pg)) )
> {
> /* NB. May recursively lock from relinquish_memory(). */
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 06/12] xenpaging: update machine_to_phys_mapping[] during page deallocation
2011-01-11 10:37 ` Keir Fraser
@ 2011-01-11 11:00 ` Olaf Hering
2011-01-11 11:29 ` Keir Fraser
0 siblings, 1 reply; 19+ messages in thread
From: Olaf Hering @ 2011-01-11 11:00 UTC (permalink / raw)
To: Keir Fraser; +Cc: xen-devel
On Tue, Jan 11, Keir Fraser wrote:
> Could we do this in free_heap_pages() instead? That definitely catches
> everything that gets placed in Xen's free pool.
Yes, this is a compile-tested patch.
The machine_to_phys_mapping[] array needs updating during page
deallocation. If that page is allocated again, a call to
get_gpfn_from_mfn() will still return an old gfn from another guest.
This will cause trouble because this gfn number has no or different
meaning in the context of the current guest.
This happens when the entire guest ram is paged-out before
xen_vga_populate_vram() runs. Then XENMEM_populate_physmap is called
with gfn 0xff000. A new page is allocated with alloc_domheap_pages.
This new page does not have a gfn yet. However, in
guest_physmap_add_entry() the passed mfn maps still to an old gfn
(perhaps from another old guest). This old gfn is in paged-out state in
this guests context and has no mfn anymore. As a result, the ASSERT()
triggers because p2m_is_ram() is true for p2m_ram_paging* types.
If the machine_to_phys_mapping[] array is updated properly, both loops
in guest_physmap_add_entry() turn into no-ops for the new page and the
mfn/gfn mapping will be done at the end of the function.
If XENMEM_add_to_physmap is used with XENMAPSPACE_gmfn,
get_gpfn_from_mfn() will return an appearently valid gfn. As a result,
guest_physmap_remove_page() is called. The ASSERT in p2m_remove_page
triggers because the passed mfn does not match the old mfn for the
passed gfn.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
v2:
move from free_domheap_pages() to free_heap_pages() as suggested by Keir
xen/common/page_alloc.c | 6 ++++++
1 file changed, 6 insertions(+)
--- xen-unstable.hg-4.1.22697.orig/xen/common/page_alloc.c
+++ xen-unstable.hg-4.1.22697/xen/common/page_alloc.c
@@ -527,6 +527,7 @@ static int reserve_offlined_page(struct
static void free_heap_pages(
struct page_info *pg, unsigned int order)
{
+ unsigned long mfn;
unsigned long mask;
unsigned int i, node = phys_to_nid(page_to_maddr(pg)), tainted = 0;
unsigned int zone = page_to_zone(pg);
@@ -536,6 +537,11 @@ static void free_heap_pages(
spin_lock(&heap_lock);
+ /* this page is not a gfn anymore */
+ mfn = page_to_mfn(pg);
+ for ( i = 0; i < (1 << order); i++ )
+ set_gpfn_from_mfn(mfn + i, INVALID_M2P_ENTRY);
+
for ( i = 0; i < (1 << order); i++ )
{
/*
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 06/12] xenpaging: update machine_to_phys_mapping[] during page deallocation
2011-01-11 11:00 ` Olaf Hering
@ 2011-01-11 11:29 ` Keir Fraser
0 siblings, 0 replies; 19+ messages in thread
From: Keir Fraser @ 2011-01-11 11:29 UTC (permalink / raw)
To: Olaf Hering; +Cc: xen-devel
On 11/01/2011 11:00, "Olaf Hering" <olaf@aepfle.de> wrote:
> On Tue, Jan 11, Keir Fraser wrote:
>
>> Could we do this in free_heap_pages() instead? That definitely catches
>> everything that gets placed in Xen's free pool.
>
> Yes, this is a compile-tested patch.
Thanks. I fixed a subtle bug (rather disgustingly, set_gpfn_from_mfn()
depends on page_get_owner(mfn_to_page(mfn))), and checked it in as c/s
22706.
-- Keir
>
> The machine_to_phys_mapping[] array needs updating during page
> deallocation. If that page is allocated again, a call to
> get_gpfn_from_mfn() will still return an old gfn from another guest.
> This will cause trouble because this gfn number has no or different
> meaning in the context of the current guest.
>
> This happens when the entire guest ram is paged-out before
> xen_vga_populate_vram() runs. Then XENMEM_populate_physmap is called
> with gfn 0xff000. A new page is allocated with alloc_domheap_pages.
> This new page does not have a gfn yet. However, in
> guest_physmap_add_entry() the passed mfn maps still to an old gfn
> (perhaps from another old guest). This old gfn is in paged-out state in
> this guests context and has no mfn anymore. As a result, the ASSERT()
> triggers because p2m_is_ram() is true for p2m_ram_paging* types.
> If the machine_to_phys_mapping[] array is updated properly, both loops
> in guest_physmap_add_entry() turn into no-ops for the new page and the
> mfn/gfn mapping will be done at the end of the function.
>
> If XENMEM_add_to_physmap is used with XENMAPSPACE_gmfn,
> get_gpfn_from_mfn() will return an appearently valid gfn. As a result,
> guest_physmap_remove_page() is called. The ASSERT in p2m_remove_page
> triggers because the passed mfn does not match the old mfn for the
> passed gfn.
>
>
> Signed-off-by: Olaf Hering <olaf@aepfle.de>
>
> ---
> v2:
> move from free_domheap_pages() to free_heap_pages() as suggested by Keir
>
> xen/common/page_alloc.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> --- xen-unstable.hg-4.1.22697.orig/xen/common/page_alloc.c
> +++ xen-unstable.hg-4.1.22697/xen/common/page_alloc.c
> @@ -527,6 +527,7 @@ static int reserve_offlined_page(struct
> static void free_heap_pages(
> struct page_info *pg, unsigned int order)
> {
> + unsigned long mfn;
> unsigned long mask;
> unsigned int i, node = phys_to_nid(page_to_maddr(pg)), tainted = 0;
> unsigned int zone = page_to_zone(pg);
> @@ -536,6 +537,11 @@ static void free_heap_pages(
>
> spin_lock(&heap_lock);
>
> + /* this page is not a gfn anymore */
> + mfn = page_to_mfn(pg);
> + for ( i = 0; i < (1 << order); i++ )
> + set_gpfn_from_mfn(mfn + i, INVALID_M2P_ENTRY);
> +
> for ( i = 0; i < (1 << order); i++ )
> {
> /*
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 07/12] xenpaging: update machine_to_phys_mapping[] during page-in
2011-01-10 16:43 [PATCH 00/12] xenpaging changes for xen-unstable Olaf Hering
` (5 preceding siblings ...)
2011-01-10 16:43 ` [PATCH 06/12] xenpaging: update machine_to_phys_mapping[] during page deallocation Olaf Hering
@ 2011-01-10 16:43 ` Olaf Hering
2011-01-10 16:43 ` [PATCH 08/12] xenpaging: drop paged pages in guest_remove_page Olaf Hering
` (5 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Olaf Hering @ 2011-01-10 16:43 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: xen-unstable.xenpaging.machine_to_phys_mapping.patch --]
[-- Type: text/plain, Size: 663 bytes --]
Update the machine_to_phys_mapping[] array during page-in. The gfn is
now at a different page and the array has still INVALID_M2P_ENTRY in the
index.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
xen/arch/x86/mm/p2m.c | 1 +
1 file changed, 1 insertion(+)
--- xen-unstable.hg-4.1.22694.orig/xen/arch/x86/mm/p2m.c
+++ xen-unstable.hg-4.1.22694/xen/arch/x86/mm/p2m.c
@@ -2850,6 +2850,7 @@ void p2m_mem_paging_resume(struct p2m_do
mfn = gfn_to_mfn(p2m, rsp.gfn, &p2mt);
p2m_lock(p2m);
set_p2m_entry(p2m, rsp.gfn, mfn, 0, p2m_ram_rw, p2m->default_access);
+ set_gpfn_from_mfn(mfn_x(mfn), gfn);
audit_p2m(p2m, 1);
p2m_unlock(p2m);
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 08/12] xenpaging: drop paged pages in guest_remove_page
2011-01-10 16:43 [PATCH 00/12] xenpaging changes for xen-unstable Olaf Hering
` (6 preceding siblings ...)
2011-01-10 16:43 ` [PATCH 07/12] xenpaging: update machine_to_phys_mapping[] during page-in Olaf Hering
@ 2011-01-10 16:43 ` Olaf Hering
2011-01-14 16:53 ` Olaf Hering
2011-01-10 16:43 ` [PATCH 09/12] xenpaging: prevent page-out of gfn 0x80 Olaf Hering
` (4 subsequent siblings)
12 siblings, 1 reply; 19+ messages in thread
From: Olaf Hering @ 2011-01-10 16:43 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: xen-unstable.xenpaging.guest_remove_page.patch --]
[-- Type: text/plain, Size: 7306 bytes --]
Simply drop paged-pages in guest_remove_page(), and notify xenpaging to
drop its reference to the gfn. If the ring is full, the page will
remain in paged-out state in xenpaging. This is not an issue, it just
means this gfn will not be nominated again.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
v3:
send one-way notification to pager to release page
use new mem_event_check_ring() feature to not pause vcpu when ring is full
v2:
resume dropped page to unpause vcpus
tools/xenpaging/xenpaging.c | 39 ++++++++++++++++++++------------
xen/arch/x86/mm/p2m.c | 49 ++++++++++++++++++++++++++++++-----------
xen/common/memory.c | 6 +++++
xen/include/asm-x86/p2m.h | 4 +++
xen/include/public/mem_event.h | 1
5 files changed, 72 insertions(+), 27 deletions(-)
--- xen-unstable.hg-4.1.22694.orig/tools/xenpaging/xenpaging.c
+++ xen-unstable.hg-4.1.22694/tools/xenpaging/xenpaging.c
@@ -638,25 +638,34 @@ int main(int argc, char *argv[])
goto out;
}
- /* Populate the page */
- rc = xenpaging_populate_page(paging, &req.gfn, fd, i);
- if ( rc != 0 )
+ if ( req.flags & MEM_EVENT_FLAG_DROP_PAGE )
{
- ERROR("Error populating page");
- goto out;
+ DPRINTF("drop_page ^ gfn %"PRIx64" pageslot %d\n", req.gfn, i);
+ /* Notify policy of page being dropped */
+ policy_notify_paged_in(req.gfn);
}
+ else
+ {
+ /* Populate the page */
+ rc = xenpaging_populate_page(paging, &req.gfn, fd, i);
+ if ( rc != 0 )
+ {
+ ERROR("Error populating page");
+ goto out;
+ }
- /* Prepare the response */
- rsp.gfn = req.gfn;
- rsp.p2mt = req.p2mt;
- rsp.vcpu_id = req.vcpu_id;
- rsp.flags = req.flags;
+ /* Prepare the response */
+ rsp.gfn = req.gfn;
+ rsp.p2mt = req.p2mt;
+ rsp.vcpu_id = req.vcpu_id;
+ rsp.flags = req.flags;
- rc = xenpaging_resume_page(paging, &rsp, 1);
- if ( rc != 0 )
- {
- ERROR("Error resuming page");
- goto out;
+ rc = xenpaging_resume_page(paging, &rsp, 1);
+ if ( rc != 0 )
+ {
+ ERROR("Error resuming page");
+ goto out;
+ }
}
/* Evict a new page to replace the one we just paged in */
--- xen-unstable.hg-4.1.22694.orig/xen/arch/x86/mm/p2m.c
+++ xen-unstable.hg-4.1.22694/xen/arch/x86/mm/p2m.c
@@ -2211,12 +2211,15 @@ p2m_remove_page(struct p2m_domain *p2m,
P2M_DEBUG("removing gfn=%#lx mfn=%#lx\n", gfn, mfn);
- for ( i = 0; i < (1UL << page_order); i++ )
+ if ( mfn_valid(_mfn(mfn)) )
{
- mfn_return = p2m->get_entry(p2m, gfn + i, &t, &a, p2m_query);
- if ( !p2m_is_grant(t) )
- set_gpfn_from_mfn(mfn+i, INVALID_M2P_ENTRY);
- ASSERT( !p2m_is_valid(t) || mfn + i == mfn_x(mfn_return) );
+ for ( i = 0; i < (1UL << page_order); i++ )
+ {
+ mfn_return = p2m->get_entry(p2m, gfn + i, &t, &a, p2m_query);
+ if ( !p2m_is_grant(t) )
+ set_gpfn_from_mfn(mfn+i, INVALID_M2P_ENTRY);
+ ASSERT( !p2m_is_valid(t) || mfn + i == mfn_x(mfn_return) );
+ }
}
set_p2m_entry(p2m, gfn, _mfn(INVALID_MFN), page_order, p2m_invalid, p2m->default_access);
}
@@ -2772,6 +2775,25 @@ int p2m_mem_paging_evict(struct p2m_doma
return 0;
}
+void p2m_mem_paging_drop_page(struct p2m_domain *p2m, unsigned long gfn)
+{
+ struct vcpu *v = current;
+ mem_event_request_t req;
+ struct domain *d = p2m->domain;
+
+ /* Check that there's space on the ring for this request */
+ if ( mem_event_check_ring(d) == 0)
+ {
+ /* Send release notification to pager */
+ memset(&req, 0, sizeof(req));
+ req.flags |= MEM_EVENT_FLAG_DROP_PAGE;
+ req.gfn = gfn;
+ req.vcpu_id = v->vcpu_id;
+
+ mem_event_put_request(d, &req);
+ }
+}
+
void p2m_mem_paging_populate(struct p2m_domain *p2m, unsigned long gfn)
{
struct vcpu *v = current;
@@ -2846,13 +2868,16 @@ void p2m_mem_paging_resume(struct p2m_do
/* Pull the response off the ring */
mem_event_get_response(d, &rsp);
- /* Fix p2m entry */
- mfn = gfn_to_mfn(p2m, rsp.gfn, &p2mt);
- p2m_lock(p2m);
- set_p2m_entry(p2m, rsp.gfn, mfn, 0, p2m_ram_rw, p2m->default_access);
- set_gpfn_from_mfn(mfn_x(mfn), gfn);
- audit_p2m(p2m, 1);
- p2m_unlock(p2m);
+ /* Fix p2m entry if the page was not dropped */
+ if ( !(rsp.flags & MEM_EVENT_FLAG_DROP_PAGE) )
+ {
+ mfn = gfn_to_mfn(p2m, rsp.gfn, &p2mt);
+ p2m_lock(p2m);
+ set_p2m_entry(p2m, rsp.gfn, mfn, 0, p2m_ram_rw, p2m->default_access);
+ set_gpfn_from_mfn(mfn_x(mfn), rsp.gfn);
+ audit_p2m(p2m, 1);
+ p2m_unlock(p2m);
+ }
/* Unpause domain */
if ( rsp.flags & MEM_EVENT_FLAG_VCPU_PAUSED )
--- xen-unstable.hg-4.1.22694.orig/xen/common/memory.c
+++ xen-unstable.hg-4.1.22694/xen/common/memory.c
@@ -163,6 +163,12 @@ int guest_remove_page(struct domain *d,
#ifdef CONFIG_X86
mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(d), gmfn, &p2mt));
+ if ( unlikely(p2m_is_paging(p2mt)) )
+ {
+ guest_physmap_remove_page(d, gmfn, mfn, 0);
+ p2m_mem_paging_drop_page(p2m_get_hostp2m(d), gmfn);
+ return 1;
+ }
#else
mfn = gmfn_to_mfn(d, gmfn);
#endif
--- xen-unstable.hg-4.1.22694.orig/xen/include/asm-x86/p2m.h
+++ xen-unstable.hg-4.1.22694/xen/include/asm-x86/p2m.h
@@ -511,6 +511,8 @@ int set_shared_p2m_entry(struct p2m_doma
int p2m_mem_paging_nominate(struct p2m_domain *p2m, unsigned long gfn);
/* Evict a frame */
int p2m_mem_paging_evict(struct p2m_domain *p2m, unsigned long gfn);
+/* Tell xenpaging to drop a paged out frame */
+void p2m_mem_paging_drop_page(struct p2m_domain *p2m, unsigned long gfn);
/* Start populating a paged out frame */
void p2m_mem_paging_populate(struct p2m_domain *p2m, unsigned long gfn);
/* Prepare the p2m for paging a frame in */
@@ -518,6 +520,8 @@ int p2m_mem_paging_prep(struct p2m_domai
/* Resume normal operation (in case a domain was paused) */
void p2m_mem_paging_resume(struct p2m_domain *p2m);
#else
+static inline void p2m_mem_paging_drop_page(struct p2m_domain *p2m, unsigned long gfn)
+{ }
static inline void p2m_mem_paging_populate(struct p2m_domain *p2m, unsigned long gfn)
{ }
#endif
--- xen-unstable.hg-4.1.22694.orig/xen/include/public/mem_event.h
+++ xen-unstable.hg-4.1.22694/xen/include/public/mem_event.h
@@ -33,6 +33,7 @@
/* Memory event flags */
#define MEM_EVENT_FLAG_VCPU_PAUSED (1 << 0)
+#define MEM_EVENT_FLAG_DROP_PAGE (1 << 1)
/* Reasons for the memory event request */
#define MEM_EVENT_REASON_UNKNOWN 0 /* typical reason */
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 08/12] xenpaging: drop paged pages in guest_remove_page
2011-01-10 16:43 ` [PATCH 08/12] xenpaging: drop paged pages in guest_remove_page Olaf Hering
@ 2011-01-14 16:53 ` Olaf Hering
0 siblings, 0 replies; 19+ messages in thread
From: Olaf Hering @ 2011-01-14 16:53 UTC (permalink / raw)
To: xen-devel
On Mon, Jan 10, Olaf Hering wrote:
> Simply drop paged-pages in guest_remove_page(), and notify xenpaging to
> drop its reference to the gfn. If the ring is full, the page will
> remain in paged-out state in xenpaging. This is not an issue, it just
> means this gfn will not be nominated again.
> send one-way notification to pager to release page
Here I need some help to make that a true one-way event.
The currently applied version of the patch just fills up the ring, with
the result that the guest can not proceed because there is no way to
tell the pager about required page-in requests.
How can the request which was just consumed with get_response() be freed
from the ring buffer? I tried a modified version of
mem_event_pause_vcpu() which does not call mem_event_pause_vcpu(), but
that does not change anything. It seems the stuck guest is a result of
incorrect mem_event_ring handling.
Olaf
> +void p2m_mem_paging_drop_page(struct p2m_domain *p2m, unsigned long gfn)
> +{
> + struct vcpu *v = current;
> + mem_event_request_t req;
> + struct domain *d = p2m->domain;
> +
> + /* Check that there's space on the ring for this request */
> + if ( mem_event_check_ring(d) == 0)
> + {
> + /* Send release notification to pager */
> + memset(&req, 0, sizeof(req));
> + req.flags |= MEM_EVENT_FLAG_DROP_PAGE;
> + req.gfn = gfn;
> + req.vcpu_id = v->vcpu_id;
> +
> + mem_event_put_request(d, &req);
> + }
> +}
> +
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 09/12] xenpaging: prevent page-out of gfn 0x80
2011-01-10 16:43 [PATCH 00/12] xenpaging changes for xen-unstable Olaf Hering
` (7 preceding siblings ...)
2011-01-10 16:43 ` [PATCH 08/12] xenpaging: drop paged pages in guest_remove_page Olaf Hering
@ 2011-01-10 16:43 ` Olaf Hering
2011-01-10 16:43 ` [PATCH 10/12] xenpaging: handle HVMCOPY_gfn_paged_out in copy_from/to_user Olaf Hering
` (3 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Olaf Hering @ 2011-01-10 16:43 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: xen-unstable.xenpaging.realmode_gfn_0x80.patch --]
[-- Type: text/plain, Size: 1169 bytes --]
Add a workaround for missing handling of paged-out pages during BIOS startup.
For some reason, only gfn 0x80 is affected.
(XEN) HVM3: HVM Loader
(XEN) traps.c:649:d3 Bad GMFN 80 (MFN ffffffffff) to MSR 40000000
(XEN) HVM3: Detected Xen v4.1
(XEN) HVM3: HVMLoader bug at util.c:604
(XEN) hvm.c:1085:d3 Triple fault on VCPU0 - invoking HVM system reset.
(XEN) HVM4: HVM Loader
(XEN) traps.c:649:d4 Bad GMFN 80 (MFN ffffffffff) to MSR 40000000
(XEN) io.c:194:d4 MMIO emulation failed @ 0018:9ffff: 00 6a 10 80 c4 82
(XEN) hvm.c:1085:d4 Triple fault on VCPU0 - invoking HVM system reset.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
Another part of the bugfix is the missing p2m_mem_paging_populate() call in
gfn_to_mfn()
tools/xenpaging/policy_default.c | 3 +++
1 file changed, 3 insertions(+)
--- xen-unstable.hg-4.1.22571.orig/tools/xenpaging/policy_default.c
+++ xen-unstable.hg-4.1.22571/tools/xenpaging/policy_default.c
@@ -76,6 +76,9 @@ int policy_init(xenpaging_t *paging)
/* Don't page out page 0 */
set_bit(0, bitmap);
+ /* this is the trap page, disabled for the time being */
+ set_bit(0x80, bitmap);
+
out:
return rc;
}
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 10/12] xenpaging: handle HVMCOPY_gfn_paged_out in copy_from/to_user
2011-01-10 16:43 [PATCH 00/12] xenpaging changes for xen-unstable Olaf Hering
` (8 preceding siblings ...)
2011-01-10 16:43 ` [PATCH 09/12] xenpaging: prevent page-out of gfn 0x80 Olaf Hering
@ 2011-01-10 16:43 ` Olaf Hering
2011-01-10 16:43 ` [PATCH 11/12] xenpaging: start xenpaging via config option Olaf Hering
` (2 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Olaf Hering @ 2011-01-10 16:43 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: xen-unstable.xenpaging.HVMCOPY_gfn_paged_out.patch --]
[-- Type: text/plain, Size: 5000 bytes --]
copy_from_user_hvm can fail when __hvm_copy returns
HVMCOPY_gfn_paged_out for a referenced gfn, for example during guests
pagetable walk. This has to be handled in some way.
For the time being, return -EAGAIN for the most common case (xen_balloon
driver crashing in guest) until the recently added waitqueues will be
used.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
xen/arch/x86/hvm/hvm.c | 4 ++++
xen/common/memory.c | 39 ++++++++++++++++++++++++++++++++++-----
2 files changed, 38 insertions(+), 5 deletions(-)
--- xen-unstable.hg-4.1.22697.orig/xen/arch/x86/hvm/hvm.c
+++ xen-unstable.hg-4.1.22697/xen/arch/x86/hvm/hvm.c
@@ -2154,6 +2154,8 @@ unsigned long copy_to_user_hvm(void *to,
rc = hvm_copy_to_guest_virt_nofault((unsigned long)to, (void *)from,
len, 0);
+ if ( unlikely(rc == HVMCOPY_gfn_paged_out) )
+ return -EAGAIN;
return rc ? len : 0; /* fake a copy_to_user() return code */
}
@@ -2171,6 +2173,8 @@ unsigned long copy_from_user_hvm(void *t
#endif
rc = hvm_copy_from_guest_virt_nofault(to, (unsigned long)from, len, 0);
+ if ( unlikely(rc == HVMCOPY_gfn_paged_out) )
+ return -EAGAIN;
return rc ? len : 0; /* fake a copy_from_user() return code */
}
--- xen-unstable.hg-4.1.22697.orig/xen/common/memory.c
+++ xen-unstable.hg-4.1.22697/xen/common/memory.c
@@ -48,6 +48,7 @@ static void increase_reservation(struct
{
struct page_info *page;
unsigned long i;
+ unsigned long ctg_ret;
xen_pfn_t mfn;
struct domain *d = a->domain;
@@ -81,8 +82,13 @@ static void increase_reservation(struct
if ( !guest_handle_is_null(a->extent_list) )
{
mfn = page_to_mfn(page);
- if ( unlikely(__copy_to_guest_offset(a->extent_list, i, &mfn, 1)) )
+ ctg_ret = __copy_to_guest_offset(a->extent_list, i, &mfn, 1);
+ if ( unlikely(ctg_ret) )
+ {
+ if ( (long)ctg_ret == -EAGAIN )
+ a->preempted = 1;
goto out;
+ }
}
}
@@ -94,6 +100,7 @@ static void populate_physmap(struct memo
{
struct page_info *page;
unsigned long i, j;
+ unsigned long cftg_ret;
xen_pfn_t gpfn, mfn;
struct domain *d = a->domain;
@@ -112,8 +119,13 @@ static void populate_physmap(struct memo
goto out;
}
- if ( unlikely(__copy_from_guest_offset(&gpfn, a->extent_list, i, 1)) )
+ cftg_ret = __copy_from_guest_offset(&gpfn, a->extent_list, i, 1);
+ if ( unlikely(cftg_ret) )
+ {
+ if ( (long)cftg_ret == -EAGAIN )
+ a->preempted = 1;
goto out;
+ }
if ( a->memflags & MEMF_populate_on_demand )
{
@@ -143,8 +155,13 @@ static void populate_physmap(struct memo
set_gpfn_from_mfn(mfn + j, gpfn + j);
/* Inform the domain of the new page's machine address. */
- if ( unlikely(__copy_to_guest_offset(a->extent_list, i, &mfn, 1)) )
+ cftg_ret = __copy_to_guest_offset(a->extent_list, i, &mfn, 1);
+ if ( unlikely(cftg_ret) )
+ {
+ if ( (long)cftg_ret == -EAGAIN )
+ a->preempted = 1;
goto out;
+ }
}
}
}
@@ -213,6 +230,7 @@ int guest_remove_page(struct domain *d,
static void decrease_reservation(struct memop_args *a)
{
unsigned long i, j;
+ unsigned long cfg_ret;
xen_pfn_t gmfn;
if ( !guest_handle_subrange_okay(a->extent_list, a->nr_done,
@@ -227,8 +245,13 @@ static void decrease_reservation(struct
goto out;
}
- if ( unlikely(__copy_from_guest_offset(&gmfn, a->extent_list, i, 1)) )
+ cfg_ret = __copy_from_guest_offset(&gmfn, a->extent_list, i, 1);
+ if ( unlikely(cfg_ret) )
+ {
+ if ( (long)cfg_ret == -EAGAIN )
+ a->preempted = 1;
goto out;
+ }
if ( tb_init_done )
{
@@ -509,6 +532,7 @@ long do_memory_op(unsigned long cmd, XEN
int rc, op;
unsigned int address_bits;
unsigned long start_extent;
+ unsigned long cfg_ret;
struct xen_memory_reservation reservation;
struct memop_args args;
domid_t domid;
@@ -522,8 +546,13 @@ long do_memory_op(unsigned long cmd, XEN
case XENMEM_populate_physmap:
start_extent = cmd >> MEMOP_EXTENT_SHIFT;
- if ( copy_from_guest(&reservation, arg, 1) )
+ cfg_ret = copy_from_guest(&reservation, arg, 1);
+ if ( unlikely(cfg_ret) )
+ {
+ if ( (long)cfg_ret == -EAGAIN )
+ return hypercall_create_continuation(__HYPERVISOR_memory_op, "lh", cmd, arg);
return start_extent;
+ }
/* Is size too large for us to encode a continuation? */
if ( reservation.nr_extents > (ULONG_MAX >> MEMOP_EXTENT_SHIFT) )
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 11/12] xenpaging: start xenpaging via config option
2011-01-10 16:43 [PATCH 00/12] xenpaging changes for xen-unstable Olaf Hering
` (9 preceding siblings ...)
2011-01-10 16:43 ` [PATCH 10/12] xenpaging: handle HVMCOPY_gfn_paged_out in copy_from/to_user Olaf Hering
@ 2011-01-10 16:43 ` Olaf Hering
2011-01-10 16:43 ` [PATCH 12/12] xenpaging: document missing live migration Olaf Hering
2011-01-11 17:20 ` [PATCH 00/12] xenpaging changes for xen-unstable Ian Jackson
12 siblings, 0 replies; 19+ messages in thread
From: Olaf Hering @ 2011-01-10 16:43 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: xen-unstable.xenpaging.autostart.patch --]
[-- Type: text/plain, Size: 9570 bytes --]
Start xenpaging via config option.
TODO: add config option for different pagefile directory
TODO: add libxl support
TODO: parse config values like 42K, 42M, 42G, 42%
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
v3:
move debug for stopping xenpaging to destroyXenPaging
v2:
unlink logfile instead of truncating it.
allows hardlinking for further inspection
tools/examples/xmexample.hvm | 3 +
tools/python/README.XendConfig | 1
tools/python/README.sxpcfg | 1
tools/python/xen/xend/XendConfig.py | 3 +
tools/python/xen/xend/XendDomainInfo.py | 5 +
tools/python/xen/xend/image.py | 87 ++++++++++++++++++++++++++++++++
tools/python/xen/xm/create.py | 5 +
tools/python/xen/xm/xenapi_create.py | 1
8 files changed, 106 insertions(+)
--- xen-unstable.hg-4.1.22571.orig/tools/examples/xmexample.hvm
+++ xen-unstable.hg-4.1.22571/tools/examples/xmexample.hvm
@@ -127,6 +127,9 @@ disk = [ 'file:/var/images/min-el3-i386.
# Device Model to be used
device_model = 'qemu-dm'
+# xenpaging, number of pages, or -1 for entire guest memory range
+xenpaging = 42
+
#-----------------------------------------------------------------------------
# boot on floppy (a), hard disk (c), Network (n) or CD-ROM (d)
# default: hard disk, cd-rom, floppy
--- xen-unstable.hg-4.1.22571.orig/tools/python/README.XendConfig
+++ xen-unstable.hg-4.1.22571/tools/python/README.XendConfig
@@ -120,6 +120,7 @@ otherConfig
image.vncdisplay
image.vncunused
image.hvm.device_model
+ image.hvm.xenpaging
image.hvm.display
image.hvm.xauthority
image.hvm.vncconsole
--- xen-unstable.hg-4.1.22571.orig/tools/python/README.sxpcfg
+++ xen-unstable.hg-4.1.22571/tools/python/README.sxpcfg
@@ -51,6 +51,7 @@ image
- vncunused
(HVM)
- device_model
+ - xenpaging
- display
- xauthority
- vncconsole
--- xen-unstable.hg-4.1.22571.orig/tools/python/xen/xend/XendConfig.py
+++ xen-unstable.hg-4.1.22571/tools/python/xen/xend/XendConfig.py
@@ -147,6 +147,7 @@ XENAPI_PLATFORM_CFG_TYPES = {
'apic': int,
'boot': str,
'device_model': str,
+ 'xenpaging': int,
'loader': str,
'display' : str,
'fda': str,
@@ -508,6 +509,8 @@ class XendConfig(dict):
self['platform']['nomigrate'] = 0
if self.is_hvm():
+ if 'xenpaging' not in self['platform']:
+ self['platform']['xenpaging'] = None
if 'timer_mode' not in self['platform']:
self['platform']['timer_mode'] = 1
if 'viridian' not in self['platform']:
--- xen-unstable.hg-4.1.22571.orig/tools/python/xen/xend/XendDomainInfo.py
+++ xen-unstable.hg-4.1.22571/tools/python/xen/xend/XendDomainInfo.py
@@ -2390,6 +2390,7 @@ class XendDomainInfo:
if self.image:
self.image.createDeviceModel()
+ self.image.createXenPaging()
#if have pass-through devs, need the virtual pci slots info from qemu
self.pci_device_configure_boot()
@@ -2402,6 +2403,10 @@ class XendDomainInfo:
self.image.destroyDeviceModel()
except Exception, e:
log.exception("Device model destroy failed %s" % str(e))
+ try:
+ self.image.destroyXenPaging()
+ except Exception, e:
+ log.exception("stopping xenpaging failed %s" % str(e))
else:
log.debug("No device model")
--- xen-unstable.hg-4.1.22571.orig/tools/python/xen/xend/image.py
+++ xen-unstable.hg-4.1.22571/tools/python/xen/xend/image.py
@@ -122,12 +122,16 @@ class ImageHandler:
self.vm.permissionsVm("image/cmdline", { 'dom': self.vm.getDomid(), 'read': True } )
self.device_model = vmConfig['platform'].get('device_model')
+ self.xenpaging = vmConfig['platform'].get('xenpaging')
+ if self.xenpaging == 0:
+ self.xenpaging = None
self.display = vmConfig['platform'].get('display')
self.xauthority = vmConfig['platform'].get('xauthority')
self.vncconsole = int(vmConfig['platform'].get('vncconsole', 0))
self.dmargs = self.parseDeviceModelArgs(vmConfig)
self.pid = None
+ self.xenpaging_pid = None
rtc_timeoffset = int(vmConfig['platform'].get('rtc_timeoffset', 0))
if int(vmConfig['platform'].get('localtime', 0)):
if time.localtime(time.time())[8]:
@@ -392,6 +396,89 @@ class ImageHandler:
sentinel_fifos_inuse[sentinel_path_fifo] = 1
self.sentinel_path_fifo = sentinel_path_fifo
+ def createXenPaging(self):
+ if self.xenpaging is None:
+ return
+ if self.xenpaging_pid:
+ return
+ xenpaging_bin = auxbin.pathTo("xenpaging")
+ args = [xenpaging_bin]
+ args = args + ([ "%d" % self.vm.getDomid()])
+ args = args + ([ "%s" % self.xenpaging])
+ env = dict(os.environ)
+ self.xenpaging_logfile = "/var/log/xen/xenpaging-%s.log" % str(self.vm.info['name_label'])
+ logfile_mode = os.O_WRONLY|os.O_CREAT|os.O_APPEND|os.O_TRUNC
+ null = os.open("/dev/null", os.O_RDONLY)
+ try:
+ os.unlink(self.xenpaging_logfile)
+ except:
+ pass
+ logfd = os.open(self.xenpaging_logfile, logfile_mode, 0644)
+ sys.stderr.flush()
+ contract = osdep.prefork("%s:%d" % (self.vm.getName(), self.vm.getDomid()))
+ xenpaging_pid = os.fork()
+ if xenpaging_pid == 0: #child
+ try:
+ xenpaging_dir = "/var/lib/xen/xenpaging"
+ osdep.postfork(contract)
+ os.dup2(null, 0)
+ os.dup2(logfd, 1)
+ os.dup2(logfd, 2)
+ try:
+ os.chdir(xenpaging_dir)
+ except:
+ log.warn("chdir %s failed" % xenpaging_dir)
+ try:
+ log.info("starting %s" % args)
+ os.execve(xenpaging_bin, args, env)
+ except Exception, e:
+ print >>sys.stderr, (
+ 'failed to execute xenpaging: %s: %s' %
+ xenpaging_bin, utils.exception_string(e))
+ os._exit(126)
+ except Exception, e:
+ log.warn("staring xenpaging in %s failed" % xenpaging_dir)
+ os._exit(127)
+ else:
+ osdep.postfork(contract, abandon=True)
+ self.xenpaging_pid = xenpaging_pid
+ os.close(null)
+ os.close(logfd)
+
+ def destroyXenPaging(self):
+ if self.xenpaging is None:
+ return
+ log.debug("stopping xenpaging")
+ if self.xenpaging_pid:
+ try:
+ os.kill(self.xenpaging_pid, signal.SIGHUP)
+ except OSError, exn:
+ log.exception(exn)
+ for i in xrange(100):
+ try:
+ (p, rv) = os.waitpid(self.xenpaging_pid, os.WNOHANG)
+ if p == self.xenpaging_pid:
+ break
+ except OSError:
+ # This is expected if Xend has been restarted within
+ # the life of this domain. In this case, we can kill
+ # the process, but we can't wait for it because it's
+ # not our child. We continue this loop, and after it is
+ # terminated make really sure the process is going away
+ # (SIGKILL).
+ pass
+ time.sleep(0.1)
+ else:
+ log.warning("xenpaging %d took more than 10s "
+ "to terminate: sending SIGKILL" % self.xenpaging_pid)
+ try:
+ os.kill(self.xenpaging_pid, signal.SIGKILL)
+ os.waitpid(self.xenpaging_pid, 0)
+ except OSError:
+ # This happens if the process doesn't exist.
+ pass
+ self.xenpaging_pid = None
+
def createDeviceModel(self, restore = False):
if self.device_model is None:
return
--- xen-unstable.hg-4.1.22571.orig/tools/python/xen/xm/create.py
+++ xen-unstable.hg-4.1.22571/tools/python/xen/xm/create.py
@@ -491,6 +491,10 @@ gopts.var('nfs_root', val="PATH",
fn=set_value, default=None,
use="Set the path of the root NFS directory.")
+gopts.var('xenpaging', val='NUM',
+ fn=set_int, default=None,
+ use="Number of pages to swap.")
+
gopts.var('device_model', val='FILE',
fn=set_value, default=None,
use="Path to device model program.")
@@ -1076,6 +1080,7 @@ def configure_hvm(config_image, vals):
args = [ 'acpi', 'apic',
'boot',
'cpuid', 'cpuid_check',
+ 'xenpaging',
'device_model', 'display',
'fda', 'fdb',
'gfx_passthru', 'guest_os_type',
--- xen-unstable.hg-4.1.22571.orig/tools/python/xen/xm/xenapi_create.py
+++ xen-unstable.hg-4.1.22571/tools/python/xen/xm/xenapi_create.py
@@ -1085,6 +1085,7 @@ class sxp2xml:
'acpi',
'apic',
'boot',
+ 'xenpaging',
'device_model',
'loader',
'fda',
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 12/12] xenpaging: document missing live migration
2011-01-10 16:43 [PATCH 00/12] xenpaging changes for xen-unstable Olaf Hering
` (10 preceding siblings ...)
2011-01-10 16:43 ` [PATCH 11/12] xenpaging: start xenpaging via config option Olaf Hering
@ 2011-01-10 16:43 ` Olaf Hering
2011-01-11 17:20 ` [PATCH 00/12] xenpaging changes for xen-unstable Ian Jackson
12 siblings, 0 replies; 19+ messages in thread
From: Olaf Hering @ 2011-01-10 16:43 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: xen-unstable.xenpaging.doc.patch --]
[-- Type: text/plain, Size: 429 bytes --]
live migration does not work yet
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
docs/misc/xenpaging.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- xen-unstable.hg-4.1.22571.orig/docs/misc/xenpaging.txt
+++ xen-unstable.hg-4.1.22571/docs/misc/xenpaging.txt
@@ -42,7 +42,7 @@ changes.
Todo:
- implement stopping of xenpaging
-- implement/test live migration
+- implement live migration
# vim: tw=72
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 00/12] xenpaging changes for xen-unstable
2011-01-10 16:43 [PATCH 00/12] xenpaging changes for xen-unstable Olaf Hering
` (11 preceding siblings ...)
2011-01-10 16:43 ` [PATCH 12/12] xenpaging: document missing live migration Olaf Hering
@ 2011-01-11 17:20 ` Ian Jackson
12 siblings, 0 replies; 19+ messages in thread
From: Ian Jackson @ 2011-01-11 17:20 UTC (permalink / raw)
To: Olaf Hering; +Cc: xen-devel
Olaf Hering writes ("[Xen-devel] [PATCH 00/12] xenpaging changes for xen-unstable"):
> Here are some changes for xenpaging in xen-unstable.
Thanks.
> New to this series since my last post are patch 1 to 5.
> They are likely non-controversial and could be applied.
Yes, I intend to apply 1-5 to xen-unstable.hg now unless someone
shouts to tell me not to.
> Patches 6 and 7 are required to maintain the machine_to_phys_mapping[]
> array properly. Unless there are objections to the deallocation part,
> they could be applied.
>
> Patch 8 could be applied as well.
Does 8 depend on 6 and 7 ?
> As it stands right now, a guest will hang hard with xenpaging once the
> balloon driver is loaded in the guest. Its not clear what the issue is,
> no memory_op hypercall has been issued yet. xm vcpu-list indicates the
> guest makes no progress. I will debug this further.
Thanks. Bear in mind that we are in at the end of the release cycle
now and the tree is becoming more and more frozen.
Since xenpaging doesn't work properly without your patches they're
bugfixes but we do want to get all of them in sooner rather than
later. It's possible that we'll have to release without all the
changes you might want to make :-/.
Thanks,
Ian.
^ permalink raw reply [flat|nested] 19+ messages in thread