WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] xen: correctly rebuild mfn list list after migration

To: jeremy@xxxxxxxx
Subject: [Xen-devel] [PATCH] xen: correctly rebuild mfn list list after migration.
From: Ian Campbell <ian.campbell@xxxxxxxxxx>
Date: Tue, 12 Oct 2010 11:14:48 +0100
Cc: xen-devel@xxxxxxxxxxxxxxxxxxx, Ian Campbell <ian.campbell@xxxxxxxxxx>
Delivery-date: Tue, 12 Oct 2010 03:15:40 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Otherwise the second migration attempt fails because the mfn_list_list
still refers to all the old mfns.

We need to update the entires in both p2m_top_mfn and the mid_mfn
pages which p2m_top_mfn refers to.

In order to do this we need to keep track of the virtual addresses
mapping the p2m_mid_mfn pages since we cannot rely on
mfn_to_virt(p2m_top_mfn[idx]) since p2m_top_mfn[idx] will still
contain the old MFN after a migration, which may now belong to another
domain and hence have a different mapping in the m2p.

Therefore add and maintain a third top level page, p2m_mid_mfn_p[],
which tracks the virtual addresses of the mfns contained in
p2m_top_mfn[].

We also need to update the content of the p2m_mid_missing_mfn page on
resume to refer to the page's new mfn.

p2m_missing does not need updating since the migration process takes
care of the leaf p2m pages for us.

Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
---
 arch/x86/xen/mmu.c |   49 ++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 16a8e25..8788064 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -185,6 +185,8 @@ DEFINE_PER_CPU(unsigned long, xen_current_cr3);      /* 
actual vcpu cr3 */
  *    / \      / \         /           /
  *  p2m p2m p2m p2m p2m p2m p2m ...
  *
+ * The p2m_mid_mfn pages are mapped by p2m_mid_mfn_p.
+ *
  * The p2m_top and p2m_top_mfn levels are limited to 1 page, so the
  * maximum representable pseudo-physical address space is:
  *  P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE pages
@@ -209,6 +211,7 @@ static RESERVE_BRK_ARRAY(unsigned long, 
p2m_mid_missing_mfn, P2M_MID_PER_PAGE);
 
 static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE);
 static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE);
+static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_mfn_p, P2M_TOP_PER_PAGE);
 
 RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * 
P2M_MID_PER_PAGE)));
 RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * 
P2M_MID_PER_PAGE)));
@@ -245,6 +248,14 @@ static void p2m_top_mfn_init(unsigned long *top)
                top[i] = virt_to_mfn(p2m_mid_missing_mfn);
 }
 
+static void p2m_mid_mfn_p_init(unsigned long **top)
+{
+       unsigned i;
+
+       for (i = 0; i < P2M_TOP_PER_PAGE; i++)
+               top[i] = p2m_mid_missing_mfn;
+}
+
 static void p2m_mid_init(unsigned long **mid)
 {
        unsigned i;
@@ -301,15 +312,21 @@ EXPORT_SYMBOL(create_lookup_pte_addr);
  */
 void xen_build_mfn_list_list(void)
 {
-       unsigned pfn;
+       unsigned long pfn;
 
        /* Pre-initialize p2m_top_mfn to be completely missing */
        if (p2m_top_mfn == NULL) {
                p2m_mid_missing_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
                p2m_mid_mfn_init(p2m_mid_missing_mfn);
 
+               p2m_mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
+               p2m_mid_mfn_p_init(p2m_mid_mfn_p);
+
                p2m_top_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
                p2m_top_mfn_init(p2m_top_mfn);
+       } else {
+               /* Reinitialise, mfn's all change after migration */
+               p2m_mid_mfn_init(p2m_mid_missing_mfn);
        }
 
        for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += P2M_PER_PAGE) {
@@ -322,14 +339,19 @@ void xen_build_mfn_list_list(void)
                mid = p2m_top[topidx];
 
                /* Don't bother allocating any mfn mid levels if
-                  they're just missing */
-               if (mid[mididx] == p2m_missing)
+                * they're just missing, just update the stored mfn,
+                * since all could have changed over a migrate.
+                */
+               if (mid == p2m_mid_missing) {
+                       p2m_top_mfn[topidx] = virt_to_mfn(p2m_mid_missing);
+                       pfn += P2M_MID_PER_PAGE - 1;
                        continue;
+               }
 
-               mid_mfn = p2m_top_mfn[topidx];
-               mid_mfn_p = mfn_to_virt(mid_mfn);
+               mid_mfn_p = p2m_mid_mfn_p[topidx];
+               mid_mfn = virt_to_mfn(mid_mfn_p);
 
-               if (mid_mfn_p == p2m_mid_missing_mfn) {
+               if (mid_mfn_p == p2m_missing) {
                        /*
                         * XXX boot-time only!  We should never find
                         * missing parts of the mfn tree after
@@ -340,10 +362,11 @@ void xen_build_mfn_list_list(void)
                        p2m_mid_mfn_init(mid_mfn_p);
 
                        mid_mfn = virt_to_mfn(mid_mfn_p);
-                       
-                       p2m_top_mfn[topidx] = mid_mfn;
+                       p2m_mid_mfn_p[topidx] = mid_mfn_p;
                }
 
+               p2m_top_mfn[topidx] = mid_mfn;
+
                mid_mfn_p[mididx] = virt_to_mfn(mid[mididx]);
        }
 }
@@ -362,7 +385,7 @@ void __init xen_build_dynamic_phys_to_machine(void)
 {
        unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list;
        unsigned long max_pfn = min(MAX_DOMAIN_PAGES, xen_start_info->nr_pages);
-       unsigned pfn;
+       unsigned long pfn;
 
        xen_max_p2m_pfn = max_pfn;
 
@@ -452,7 +475,9 @@ static bool alloc_p2m(unsigned long pfn)
        }
 
        top_mfn_p = &p2m_top_mfn[topidx];
-       mid_mfn = mfn_to_virt(*top_mfn_p);
+       mid_mfn = p2m_mid_mfn_p[topidx];
+
+       BUG_ON(mid_mfn != mfn_to_virt(*top_mfn_p));
 
        if (mid_mfn == p2m_mid_missing_mfn) {
                /* Separately check the mid mfn level */
@@ -464,11 +489,13 @@ static bool alloc_p2m(unsigned long pfn)
                        return false;
 
                p2m_mid_mfn_init(mid_mfn);
-               
+
                missing_mfn = virt_to_mfn(p2m_mid_missing_mfn);
                mid_mfn_mfn = virt_to_mfn(mid_mfn);
                if (cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn) != missing_mfn)
                        free_p2m_page(mid_mfn);
+               else
+                       p2m_mid_mfn_p[topidx] = mid_mfn;
        }
 
        if (p2m_top[topidx][mididx] == p2m_missing) {
-- 
1.5.6.5


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel