ia64/xen-unstable

changeset 13491:1e590ddb1277

[HVM] save restore: frame work

Signed-off-by: Zhai Edwin <edwin.zhai@intel.com>

frame work for HVM save restore in Control Panel
author Tim Deegan <Tim.Deegan@xensource.com>
date Thu Jan 18 16:48:03 2007 +0000 (2007-01-18)
parents d64601b977b0
children 44668189f354
files tools/libxc/Makefile tools/libxc/xc_hvm_restore.c tools/libxc/xc_hvm_save.c tools/libxc/xenguest.h tools/python/xen/lowlevel/xc/xc.c tools/python/xen/xend/XendCheckpoint.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/image.py tools/xcutils/xc_restore.c tools/xcutils/xc_save.c
line diff
     1.1 --- a/tools/libxc/Makefile	Thu Jan 18 16:21:08 2007 +0000
     1.2 +++ b/tools/libxc/Makefile	Thu Jan 18 16:48:03 2007 +0000
     1.3 @@ -27,7 +27,7 @@ GUEST_SRCS-y += xg_private.c
     1.4  GUEST_SRCS-$(CONFIG_X86) += xc_linux_build.c
     1.5  GUEST_SRCS-$(CONFIG_IA64) += xc_linux_build.c
     1.6  GUEST_SRCS-$(CONFIG_MIGRATE) += xc_linux_restore.c xc_linux_save.c
     1.7 -GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c
     1.8 +GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c xc_hvm_restore.c xc_hvm_save.c
     1.9  
    1.10  -include $(XEN_TARGET_ARCH)/Makefile
    1.11  
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/libxc/xc_hvm_restore.c	Thu Jan 18 16:48:03 2007 +0000
     2.3 @@ -0,0 +1,42 @@
     2.4 +/******************************************************************************
     2.5 + * xc_hvm_restore.c
     2.6 + *
     2.7 + * Restore the state of a HVM guest.
     2.8 + *
     2.9 + * Copyright (c) 2003, K A Fraser.
    2.10 + * Copyright (c) 2006 Intel Corperation
    2.11 + * rewriten for hvm guest by Zhai Edwin <edwin.zhai@intel.com>
    2.12 + *
    2.13 + * This program is free software; you can redistribute it and/or modify it
    2.14 + * under the terms and conditions of the GNU General Public License,
    2.15 + * version 2, as published by the Free Software Foundation.
    2.16 + *
    2.17 + * This program is distributed in the hope it will be useful, but WITHOUT
    2.18 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    2.19 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
    2.20 + * more details.
    2.21 + *
    2.22 + * You should have received a copy of the GNU General Public License along with
    2.23 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    2.24 + * Place - Suite 330, Boston, MA 02111-1307 USA.
    2.25 + *
    2.26 + */
    2.27 +
    2.28 +#include <stdlib.h>
    2.29 +#include <unistd.h>
    2.30 +
    2.31 +#include "xg_private.h"
    2.32 +#include "xg_save_restore.h"
    2.33 +
    2.34 +#include <xen/hvm/ioreq.h>
    2.35 +#include <xen/hvm/params.h>
    2.36 +#include <xen/hvm/e820.h>
    2.37 +
    2.38 +int xc_hvm_restore(int xc_handle, int io_fd,
    2.39 +                     uint32_t dom, unsigned long nr_pfns,
    2.40 +                     unsigned int store_evtchn, unsigned long *store_mfn,
    2.41 +                     unsigned int console_evtchn, unsigned long *console_mfn,
    2.42 +                     unsigned int pae, unsigned int apic)
    2.43 +{
    2.44 +    return 0;
    2.45 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/libxc/xc_hvm_save.c	Thu Jan 18 16:48:03 2007 +0000
     3.3 @@ -0,0 +1,40 @@
     3.4 +/******************************************************************************
     3.5 + * xc_hvm_save.c
     3.6 + *
     3.7 + * Save the state of a running HVM guest.
     3.8 + *
     3.9 + * Copyright (c) 2003, K A Fraser.
    3.10 + * Copyright (c) 2006 Intel Corperation
    3.11 + * rewriten for hvm guest by Zhai Edwin <edwin.zhai@intel.com>
    3.12 + *
    3.13 + * This program is free software; you can redistribute it and/or modify it
    3.14 + * under the terms and conditions of the GNU General Public License,
    3.15 + * version 2, as published by the Free Software Foundation.
    3.16 + *
    3.17 + * This program is distributed in the hope it will be useful, but WITHOUT
    3.18 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.19 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
    3.20 + * more details.
    3.21 + *
    3.22 + * You should have received a copy of the GNU General Public License along with
    3.23 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    3.24 + * Place - Suite 330, Boston, MA 02111-1307 USA.
    3.25 + *
    3.26 + */
    3.27 +
    3.28 +#include <inttypes.h>
    3.29 +#include <time.h>
    3.30 +#include <stdlib.h>
    3.31 +#include <unistd.h>
    3.32 +#include <sys/time.h>
    3.33 +
    3.34 +#include "xc_private.h"
    3.35 +#include "xg_private.h"
    3.36 +#include "xg_save_restore.h"
    3.37 +
    3.38 +int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
    3.39 +                  uint32_t max_factor, uint32_t flags, int (*suspend)(int))
    3.40 +{
    3.41 +
    3.42 +    return 0;
    3.43 +}
     4.1 --- a/tools/libxc/xenguest.h	Thu Jan 18 16:21:08 2007 +0000
     4.2 +++ b/tools/libxc/xenguest.h	Thu Jan 18 16:48:03 2007 +0000
     4.3 @@ -11,6 +11,7 @@
     4.4  
     4.5  #define XCFLAGS_LIVE      1
     4.6  #define XCFLAGS_DEBUG     2
     4.7 +#define XCFLAGS_HVM       4
     4.8  
     4.9  
    4.10  /**
    4.11 @@ -25,6 +26,13 @@ int xc_linux_save(int xc_handle, int io_
    4.12                    uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
    4.13                    int (*suspend)(int domid));
    4.14  
    4.15 +/**
    4.16 + * This function will save a hvm domain running unmodified guest.
    4.17 + * @return 0 on success, -1 on failure
    4.18 + */
    4.19 +int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
    4.20 +                  uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
    4.21 +                  int (*suspend)(int domid));
    4.22  
    4.23  /**
    4.24   * This function will restore a saved domain running Linux.
    4.25 @@ -43,6 +51,18 @@ int xc_linux_restore(int xc_handle, int 
    4.26                       unsigned long *console_mfn);
    4.27  
    4.28  /**
    4.29 + * This function will restore a saved hvm domain running unmodified guest.
    4.30 + *
    4.31 + * @parm store_mfn pass mem size & returned with the mfn of the store page
    4.32 + * @return 0 on success, -1 on failure
    4.33 + */
    4.34 +int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom,
    4.35 +                      unsigned long nr_pfns, unsigned int store_evtchn,
    4.36 +                      unsigned long *store_mfn, unsigned int console_evtchn,
    4.37 +                      unsigned long *console_mfn,
    4.38 +                      unsigned int pae, unsigned int apic);
    4.39 +
    4.40 +/**
    4.41   * This function will create a domain for a paravirtualized Linux
    4.42   * using file names pointing to kernel and ramdisk
    4.43   *
     5.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Thu Jan 18 16:21:08 2007 +0000
     5.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Thu Jan 18 16:48:03 2007 +0000
     5.3 @@ -160,6 +160,20 @@ static PyObject *pyxc_domain_destroy(XcO
     5.4      return dom_op(self, args, xc_domain_destroy);
     5.5  }
     5.6  
     5.7 +static PyObject *pyxc_domain_shutdown(XcObject *self, PyObject *args)
     5.8 +{
     5.9 +    uint32_t dom, reason;
    5.10 +
    5.11 +    if (!PyArg_ParseTuple(args, "ii", &dom, &reason))
    5.12 +      return NULL;
    5.13 +
    5.14 +    if (xc_domain_shutdown(self->xc_handle, dom, reason) != 0)
    5.15 +        return pyxc_error_to_exception();
    5.16 +    
    5.17 +    Py_INCREF(zero);
    5.18 +    return zero;
    5.19 +}
    5.20 +
    5.21  
    5.22  static PyObject *pyxc_vcpu_setaffinity(XcObject *self,
    5.23                                         PyObject *args,
    5.24 @@ -1029,6 +1043,14 @@ static PyMethodDef pyxc_methods[] = {
    5.25        " dom [int]:    Identifier of domain to be destroyed.\n\n"
    5.26        "Returns: [int] 0 on success; -1 on error.\n" },
    5.27  
    5.28 +    { "domain_shutdown", 
    5.29 +      (PyCFunction)pyxc_domain_shutdown,
    5.30 +      METH_VARARGS, "\n"
    5.31 +      "Shutdown a domain.\n"
    5.32 +      " dom       [int, 0]:      Domain identifier to use.\n"
    5.33 +      " reason     [int, 0]:      Reason for shutdown.\n"
    5.34 +      "Returns: [int] 0 on success; -1 on error.\n" },
    5.35 +
    5.36      { "vcpu_setaffinity", 
    5.37        (PyCFunction)pyxc_vcpu_setaffinity, 
    5.38        METH_VARARGS | METH_KEYWORDS, "\n"
     6.1 --- a/tools/python/xen/xend/XendCheckpoint.py	Thu Jan 18 16:21:08 2007 +0000
     6.2 +++ b/tools/python/xen/xend/XendCheckpoint.py	Thu Jan 18 16:48:03 2007 +0000
     6.3 @@ -22,11 +22,14 @@ from xen.xend.XendConfig import XendConf
     6.4  from xen.xend.XendConstants import *
     6.5  
     6.6  SIGNATURE = "LinuxGuestRecord"
     6.7 +QEMU_SIGNATURE = "QemuDeviceModelRecord"
     6.8 +dm_batch = 512
     6.9  XC_SAVE = "xc_save"
    6.10  XC_RESTORE = "xc_restore"
    6.11  
    6.12  
    6.13  sizeof_int = calcsize("i")
    6.14 +sizeof_unsigned_int = calcsize("I")
    6.15  sizeof_unsigned_long = calcsize("L")
    6.16  
    6.17  
    6.18 @@ -69,6 +72,11 @@ def save(fd, dominfo, network, live, dst
    6.19                      "could not write guest state file: config len")
    6.20          write_exact(fd, config, "could not write guest state file: config")
    6.21  
    6.22 +        image_cfg = dominfo.info.get('image', {})
    6.23 +        hvm = image_cfg.has_key('hvm')
    6.24 +
    6.25 +        if hvm:
    6.26 +            log.info("save hvm domain")
    6.27          # xc_save takes three customization parameters: maxit, max_f, and
    6.28          # flags the last controls whether or not save is 'live', while the
    6.29          # first two further customize behaviour when 'live' save is
    6.30 @@ -76,7 +84,7 @@ def save(fd, dominfo, network, live, dst
    6.31          # libxenguest; see the comments and/or code in xc_linux_save() for
    6.32          # more information.
    6.33          cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd),
    6.34 -               str(dominfo.getDomid()), "0", "0", str(int(live)) ]
    6.35 +               str(dominfo.getDomid()), "0", "0", str(int(live) | (int(hvm) << 2)) ]
    6.36          log.debug("[xc_save]: %s", string.join(cmd))
    6.37  
    6.38          def saveInputHandler(line, tochild):
    6.39 @@ -90,12 +98,29 @@ def save(fd, dominfo, network, live, dst
    6.40                  log.info("Domain %d suspended.", dominfo.getDomid())
    6.41                  dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP3,
    6.42                                         domain_name)
    6.43 +                #send signal to device model for save
    6.44 +                if hvm:
    6.45 +                    log.info("release_devices for hvm domain")
    6.46 +                    dominfo._releaseDevices(True)
    6.47                  tochild.write("done\n")
    6.48                  tochild.flush()
    6.49                  log.debug('Written done')
    6.50  
    6.51          forkHelper(cmd, fd, saveInputHandler, False)
    6.52  
    6.53 +        # put qemu device model state
    6.54 +        if hvm:
    6.55 +            write_exact(fd, QEMU_SIGNATURE, "could not write qemu signature")
    6.56 +            qemu_fd = os.open("/tmp/xen.qemu-dm.%d" % dominfo.getDomid(), os.O_RDONLY)
    6.57 +            while True:
    6.58 +                buf = os.read(qemu_fd, dm_batch)
    6.59 +                if len(buf):
    6.60 +                    write_exact(fd, buf, "could not write device model state")
    6.61 +                else:
    6.62 +                    break
    6.63 +            os.close(qemu_fd)
    6.64 +            os.remove("/tmp/xen.qemu-dm.%d" % dominfo.getDomid())
    6.65 +
    6.66          dominfo.destroyDomain()
    6.67          try:
    6.68              dominfo.setName(domain_name)
    6.69 @@ -149,19 +174,49 @@ def restore(xd, fd, dominfo = None, paus
    6.70  
    6.71      nr_pfns = (dominfo.getMemoryTarget() + 3) / 4 
    6.72  
    6.73 +    # if hvm, pass mem size to calculate the store_mfn
    6.74 +    hvm  = 0
    6.75 +    apic = 0
    6.76 +    pae  = 0
    6.77 +    image_cfg = dominfo.info.get('image', {})
    6.78 +    hvm  = image_cfg.has_key('hvm')
    6.79 +    if hvm:
    6.80 +        # the 'memory' in config has been removed
    6.81 +        hvm  = dominfo.info['memory_static_min']
    6.82 +        apic = dominfo.info['image']['hvm'].get('apic', 0)
    6.83 +        pae  = dominfo.info['image']['hvm'].get('pae',  0)
    6.84 +        log.info("restore hvm domain %d, mem=%d, apic=%d, pae=%d",
    6.85 +                 dominfo.domid, hvm, apic, pae)
    6.86 +
    6.87      try:
    6.88 -        l = read_exact(fd, sizeof_unsigned_long,
    6.89 -                       "not a valid guest state file: pfn count read")
    6.90 +        if hvm:
    6.91 +            l = read_exact(fd, sizeof_unsigned_int,
    6.92 +                           "not a valid hvm guest state file: pfn count read")
    6.93 +            nr_pfns = unpack("I", l)[0]    # native sizeof int
    6.94 +        else: 
    6.95 +            l = read_exact(fd, sizeof_unsigned_long,
    6.96 +                           "not a valid guest state file: pfn count read")
    6.97 +
    6.98          max_pfn = unpack("L", l)[0]    # native sizeof long
    6.99          if max_pfn > 16*1024*1024:     # XXX 
   6.100              raise XendError(
   6.101                  "not a valid guest state file: pfn count out of range")
   6.102  
   6.103 -        balloon.free(xc.pages_to_kib(nr_pfns))
   6.104 +        shadow = dominfo.info['shadow_memory']
   6.105 +        log.debug("restore:shadow=0x%x, _static_max=0x%x, _static_min=0x%x, "
   6.106 +                  "nr_pfns=0x%x.", dominfo.info['shadow_memory'],
   6.107 +                  dominfo.info['memory_static_max'],
   6.108 +                  dominfo.info['memory_static_min'], nr_pfns)
   6.109 +
   6.110 +
   6.111 +        balloon.free(xc.pages_to_kib(nr_pfns) + shadow * 1024)
   6.112 +
   6.113 +        shadow_cur = xc.shadow_mem_control(dominfo.getDomid(), shadow)
   6.114 +        dominfo.info['shadow_memory'] = shadow_cur
   6.115  
   6.116          cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE),
   6.117                          fd, dominfo.getDomid(), max_pfn,
   6.118 -                        store_port, console_port])
   6.119 +                        store_port, console_port, hvm, pae, apic])
   6.120          log.debug("[xc_restore]: %s", string.join(cmd))
   6.121  
   6.122          handler = RestoreInputHandler()
   6.123 @@ -171,10 +226,30 @@ def restore(xd, fd, dominfo = None, paus
   6.124          if handler.store_mfn is None or handler.console_mfn is None:
   6.125              raise XendError('Could not read store/console MFN')
   6.126  
   6.127 -        os.read(fd, 1)           # Wait for source to close connection
   6.128          dominfo.waitForDevices() # Wait for backends to set up
   6.129          if not paused:
   6.130              dominfo.unpause()
   6.131 +
   6.132 +         # get qemu state and create a tmp file for dm restore
   6.133 +        if hvm:
   6.134 +            qemu_signature = read_exact(fd, len(QEMU_SIGNATURE),
   6.135 +                                        "invalid device model signature read")
   6.136 +            if qemu_signature != QEMU_SIGNATURE:
   6.137 +                raise XendError("not a valid device model state: found '%s'" %
   6.138 +                                qemu_signature)
   6.139 +            qemu_fd = os.open("/tmp/xen.qemu-dm.%d" % dominfo.getDomid(),
   6.140 +                              os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
   6.141 +            while True:
   6.142 +                buf = os.read(fd, dm_batch)
   6.143 +                if len(buf):
   6.144 +                    write_exact(qemu_fd, buf,
   6.145 +                                "could not write dm state to tmp file")
   6.146 +                else:
   6.147 +                    break
   6.148 +            os.close(qemu_fd)
   6.149 +
   6.150 +
   6.151 +        os.read(fd, 1)           # Wait for source to close connection
   6.152          
   6.153          dominfo.completeRestore(handler.store_mfn, handler.console_mfn)
   6.154          
     7.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Thu Jan 18 16:21:08 2007 +0000
     7.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Thu Jan 18 16:48:03 2007 +0000
     7.3 @@ -451,6 +451,16 @@ class XendDomainInfo:
     7.4          self._removeVm('xend/previous_restart_time')
     7.5          self.storeDom("control/shutdown", reason)
     7.6  
     7.7 +        ## shutdown hypercall for hvm domain desides xenstore write
     7.8 +        image_cfg = self.info.get('image', {})
     7.9 +        hvm = image_cfg.has_key('hvm')
    7.10 +        if hvm:
    7.11 +            for code in DOMAIN_SHUTDOWN_REASONS.keys():
    7.12 +                if DOMAIN_SHUTDOWN_REASONS[code] == reason:
    7.13 +                    break
    7.14 +            xc.domain_shutdown(self.domid, code)
    7.15 +
    7.16 +
    7.17      def pause(self):
    7.18          """Pause domain
    7.19          
    7.20 @@ -1228,8 +1238,11 @@ class XendDomainInfo:
    7.21          if self.image:
    7.22              self.image.createDeviceModel()
    7.23  
    7.24 -    def _releaseDevices(self):
    7.25 +    def _releaseDevices(self, suspend = False):
    7.26          """Release all domain's devices.  Nothrow guarantee."""
    7.27 +        if suspend and self.image:
    7.28 +            self.image.destroy(suspend)
    7.29 +            return
    7.30  
    7.31          while True:
    7.32              t = xstransact("%s/device" % self.dompath)
    7.33 @@ -1395,6 +1408,7 @@ class XendDomainInfo:
    7.34                  self.info['shadow_memory'] * 1024,
    7.35                  self.info['memory_static_max'] * 1024)
    7.36  
    7.37 +            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'],)
    7.38              # Round shadow up to a multiple of a MiB, as shadow_mem_control
    7.39              # takes MiB and we must not round down and end up under-providing.
    7.40              shadow = ((shadow + 1023) / 1024) * 1024
    7.41 @@ -1494,6 +1508,16 @@ class XendDomainInfo:
    7.42          self.console_mfn = console_mfn
    7.43  
    7.44          self._introduceDomain()
    7.45 +        image_cfg = self.info.get('image', {})
    7.46 +        hvm = image_cfg.has_key('hvm')
    7.47 +        if hvm:
    7.48 +            self.image = image.create(self,
    7.49 +                    self.info,
    7.50 +                    self.info['image'],
    7.51 +                    self.info['devices'])
    7.52 +            if self.image:
    7.53 +                self.image.createDeviceModel(True)
    7.54 +                self.image.register_shutdown_watch()
    7.55          self._storeDomDetails()
    7.56          self._registerWatches()
    7.57          self.refreshShutdown()
     8.1 --- a/tools/python/xen/xend/image.py	Thu Jan 18 16:21:08 2007 +0000
     8.2 +++ b/tools/python/xen/xend/image.py	Thu Jan 18 16:48:03 2007 +0000
     8.3 @@ -173,7 +173,7 @@ class ImageHandler:
     8.4          """Build the domain. Define in subclass."""
     8.5          raise NotImplementedError()
     8.6  
     8.7 -    def createDeviceModel(self):
     8.8 +    def createDeviceModel(self, restore = False):
     8.9          """Create device model for the domain (define in subclass if needed)."""
    8.10          pass
    8.11      
    8.12 @@ -478,7 +478,7 @@ class HVMImageHandler(ImageHandler):
    8.13  
    8.14          return ret
    8.15  
    8.16 -    def createDeviceModel(self):
    8.17 +    def createDeviceModel(self, restore = False):
    8.18          if self.pid:
    8.19              return
    8.20          # Execute device model.
    8.21 @@ -487,6 +487,8 @@ class HVMImageHandler(ImageHandler):
    8.22          args = args + ([ "-d",  "%d" % self.vm.getDomid(),
    8.23                    "-m", "%s" % (self.getRequiredInitialReservation() / 1024)])
    8.24          args = args + self.dmargs
    8.25 +        if restore:
    8.26 +            args = args + ([ "-loadvm", "/tmp/xen.qemu-dm.%d" % self.vm.getDomid() ])
    8.27          env = dict(os.environ)
    8.28          if self.display:
    8.29              env['DISPLAY'] = self.display
    8.30 @@ -505,12 +507,16 @@ class HVMImageHandler(ImageHandler):
    8.31          self.register_reboot_feature_watch()
    8.32          self.pid = self.vm.gatherDom(('image/device-model-pid', int))
    8.33  
    8.34 -    def destroy(self):
    8.35 +    def destroy(self, suspend = False):
    8.36          self.unregister_shutdown_watch()
    8.37          self.unregister_reboot_feature_watch();
    8.38          if self.pid:
    8.39              try:
    8.40 -                os.kill(self.pid, signal.SIGKILL)
    8.41 +                sig = signal.SIGKILL
    8.42 +                if suspend:
    8.43 +                    log.info("use sigusr1 to signal qemu %d", self.pid)
    8.44 +                    sig = signal.SIGUSR1
    8.45 +                os.kill(self.pid, sig)
    8.46              except OSError, exn:
    8.47                  log.exception(exn)
    8.48              try:
     9.1 --- a/tools/xcutils/xc_restore.c	Thu Jan 18 16:21:08 2007 +0000
     9.2 +++ b/tools/xcutils/xc_restore.c	Thu Jan 18 16:48:03 2007 +0000
     9.3 @@ -19,12 +19,13 @@ int
     9.4  main(int argc, char **argv)
     9.5  {
     9.6      unsigned int xc_fd, io_fd, domid, nr_pfns, store_evtchn, console_evtchn;
     9.7 +    unsigned int hvm, pae, apic;
     9.8      int ret;
     9.9      unsigned long store_mfn, console_mfn;
    9.10  
    9.11 -    if (argc != 6)
    9.12 +    if (argc != 9)
    9.13  	errx(1,
    9.14 -	     "usage: %s iofd domid nr_pfns store_evtchn console_evtchn",
    9.15 +	     "usage: %s iofd domid nr_pfns store_evtchn console_evtchn hvm pae apic",
    9.16  	     argv[0]);
    9.17  
    9.18      xc_fd = xc_interface_open();
    9.19 @@ -36,9 +37,19 @@ main(int argc, char **argv)
    9.20      nr_pfns = atoi(argv[3]);
    9.21      store_evtchn = atoi(argv[4]);
    9.22      console_evtchn = atoi(argv[5]);
    9.23 +    hvm  = atoi(argv[6]);
    9.24 +    pae  = atoi(argv[7]);
    9.25 +    apic = atoi(argv[8]);
    9.26  
    9.27 -    ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
    9.28 -			   &store_mfn, console_evtchn, &console_mfn);
    9.29 +    if (hvm) {
    9.30 +         /* pass the memsize to xc_hvm_restore to find the store_mfn */
    9.31 +        store_mfn = hvm;
    9.32 +        ret = xc_hvm_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
    9.33 +                &store_mfn, console_evtchn, &console_mfn, pae, apic);
    9.34 +    } else 
    9.35 +        ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
    9.36 +                &store_mfn, console_evtchn, &console_mfn);
    9.37 +
    9.38      if (ret == 0) {
    9.39  	printf("store-mfn %li\n", store_mfn);
    9.40  	printf("console-mfn %li\n", console_mfn);
    10.1 --- a/tools/xcutils/xc_save.c	Thu Jan 18 16:21:08 2007 +0000
    10.2 +++ b/tools/xcutils/xc_save.c	Thu Jan 18 16:48:03 2007 +0000
    10.3 @@ -51,7 +51,10 @@ main(int argc, char **argv)
    10.4      max_f = atoi(argv[4]);
    10.5      flags = atoi(argv[5]);
    10.6  
    10.7 -    ret = xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
    10.8 +    if (flags & XCFLAGS_HVM)
    10.9 +        ret = xc_hvm_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
   10.10 +    else 
   10.11 +        ret = xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
   10.12  
   10.13      xc_interface_close(xc_fd);
   10.14