Index: ioemu/hw/cirrus_vga.c
===================================================================
--- ioemu.orig/hw/cirrus_vga.c	2007-05-03 15:03:18.000000000 +0100
+++ ioemu/hw/cirrus_vga.c	2007-05-03 15:08:02.000000000 +0100
@@ -3011,11 +3011,42 @@
     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, s->vram_ptr);
+        fprintf(stderr, "cirrus_stop_acc:unset_vram_mapping.\n");
+    }
+}
+
+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);
@@ -3050,11 +3081,20 @@
     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;
@@ -3093,6 +3133,14 @@
     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;
     cirrus_update_bank_ptr(s, 0);
@@ -3298,6 +3346,8 @@
                     ds, vga_ram_base, vga_ram_offset, vga_ram_size);
     cirrus_init_common(s, device_id, 1);
 
+    register_savevm("cirrus_vga_pci", 0, 1, generic_pci_save, generic_pci_load, d);
+
     /* setup memory space */
     /* memory #0 LFB */
     /* memory #1 memory-mapped I/O */
Index: ioemu/vl.c
===================================================================
--- ioemu.orig/vl.c	2007-05-03 15:03:18.000000000 +0100
+++ ioemu/vl.c	2007-05-03 15:08:04.000000000 +0100
@@ -4470,6 +4470,11 @@
         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)
@@ -5056,6 +5061,7 @@
 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)
@@ -5816,6 +5822,15 @@
     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)
 {
 #ifdef CONFIG_GDBSTUB
@@ -6581,6 +6596,26 @@
             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);
+
+        sigaction(SIGUSR1, &act, NULL);
+
+        /* 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, possible issue for HVM save!\n");
+
+    }
+
     main_loop();
     quit_timers();
     return 0;
Index: ioemu/hw/pci.c
===================================================================
--- ioemu.orig/hw/pci.c	2007-05-03 15:03:12.000000000 +0100
+++ ioemu/hw/pci.c	2007-05-03 15:08:02.000000000 +0100
@@ -40,6 +40,8 @@
 static int pci_irq_index;
 static PCIBus *first_bus;
 
+static void pci_update_mappings(PCIDevice *d);
+
 PCIBus *pci_register_bus(pci_set_irq_fn set_irq, void *pic, int devfn_min)
 {
     PCIBus *bus;
@@ -71,6 +73,7 @@
         return -EINVAL;
 
     qemu_get_buffer(f, s->config, 256);
+    pci_update_mappings(s);
     return 0;
 }
 
Index: ioemu/hw/ide.c
===================================================================
--- ioemu.orig/hw/ide.c	2007-05-03 15:03:12.000000000 +0100
+++ ioemu/hw/ide.c	2007-05-03 15:08:04.000000000 +0100
@@ -2405,6 +2405,8 @@
               pic_set_irq_new, isa_pic, 15);
     ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
     ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
+
+    register_savevm("ide_pci", 0, 1, generic_pci_save, generic_pci_load, d);
 }
 
 /***********************************************************/
Index: ioemu/target-i386-dm/helper2.c
===================================================================
--- ioemu.orig/target-i386-dm/helper2.c	2007-05-03 15:03:18.000000000 +0100
+++ ioemu/target-i386-dm/helper2.c	2007-05-03 15:09:10.000000000 +0100
@@ -540,8 +540,10 @@
 {
     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);
+    char qemu_file[20];
 
     qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env);
 
@@ -549,7 +551,15 @@
         /* Wait up to 10 msec. */
         main_loop_wait(10);
 
-    destroy_hvm_domain();
+    fprintf(logfile, "device model received suspend signal!\n");
+
+    /* Pull all outstanding ioreqs through the system */
+    main_loop_wait(1); /* For the select() on events */
+
+    /* Save the device state */
+    sprintf(qemu_file, "/tmp/xen.qemu-dm.%d", domid);
+    if (qemu_savevm(qemu_file) < 0)
+        fprintf(stderr, "qemu save fail.\n");
 
     return 0;
 }
