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-changelog

[Xen-changelog] [xen-unstable] Tools: fix save/restore of 32-bit PV gues

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Tools: fix save/restore of 32-bit PV guests with 64-bit tools
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 13 Feb 2008 06:30:10 -0800
Delivery-date: Wed, 13 Feb 2008 06:30:07 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1202899393 0
# Node ID 0164d924cebacfef62673a49c2f4ad395df5444b
# Parent  27314cfbcefe8ee261da3ea827eb8336c32ad987
Tools: fix save/restore of 32-bit PV guests with 64-bit tools
by removing some obvious typos, handling CR3 folding and hvirt_start
based on guest word-size, and understanding 32-bit INVALID_MFN.

Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxx>
---
 tools/libxc/xc_domain_restore.c |   12 +++++-----
 tools/libxc/xc_domain_save.c    |   48 ++++++++++++++++++++--------------------
 tools/libxc/xg_private.h        |    4 ++-
 tools/libxc/xg_save_restore.h   |   17 ++++++++++++++
 4 files changed, 51 insertions(+), 30 deletions(-)

diff -r 27314cfbcefe -r 0164d924ceba tools/libxc/xc_domain_restore.c
--- a/tools/libxc/xc_domain_restore.c   Wed Feb 13 10:42:09 2008 +0000
+++ b/tools/libxc/xc_domain_restore.c   Wed Feb 13 10:43:13 2008 +0000
@@ -251,7 +251,7 @@ static xen_pfn_t *load_p2m_frame_list(
 
     /* Now that we know the guest's word-size, can safely allocate 
      * the p2m frame list */
-    if ( (p2m_frame_list = malloc(P2M_FL_SIZE)) == NULL )
+    if ( (p2m_frame_list = malloc(P2M_TOOLS_FL_SIZE)) == NULL )
     {
         ERROR("Couldn't allocate p2m_frame_list array");
         return NULL;
@@ -1040,7 +1040,7 @@ int xc_domain_restore(int xc_handle, int
             SET_FIELD(&ctxt, gdt_frames[j], p2m[pfn]);
         }
         /* Uncanonicalise the page table base pointer. */
-        pfn = xen_cr3_to_pfn(GET_FIELD(&ctxt, ctrlreg[3]));
+        pfn = UNFOLD_CR3(GET_FIELD(&ctxt, ctrlreg[3]));
 
         if ( pfn >= p2m_size )
         {
@@ -1057,12 +1057,12 @@ int xc_domain_restore(int xc_handle, int
                   (unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
             goto out;
         }
-        SET_FIELD(&ctxt, ctrlreg[3], xen_pfn_to_cr3(p2m[pfn]));
+        SET_FIELD(&ctxt, ctrlreg[3], FOLD_CR3(p2m[pfn]));
 
         /* Guest pagetable (x86/64) stored in otherwise-unused CR1. */
         if ( (pt_levels == 4) && (ctxt.x64.ctrlreg[1] & 1) )
         {
-            pfn = xen_cr3_to_pfn(ctxt.x64.ctrlreg[1] & ~1);
+            pfn = UNFOLD_CR3(ctxt.x64.ctrlreg[1] & ~1);
             if ( pfn >= p2m_size )
             {
                 ERROR("User PT base is bad: pfn=%lu p2m_size=%lu",
@@ -1077,7 +1077,7 @@ int xc_domain_restore(int xc_handle, int
                       (unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
                 goto out;
             }
-            ctxt.x64.ctrlreg[1] = xen_pfn_to_cr3(p2m[pfn]);
+            ctxt.x64.ctrlreg[1] = FOLD_CR3(p2m[pfn]);
         }
         domctl.cmd = XEN_DOMCTL_setvcpucontext;
         domctl.domain = (domid_t)dom;
@@ -1158,7 +1158,7 @@ int xc_domain_restore(int xc_handle, int
     if ( guest_width > sizeof (xen_pfn_t) )
         for ( i = p2m_size - 1; i >= 0; i-- )
             ((uint64_t *)p2m)[i] = p2m[i];
-    else if ( guest_width > sizeof (xen_pfn_t) )
+    else if ( guest_width < sizeof (xen_pfn_t) )
         for ( i = 0; i < p2m_size; i++ )   
             ((uint32_t *)p2m)[i] = p2m[i];
 
diff -r 27314cfbcefe -r 0164d924ceba tools/libxc/xc_domain_save.c
--- a/tools/libxc/xc_domain_save.c      Wed Feb 13 10:42:09 2008 +0000
+++ b/tools/libxc/xc_domain_save.c      Wed Feb 13 10:43:13 2008 +0000
@@ -61,10 +61,11 @@ unsigned int guest_width;
 
 #define mfn_to_pfn(_mfn)  (live_m2p[(_mfn)])
 
-#define pfn_to_mfn(_pfn)                                \
-  ((xen_pfn_t) ((guest_width==8)                       \
-                ? (((uint64_t *)live_p2m)[(_pfn)])      \
-                : (((uint32_t *)live_p2m)[(_pfn)])))
+#define pfn_to_mfn(_pfn)                                            \
+  ((xen_pfn_t) ((guest_width==8)                                    \
+                ? (((uint64_t *)live_p2m)[(_pfn)])                  \
+                : ((((uint32_t *)live_p2m)[(_pfn)]) == 0xffffffffU  \
+                   ? (-1UL) : (((uint32_t *)live_p2m)[(_pfn)]))))
 
 /*
  * Returns TRUE if the given machine frame number has a unique mapping
@@ -496,10 +497,9 @@ static int canonicalize_pagetable(unsign
         xen_start = L3_PAGETABLE_ENTRIES_PAE;
 
     /*
-    ** in PAE only the L2 mapping the top 1GB contains Xen mappings.
-    ** We can spot this by looking for the guest linear mapping which
-    ** Xen always ensures is present in that L2. Guests must ensure
-    ** that this check will fail for other L2s.
+    ** In PAE only the L2 mapping the top 1GB contains Xen mappings.
+    ** We can spot this by looking for the guest's mappingof the m2p.
+    ** Guests must ensure that this check will fail for other L2s.
     */
     if ( (pt_levels == 3) && (type == XEN_DOMCTL_PFINFO_L2TAB) )
     {
@@ -555,7 +555,13 @@ static int canonicalize_pagetable(unsign
                 /* This will happen if the type info is stale which
                    is quite feasible under live migration */
                 pfn  = 0;  /* zap it - we'll retransmit this page later */
-                race = 1;  /* inform the caller of race; fatal if !live */ 
+                /* XXX: We can't spot Xen mappings in compat-mode L2es 
+                 * from 64-bit tools, but the only thing in them is the
+                 * compat m2p, so we quietly zap them.  This doesn't
+                 * count as a race, so don't report it. */
+                if ( !(type == XEN_DOMCTL_PFINFO_L2TAB 
+                       && sizeof (unsigned long) > guest_width) )
+                     race = 1;  /* inform the caller; fatal if !live */ 
             }
             else
                 pfn = mfn_to_pfn(mfn);
@@ -690,7 +696,7 @@ static xen_pfn_t *map_and_save_p2m_table
             else
                 p2m_frame_list_list[i] = 0;
     else if ( guest_width < sizeof(unsigned long) )
-        for ( i = PAGE_SIZE/sizeof(unsigned long) - 1; i >= 0; i++ )
+        for ( i = PAGE_SIZE/sizeof(unsigned long) - 1; i >= 0; i-- )
             p2m_frame_list_list[i] = ((uint32_t *)p2m_frame_list_list)[i];
 
     live_p2m_frame_list =
@@ -704,19 +710,20 @@ static xen_pfn_t *map_and_save_p2m_table
     }
 
     /* Get a local copy of the live_P2M_frame_list */
-    if ( !(p2m_frame_list = malloc(P2M_FL_SIZE)) )
+    if ( !(p2m_frame_list = malloc(P2M_TOOLS_FL_SIZE)) )
     {
         ERROR("Couldn't allocate p2m_frame_list array");
         goto out;
     }
-    memcpy(p2m_frame_list, live_p2m_frame_list, P2M_FL_SIZE);
+    memset(p2m_frame_list, 0, P2M_TOOLS_FL_SIZE);
+    memcpy(p2m_frame_list, live_p2m_frame_list, P2M_GUEST_FL_SIZE);
 
     /* Canonicalize guest's unsigned long vs ours */
     if ( guest_width > sizeof(unsigned long) )
         for ( i = 0; i < P2M_FL_ENTRIES; i++ )
             p2m_frame_list[i] = ((uint64_t *)p2m_frame_list)[i];
     else if ( guest_width < sizeof(unsigned long) )
-        for ( i = P2M_FL_ENTRIES - 1; i >= 0; i++ )
+        for ( i = P2M_FL_ENTRIES - 1; i >= 0; i-- )
             p2m_frame_list[i] = ((uint32_t *)p2m_frame_list)[i];
 
 
@@ -1559,31 +1566,26 @@ int xc_domain_save(int xc_handle, int io
         }
 
         /* Canonicalise the page table base pointer. */
-        if ( !MFN_IS_IN_PSEUDOPHYS_MAP(xen_cr3_to_pfn(
-                                          GET_FIELD(&ctxt, ctrlreg[3]))) )
+        if ( !MFN_IS_IN_PSEUDOPHYS_MAP(UNFOLD_CR3(
+                                           GET_FIELD(&ctxt, ctrlreg[3]))) )
         {
             ERROR("PT base is not in range of pseudophys map");
             goto out;
         }
         SET_FIELD(&ctxt, ctrlreg[3], 
-            xen_pfn_to_cr3(
-                mfn_to_pfn(
-                    xen_cr3_to_pfn(
-                        GET_FIELD(&ctxt, ctrlreg[3])))));
+            FOLD_CR3(mfn_to_pfn(UNFOLD_CR3(GET_FIELD(&ctxt, ctrlreg[3])))));
 
         /* Guest pagetable (x86/64) stored in otherwise-unused CR1. */
         if ( (pt_levels == 4) && ctxt.x64.ctrlreg[1] )
         {
-            if ( !MFN_IS_IN_PSEUDOPHYS_MAP(
-                     xen_cr3_to_pfn(ctxt.x64.ctrlreg[1])) )
+            if ( !MFN_IS_IN_PSEUDOPHYS_MAP(UNFOLD_CR3(ctxt.x64.ctrlreg[1])) )
             {
                 ERROR("PT base is not in range of pseudophys map");
                 goto out;
             }
             /* Least-significant bit means 'valid PFN'. */
             ctxt.x64.ctrlreg[1] = 1 |
-                xen_pfn_to_cr3(
-                    mfn_to_pfn(xen_cr3_to_pfn(ctxt.x64.ctrlreg[1])));
+                FOLD_CR3(mfn_to_pfn(UNFOLD_CR3(ctxt.x64.ctrlreg[1])));
         }
 
         if ( write_exact(io_fd, &ctxt, ((guest_width==8) 
diff -r 27314cfbcefe -r 0164d924ceba tools/libxc/xg_private.h
--- a/tools/libxc/xg_private.h  Wed Feb 13 10:42:09 2008 +0000
+++ b/tools/libxc/xg_private.h  Wed Feb 13 10:43:13 2008 +0000
@@ -155,7 +155,9 @@ typedef l4_pgentry_64_t l4_pgentry_t;
 #define P2M_FL_ENTRIES  (((p2m_size)+FPP-1)/FPP)
 
 /* Size in bytes of the pfn_to_mfn_frame_list     */
-#define P2M_FL_SIZE     ((P2M_FL_ENTRIES)*(guest_width))
+#define P2M_GUEST_FL_SIZE ((P2M_FL_ENTRIES) * (guest_width))
+#define P2M_TOOLS_FL_SIZE ((P2M_FL_ENTRIES) *                           \
+                           MAX((sizeof (xen_pfn_t)), guest_width))
 
 /* Masks for PTE<->PFN conversions */
 #define MADDR_BITS_X86  ((guest_width == 8) ? 52 : 44)
diff -r 27314cfbcefe -r 0164d924ceba tools/libxc/xg_save_restore.h
--- a/tools/libxc/xg_save_restore.h     Wed Feb 13 10:42:09 2008 +0000
+++ b/tools/libxc/xg_save_restore.h     Wed Feb 13 10:43:13 2008 +0000
@@ -68,6 +68,13 @@ static inline int get_platform_info(int 
 
     *guest_width = domctl.u.address_size.size / 8;
 
+    /* 64-bit tools will see the 64-bit hvirt_start, but 32-bit guests 
+     * will be using the compat one. */
+    if ( *guest_width < sizeof (unsigned long) )
+        /* XXX need to fix up a way of extracting this value from Xen if
+         * XXX it becomes variable for domU */
+        *hvirt_start = 0xf5800000;
+
     if (strstr(xen_caps, "xen-3.0-x86_64"))
         /* Depends on whether it's a compat 32-on-64 guest */
         *pt_levels = ( (*guest_width == 8) ? 4 : 3 );
@@ -136,6 +143,16 @@ typedef union
         (_p)->x32._f = (_v);                    \
 } while (0)
 
+#define UNFOLD_CR3(_c)                                                  \
+  ((uint64_t)((guest_width == 8)                                        \
+              ? ((_c) >> 12)                                            \
+              : (((uint32_t)(_c) >> 12) | ((uint32_t)(_c) << 20))))
+
+#define FOLD_CR3(_c)                                                    \
+  ((uint64_t)((guest_width == 8)                                        \
+              ? ((uint64_t)(_c)) << 12                                  \
+              : (((uint32_t)(_c) << 12) | ((uint32_t)(_c) >> 20))))
+
 #define MEMCPY_FIELD(_d, _s, _f) do {                              \
     if (guest_width == 8)                                          \
         memcpy(&(_d)->x64._f, &(_s)->x64._f,sizeof((_d)->x64._f)); \

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] Tools: fix save/restore of 32-bit PV guests with 64-bit tools, Xen patchbot-unstable <=