[PATCH 5/8] HVM save restore: device model support
Signed-off-by: Zhai Edwin <edwin.zhai@xxxxxxxxx>
qemu's save/restore including vga acceleration support
diff -r f534d1614a25 tools/ioemu/hw/cirrus_vga.c
--- a/tools/ioemu/hw/cirrus_vga.c Tue Jan 09 16:15:19 2007 +0800
+++ b/tools/ioemu/hw/cirrus_vga.c Tue Jan 09 16:16:39 2007 +0800
@@ -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;
@@ -3297,6 +3347,8 @@ void pci_cirrus_vga_init(PCIBus *bus, Di
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 */
diff -r f534d1614a25 tools/ioemu/hw/ide.c
--- a/tools/ioemu/hw/ide.c Tue Jan 09 16:15:19 2007 +0800
+++ b/tools/ioemu/hw/ide.c Tue Jan 09 16:16:39 2007 +0800
@@ -2512,6 +2512,9 @@ void pci_piix3_ide_init(PCIBus *bus, Blo
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);
+
#ifdef DMA_MULTI_THREAD
dma_create_thread();
#endif //DMA_MULTI_THREAD
diff -r f534d1614a25 tools/ioemu/hw/pci.c
--- a/tools/ioemu/hw/pci.c Tue Jan 09 16:15:19 2007 +0800
+++ b/tools/ioemu/hw/pci.c Tue Jan 09 16:16:39 2007 +0800
@@ -63,6 +63,7 @@ void generic_pci_save(QEMUFile* f, void
qemu_put_buffer(f, s->config, 256);
}
+void pci_update_mappings(PCIDevice *d);
int generic_pci_load(QEMUFile* f, void *opaque, int version_id)
{
PCIDevice* s=(PCIDevice*)opaque;
@@ -71,6 +72,7 @@ int generic_pci_load(QEMUFile* f, void *
return -EINVAL;
qemu_get_buffer(f, s->config, 256);
+ pci_update_mappings(s);
return 0;
}
diff -r f534d1614a25 tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c Tue Jan 09 16:15:19 2007 +0800
+++ b/tools/ioemu/target-i386-dm/helper2.c Tue Jan 09 16:16:39 2007 +0800
@@ -546,6 +546,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);
@@ -563,12 +564,24 @@ 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. */
main_loop_wait(10);
}
- 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;
}
diff -r f534d1614a25 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c Tue Jan 09 16:15:19 2007 +0800
+++ b/tools/ioemu/vl.c Tue Jan 09 16:16:39 2007 +0800
@@ -4441,6 +4441,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)
@@ -5027,6 +5032,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)
@@ -5806,6 +5812,14 @@ int set_mm_mapping(int xc_handle, uint32
}
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;
}
#if defined(__i386__) || defined(__x86_64__)
@@ -6718,6 +6732,26 @@ 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);
+
+ 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;
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|