63 lines
2.6 KiB
Diff
63 lines
2.6 KiB
Diff
|
changeset: 23507:0a29c8c3ddf7
|
||
|
user: Keir Fraser <keir@xen.org>
|
||
|
date: Fri Jun 10 08:19:07 2011 +0100
|
||
|
files: xen/common/page_alloc.c
|
||
|
description:
|
||
|
xenpaging: update machine_to_phys_mapping[] during page deallocation
|
||
|
|
||
|
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, 5 insertions(+), 1 deletion(-)
|
||
|
|
||
|
Index: xen-4.1.2-testing/xen/common/page_alloc.c
|
||
|
===================================================================
|
||
|
--- xen-4.1.2-testing.orig/xen/common/page_alloc.c
|
||
|
+++ xen-4.1.2-testing/xen/common/page_alloc.c
|
||
|
@@ -528,7 +528,7 @@ static int reserve_offlined_page(struct
|
||
|
static void free_heap_pages(
|
||
|
struct page_info *pg, unsigned int order)
|
||
|
{
|
||
|
- unsigned long mask;
|
||
|
+ unsigned long mask, mfn = page_to_mfn(pg);
|
||
|
unsigned int i, node = phys_to_nid(page_to_maddr(pg)), tainted = 0;
|
||
|
unsigned int zone = page_to_zone(pg);
|
||
|
|
||
|
@@ -539,6 +539,10 @@ static void free_heap_pages(
|
||
|
|
||
|
for ( i = 0; i < (1 << order); i++ )
|
||
|
{
|
||
|
+ /* This page is not a guest frame any more. */
|
||
|
+ page_set_owner(&pg[i], NULL); /* set_gpfn_from_mfn snoops pg owner */
|
||
|
+ set_gpfn_from_mfn(mfn + i, INVALID_M2P_ENTRY);
|
||
|
+
|
||
|
/*
|
||
|
* Cannot assume that count_info == 0, as there are some corner cases
|
||
|
* where it isn't the case and yet it isn't a bug:
|