Skip to contentSkip to conversation

vmx domain save/restore support

PATCH New Zhai, Edwin 1 participant 1 message Jul 19, 2006 Arm/actions semi architecture

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 vmx domain save/restore support

attached is the vmx domain save/restore patch. works well for different guest/host combination W/O breaking domu save/restore according to my test. pls. first apply xiaowei's qemu dm fix.

===know issue===
* shpage pfn *
HV look for shpage pfn in an e820 entry when init. but some
guest(win/em64t linux) will reuse this e820 ram, which cause losing shpage pfn when restore. so this entry is marked as "reserved" to avoid guest reuse (in this patch xc_hvm_build.c). we can change this if having good solution in future.

* 64bit host vmx restore python err *
when restore vmx guest on em64t host, i got a error "ERROR
(xmlrpclib2:167) int exceeds XML-RPC limits" W/O blocking restore. "xend restart" can be a work around.

* guest smp support *
i'm doing guest smp support including apic/vmcs save/restore now. so
turn on "apic" in config file may cause save/restore failure.

* guest save/restore across platform*
e.g save 32 guest on 64 host, then restore 32 guest on 32 host. we
can't support this because save/restore face different vcpu_context format on different host. need universal format for this.

=== test report ===

"+" stands for okay, "-" stands for fail

32b host:
+ 32/32
+ 32win/32

pae host:
+ 32/pae
+ pae/pae
+ 32win/pae
+ pae_win/pae

em64t host:
+ 32/64
+ pae/64
+ 64/64
+ 32win/64
+ pae_win/64

sometimes pae_win/64 are not stable:(

# HG changeset patch
# User Edwin Zhai <[email protected]>
# Node ID 2abb1c801ab72ee7e88b144871162fe2e47a0970 # Parent 98c3ddf83a59b0cbbdce63bb210adfd0d2ec1aea vmx save/restore support

tools/ioemu/hw/cirrus_vga.c +50 -0
diff -r 98c3ddf83a59 -r 2abb1c801ab7 tools/ioemu/hw/cirrus_vga.c
@@ -3010,11 +3010,44 @@ static CPUWriteMemoryFunc *cirrus_mmio_w
     cirrus_mmio_writel,
 };
 
