[PATCH 1/8] HVM save restore: frame work Signed-off-by: Zhai Edwin <edwin.zhai@intel.com> frame work for HVM save restore in Control Panel diff -r 3cd320cf8abb tools/libxc/Makefile --- a/tools/libxc/Makefile Tue Jan 09 15:26:37 2007 +0800 +++ b/tools/libxc/Makefile Tue Jan 09 15:29:20 2007 +0800 @@ -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 3cd320cf8abb tools/libxc/xenguest.h --- a/tools/libxc/xenguest.h Tue Jan 09 15:26:37 2007 +0800 +++ b/tools/libxc/xenguest.h Tue Jan 09 15:29:20 2007 +0800 @@ -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 3cd320cf8abb tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Tue Jan 09 15:26:37 2007 +0800 +++ b/tools/python/xen/lowlevel/xc/xc.c Tue Jan 09 15:29:20 2007 +0800 @@ -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 3cd320cf8abb tools/python/xen/xend/XendCheckpoint.py --- a/tools/python/xen/xend/XendCheckpoint.py Tue Jan 09 15:26:37 2007 +0800 +++ b/tools/python/xen/xend/XendCheckpoint.py Tue Jan 09 15:29:20 2007 +0800 @@ -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: @@ -147,19 +172,43 @@ def restore(xd, fd, dominfo = None, paus assert store_port assert console_port + #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") - nr_pfns = unpack("L", l)[0] # native sizeof long + 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") + nr_pfns = unpack("L", l)[0] # native sizeof long if nr_pfns > 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(), nr_pfns, - store_port, console_port]) + store_port, console_port, hvm, pae, apic]) log.debug("[xc_restore]: %s", string.join(cmd)) handler = RestoreInputHandler() @@ -169,10 +218,29 @@ 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), + "not a valid device model state: 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 3cd320cf8abb tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Tue Jan 09 15:26:37 2007 +0800 +++ b/tools/python/xen/xend/XendDomainInfo.py Tue Jan 09 15:29:20 2007 +0800 @@ -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 @@ -1223,8 +1233,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) @@ -1390,6 +1403,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 @@ -1489,6 +1503,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 3cd320cf8abb tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Tue Jan 09 15:26:37 2007 +0800 +++ b/tools/python/xen/xend/image.py Tue Jan 09 15:29:20 2007 +0800 @@ -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 3cd320cf8abb tools/xcutils/xc_restore.c --- a/tools/xcutils/xc_restore.c Tue Jan 09 15:26:37 2007 +0800 +++ b/tools/xcutils/xc_restore.c Tue Jan 09 15:29:20 2007 +0800 @@ -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 3cd320cf8abb tools/xcutils/xc_save.c --- a/tools/xcutils/xc_save.c Tue Jan 09 15:26:37 2007 +0800 +++ b/tools/xcutils/xc_save.c Tue Jan 09 15:29:20 2007 +0800 @@ -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); diff -r 3cd320cf8abb tools/libxc/xc_hvm_restore.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxc/xc_hvm_restore.c Tue Jan 09 15:29:20 2007 +0800 @@ -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@intel.com> + * + * 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 3cd320cf8abb tools/libxc/xc_hvm_save.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxc/xc_hvm_save.c Tue Jan 09 15:29:20 2007 +0800 @@ -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@intel.com> + * + * 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; +} _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel