mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
[HVM] save restore: device model support
Signed-off-by: Zhai Edwin <edwin.zhai@intel.com> qemu's save/restore including vga acceleration support
This commit is contained in:
1 parent
9e19e45e05
commit
9a3e4bbea4
5 files changed
+105
-1
No files matched your search
@@ -3010,11 +3010,44 @@ static CPUWriteMemoryFunc *cirrus_mmio_write[3] = {
|
||||
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, void *opaque)
|
||||
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;
|
||||
@@ -3092,6 +3134,14 @@ static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
|
||||
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);
|
||||
@@ -3297,6 +3347,8 @@ void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
|
||||
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 */
|
||||
|
||||
@@ -2512,6 +2512,9 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn)
|
||||
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
|
||||
|
||||
@@ -63,6 +63,7 @@ void generic_pci_save(QEMUFile* f, void *opaque)
|
||||
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 *opaque, int version_id)
|
||||
return -EINVAL;
|
||||
|
||||
qemu_get_buffer(f, s->config, 256);
|
||||
pci_update_mappings(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 @@ typedef struct QEMUResetEntry {
|
||||
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)
|
||||
@@ -5808,6 +5814,14 @@ int set_mm_mapping(int xc_handle, uint32_t domid,
|
||||
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__)
|
||||
static struct map_cache *mapcache_entry;
|
||||
static unsigned long nr_buckets;
|
||||
@@ -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;
|
||||
|
||||