aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rwxr-xr-xtools/examples/xc_dom_control.py5
-rw-r--r--tools/xc/lib/xc_linux_save.c90
-rw-r--r--tools/xc/lib/xc_private.c74
-rw-r--r--tools/xc/lib/xc_private.h47
4 files changed, 142 insertions, 74 deletions
diff --git a/tools/examples/xc_dom_control.py b/tools/examples/xc_dom_control.py
index 080af6f366..4f0bd5de52 100755
--- a/tools/examples/xc_dom_control.py
+++ b/tools/examples/xc_dom_control.py
@@ -137,7 +137,10 @@ elif cmd == 'suspend':
os.kill(pid, signal.SIGTERM)
xc.domain_stop( dom=dom )
- time.sleep(0.1);
+
+ while not xc.domain_getinfo( first_dom=dom, max_doms=1 )[0]['stopped']:
+ time.sleep(0.1);
+
rc = xc.linux_save( dom=dom, state_file=file, progress=1)
if rc == 0 : xc.domain_destroy( dom=dom, force=1 )
diff --git a/tools/xc/lib/xc_linux_save.c b/tools/xc/lib/xc_linux_save.c
index 0a367234de..fb6fbd6f57 100644
--- a/tools/xc/lib/xc_linux_save.c
+++ b/tools/xc/lib/xc_linux_save.c
@@ -10,6 +10,8 @@
#include <asm-xen/suspend.h>
#include <zlib.h>
+#define BATCH_SIZE 512 /* 1024 pages (4MB) at a time */
+
/* This may allow us to create a 'quiet' command-line option, if necessary. */
#define verbose_printf(_f, _a...) \
do { \
@@ -38,33 +40,7 @@
_res; \
})
-static int check_pfn_ownership(int xc_handle,
- unsigned long mfn,
- u64 dom)
-{
- dom0_op_t op;
- op.cmd = DOM0_GETPAGEFRAMEINFO;
- op.u.getpageframeinfo.pfn = mfn;
- op.u.getpageframeinfo.domain = (domid_t)dom;
- return (do_dom0_op(xc_handle, &op) >= 0);
-}
-#define GETPFN_ERR (~0U)
-static unsigned int get_pfn_type(int xc_handle,
- unsigned long mfn,
- u64 dom)
-{
- dom0_op_t op;
- op.cmd = DOM0_GETPAGEFRAMEINFO;
- op.u.getpageframeinfo.pfn = mfn;
- op.u.getpageframeinfo.domain = (domid_t)dom;
- if ( do_dom0_op(xc_handle, &op) < 0 )
- {
- PERROR("Unexpected failure when getting page frame info!");
- return GETPFN_ERR;
- }
- return op.u.getpageframeinfo.type;
-}
static int checked_write(gzFile fd, void *buf, size_t count)
{
@@ -281,28 +257,59 @@ int xc_linux_save(int xc_handle,
/*
- * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this
- * loop we have each MFN mapped at most once. Note that there may be MFNs
- * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP.
+ * Quick sanity check.
*/
for ( i = 0; i < srec.nr_pfns; i++ )
{
mfn = live_pfn_to_mfn_table[i];
-#if 1 /* XXX use the master mfn_to_pfn table???? */
-
-
if( live_mfn_to_pfn_table[mfn] != i )
printf("i=%d mfn=%d live_mfn_to_pfn_table=%d\n",
i,mfn,live_mfn_to_pfn_table[mfn]);
+ }
- /* Query page type by MFN, but store it by PFN. */
- if ( (pfn_type[i] = get_pfn_type(xc_handle, mfn, domid)) ==
- GETPFN_ERR )
- goto out;
-#endif
+/* test new pfn_type stuff */
+ {
+ int n, i, j;
+
+ if ( mlock( pfn_type, srec.nr_pfns * sizeof(unsigned long) ) )
+ {
+ ERROR("Unable to mlock");
+ goto out;
+ }
+ for ( n = 0; n < srec.nr_pfns; )
+ {
+
+ for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
+ {
+ pfn_type[i] = live_pfn_to_mfn_table[i];
+ }
+
+ if ( get_pfn_type_batch(xc_handle, domid, j, &pfn_type[n]) )
+ {
+ ERROR("get_pfn_type_batch failed");
+ goto out;
+ }
+
+ for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
+ {
+
+ pfn_type[i] >>= 29;
+
+ if(pfn_type[i] == 7)
+ {
+ ERROR("bogus page");
+ goto out;
+ }
+
+/* if(pfn_type[i])
+ printf("i=%d type=%d\n",i,pfn_type[i]); */
+ }
+
+ n+=j;
+ }
}
@@ -354,13 +361,6 @@ int xc_linux_save(int xc_handle,
goto out;
}
- /* Belts and braces safety check on the shared info record */
- if ( !check_pfn_ownership(xc_handle, shared_info_frame, domid) )
- {
- ERROR("Invalid shared_info_frame");
- goto out;
- }
-
if ( !checked_write(gfd, "LinuxGuestRecord", 16) ||
!checked_write(gfd, name, sizeof(name)) ||
!checked_write(gfd, &srec.nr_pfns, sizeof(unsigned long)) ||
@@ -376,8 +376,6 @@ int xc_linux_save(int xc_handle,
verbose_printf("Saving memory pages: 0%%");
-#define BATCH_SIZE 1024 /* 1024 pages (4MB) at a time */
-
if ( (mapper_handle2 = mfn_mapper_init(xc_handle, domid,
BATCH_SIZE*4096, PROT_READ ))
== NULL )
diff --git a/tools/xc/lib/xc_private.c b/tools/xc/lib/xc_private.c
index 0c9092b607..d137176ca8 100644
--- a/tools/xc/lib/xc_private.c
+++ b/tools/xc/lib/xc_private.c
@@ -168,29 +168,7 @@ void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset,
/*******************/
-typedef struct dom0_op_compact_getpageframeinfo {
- unsigned long cmd;
- unsigned long interface_version; /* DOM0_INTERFACE_VERSION */
- dom0_getpageframeinfo_t getpageframeinfo;
-} dom0_op_compact_getpageframeinfo_t;
-
-
-typedef struct mfn_typer {
- domid_t dom;
- int max;
- int nr_multicall_ents;
- multicall_entry_t *multicall_list;
- dom0_op_compact_getpageframeinfo_t *gpf_list;
-} mfn_typer_t;
-
-
-mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num );
-
-void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn );
-
-int mfn_typer_flush_queue(mfn_typer_t *t);
-
-unsigned int mfn_typer_get_result(mfn_typer_t *t, int idx);
+#if 0
mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num )
{
@@ -199,8 +177,8 @@ mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num )
dom0_op_compact_getpageframeinfo_t *d;
t = calloc(1, sizeof(mfn_typer_t) );
- m = calloc(1, sizeof(multicall_entry_t)*num );
- d = calloc(1, sizeof(dom0_op_compact_getpageframeinfo_t)*num );
+ m = calloc(num, sizeof(multicall_entry_t));
+ d = calloc(num, sizeof(dom0_op_compact_getpageframeinfo_t));
if (!t || !m || !d)
{
@@ -210,6 +188,16 @@ mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num )
return NULL;
}
+printf("sizeof(m)=%d sizeof(d)=%d m=%p d=%p\n",sizeof(multicall_entry_t), sizeof(dom0_op_compact_getpageframeinfo_t),m,d);
+
+ if ( (mlock(m, sizeof(multicall_entry_t)*num ) != 0) ||
+ (mlock(d, sizeof(dom0_op_compact_getpageframeinfo_t)*num ) != 0) )
+ {
+ PERROR("Could not lock memory for Xen hypercall");
+ return NULL;
+ }
+
+ t->xc_handle = xc_handle;
t->max = num;
t->nr_multicall_ents=0;
t->multicall_list=m;
@@ -229,7 +217,7 @@ void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn )
d->interface_version = DOM0_INTERFACE_VERSION;
d->getpageframeinfo.pfn = mfn;
d->getpageframeinfo.domain = t->dom;
- d->getpageframeinfo.type = ~0UL;
+ d->getpageframeinfo.type = 1000; //~0UL;
m->op = __HYPERVISOR_dom0_op;
m->args[0] = (unsigned long)d;
@@ -240,7 +228,7 @@ void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn )
int mfn_typer_flush_queue(mfn_typer_t *t)
{
if (t->nr_multicall_ents == 0) return 0;
- (void)HYPERVISOR_multicall(t->multicall_list, t->nr_multicall_ents);
+ do_multicall_op(t->xc_handle, t->multicall_list, t->nr_multicall_ents);
t->nr_multicall_ents = 0;
}
@@ -249,6 +237,38 @@ unsigned int mfn_typer_get_result(mfn_typer_t *t, int idx)
return t->gpf_list[idx].getpageframeinfo.type;
}
+#endif
+
+/* NB: arr must be mlock'ed */
+
+int get_pfn_type_batch(int xc_handle,
+ u64 dom, int num, unsigned long *arr)
+{
+ dom0_op_t op;
+ op.cmd = DOM0_GETPAGEFRAMEINFO2;
+ op.u.getpageframeinfo2.domain = (domid_t)dom;
+ op.u.getpageframeinfo2.num = num;
+ op.u.getpageframeinfo2.array = arr;
+ return do_dom0_op(xc_handle, &op);
+}
+
+#define GETPFN_ERR (~0U)
+unsigned int get_pfn_type(int xc_handle,
+ unsigned long mfn,
+ u64 dom)
+{
+ dom0_op_t op;
+ op.cmd = DOM0_GETPAGEFRAMEINFO;
+ op.u.getpageframeinfo.pfn = mfn;
+ op.u.getpageframeinfo.domain = (domid_t)dom;
+ if ( do_dom0_op(xc_handle, &op) < 0 )
+ {
+ PERROR("Unexpected failure when getting page frame info!");
+ return GETPFN_ERR;
+ }
+ return op.u.getpageframeinfo.type;
+}
+
/*******************/
diff --git a/tools/xc/lib/xc_private.h b/tools/xc/lib/xc_private.h
index 198c703eaf..eaa301772d 100644
--- a/tools/xc/lib/xc_private.h
+++ b/tools/xc/lib/xc_private.h
@@ -110,6 +110,27 @@ static inline int do_dom0_op(int xc_handle, dom0_op_t *op)
out1: return ret;
}
+static inline int do_multicall_op(int xc_handle,
+ void *call_list, int nr_calls)
+{
+ int ret = -1;
+ privcmd_hypercall_t hypercall;
+
+ hypercall.op = __HYPERVISOR_multicall;
+ hypercall.arg[0] = (unsigned long)call_list;
+ hypercall.arg[1] = (unsigned long)nr_calls;
+
+ if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
+ {
+ if ( errno == EACCES )
+ fprintf(stderr, "Dom0 operation failed -- need to"
+ " rebuild the user-space tool set?\n");
+ goto out1;
+ }
+
+ out1: return ret;
+}
+
static inline int do_network_op(int xc_handle, network_op_t *op)
{
int ret = -1;
@@ -222,5 +243,31 @@ int mfn_mapper_flush_queue(mfn_mapper_t *t);
void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset,
unsigned long mfn, int size );
+/*********************/
+
+
+#if 0
+typedef struct mfn_typer {
+ domid_t dom;
+ int xc_handle;
+ int max;
+ dom0_op_t op;
+} mfn_typer_t;
+
+
+mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num );
+
+void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn );
+
+int mfn_typer_flush_queue(mfn_typer_t *t);
+#endif
+
+int get_pfn_type_batch(int xc_handle,
+ u64 dom, int num, unsigned long *arr);
+
+unsigned int get_pfn_type(int xc_handle,
+ unsigned long mfn,
+ u64 dom);
+
#endif /* __XC_PRIVATE_H__ */