+void cirrus_stop_acc(CirrusVGAState *s)
+{
+    if (s->map_addr){
+        int error;
+        s->map_addr = 0;
+        error = unset_vram_mapping(s->cirrus_lfb_addr,
+                s->cirrus_lfb_end);
+        fprintf(stderr, "cirrus_stop_acc:unset_vram_mapping.\n");
+
+        munmap(s->vram_ptr, VGA_RAM_SIZE);
+    }
+}
+
+void cirrus_restart_acc(CirrusVGAState *s)
+{
+    if (s->cirrus_lfb_addr && s->cirrus_lfb_end) {
+        void *vram_pointer, *old_vram;
+        fprintf(stderr, "cirrus_vga_load:re-enable vga acc.lfb_addr=0x%lx, lfb_end=0x%lx.\n",
+                s->cirrus_lfb_addr, s->cirrus_lfb_end);
+        vram_pointer = set_vram_mapping(s->cirrus_lfb_addr ,s->cirrus_lfb_end);
+        if (!vram_pointer){
+            fprintf(stderr, "cirrus_vga_load:NULL vram_pointer\n");
+        } else {
+            old_vram = vga_update_vram((VGAState *)s, vram_pointer,
+                    VGA_RAM_SIZE);
+            qemu_free(old_vram);
+            s->map_addr = s->cirrus_lfb_addr;
+            s->map_end = s->cirrus_lfb_end;
+        }
+    }
+}
+
 /* load/save state */
 
 static void cirrus_vga_save(QEMUFile *f, void *opaque)
 {
     CirrusVGAState *s = opaque;
+    uint8_t vga_acc;
 
     qemu_put_be32s(f, &s->latch);
     qemu_put_8s(f, &s->sr_index);
@@ -3049,11 +3082,20 @@ static void cirrus_vga_save(QEMUFile *f,
     qemu_put_be32s(f, &s->hw_cursor_y);
     /* XXX: we do not save the bitblt state - we assume we do not save
        the state when the blitter is active */
+
+    vga_acc = (!!s->map_addr);
+    qemu_put_8s(f, &vga_acc);
+    qemu_put_be64s(f, (uint64_t*)&s->cirrus_lfb_addr);
+    qemu_put_be64s(f, (uint64_t*)&s->cirrus_lfb_end);
+    qemu_put_buffer(f, s->vram_ptr, VGA_RAM_SIZE); 
+    if (vga_acc)
+        cirrus_stop_acc(s);
 }
 
 static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
 {
     CirrusVGAState *s = opaque;
+    uint8_t vga_acc = 0;
 
     if (version_id != 1)
         return -EINVAL;
@@ -3091,6 +3133,14 @@ static int cirrus_vga_load(QEMUFile *f, 
 
     qemu_get_be32s(f, &s->hw_cursor_x);
     qemu_get_be32s(f, &s->hw_cursor_y);
+
+    qemu_get_8s(f, &vga_acc);
+    qemu_get_be64s(f, (uint64_t*)&s->cirrus_lfb_addr);
+    qemu_get_be64s(f, (uint64_t*)&s->cirrus_lfb_end);
+    qemu_get_buffer(f, s->vram_ptr, VGA_RAM_SIZE); 
+    if (vga_acc){
+        cirrus_restart_acc(s);
+    }
 
     /* force refresh */
     s->graphic_mode = -1;
tools/ioemu/target-i386-dm/helper2.c +14 -1
diff -r 98c3ddf83a59 -r 2abb1c801ab7 tools/ioemu/target-i386-dm/helper2.c
@@ -457,6 +457,7 @@ int main_loop(void)
 {
     extern int vm_running;
     extern int shutdown_requested;
+    extern int suspend_requested;
     CPUState *env = cpu_single_env;
     int evtchn_fd = xc_evtchn_fd(xce_handle);
 
@@ -472,6 +473,10 @@ int main_loop(void)
                 qemu_system_reset();
                 reset_requested = 0;
             }
+            if (suspend_requested) {
+                fprintf(logfile, "device model received suspend signal!\n");
+                break;
+            }
         }
 
         /* Wait up to 10 msec. */
@@ -483,7 +488,15 @@ int main_loop(void)
                              shared_page->vcpu_iodata[send_vcpu].dm_eport);
         }
     }
-    destroy_hvm_domain();
+    if (!suspend_requested)
+        destroy_hvm_domain();
+    else {
+        char qemu_file[20];
+        sprintf(qemu_file, "/tmp/xen.qemu-dm.%d", domid);
+        if (qemu_savevm(qemu_file) < 0)
+            fprintf(stderr, "qemu save fail.\n");
+    }
+
     return 0;
 }
 
tools/ioemu/vl.c +35 -0
diff -r 98c3ddf83a59 -r 2abb1c801ab7 tools/ioemu/vl.c
@@ -3884,6 +3884,11 @@ int qemu_loadvm(const char *filename)
         qemu_fseek(f, cur_pos + record_len, SEEK_SET);
     }
     fclose(f);
+
+    /* del tmp file */
+    if (unlink(filename) == -1)
+        fprintf(stderr, "delete tmp qemu state file failed.\n");
+
     ret = 0;
  the_end:
     if (saved_vm_running)
@@ -4470,6 +4475,7 @@ static QEMUResetEntry *first_reset_entry
 static QEMUResetEntry *first_reset_entry;
 int reset_requested;
 int shutdown_requested;
+int suspend_requested;
 static int powerdown_requested;
 
 void qemu_register_reset(QEMUResetHandler *func, void *opaque)
@@ -5242,6 +5248,14 @@ int set_mm_mapping(int xc_handle, uint32
 #endif
 
     return 0;
+}
+
+void suspend(int sig)
+{
+   fprintf(logfile, "suspend sig handler called with requested=%d!\n", suspend_requested);
+    if (sig != SIGUSR1)
+        fprintf(logfile, "suspend signal dismatch, get sig=%d!\n", sig);
+    suspend_requested = 1;
 }
 
 int main(int argc, char **argv)
@@ -6010,6 +6024,27 @@ int main(int argc, char **argv)
             vm_start();
         }
     }
+
+    /* register signal for the suspend request when save */
+    {
+        struct sigaction act;
+        sigset_t set;
+        act.sa_handler = suspend;
+        act.sa_flags = SA_RESTART;
+        sigemptyset(&act.sa_mask);
+
+        if (sigaction(SIGUSR1, &act, 0) == -1)
+            fprintf(stderr, "sigaction fail!\n");
+
+        /* control panel mask some signals when spawn qemu, need unmask here*/
+        sigemptyset(&set);
+        sigaddset(&set, SIGUSR1);
+        sigaddset(&set, SIGTERM);
+        if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1)
+            fprintf(stderr, "unblock signal fail!\n");
+
+    }
+
     main_loop();
     quit_timers();
     return 0;
tools/libxc/Makefile +1 -1
diff -r 98c3ddf83a59 -r 2abb1c801ab7 tools/libxc/Makefile
@@ -33,7 +33,7 @@ GUEST_SRCS-$(CONFIG_X86) += xc_linux_bui
 GUEST_SRCS-$(CONFIG_X86) += xc_linux_build.c
 GUEST_SRCS-$(CONFIG_IA64) += xc_ia64_stubs.c 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
 
 CFLAGS   += -Werror
 CFLAGS   += -fno-strict-aliasing
tools/libxc/xc_domain.c +44 -0

50 lines not on this page · raw message

tools/libxc/xc_hvm_build.c +2 -2
diff -r 98c3ddf83a59 -r 2abb1c801ab7 tools/libxc/xc_hvm_build.c
@@ -60,11 +60,11 @@ static unsigned char build_e820map(void 
 
     /* XXX: Doesn't work for > 4GB yet */
     e820entry[nr_map].addr = 0x0;
-    e820entry[nr_map].size = 0x9F800;
+    e820entry[nr_map].size = 0x90000;
     e820entry[nr_map].type = E820_RAM;
     nr_map++;
 
-    e820entry[nr_map].addr = 0x9F800;
+    e820entry[nr_map].addr = 0x90000;
     e820entry[nr_map].size = 0x800;
     e820entry[nr_map].type = E820_RESERVED;
     nr_map++;
tools/libxc/xc_linux_save.c +1 -10
diff -r 98c3ddf83a59 -r 2abb1c801ab7 tools/libxc/xc_linux_save.c
@@ -261,15 +261,6 @@ static int ratewrite(int io_fd, void *bu
 #endif
 
 
-static inline ssize_t write_exact(int fd, void *buf, size_t count)
-{
-    if(write(fd, buf, count) != count)
-        return 0;
-    return 1;
-}
-
-
-
 static int print_stats(int xc_handle, uint32_t domid, int pages_sent,
                        xc_shadow_control_stats_t *stats, int print)
 {
@@ -358,7 +349,7 @@ static int analysis_phase(int xc_handle,
 }
 
 
-static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
+int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
                              int dom, xc_dominfo_t *info,
                              vcpu_guest_context_t *ctxt)
 {
tools/libxc/xenctrl.h +24 -0
diff -r 98c3ddf83a59 -r 2abb1c801ab7 tools/libxc/xenctrl.h
@@ -286,6 +286,30 @@ int xc_domain_getinfolist(int xc_handle,
                           xc_domaininfo_t *info);
 
 /**
+ * This function returns information about the context of a hvm domain
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm domid the domain to get information from
+ * @parm hvm_ctxt a pointer to a structure to store the execution context of the
+ *            hvm domain
+ * @return 0 on success, -1 on failure
+ */
+int xc_domain_hvm_getcontext(int xc_handle,
+                             uint32_t domid,
+                             hvm_domain_context_t *hvm_ctxt);
+
+/**
+ * This function will set the context for hvm domain
+ *
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm domid the domain to set the hvm domain context for
+ * @parm hvm_ctxt pointer to the the hvm context with the values to set
+ * @return 0 on success, -1 on failure
+ */
+int xc_domain_hvm_setcontext(int xc_handle,
+                             uint32_t domid,
+                             hvm_domain_context_t *hvm_ctxt);
+
+/**
  * This function returns information about the execution context of a
  * particular vcpu of a domain.
  *
tools/libxc/xenguest.h +19 -0
diff -r 98c3ddf83a59 -r 2abb1c801ab7 tools/libxc/xenguest.h
@@ -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,17 @@ 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);
 
 /**
  * This function will create a domain for a paravirtualized Linux
tools/libxc/xg_save_restore.h +10 -0
diff -r 98c3ddf83a59 -r 2abb1c801ab7 tools/libxc/xg_save_restore.h
@@ -65,6 +65,16 @@ static int get_platform_info(int xc_hand
     return 1;
 }
 
+static inline ssize_t write_exact(int fd, void *buf, size_t count)
+{
+    if(write(fd, buf, count) != count)
+        return 0;
+    return 1;
+}
+
+extern int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
+                             int dom, xc_dominfo_t *info,
+                             vcpu_guest_context_t *ctxt);
 
 /*
 ** Save/restore deal with the mfn_to_pfn (M2P) and pfn_to_mfn (P2M) tables.
tools/python/xen/lowlevel/xc/xc.c +22 -0
diff -r 98c3ddf83a59 -r 2abb1c801ab7 tools/python/xen/lowlevel/xc/xc.c
@@ -132,6 +132,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 PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
 }
 
 
@@ -966,6 +980,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", 
tools/python/xen/xend/XendCheckpoint.py +58 -6

116 lines not on this page · raw message

tools/python/xen/xend/XendDomainInfo.py +18 -1
diff -r 98c3ddf83a59 -r 2abb1c801ab7 tools/python/xen/xend/XendDomainInfo.py
@@ -668,6 +668,13 @@ class XendDomainInfo:
         self.console_mfn = console_mfn
 
         self.introduceDomain()
+        if self.info['image'][0] == 'hvm':
+            self.image = image.create(self,
+                                      self.info['image'],
+                                      self.info['device'])
+            if self.image:
+                log.debug("createDevicemodel for hvm domain restore")
+                self.image.createDeviceModel(True)
         self.storeDomDetails()
         self.registerWatches()
         self.refreshShutdown()
@@ -945,6 +952,13 @@ class XendDomainInfo:
             raise XendError('Invalid reason: %s' % reason)
         self.storeDom("control/shutdown", reason)
 
+        ## shutdown hypercall for hvm domain desides xenstore write
+        if self.info['image'][0] == 'hvm':
+            for code in shutdown_reasons.keys():
+                if shutdown_reasons[code] == reason:
+                    break
+            xc.domain_shutdown(self.domid, code)
+
 
     ## private:
 
@@ -1417,8 +1431,11 @@ class XendDomainInfo:
 
     ## private:
 
-    def release_devices(self):
+    def release_devices(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)
tools/python/xen/xend/image.py +10 -4
diff -r 98c3ddf83a59 -r 2abb1c801ab7 tools/python/xen/xend/image.py
@@ -157,7 +157,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
     
@@ -331,7 +331,7 @@ class HVMImageHandler(ImageHandler):
             ret = ret + ['-vnc', '%d' % vncdisplay, '-k', 'en-us']
         return ret
 
-    def createDeviceModel(self):
+    def createDeviceModel(self, restore = False):
         if self.pid:
             return
         # Execute device model.
@@ -340,6 +340,8 @@ class HVMImageHandler(ImageHandler):
         args = args + ([ "-d",  "%d" % self.vm.getDomid(),
                   "-m", "%s" % (self.vm.getMemoryTarget() / 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
@@ -351,12 +353,16 @@ class HVMImageHandler(ImageHandler):
         self.pid = os.spawnve(os.P_NOWAIT, self.device_model, args, env)
         log.info("device model pid: %d", self.pid)
 
-    def destroy(self):
+    def destroy(self, suspend = False):
         self.unregister_shutdown_watch();
         import signal
         if not self.pid:
             return
-        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)
         os.waitpid(self.pid, 0)
         self.pid = 0
 
tools/xcutils/xc_restore.c +13 -4
diff -r 98c3ddf83a59 -r 2abb1c801ab7 tools/xcutils/xc_restore.c
@@ -18,12 +18,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;
     int ret;
     unsigned long store_mfn, console_mfn;
 
-    if (argc != 7)
+    if (argc != 8)
 	errx(1,
-	     "usage: %s xcfd iofd domid nr_pfns store_evtchn console_evtchn",
+	     "usage: %s xcfd iofd domid nr_pfns store_evtchn console_evtchn is_hvm",
 	     argv[0]);
 
     xc_fd = atoi(argv[1]);
@@ -32,9 +33,17 @@ main(int argc, char **argv)
     nr_pfns = atoi(argv[4]);
     store_evtchn = atoi(argv[5]);
     console_evtchn = atoi(argv[6]);
+    hvm = atoi(argv[7]);
 
-    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);
+    } 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);
tools/xcutils/xc_save.c +4 -1
diff -r 98c3ddf83a59 -r 2abb1c801ab7 tools/xcutils/xc_save.c
@@ -47,5 +47,8 @@ main(int argc, char **argv)
     max_f = atoi(argv[5]);
     flags = atoi(argv[6]);
 
-    return xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
+    if (flags & XCFLAGS_HVM)
+        return xc_hvm_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
+    else
+        return xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
 }
xen/arch/x86/dom0_ops.c +20 -0
diff -r 98c3ddf83a59 -r 2abb1c801ab7 xen/arch/x86/dom0_ops.c
@@ -454,6 +454,7 @@ void arch_getdomaininfo_ctxt(
     if ( hvm_guest(v) )
     {
         hvm_store_cpu_guest_regs(v, &c->user_regs, c->ctrlreg);
+        hvm_save_cpu_context(v, &c->hvmcpu_ctxt);
     }
     else
     {
@@ -473,6 +474,25 @@ void arch_getdomaininfo_ctxt(
     c->ctrlreg[3] = xen_pfn_to_cr3(pagetable_get_pfn(v->arch.guest_table));
 
     c->vm_assist = v->domain->vm_assist;
+}
+
+void arch_gethvm_ctxt(
+    struct vcpu *v, struct hvm_domain_context *c)
+{
+    if ( !hvm_guest(v) )
+        return;
+
+    hvm_save(v, c);
+
+}
+
+void arch_sethvm_ctxt(
+        struct vcpu *v, struct hvm_domain_context *c)
+{
+    if ( !hvm_guest(v) )
+        return;
+
+    hvm_load(v, c);
 }
 
 /*
xen/arch/x86/hvm/hvm.c +12 -0
diff -r 98c3ddf83a59 -r 2abb1c801ab7 xen/arch/x86/hvm/hvm.c
@@ -182,6 +182,8 @@ static void hvm_get_info(struct domain *
     unmap_domain_page(p);
 }
 
+extern void arch_sethvm_ctxt(
+    struct vcpu *, struct hvm_domain_context *);
 void hvm_setup_platform(struct domain* d)
 {
     struct hvm_domain *platform;
@@ -211,6 +213,16 @@ void hvm_setup_platform(struct domain* d
 
     init_timer(&platform->pl_time.periodic_tm.timer, pt_timer_fn, v, v->processor);
     pit_init(v, cpu_khz);
+
+    /* restore hvm context including pic/pit/shpage */
+    shpage_init(get_sp(d));
+
+    if (platform->hvm_ctxt) {
+        arch_sethvm_ctxt(current, platform->hvm_ctxt);
+        xfree(platform->hvm_ctxt);
+        platform->hvm_ctxt = NULL;
+    }
+
 }
 
 void pic_irq_request(void *data, int level)
xen/arch/x86/hvm/i8254.c +138 -0

150 lines not on this page · raw message

xen/arch/x86/hvm/i8259.c +79 -0

91 lines not on this page · raw message

xen/arch/x86/hvm/intercept.c +262 -0

274 lines not on this page · raw message

xen/arch/x86/hvm/svm/svm.c +8 -0
diff -r 98c3ddf83a59 -r 2abb1c801ab7 xen/arch/x86/hvm/svm/svm.c
@@ -763,6 +763,7 @@ static void svm_relinquish_guest_resourc
 {
     extern void destroy_vmcb(struct arch_svm_struct *); /* XXX */
     struct vcpu *v;
+    HVMStateEntry *se, *dse;
 
     for_each_vcpu ( d, v )
     {
@@ -780,6 +781,13 @@ static void svm_relinquish_guest_resourc
     }
 
     kill_timer(&d->arch.hvm_domain.pl_time.periodic_tm.timer);
+
+    se = d->arch.hvm_domain.first_se;
+    while (se) {
+        dse = se;
+        se = se->next;
+        xfree(dse);
+    }
 
     if ( d->arch.hvm_domain.shared_page_va )
         unmap_domain_page_global(
xen/arch/x86/hvm/vmx/vmcs.c +1 -0
diff -r 98c3ddf83a59 -r 2abb1c801ab7 xen/arch/x86/hvm/vmx/vmcs.c
@@ -572,6 +572,7 @@ void arch_vmx_do_launch(struct vcpu *v)
     }
 
     vmx_do_launch(v);
+    hvm_load_cpu_context(v, &v->arch.guest_context.hvmcpu_ctxt);
     reset_stack_and_jump(vmx_asm_do_vmentry);
 }
 
xen/arch/x86/hvm/vmx/vmx.c +342 -0

366 lines not on this page · raw message

xen/common/dom0_ops.c +73 -0

85 lines not on this page · raw message

xen/include/asm-x86/hvm/domain.h +16 -0
diff -r 98c3ddf83a59 -r 2abb1c801ab7 xen/include/asm-x86/hvm/domain.h
@@ -30,6 +30,20 @@
 
 #define HVM_PBUF_SIZE   80
 
+typedef void SaveStateHandler(hvm_domain_context_t *h, void *opaque);
+typedef int LoadStateHandler(hvm_domain_context_t *h, void *opaque, int version_id);
+
+#define HVM_SE_IDSTR_LEN 32
+typedef struct HVMStateEntry {
+    char idstr[HVM_SE_IDSTR_LEN];
+    int instance_id;
+    int version_id;
+    SaveStateHandler *save_state;
+    LoadStateHandler *load_state;
+    void *opaque;
+    struct HVMStateEntry *next;
+} HVMStateEntry;
+
 struct hvm_domain {
     unsigned long          shared_page_va;
     unsigned int           nr_vcpus;
@@ -48,6 +62,8 @@ struct hvm_domain {
 
     int                    pbuf_index;
     char                   pbuf[HVM_PBUF_SIZE];
+    struct hvm_domain_context *hvm_ctxt;
+    HVMStateEntry *first_se;
 };
 
 #endif /* __ASM_X86_HVM_DOMAIN_H__ */
xen/include/asm-x86/hvm/hvm.h +21 -0
diff -r 98c3ddf83a59 -r 2abb1c801ab7 xen/include/asm-x86/hvm/hvm.h
@@ -47,6 +47,13 @@ struct hvm_function_table {
         struct vcpu *v, struct cpu_user_regs *r, unsigned long *crs);
     void (*load_cpu_guest_regs)(
         struct vcpu *v, struct cpu_user_regs *r);
+
+    /* save and load hvm guest cpu context for save/restore */
+    void (*save_cpu_ctxt)(
+        struct vcpu *v, struct hvmcpu_context *ctxt);
+    void (*load_cpu_ctxt)(
+        struct vcpu *v, struct hvmcpu_context *ctxt);
+
     /*
      * Examine specifics of the guest state:
      * 1) determine whether the guest is in real or vm8086 mode,
@@ -103,6 +110,20 @@ hvm_load_cpu_guest_regs(struct vcpu *v, 
     hvm_funcs.load_cpu_guest_regs(v, r);
 }
 
+static inline void
+hvm_save_cpu_context(
+        struct vcpu *v, struct hvmcpu_context *ctxt)
+{
+    hvm_funcs.save_cpu_ctxt(v, ctxt);
+}
+
+static inline void
+hvm_load_cpu_context(
+        struct vcpu *v, struct hvmcpu_context *ctxt)
+{
+    hvm_funcs.load_cpu_ctxt(v, ctxt);
+}
+
 static inline int
 hvm_realmode(struct vcpu *v)
 {
xen/include/asm-x86/hvm/support.h +124 -0

136 lines not on this page · raw message

xen/include/public/arch-x86_32.h +8 -0
diff -r 98c3ddf83a59 -r 2abb1c801ab7 xen/include/public/arch-x86_32.h
@@ -142,6 +142,13 @@ DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t)
 DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
 
 typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
+
+#include "vmcs_data.h"
+
+struct hvmcpu_context {
+    uint32_t valid;
+    struct vmcs_data data;
+};
 
 /*
  * The following is all CPU context. Note that the fpu_ctxt block is filled 
@@ -174,6 +181,7 @@ struct vcpu_guest_context {
     unsigned long failsafe_callback_cs;     /* CS:EIP of failsafe callback  */
     unsigned long failsafe_callback_eip;
     unsigned long vm_assist;                /* VMASST_TYPE_* bitmap */
+    struct hvmcpu_context hvmcpu_ctxt;          /* whole vmcs region */
 };
 typedef struct vcpu_guest_context vcpu_guest_context_t;
 DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
xen/include/public/arch-x86_64.h +8 -0
diff -r 98c3ddf83a59 -r 2abb1c801ab7 xen/include/public/arch-x86_64.h
@@ -212,6 +212,13 @@ DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t)
 #undef __DECL_REG
 
 typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
+
+#include "vmcs_data.h"
+
+struct hvmcpu_context {
+    uint32_t valid;
+    struct vmcs_data data;
+};
 
 /*
  * The following is all CPU context. Note that the fpu_ctxt block is filled 
@@ -249,6 +256,7 @@ struct vcpu_guest_context {
     uint64_t      fs_base;
     uint64_t      gs_base_kernel;
     uint64_t      gs_base_user;
+    struct hvmcpu_context hvmcpu_ctxt;          /* whole vmcs region */
 };
 typedef struct vcpu_guest_context vcpu_guest_context_t;
 DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
