[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v2 5/6] libxc: introduce xc_map_domain_meminfo (and xc_unmap_domain_meminfo)



And use it in xc_exchange_page(). This is basically because the
following change need something really similar to the set of
steps that are here abstracted in these two functions.

Despite of the change in the interface and in the signature of
some functions, this is pure code motion. No functional changes
involved.

Signed-off-by: Dario Faggioli <dario.faggioli@xxxxxxxxxx>
---
 tools/libxc/xc_domain.c       |  127 ++++++++++++++++++++++++++++
 tools/libxc/xc_offline_page.c |  185 +++++++----------------------------------
 tools/libxc/xenguest.h        |   17 ++++
 tools/libxc/xg_private.h      |    9 ++
 4 files changed, 183 insertions(+), 155 deletions(-)

diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index 3210e34..81316d3 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -21,6 +21,8 @@
  */
 
 #include "xc_private.h"
+#include "xc_core.h"
+#include "xg_private.h"
 #include "xg_save_restore.h"
 #include <xen/memory.h>
 #include <xen/hvm/hvm_op.h>
@@ -1477,6 +1479,131 @@ int xc_domain_bind_pt_isa_irq(
                                   PT_IRQ_TYPE_ISA, 0, 0, 0, machine_irq));
 }
 
+int xc_unmap_domain_meminfo(xc_interface *xch, struct xc_domain_meminfo *minfo)
+{
+    struct domain_info_context _di = { .guest_width = minfo->guest_width };
+    struct domain_info_context *dinfo = &_di;
+
+    free(minfo->pfn_type);
+    if ( minfo->p2m_table )
+        munmap(minfo->p2m_table, P2M_FLL_ENTRIES * PAGE_SIZE);
+    minfo->p2m_table = NULL;
+
+    return 0;
+}
+
+int xc_map_domain_meminfo(xc_interface *xch, int domid,
+                          struct xc_domain_meminfo *minfo)
+{
+    struct domain_info_context _di;
+    struct domain_info_context *dinfo = &_di;
+
+    xc_dominfo_t info;
+    shared_info_any_t *live_shinfo;
+    xen_capabilities_info_t xen_caps = "";
+    int i;
+
+    /* Only be initialized once */
+    if ( minfo->pfn_type || minfo->p2m_table )
+    {
+        errno = EINVAL;
+        return -1;
+    }
+
+    if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 )
+    {
+        PERROR("Could not get domain info");
+        return -1;
+    }
+
+    if ( xc_domain_get_guest_width(xch, domid, &minfo->guest_width) )
+    {
+        PERROR("Could not get domain address size");
+        return -1;
+    }
+    _di.guest_width = minfo->guest_width;
+
+    /* Get page table levels (see get_platform_info() in xg_save_restore.h */
+    if ( xc_version(xch, XENVER_capabilities, &xen_caps) )
+    {
+        PERROR("Could not get Xen capabilities (for page table levels)");
+        return -1;
+    }
+    if ( strstr(xen_caps, "xen-3.0-x86_64") )
+        /* Depends on whether it's a compat 32-on-64 guest */
+        minfo->pt_levels = ( (minfo->guest_width == 8) ? 4 : 3 );
+    else if ( strstr(xen_caps, "xen-3.0-x86_32p") )
+        minfo->pt_levels = 3;
+    else if ( strstr(xen_caps, "xen-3.0-x86_32") )
+        minfo->pt_levels = 2;
+    else
+    {
+        errno = EFAULT;
+        return -1;
+    }
+
+    /* We need the shared info page for mapping the P2M */
+    live_shinfo = xc_map_foreign_range(xch, domid, PAGE_SIZE, PROT_READ,
+                                       info.shared_info_frame);
+    if ( !live_shinfo )
+    {
+        PERROR("Could not map the shared info frame (MFN 0x%lx)",
+               info.shared_info_frame);
+        return -1;
+    }
+
+    if ( xc_core_arch_map_p2m_writable(xch, minfo->guest_width, &info,
+                                       live_shinfo, &minfo->p2m_table,
+                                       &minfo->p2m_size) )
+    {
+        PERROR("Could not map the P2M table");
+        munmap(live_shinfo, PAGE_SIZE);
+        return -1;
+    }
+    munmap(live_shinfo, PAGE_SIZE);
+    _di.p2m_size = minfo->p2m_size;
+
+    /* Make space and prepare for getting the PFN types */
+    minfo->pfn_type = calloc(sizeof(*minfo->pfn_type), minfo->p2m_size);
+    if ( !minfo->pfn_type )
+    {
+        PERROR("Could not allocate memory for the PFN types");
+        goto failed;
+    }
+    for ( i = 0; i < minfo->p2m_size; i++ )
+        minfo->pfn_type[i] = pfn_to_mfn(i, minfo->p2m_table,
+                                        minfo->guest_width);
+
+    /* Retrieve PFN types in batches */
+    for ( i = 0; i < minfo->p2m_size ; i+=1024 )
+    {
+        int count = ((minfo->p2m_size - i ) > 1024 ) ?
+                        1024: (minfo->p2m_size - i);
+
+        if ( xc_get_pfn_type_batch(xch, domid, count, minfo->pfn_type + i) )
+        {
+            PERROR("Could not get %d-eth batch of PFN types", (i+1)/1024);
+            goto failed;
+        }
+    }
+
+    return 0;
+
+failed:
+    if ( minfo->pfn_type )
+    {
+        free(minfo->pfn_type);
+        minfo->pfn_type = NULL;
+    }
+    if ( minfo->p2m_table )
+    {
+        munmap(minfo->p2m_table, P2M_FLL_ENTRIES * PAGE_SIZE);
+        minfo->p2m_table = NULL;
+    }
+
+    return -1;
+}
+
 int xc_domain_memory_mapping(
     xc_interface *xch,
     uint32_t domid,
diff --git a/tools/libxc/xc_offline_page.c b/tools/libxc/xc_offline_page.c
index 1f6dbc6..fbb53f5 100644
--- a/tools/libxc/xc_offline_page.c
+++ b/tools/libxc/xc_offline_page.c
@@ -33,17 +33,6 @@
 #include "xg_private.h"
 #include "xg_save_restore.h"
 
-struct domain_mem_info{
-    int domid;
-    unsigned int pt_level;
-    unsigned int guest_width;
-    xen_pfn_t *pfn_type;
-    xen_pfn_t *p2m_table;
-    unsigned long p2m_size;
-    xen_pfn_t *m2p_table;
-    int max_mfn;
-};
-
 struct pte_backup_entry
 {
     xen_pfn_t table_mfn;
@@ -180,139 +169,6 @@ static int xc_is_page_granted_v2(xc_interface *xch, 
xen_pfn_t gpfn,
    return (i != gnt_num);
 }
 
-static xen_pfn_t pfn_to_mfn(xen_pfn_t pfn, xen_pfn_t *p2m, int gwidth)
-{
-  return ((xen_pfn_t) ((gwidth==8)?
-                       (((uint64_t *)p2m)[(pfn)]):
-                       ((((uint32_t *)p2m)[(pfn)]) == 0xffffffffU ?
-                            (-1UL) :
-                            (((uint32_t *)p2m)[(pfn)]))));
-}
-
-static int get_pt_level(xc_interface *xch, uint32_t domid,
-                        unsigned int *pt_level,
-                        unsigned int *gwidth)
-{
-    xen_capabilities_info_t xen_caps = "";
-
-    if (xc_version(xch, XENVER_capabilities, &xen_caps) != 0)
-        return -1;
-
-    if (xc_domain_get_guest_width(xch, domid, gwidth) != 0)
-        return -1;
-
-    if (strstr(xen_caps, "xen-3.0-x86_64"))
-        /* Depends on whether it's a compat 32-on-64 guest */
-        *pt_level = ( (*gwidth == 8) ? 4 : 3 );
-    else if (strstr(xen_caps, "xen-3.0-x86_32p"))
-        *pt_level = 3;
-    else if (strstr(xen_caps, "xen-3.0-x86_32"))
-        *pt_level = 2;
-    else
-        return -1;
-
-    return 0;
-}
-
-static int close_mem_info(xc_interface *xch, struct domain_mem_info *minfo)
-{
-    if (minfo->pfn_type)
-        free(minfo->pfn_type);
-    munmap(minfo->m2p_table, M2P_SIZE(minfo->max_mfn));
-    munmap(minfo->p2m_table, P2M_FLL_ENTRIES * PAGE_SIZE);
-    minfo->p2m_table = minfo->m2p_table = NULL;
-
-    return 0;
-}
-
-static int init_mem_info(xc_interface *xch, int domid,
-                 struct domain_mem_info *minfo,
-                 xc_dominfo_t *info)
-{
-    uint64_aligned_t shared_info_frame;
-    shared_info_any_t *live_shinfo = NULL;
-    int i, rc;
-
-    /* Only be initialized once */
-    if (minfo->pfn_type || minfo->m2p_table || minfo->p2m_table)
-        return -EINVAL;
-
-    if ( get_pt_level(xch, domid, &minfo->pt_level,
-                      &minfo->guest_width) )
-    {
-        ERROR("Unable to get PT level info.");
-        return -EFAULT;
-    }
-    dinfo->guest_width = minfo->guest_width;
-
-    shared_info_frame = info->shared_info_frame;
-
-    live_shinfo = xc_map_foreign_range(xch, domid,
-                     PAGE_SIZE, PROT_READ, shared_info_frame);
-    if ( !live_shinfo )
-    {
-        ERROR("Couldn't map live_shinfo");
-        return -EFAULT;
-    }
-
-    if ( (rc = xc_core_arch_map_p2m_writable(xch, minfo->guest_width,
-              info, live_shinfo, &minfo->p2m_table,  &minfo->p2m_size)) )
-    {
-        ERROR("Couldn't map p2m table %x\n", rc);
-        goto failed;
-    }
-    munmap(live_shinfo, PAGE_SIZE);
-    live_shinfo = NULL;
-
-    dinfo->p2m_size = minfo->p2m_size;
-
-    minfo->max_mfn = xc_maximum_ram_page(xch);
-    if ( !(minfo->m2p_table =
-        xc_map_m2p(xch, minfo->max_mfn, PROT_READ, NULL)) )
-    {
-        ERROR("Failed to map live M2P table");
-        goto failed;
-    }
-
-    /* Get pfn type */
-    minfo->pfn_type = calloc(sizeof(*minfo->pfn_type), minfo->p2m_size);
-    if (!minfo->pfn_type)
-    {
-        ERROR("Failed to malloc pfn_type\n");
-        goto failed;
-    }
-
-    for (i = 0; i < minfo->p2m_size; i++)
-        minfo->pfn_type[i] = pfn_to_mfn(i, minfo->p2m_table,
-                                        minfo->guest_width);
-
-    for (i = 0; i < minfo->p2m_size ; i+=1024)
-    {
-        int count = ((dinfo->p2m_size - i ) > 1024 ) ? 1024: (dinfo->p2m_size 
- i);
-        if ( ( rc = xc_get_pfn_type_batch(xch, domid, count,
-                  minfo->pfn_type + i)) )
-        {
-            ERROR("Failed to get pfn_type %x\n", rc);
-            goto failed;
-        }
-    }
-    return 0;
-
-failed:
-    if (minfo->pfn_type)
-    {
-        free(minfo->pfn_type);
-        minfo->pfn_type = NULL;
-    }
-    if (live_shinfo)
-        munmap(live_shinfo, PAGE_SIZE);
-    munmap(minfo->m2p_table, M2P_SIZE(minfo->max_mfn));
-    munmap(minfo->p2m_table, P2M_FLL_ENTRIES * PAGE_SIZE);
-    minfo->p2m_table = minfo->m2p_table = NULL;
-
-    return -1;
-}
-
 static int backup_ptes(xen_pfn_t table_mfn, int offset,
                        struct pte_backup *backup)
 {
@@ -402,7 +258,7 @@ static int __update_pte(xc_interface *xch,
 }
 
 static int change_pte(xc_interface *xch, int domid,
-                     struct domain_mem_info *minfo,
+                     struct xc_domain_meminfo *minfo,
                      struct pte_backup *backup,
                      struct xc_mmu *mmu,
                      pte_func func,
@@ -412,7 +268,7 @@ static int change_pte(xc_interface *xch, int domid,
     uint64_t i;
     void *content = NULL;
 
-    pte_num = PAGE_SIZE / ((minfo->pt_level == 2) ? 4 : 8);
+    pte_num = PAGE_SIZE / ((minfo->pt_levels == 2) ? 4 : 8);
 
     for (i = 0; i < minfo->p2m_size; i++)
     {
@@ -435,7 +291,7 @@ static int change_pte(xc_interface *xch, int domid,
 
             for (j = 0; j < pte_num; j++)
             {
-                if ( minfo->pt_level == 2 )
+                if ( minfo->pt_levels == 2 )
                     pte = ((const uint32_t*)content)[j];
                 else
                     pte = ((const uint64_t*)content)[j];
@@ -447,7 +303,7 @@ static int change_pte(xc_interface *xch, int domid,
                     case 1:
                     if ( xc_add_mmu_update(xch, mmu,
                           table_mfn << PAGE_SHIFT |
-                          j * ( (minfo->pt_level == 2) ?
+                          j * ( (minfo->pt_levels == 2) ?
                               sizeof(uint32_t): sizeof(uint64_t)) |
                           MMU_PT_UPDATE_PRESERVE_AD,
                           new_pte) )
@@ -480,7 +336,7 @@ failed:
 }
 
 static int update_pte(xc_interface *xch, int domid,
-                     struct domain_mem_info *minfo,
+                     struct xc_domain_meminfo *minfo,
                      struct pte_backup *backup,
                      struct xc_mmu *mmu,
                      unsigned long new_mfn)
@@ -490,7 +346,7 @@ static int update_pte(xc_interface *xch, int domid,
 }
 
 static int clear_pte(xc_interface *xch, int domid,
-                     struct domain_mem_info *minfo,
+                     struct xc_domain_meminfo *minfo,
                      struct pte_backup *backup,
                      struct xc_mmu *mmu,
                      xen_pfn_t mfn)
@@ -538,7 +394,7 @@ static int is_page_exchangable(xc_interface *xch, int 
domid, xen_pfn_t mfn,
 int xc_exchange_page(xc_interface *xch, int domid, xen_pfn_t mfn)
 {
     xc_dominfo_t info;
-    struct domain_mem_info minfo;
+    struct xc_domain_meminfo minfo;
     struct xc_mmu *mmu = NULL;
     struct pte_backup old_ptes = {NULL, 0, 0};
     grant_entry_v1_t *gnttab_v1 = NULL;
@@ -549,6 +405,8 @@ int xc_exchange_page(xc_interface *xch, int domid, 
xen_pfn_t mfn)
     int rc, result = -1;
     uint32_t status;
     xen_pfn_t new_mfn, gpfn;
+    xen_pfn_t *m2p_table;
+    int max_mfn;
 
     if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 )
     {
@@ -568,10 +426,26 @@ int xc_exchange_page(xc_interface *xch, int domid, 
xen_pfn_t mfn)
         return -EINVAL;
     }
 
-    /* Get domain's memory information */
+    /* Map M2P and obtain gpfn */
+    max_mfn = xc_maximum_ram_page(xch);
+    if ( !(m2p_table = xc_map_m2p(xch, max_mfn, PROT_READ, NULL)) )
+    {
+        PERROR("Failed to map live M2P table");
+        return -EFAULT;
+    }
+    gpfn = m2p_table[mfn];
+
+    /* Map domain's memory information */
     memset(&minfo, 0, sizeof(minfo));
-    init_mem_info(xch, domid, &minfo, &info);
-    gpfn = minfo.m2p_table[mfn];
+    if ( xc_map_domain_meminfo(xch, domid, &minfo) )
+    {
+        PERROR("Could not map domain's memory information\n");
+        return -EFAULT;
+    }
+
+    /* For translation macros */
+    dinfo->guest_width = minfo.guest_width;
+    dinfo->p2m_size = minfo.p2m_size;
 
     /* Don't exchange CR3 for PAE guest in PAE host environment */
     if (minfo.guest_width > sizeof(long))
@@ -766,7 +640,8 @@ failed:
     if (gnttab_v2)
         munmap(gnttab_v2, gnt_num / (PAGE_SIZE/sizeof(grant_entry_v2_t)));
 
-    close_mem_info(xch, &minfo);
+    xc_unmap_domain_meminfo(xch, &minfo);
+    munmap(m2p_table, M2P_SIZE(max_mfn));
 
     return result;
 }
diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h
index 4714bd2..c12091f 100644
--- a/tools/libxc/xenguest.h
+++ b/tools/libxc/xenguest.h
@@ -276,6 +276,23 @@ int xc_exchange_page(xc_interface *xch, int domid, 
xen_pfn_t mfn);
 
 
 /**
+ * Memory related information, such as PFN types, the P2M table,
+ * the guest word width and the guest page table levels.
+ */
+struct xc_domain_meminfo {
+    unsigned int pt_levels;
+    unsigned int guest_width;
+    xen_pfn_t *pfn_type;
+    xen_pfn_t *p2m_table;
+    unsigned long p2m_size;
+};
+
+int xc_map_domain_meminfo(xc_interface *xch, int domid,
+                          struct xc_domain_meminfo *minfo);
+
+int xc_unmap_domain_meminfo(xc_interface *xch, struct xc_domain_meminfo *mem);
+
+/**
  * This function map m2p table
  * @parm xch a handle to an open hypervisor interface
  * @parm max_mfn the max pfn
diff --git a/tools/libxc/xg_private.h b/tools/libxc/xg_private.h
index db02ccf..5ff2124 100644
--- a/tools/libxc/xg_private.h
+++ b/tools/libxc/xg_private.h
@@ -136,6 +136,15 @@ struct domain_info_context {
     unsigned long p2m_size;
 };
 
+static inline xen_pfn_t pfn_to_mfn(xen_pfn_t pfn, xen_pfn_t *p2m, int gwidth)
+{
+  return ((xen_pfn_t) ((gwidth==8)?
+                       (((uint64_t *)p2m)[(pfn)]):
+                       ((((uint32_t *)p2m)[(pfn)]) == 0xffffffffU ?
+                            (-1UL) :
+                            (((uint32_t *)p2m)[(pfn)]))));
+}
+
 /* Number of xen_pfn_t in a page */
 #define FPP             (PAGE_SIZE/(dinfo->guest_width))
 


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.