# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
# Date 1169138883 0
# Node ID 1e590ddb127789cfde6ed29eef0127b79bfff2a8
# Parent d64601b977b03e0752792396706255e805d87fdc
[HVM] save restore: frame work
Signed-off-by: Zhai Edwin <edwin.zhai@xxxxxxxxx>
frame work for HVM save restore in Control Panel
---
tools/libxc/Makefile | 2
tools/libxc/xc_hvm_restore.c | 42 +++++++++++++++
tools/libxc/xc_hvm_save.c | 40 ++++++++++++++
tools/libxc/xenguest.h | 20 +++++++
tools/python/xen/lowlevel/xc/xc.c | 22 ++++++++
tools/python/xen/xend/XendCheckpoint.py | 87 +++++++++++++++++++++++++++++---
tools/python/xen/xend/XendDomainInfo.py | 26 +++++++++
tools/python/xen/xend/image.py | 14 +++--
tools/xcutils/xc_restore.c | 19 +++++-
tools/xcutils/xc_save.c | 5 +
10 files changed, 260 insertions(+), 17 deletions(-)
diff -r d64601b977b0 -r 1e590ddb1277 tools/libxc/Makefile
--- a/tools/libxc/Makefile Thu Jan 18 16:21:08 2007 +0000
+++ b/tools/libxc/Makefile Thu Jan 18 16:48:03 2007 +0000
@@ -27,7 +27,7 @@ GUEST_SRCS-$(CONFIG_X86) += xc_linux_bui
GUEST_SRCS-$(CONFIG_X86) += xc_linux_build.c
GUEST_SRCS-$(CONFIG_IA64) += xc_linux_build.c
GUEST_SRCS-$(CONFIG_MIGRATE) += xc_linux_restore.c xc_linux_save.c
-GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c
+GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c xc_hvm_restore.c xc_hvm_save.c
-include $(XEN_TARGET_ARCH)/Makefile
diff -r d64601b977b0 -r 1e590ddb1277 tools/libxc/xc_hvm_restore.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxc/xc_hvm_restore.c Thu Jan 18 16:48:03 2007 +0000
@@ -0,0 +1,42 @@
+/******************************************************************************
+ * xc_hvm_restore.c
+ *
+ * Restore the state of a HVM guest.
+ *
+ * Copyright (c) 2003, K A Fraser.
+ * Copyright (c) 2006 Intel Corperation
+ * rewriten for hvm guest by Zhai Edwin <edwin.zhai@xxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "xg_private.h"
+#include "xg_save_restore.h"
+
+#include <xen/hvm/ioreq.h>
+#include <xen/hvm/params.h>
+#include <xen/hvm/e820.h>
+
+int xc_hvm_restore(int xc_handle, int io_fd,
+ uint32_t dom, unsigned long nr_pfns,
+ unsigned int store_evtchn, unsigned long *store_mfn,
+ unsigned int console_evtchn, unsigned long *console_mfn,
+ unsigned int pae, unsigned int apic)
+{
+ return 0;
+}
diff -r d64601b977b0 -r 1e590ddb1277 tools/libxc/xc_hvm_save.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxc/xc_hvm_save.c Thu Jan 18 16:48:03 2007 +0000
@@ -0,0 +1,40 @@
+/******************************************************************************
+ * xc_hvm_save.c
+ *
+ * Save the state of a running HVM guest.
+ *
+ * Copyright (c) 2003, K A Fraser.
+ * Copyright (c) 2006 Intel Corperation
+ * rewriten for hvm guest by Zhai Edwin <edwin.zhai@xxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <inttypes.h>
+#include <time.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include "xc_private.h"
+#include "xg_private.h"
+#include "xg_save_restore.h"
+
+int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
+ uint32_t max_factor, uint32_t flags, int (*suspend)(int))
+{
+
+ return 0;
+}
diff -r d64601b977b0 -r 1e590ddb1277 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h Thu Jan 18 16:21:08 2007 +0000
+++ b/tools/libxc/xenguest.h Thu Jan 18 16:48:03 2007 +0000
@@ -11,6 +11,7 @@
#define XCFLAGS_LIVE 1
#define XCFLAGS_DEBUG 2
+#define XCFLAGS_HVM 4
/**
@@ -25,6 +26,13 @@ int xc_linux_save(int xc_handle, int io_
uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
int (*suspend)(int domid));
+/**
+ * This function will save a hvm domain running unmodified guest.
+ * @return 0 on success, -1 on failure
+ */
+int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
+ uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
+ int (*suspend)(int domid));
/**
* This function will restore a saved domain running Linux.
@@ -41,6 +49,18 @@ int xc_linux_restore(int xc_handle, int
unsigned long nr_pfns, unsigned int store_evtchn,
unsigned long *store_mfn, unsigned int console_evtchn,
unsigned long *console_mfn);
+
+/**
+ * This function will restore a saved hvm domain running unmodified guest.
+ *
+ * @parm store_mfn pass mem size & returned with the mfn of the store page
+ * @return 0 on success, -1 on failure
+ */
+int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom,
+ unsigned long nr_pfns, unsigned int store_evtchn,
+ unsigned long *store_mfn, unsigned int console_evtchn,
+ unsigned long *console_mfn,
+ unsigned int pae, unsigned int apic);
/**
* This function will create a domain for a paravirtualized Linux
diff -r d64601b977b0 -r 1e590ddb1277 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu Jan 18 16:21:08 2007 +0000
+++ b/tools/python/xen/lowlevel/xc/xc.c Thu Jan 18 16:48:03 2007 +0000
@@ -158,6 +158,20 @@ static PyObject *pyxc_domain_destroy(XcO
static PyObject *pyxc_domain_destroy(XcObject *self, PyObject *args)
{
return dom_op(self, args, xc_domain_destroy);
+}
+
+static PyObject *pyxc_domain_shutdown(XcObject *self, PyObject *args)
+{
+ uint32_t dom, reason;
+
+ if (!PyArg_ParseTuple(args, "ii", &dom, &reason))
+ return NULL;
+
+ if (xc_domain_shutdown(self->xc_handle, dom, reason) != 0)
+ return pyxc_error_to_exception();
+
+ Py_INCREF(zero);
+ return zero;
}
@@ -1027,6 +1041,14 @@ static PyMethodDef pyxc_methods[] = {
METH_VARARGS, "\n"
"Destroy a domain.\n"
" dom [int]: Identifier of domain to be destroyed.\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "domain_shutdown",
+ (PyCFunction)pyxc_domain_shutdown,
+ METH_VARARGS, "\n"
+ "Shutdown a domain.\n"
+ " dom [int, 0]: Domain identifier to use.\n"
+ " reason [int, 0]: Reason for shutdown.\n"
"Returns: [int] 0 on success; -1 on error.\n" },
{ "vcpu_setaffinity",
diff -r d64601b977b0 -r 1e590ddb1277 tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py Thu Jan 18 16:21:08 2007 +0000
+++ b/tools/python/xen/xend/XendCheckpoint.py Thu Jan 18 16:48:03 2007 +0000
@@ -22,11 +22,14 @@ from xen.xend.XendConstants import *
from xen.xend.XendConstants import *
SIGNATURE = "LinuxGuestRecord"
+QEMU_SIGNATURE = "QemuDeviceModelRecord"
+dm_batch = 512
XC_SAVE = "xc_save"
XC_RESTORE = "xc_restore"
sizeof_int = calcsize("i")
+sizeof_unsigned_int = calcsize("I")
sizeof_unsigned_long = calcsize("L")
@@ -69,6 +72,11 @@ def save(fd, dominfo, network, live, dst
"could not write guest state file: config len")
write_exact(fd, config, "could not write guest state file: config")
+ image_cfg = dominfo.info.get('image', {})
+ hvm = image_cfg.has_key('hvm')
+
+ if hvm:
+ log.info("save hvm domain")
# xc_save takes three customization parameters: maxit, max_f, and
# flags the last controls whether or not save is 'live', while the
# first two further customize behaviour when 'live' save is
@@ -76,7 +84,7 @@ def save(fd, dominfo, network, live, dst
# libxenguest; see the comments and/or code in xc_linux_save() for
# more information.
cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd),
- str(dominfo.getDomid()), "0", "0", str(int(live)) ]
+ str(dominfo.getDomid()), "0", "0", str(int(live) | (int(hvm) <<
2)) ]
log.debug("[xc_save]: %s", string.join(cmd))
def saveInputHandler(line, tochild):
@@ -90,11 +98,28 @@ def save(fd, dominfo, network, live, dst
log.info("Domain %d suspended.", dominfo.getDomid())
dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP3,
domain_name)
+ #send signal to device model for save
+ if hvm:
+ log.info("release_devices for hvm domain")
+ dominfo._releaseDevices(True)
tochild.write("done\n")
tochild.flush()
log.debug('Written done')
forkHelper(cmd, fd, saveInputHandler, False)
+
+ # put qemu device model state
+ if hvm:
+ write_exact(fd, QEMU_SIGNATURE, "could not write qemu signature")
+ qemu_fd = os.open("/tmp/xen.qemu-dm.%d" % dominfo.getDomid(),
os.O_RDONLY)
+ while True:
+ buf = os.read(qemu_fd, dm_batch)
+ if len(buf):
+ write_exact(fd, buf, "could not write device model state")
+ else:
+ break
+ os.close(qemu_fd)
+ os.remove("/tmp/xen.qemu-dm.%d" % dominfo.getDomid())
dominfo.destroyDomain()
try:
@@ -149,19 +174,49 @@ def restore(xd, fd, dominfo = None, paus
nr_pfns = (dominfo.getMemoryTarget() + 3) / 4
+ # if hvm, pass mem size to calculate the store_mfn
+ hvm = 0
+ apic = 0
+ pae = 0
+ image_cfg = dominfo.info.get('image', {})
+ hvm = image_cfg.has_key('hvm')
+ if hvm:
+ # the 'memory' in config has been removed
+ hvm = dominfo.info['memory_static_min']
+ apic = dominfo.info['image']['hvm'].get('apic', 0)
+ pae = dominfo.info['image']['hvm'].get('pae', 0)
+ log.info("restore hvm domain %d, mem=%d, apic=%d, pae=%d",
+ dominfo.domid, hvm, apic, pae)
+
try:
- l = read_exact(fd, sizeof_unsigned_long,
- "not a valid guest state file: pfn count read")
+ if hvm:
+ l = read_exact(fd, sizeof_unsigned_int,
+ "not a valid hvm guest state file: pfn count read")
+ nr_pfns = unpack("I", l)[0] # native sizeof int
+ else:
+ l = read_exact(fd, sizeof_unsigned_long,
+ "not a valid guest state file: pfn count read")
+
max_pfn = unpack("L", l)[0] # native sizeof long
if max_pfn > 16*1024*1024: # XXX
raise XendError(
"not a valid guest state file: pfn count out of range")
- balloon.free(xc.pages_to_kib(nr_pfns))
+ shadow = dominfo.info['shadow_memory']
+ log.debug("restore:shadow=0x%x, _static_max=0x%x, _static_min=0x%x, "
+ "nr_pfns=0x%x.", dominfo.info['shadow_memory'],
+ dominfo.info['memory_static_max'],
+ dominfo.info['memory_static_min'], nr_pfns)
+
+
+ balloon.free(xc.pages_to_kib(nr_pfns) + shadow * 1024)
+
+ shadow_cur = xc.shadow_mem_control(dominfo.getDomid(), shadow)
+ dominfo.info['shadow_memory'] = shadow_cur
cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE),
fd, dominfo.getDomid(), max_pfn,
- store_port, console_port])
+ store_port, console_port, hvm, pae, apic])
log.debug("[xc_restore]: %s", string.join(cmd))
handler = RestoreInputHandler()
@@ -171,10 +226,30 @@ def restore(xd, fd, dominfo = None, paus
if handler.store_mfn is None or handler.console_mfn is None:
raise XendError('Could not read store/console MFN')
- os.read(fd, 1) # Wait for source to close connection
dominfo.waitForDevices() # Wait for backends to set up
if not paused:
dominfo.unpause()
+
+ # get qemu state and create a tmp file for dm restore
+ if hvm:
+ qemu_signature = read_exact(fd, len(QEMU_SIGNATURE),
+ "invalid device model signature read")
+ if qemu_signature != QEMU_SIGNATURE:
+ raise XendError("not a valid device model state: found '%s'" %
+ qemu_signature)
+ qemu_fd = os.open("/tmp/xen.qemu-dm.%d" % dominfo.getDomid(),
+ os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
+ while True:
+ buf = os.read(fd, dm_batch)
+ if len(buf):
+ write_exact(qemu_fd, buf,
+ "could not write dm state to tmp file")
+ else:
+ break
+ os.close(qemu_fd)
+
+
+ os.read(fd, 1) # Wait for source to close connection
dominfo.completeRestore(handler.store_mfn, handler.console_mfn)
diff -r d64601b977b0 -r 1e590ddb1277 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Thu Jan 18 16:21:08 2007 +0000
+++ b/tools/python/xen/xend/XendDomainInfo.py Thu Jan 18 16:48:03 2007 +0000
@@ -451,6 +451,16 @@ class XendDomainInfo:
self._removeVm('xend/previous_restart_time')
self.storeDom("control/shutdown", reason)
+ ## shutdown hypercall for hvm domain desides xenstore write
+ image_cfg = self.info.get('image', {})
+ hvm = image_cfg.has_key('hvm')
+ if hvm:
+ for code in DOMAIN_SHUTDOWN_REASONS.keys():
+ if DOMAIN_SHUTDOWN_REASONS[code] == reason:
+ break
+ xc.domain_shutdown(self.domid, code)
+
+
def pause(self):
"""Pause domain
@@ -1228,8 +1238,11 @@ class XendDomainInfo:
if self.image:
self.image.createDeviceModel()
- def _releaseDevices(self):
+ def _releaseDevices(self, suspend = False):
"""Release all domain's devices. Nothrow guarantee."""
+ if suspend and self.image:
+ self.image.destroy(suspend)
+ return
while True:
t = xstransact("%s/device" % self.dompath)
@@ -1395,6 +1408,7 @@ class XendDomainInfo:
self.info['shadow_memory'] * 1024,
self.info['memory_static_max'] * 1024)
+ log.debug("_initDomain:shadow_memory=0x%x, memory_static_max=0x%x,
memory_static_min=0x%x.", self.info['shadow_memory'],
self.info['memory_static_max'], self.info['memory_static_min'],)
# Round shadow up to a multiple of a MiB, as shadow_mem_control
# takes MiB and we must not round down and end up under-providing.
shadow = ((shadow + 1023) / 1024) * 1024
@@ -1494,6 +1508,16 @@ class XendDomainInfo:
self.console_mfn = console_mfn
self._introduceDomain()
+ image_cfg = self.info.get('image', {})
+ hvm = image_cfg.has_key('hvm')
+ if hvm:
+ self.image = image.create(self,
+ self.info,
+ self.info['image'],
+ self.info['devices'])
+ if self.image:
+ self.image.createDeviceModel(True)
+ self.image.register_shutdown_watch()
self._storeDomDetails()
self._registerWatches()
self.refreshShutdown()
diff -r d64601b977b0 -r 1e590ddb1277 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Thu Jan 18 16:21:08 2007 +0000
+++ b/tools/python/xen/xend/image.py Thu Jan 18 16:48:03 2007 +0000
@@ -173,7 +173,7 @@ class ImageHandler:
"""Build the domain. Define in subclass."""
raise NotImplementedError()
- def createDeviceModel(self):
+ def createDeviceModel(self, restore = False):
"""Create device model for the domain (define in subclass if
needed)."""
pass
@@ -478,7 +478,7 @@ class HVMImageHandler(ImageHandler):
return ret
- def createDeviceModel(self):
+ def createDeviceModel(self, restore = False):
if self.pid:
return
# Execute device model.
@@ -487,6 +487,8 @@ class HVMImageHandler(ImageHandler):
args = args + ([ "-d", "%d" % self.vm.getDomid(),
"-m", "%s" % (self.getRequiredInitialReservation() / 1024)])
args = args + self.dmargs
+ if restore:
+ args = args + ([ "-loadvm", "/tmp/xen.qemu-dm.%d" %
self.vm.getDomid() ])
env = dict(os.environ)
if self.display:
env['DISPLAY'] = self.display
@@ -505,12 +507,16 @@ class HVMImageHandler(ImageHandler):
self.register_reboot_feature_watch()
self.pid = self.vm.gatherDom(('image/device-model-pid', int))
- def destroy(self):
+ def destroy(self, suspend = False):
self.unregister_shutdown_watch()
self.unregister_reboot_feature_watch();
if self.pid:
try:
- os.kill(self.pid, signal.SIGKILL)
+ sig = signal.SIGKILL
+ if suspend:
+ log.info("use sigusr1 to signal qemu %d", self.pid)
+ sig = signal.SIGUSR1
+ os.kill(self.pid, sig)
except OSError, exn:
log.exception(exn)
try:
diff -r d64601b977b0 -r 1e590ddb1277 tools/xcutils/xc_restore.c
--- a/tools/xcutils/xc_restore.c Thu Jan 18 16:21:08 2007 +0000
+++ b/tools/xcutils/xc_restore.c Thu Jan 18 16:48:03 2007 +0000
@@ -19,12 +19,13 @@ main(int argc, char **argv)
main(int argc, char **argv)
{
unsigned int xc_fd, io_fd, domid, nr_pfns, store_evtchn, console_evtchn;
+ unsigned int hvm, pae, apic;
int ret;
unsigned long store_mfn, console_mfn;
- if (argc != 6)
+ if (argc != 9)
errx(1,
- "usage: %s iofd domid nr_pfns store_evtchn console_evtchn",
+ "usage: %s iofd domid nr_pfns store_evtchn console_evtchn hvm pae
apic",
argv[0]);
xc_fd = xc_interface_open();
@@ -36,9 +37,19 @@ main(int argc, char **argv)
nr_pfns = atoi(argv[3]);
store_evtchn = atoi(argv[4]);
console_evtchn = atoi(argv[5]);
+ hvm = atoi(argv[6]);
+ pae = atoi(argv[7]);
+ apic = atoi(argv[8]);
- ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
- &store_mfn, console_evtchn, &console_mfn);
+ if (hvm) {
+ /* pass the memsize to xc_hvm_restore to find the store_mfn */
+ store_mfn = hvm;
+ ret = xc_hvm_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
+ &store_mfn, console_evtchn, &console_mfn, pae, apic);
+ } else
+ ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
+ &store_mfn, console_evtchn, &console_mfn);
+
if (ret == 0) {
printf("store-mfn %li\n", store_mfn);
printf("console-mfn %li\n", console_mfn);
diff -r d64601b977b0 -r 1e590ddb1277 tools/xcutils/xc_save.c
--- a/tools/xcutils/xc_save.c Thu Jan 18 16:21:08 2007 +0000
+++ b/tools/xcutils/xc_save.c Thu Jan 18 16:48:03 2007 +0000
@@ -51,7 +51,10 @@ main(int argc, char **argv)
max_f = atoi(argv[4]);
flags = atoi(argv[5]);
- ret = xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
+ if (flags & XCFLAGS_HVM)
+ ret = xc_hvm_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
+ else
+ ret = xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags,
&suspend);
xc_interface_close(xc_fd);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|