xen/include/public/dom0_ops.h +27 -0
diff -r 98c3ddf83a59 -r 2abb1c801ab7 xen/include/public/dom0_ops.h
@@ -535,6 +535,31 @@ struct dom0_settimeoffset {
 };
 typedef struct dom0_settimeoffset dom0_settimeoffset_t;
 DEFINE_XEN_GUEST_HANDLE(dom0_settimeoffset_t);
+
+#define HVM_CTXT_SIZE        4096
+typedef struct hvm_domain_context {
+    uint32_t cur;
+    uint32_t size;
+    uint8_t data[HVM_CTXT_SIZE];
+} hvm_domain_context_t;
+DEFINE_XEN_GUEST_HANDLE(hvm_domain_context_t);
+#define DOM0_GETHVMCONTEXT   51
+typedef struct dom0_gethvmcontext {
+    /* IN variables. */
+    domid_t  domain;                  /* domain to be affected */
+    /* OUT variables. */
+    XEN_GUEST_HANDLE(hvm_domain_context_t) hvm_ctxt;
+} dom0_gethvmcontext_t;
+DEFINE_XEN_GUEST_HANDLE(dom0_gethvmcontext_t);
+
+#define DOM0_SETHVMCONTEXT   52
+typedef struct dom0_sethvmcontext {
+    /* IN variables. */
+    domid_t  domain;                  /* domain to be affected */
+    /* OUT variables. */
+    XEN_GUEST_HANDLE(hvm_domain_context_t) hvm_ctxt;
+} dom0_sethvmcontext_t;
+DEFINE_XEN_GUEST_HANDLE(dom0_sethvmcontext_t);
 
 struct dom0_op {
     uint32_t cmd;
@@ -579,6 +604,8 @@ struct dom0_op {
         struct dom0_hypercall_init    hypercall_init;
         struct dom0_domain_setup      domain_setup;
         struct dom0_settimeoffset     settimeoffset;
+        struct dom0_gethvmcontext     gethvmcontext;
+        struct dom0_sethvmcontext     sethvmcontext;
         uint8_t                       pad[128];
     } u;
 };
tools/libxc/xc_hvm_restore.c new file +264 -0

264 lines not on this page · raw message

tools/libxc/xc_hvm_save.c new file +207 -0

207 lines not on this page · raw message

xen/include/public/vmcs_data.h new file +68 -0

68 lines not on this page · raw message

# HG changeset patch
# User Edwin Zhai <[email protected]>
# Node ID 98c3ddf83a59b0cbbdce63bb210adfd0d2ec1aea # Parent ecb8ff1fcf1fc24561c8bd272a58828592d90806 cirrus&rtl8139 coexist issue fix

tools/ioemu/target-i386-dm/exec-dm.c +1 -1
diff -r ecb8ff1fcf1f -r 98c3ddf83a59 tools/ioemu/target-i386-dm/exec-dm.c
@@ -382,7 +382,7 @@ int iomem_index(target_phys_addr_t addr)
                 start = mmio[i].start;
                 end = mmio[i].start + mmio[i].size;
 
-                if ((addr >= start) && (addr <= end)){
+                if ((addr >= start) && (addr < end)){
                         return (mmio[i].io_index >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
                 }
         }

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel