From 9b64997f464bcef06739e9c81a927bf48c375255 Mon Sep 17 00:00:00 2001 From: blueswir1 Date: Tue, 30 Dec 2008 19:01:19 +0000 Subject: [PATCH] VM load/save support for PPC devices git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6142 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/adb.c | 56 +++++++++++++++ hw/cuda.c | 74 ++++++++++++++++++++ hw/grackle_pci.c | 18 +++++ hw/heathrow_pic.c | 39 +++++++++++ hw/ide.c | 170 ++++++++++++++++++++++++++++------------------ hw/mac_dbdma.c | 13 ++++ hw/mac_nvram.c | 21 ++++++ 7 files changed, 326 insertions(+), 65 deletions(-) diff --git a/hw/adb.c b/hw/adb.c index 0f21445757..61a3cdf210 100644 --- a/hw/adb.c +++ b/hw/adb.c @@ -262,6 +262,31 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf, return olen; } +static void adb_kbd_save(QEMUFile *f, void *opaque) +{ + KBDState *s = (KBDState *)opaque; + + qemu_put_buffer(f, s->data, sizeof(s->data)); + qemu_put_sbe32s(f, &s->rptr); + qemu_put_sbe32s(f, &s->wptr); + qemu_put_sbe32s(f, &s->count); +} + +static int adb_kbd_load(QEMUFile *f, void *opaque, int version_id) +{ + KBDState *s = (KBDState *)opaque; + + if (version_id != 1) + return -EINVAL; + + qemu_get_buffer(f, s->data, sizeof(s->data)); + qemu_get_sbe32s(f, &s->rptr); + qemu_get_sbe32s(f, &s->wptr); + qemu_get_sbe32s(f, &s->count); + + return 0; +} + static int adb_kbd_reset(ADBDevice *d) { KBDState *s = d->opaque; @@ -281,6 +306,8 @@ void adb_kbd_init(ADBBusState *bus) d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request, adb_kbd_reset, s); qemu_add_kbd_event_handler(adb_kbd_put_keycode, d); + register_savevm("adb_kbd", -1, 1, adb_kbd_save, + adb_kbd_load, s); } /***************************************************************/ @@ -413,6 +440,33 @@ static int adb_mouse_reset(ADBDevice *d) return 0; } +static void adb_mouse_save(QEMUFile *f, void *opaque) +{ + MouseState *s = (MouseState *)opaque; + + qemu_put_sbe32s(f, &s->buttons_state); + qemu_put_sbe32s(f, &s->last_buttons_state); + qemu_put_sbe32s(f, &s->dx); + qemu_put_sbe32s(f, &s->dy); + qemu_put_sbe32s(f, &s->dz); +} + +static int adb_mouse_load(QEMUFile *f, void *opaque, int version_id) +{ + MouseState *s = (MouseState *)opaque; + + if (version_id != 1) + return -EINVAL; + + qemu_get_sbe32s(f, &s->buttons_state); + qemu_get_sbe32s(f, &s->last_buttons_state); + qemu_get_sbe32s(f, &s->dx); + qemu_get_sbe32s(f, &s->dy); + qemu_get_sbe32s(f, &s->dz); + + return 0; +} + void adb_mouse_init(ADBBusState *bus) { ADBDevice *d; @@ -422,4 +476,6 @@ void adb_mouse_init(ADBBusState *bus) d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request, adb_mouse_reset, s); qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse"); + register_savevm("adb_mouse", -1, 1, adb_mouse_save, + adb_mouse_load, s); } diff --git a/hw/cuda.c b/hw/cuda.c index 216387752a..92fd69bda9 100644 --- a/hw/cuda.c +++ b/hw/cuda.c @@ -633,6 +633,79 @@ static CPUReadMemoryFunc *cuda_read[] = { &cuda_readl, }; +static void cuda_save_timer(QEMUFile *f, CUDATimer *s) +{ + qemu_put_be16s(f, &s->latch); + qemu_put_be16s(f, &s->counter_value); + qemu_put_sbe64s(f, &s->load_time); + qemu_put_sbe64s(f, &s->next_irq_time); + if (s->timer) + qemu_put_timer(f, s->timer); +} + +static void cuda_save(QEMUFile *f, void *opaque) +{ + CUDAState *s = (CUDAState *)opaque; + + qemu_put_ubyte(f, s->b); + qemu_put_ubyte(f, s->a); + qemu_put_ubyte(f, s->dirb); + qemu_put_ubyte(f, s->dira); + qemu_put_ubyte(f, s->sr); + qemu_put_ubyte(f, s->acr); + qemu_put_ubyte(f, s->pcr); + qemu_put_ubyte(f, s->ifr); + qemu_put_ubyte(f, s->ier); + qemu_put_ubyte(f, s->anh); + qemu_put_sbe32s(f, &s->data_in_size); + qemu_put_sbe32s(f, &s->data_in_index); + qemu_put_sbe32s(f, &s->data_out_index); + qemu_put_ubyte(f, s->autopoll); + qemu_put_buffer(f, s->data_in, sizeof(s->data_in)); + qemu_put_buffer(f, s->data_out, sizeof(s->data_out)); + cuda_save_timer(f, &s->timers[0]); + cuda_save_timer(f, &s->timers[1]); +} + +static void cuda_load_timer(QEMUFile *f, CUDATimer *s) +{ + qemu_get_be16s(f, &s->latch); + qemu_get_be16s(f, &s->counter_value); + qemu_get_sbe64s(f, &s->load_time); + qemu_get_sbe64s(f, &s->next_irq_time); + if (s->timer) + qemu_get_timer(f, s->timer); +} + +static int cuda_load(QEMUFile *f, void *opaque, int version_id) +{ + CUDAState *s = (CUDAState *)opaque; + + if (version_id != 1) + return -EINVAL; + + s->b = qemu_get_ubyte(f); + s->a = qemu_get_ubyte(f); + s->dirb = qemu_get_ubyte(f); + s->dira = qemu_get_ubyte(f); + s->sr = qemu_get_ubyte(f); + s->acr = qemu_get_ubyte(f); + s->pcr = qemu_get_ubyte(f); + s->ifr = qemu_get_ubyte(f); + s->ier = qemu_get_ubyte(f); + s->anh = qemu_get_ubyte(f); + qemu_get_sbe32s(f, &s->data_in_size); + qemu_get_sbe32s(f, &s->data_in_index); + qemu_get_sbe32s(f, &s->data_out_index); + s->autopoll = qemu_get_ubyte(f); + qemu_get_buffer(f, s->data_in, sizeof(s->data_in)); + qemu_get_buffer(f, s->data_out, sizeof(s->data_out)); + cuda_load_timer(f, &s->timers[0]); + cuda_load_timer(f, &s->timers[1]); + + return 0; +} + static void cuda_reset(void *opaque) { CUDAState *s = opaque; @@ -673,6 +746,7 @@ void cuda_init (int *cuda_mem_index, qemu_irq irq) s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s); *cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s); + register_savevm("cuda", -1, 1, cuda_save, cuda_load, s); qemu_register_reset(cuda_reset, s); cuda_reset(s); } diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c index 9cedb0ed7a..f875e5d234 100644 --- a/hw/grackle_pci.c +++ b/hw/grackle_pci.c @@ -105,6 +105,23 @@ static void pci_grackle_set_irq(qemu_irq *pic, int irq_num, int level) qemu_set_irq(pic[irq_num + 0x15], level); } +static void pci_grackle_save(QEMUFile* f, void *opaque) +{ + PCIDevice *d = opaque; + + pci_device_save(d, f); +} + +static int pci_grackle_load(QEMUFile* f, void *opaque, int version_id) +{ + PCIDevice *d = opaque; + + if (version_id != 1) + return -EINVAL; + + return pci_device_load(d, f); +} + static void pci_grackle_reset(void *opaque) { } @@ -164,6 +181,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic) d->config[0x26] = 0x00; // prefetchable_memory_limit d->config[0x27] = 0x85; #endif + register_savevm("grackle", 0, 1, pci_grackle_save, pci_grackle_load, d); qemu_register_reset(pci_grackle_reset, d); pci_grackle_reset(d); diff --git a/hw/heathrow_pic.c b/hw/heathrow_pic.c index c78a4ee638..f0518bb0b9 100644 --- a/hw/heathrow_pic.c +++ b/hw/heathrow_pic.c @@ -165,6 +165,43 @@ static void heathrow_pic_set_irq(void *opaque, int num, int level) heathrow_pic_update(s); } +static void heathrow_pic_save_one(QEMUFile *f, HeathrowPIC *s) +{ + qemu_put_be32s(f, &s->events); + qemu_put_be32s(f, &s->mask); + qemu_put_be32s(f, &s->levels); + qemu_put_be32s(f, &s->level_triggered); +} + +static void heathrow_pic_save(QEMUFile *f, void *opaque) +{ + HeathrowPICS *s = (HeathrowPICS *)opaque; + + heathrow_pic_save_one(f, &s->pics[0]); + heathrow_pic_save_one(f, &s->pics[1]); +} + +static void heathrow_pic_load_one(QEMUFile *f, HeathrowPIC *s) +{ + qemu_get_be32s(f, &s->events); + qemu_get_be32s(f, &s->mask); + qemu_get_be32s(f, &s->levels); + qemu_get_be32s(f, &s->level_triggered); +} + +static int heathrow_pic_load(QEMUFile *f, void *opaque, int version_id) +{ + HeathrowPICS *s = (HeathrowPICS *)opaque; + + if (version_id != 1) + return -EINVAL; + + heathrow_pic_load_one(f, &s->pics[0]); + heathrow_pic_load_one(f, &s->pics[1]); + + return 0; +} + static void heathrow_pic_reset_one(HeathrowPIC *s) { memset(s, '\0', sizeof(HeathrowPIC)); @@ -191,6 +228,8 @@ qemu_irq *heathrow_pic_init(int *pmem_index, s->irqs = irqs[0]; *pmem_index = cpu_register_io_memory(0, pic_read, pic_write, s); + register_savevm("heathrow_pic", -1, 1, heathrow_pic_save, + heathrow_pic_load, s); qemu_register_reset(heathrow_pic_reset, s); heathrow_pic_reset(s); return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64); diff --git a/hw/ide.c b/hw/ide.c index 813aca9d19..461ebd61a1 100644 --- a/hw/ide.c +++ b/hw/ide.c @@ -3058,6 +3058,71 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num, } } +static void pci_ide_save(QEMUFile* f, void *opaque) +{ + PCIIDEState *d = opaque; + int i; + + pci_device_save(&d->dev, f); + + for(i = 0; i < 2; i++) { + BMDMAState *bm = &d->bmdma[i]; + qemu_put_8s(f, &bm->cmd); + qemu_put_8s(f, &bm->status); + qemu_put_be32s(f, &bm->addr); + /* XXX: if a transfer is pending, we do not save it yet */ + } + + /* per IDE interface data */ + for(i = 0; i < 2; i++) { + IDEState *s = &d->ide_if[i * 2]; + uint8_t drive1_selected; + qemu_put_8s(f, &s->cmd); + drive1_selected = (s->cur_drive != s); + qemu_put_8s(f, &drive1_selected); + } + + /* per IDE drive data */ + for(i = 0; i < 4; i++) { + ide_save(f, &d->ide_if[i]); + } +} + +static int pci_ide_load(QEMUFile* f, void *opaque, int version_id) +{ + PCIIDEState *d = opaque; + int ret, i; + + if (version_id != 1) + return -EINVAL; + ret = pci_device_load(&d->dev, f); + if (ret < 0) + return ret; + + for(i = 0; i < 2; i++) { + BMDMAState *bm = &d->bmdma[i]; + qemu_get_8s(f, &bm->cmd); + qemu_get_8s(f, &bm->status); + qemu_get_be32s(f, &bm->addr); + /* XXX: if a transfer is pending, we do not save it yet */ + } + + /* per IDE interface data */ + for(i = 0; i < 2; i++) { + IDEState *s = &d->ide_if[i * 2]; + uint8_t drive1_selected; + qemu_get_8s(f, &s->cmd); + qemu_get_8s(f, &drive1_selected); + s->cur_drive = &d->ide_if[i * 2 + (drive1_selected != 0)]; + } + + /* per IDE drive data */ + for(i = 0; i < 4; i++) { + ide_load(f, &d->ide_if[i]); + } + return 0; +} + /* XXX: call it also when the MRDMODE is changed from the PCI config registers */ static void cmd646_update_irq(PCIIDEState *d) @@ -3145,75 +3210,11 @@ void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table, ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], irq[0]); ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], irq[1]); + register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d); qemu_register_reset(cmd646_reset, d); cmd646_reset(d); } -static void pci_ide_save(QEMUFile* f, void *opaque) -{ - PCIIDEState *d = opaque; - int i; - - pci_device_save(&d->dev, f); - - for(i = 0; i < 2; i++) { - BMDMAState *bm = &d->bmdma[i]; - qemu_put_8s(f, &bm->cmd); - qemu_put_8s(f, &bm->status); - qemu_put_be32s(f, &bm->addr); - /* XXX: if a transfer is pending, we do not save it yet */ - } - - /* per IDE interface data */ - for(i = 0; i < 2; i++) { - IDEState *s = &d->ide_if[i * 2]; - uint8_t drive1_selected; - qemu_put_8s(f, &s->cmd); - drive1_selected = (s->cur_drive != s); - qemu_put_8s(f, &drive1_selected); - } - - /* per IDE drive data */ - for(i = 0; i < 4; i++) { - ide_save(f, &d->ide_if[i]); - } -} - -static int pci_ide_load(QEMUFile* f, void *opaque, int version_id) -{ - PCIIDEState *d = opaque; - int ret, i; - - if (version_id != 1) - return -EINVAL; - ret = pci_device_load(&d->dev, f); - if (ret < 0) - return ret; - - for(i = 0; i < 2; i++) { - BMDMAState *bm = &d->bmdma[i]; - qemu_get_8s(f, &bm->cmd); - qemu_get_8s(f, &bm->status); - qemu_get_be32s(f, &bm->addr); - /* XXX: if a transfer is pending, we do not save it yet */ - } - - /* per IDE interface data */ - for(i = 0; i < 2; i++) { - IDEState *s = &d->ide_if[i * 2]; - uint8_t drive1_selected; - qemu_get_8s(f, &s->cmd); - qemu_get_8s(f, &drive1_selected); - s->cur_drive = &d->ide_if[i * 2 + (drive1_selected != 0)]; - } - - /* per IDE drive data */ - for(i = 0; i < 4; i++) { - ide_load(f, &d->ide_if[i]); - } - return 0; -} - static void piix3_reset(void *opaque) { PCIIDEState *d = opaque; @@ -3417,6 +3418,44 @@ static CPUReadMemoryFunc *pmac_ide_read[] = { pmac_ide_readl, }; +static void pmac_ide_save(QEMUFile *f, void *opaque) +{ + IDEState *s = (IDEState *)opaque; + uint8_t drive1_selected; + unsigned int i; + + /* per IDE interface data */ + qemu_put_8s(f, &s->cmd); + drive1_selected = (s->cur_drive != s); + qemu_put_8s(f, &drive1_selected); + + /* per IDE drive data */ + for(i = 0; i < 2; i++) { + ide_save(f, &s[i]); + } +} + +static int pmac_ide_load(QEMUFile *f, void *opaque, int version_id) +{ + IDEState *s = (IDEState *)opaque; + uint8_t drive1_selected; + unsigned int i; + + if (version_id != 1) + return -EINVAL; + + /* per IDE interface data */ + qemu_get_8s(f, &s->cmd); + qemu_get_8s(f, &drive1_selected); + s->cur_drive = &s[(drive1_selected != 0)]; + + /* per IDE drive data */ + for(i = 0; i < 2; i++) { + ide_load(f, &s[i]); + } + return 0; +} + static void pmac_ide_reset(void *opaque) { IDEState *s = (IDEState *)opaque; @@ -3438,6 +3477,7 @@ int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq) pmac_ide_memory = cpu_register_io_memory(0, pmac_ide_read, pmac_ide_write, &ide_if[0]); + register_savevm("ide", 0, 1, pmac_ide_save, pmac_ide_load, &ide_if[0]); qemu_register_reset(pmac_ide_reset, &ide_if[0]); pmac_ide_reset(&ide_if[0]); return pmac_ide_memory; diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c index 71f14e5e0c..13fbd7bf87 100644 --- a/hw/mac_dbdma.c +++ b/hw/mac_dbdma.c @@ -88,6 +88,18 @@ static CPUReadMemoryFunc *dbdma_read[] = { &dbdma_readl, }; +static void dbdma_save(QEMUFile *f, void *opaque) +{ +} + +static int dbdma_load(QEMUFile *f, void *opaque, int version_id) +{ + if (version_id != 1) + return -EINVAL; + + return 0; +} + static void dbdma_reset(void *opaque) { } @@ -95,6 +107,7 @@ static void dbdma_reset(void *opaque) void dbdma_init (int *dbdma_mem_index) { *dbdma_mem_index = cpu_register_io_memory(0, dbdma_read, dbdma_write, NULL); + register_savevm("dbdma", -1, 1, dbdma_save, dbdma_load, NULL); qemu_register_reset(dbdma_reset, NULL); dbdma_reset(NULL); } diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c index c1281c33df..2c900614cd 100644 --- a/hw/mac_nvram.c +++ b/hw/mac_nvram.c @@ -104,6 +104,25 @@ static CPUReadMemoryFunc *nvram_read[] = { &macio_nvram_readb, }; +static void macio_nvram_save(QEMUFile *f, void *opaque) +{ + MacIONVRAMState *s = (MacIONVRAMState *)opaque; + + qemu_put_buffer(f, s->data, s->size); +} + +static int macio_nvram_load(QEMUFile *f, void *opaque, int version_id) +{ + MacIONVRAMState *s = (MacIONVRAMState *)opaque; + + if (version_id != 1) + return -EINVAL; + + qemu_get_buffer(f, s->data, s->size); + + return 0; +} + static void macio_nvram_reset(void *opaque) { } @@ -124,6 +143,8 @@ MacIONVRAMState *macio_nvram_init (int *mem_index, target_phys_addr_t size) s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s); *mem_index = s->mem_index; + register_savevm("macio_nvram", -1, 1, macio_nvram_save, macio_nvram_load, + s); qemu_register_reset(macio_nvram_reset, s); macio_nvram_reset(s);