diff options
author | Nolan <nolan@sigbus.net> | 2009-07-20 14:11:35 -0700 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2009-07-22 10:58:47 -0500 |
commit | 777aec7ac91b1306d77897aafc8097a87bf4a672 (patch) | |
tree | 710c1182bd2fd17160576133469bb4e73fa6c542 /hw/lsi53c895a.c | |
parent | 6e5d97d01d9da6f295f9888d4b34e29fd737861a (diff) | |
download | qemu-777aec7ac91b1306d77897aafc8097a87bf4a672.zip qemu-777aec7ac91b1306d77897aafc8097a87bf4a672.tar.gz qemu-777aec7ac91b1306d77897aafc8097a87bf4a672.tar.bz2 |
Add save/restore support to the LSI logic SCSI device model.
This patch requires "Handle BH's queued by AIO completions in
qemu_aio_flush()" to work reliably. The combination of those two
patches survived 300+ migrations with heavy IO load running in the
guest.
Signed-off-by: Nolan Leake <nolan <at> sigbus.net>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/lsi53c895a.c')
-rw-r--r-- | hw/lsi53c895a.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index 516a468..f749a45 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -10,6 +10,8 @@ /* ??? Need to check if the {read,write}[wl] routines work properly on big-endian targets. */ +#include <assert.h> \ + #include "hw.h" #include "pci.h" #include "scsi-disk.h" @@ -1981,6 +1983,174 @@ void lsi_scsi_attach(DeviceState *host, BlockDriverState *bd, int id) bd->private = &s->pci_dev; } +static void lsi_scsi_save(QEMUFile *f, void *opaque) +{ + LSIState *s = opaque; + + assert(s->dma_buf == NULL); + assert(s->current_dma_len == 0); + assert(s->active_commands == 0); + + pci_device_save(&s->pci_dev, f); + + qemu_put_sbe32s(f, &s->carry); + qemu_put_sbe32s(f, &s->sense); + qemu_put_sbe32s(f, &s->msg_action); + qemu_put_sbe32s(f, &s->msg_len); + qemu_put_buffer(f, s->msg, sizeof (s->msg)); + qemu_put_sbe32s(f, &s->waiting); + + qemu_put_be32s(f, &s->dsa); + qemu_put_be32s(f, &s->temp); + qemu_put_be32s(f, &s->dnad); + qemu_put_be32s(f, &s->dbc); + qemu_put_8s(f, &s->istat0); + qemu_put_8s(f, &s->istat1); + qemu_put_8s(f, &s->dcmd); + qemu_put_8s(f, &s->dstat); + qemu_put_8s(f, &s->dien); + qemu_put_8s(f, &s->sist0); + qemu_put_8s(f, &s->sist1); + qemu_put_8s(f, &s->sien0); + qemu_put_8s(f, &s->sien1); + qemu_put_8s(f, &s->mbox0); + qemu_put_8s(f, &s->mbox1); + qemu_put_8s(f, &s->dfifo); + qemu_put_8s(f, &s->ctest2); + qemu_put_8s(f, &s->ctest3); + qemu_put_8s(f, &s->ctest4); + qemu_put_8s(f, &s->ctest5); + qemu_put_8s(f, &s->ccntl0); + qemu_put_8s(f, &s->ccntl1); + qemu_put_be32s(f, &s->dsp); + qemu_put_be32s(f, &s->dsps); + qemu_put_8s(f, &s->dmode); + qemu_put_8s(f, &s->dcntl); + qemu_put_8s(f, &s->scntl0); + qemu_put_8s(f, &s->scntl1); + qemu_put_8s(f, &s->scntl2); + qemu_put_8s(f, &s->scntl3); + qemu_put_8s(f, &s->sstat0); + qemu_put_8s(f, &s->sstat1); + qemu_put_8s(f, &s->scid); + qemu_put_8s(f, &s->sxfer); + qemu_put_8s(f, &s->socl); + qemu_put_8s(f, &s->sdid); + qemu_put_8s(f, &s->ssid); + qemu_put_8s(f, &s->sfbr); + qemu_put_8s(f, &s->stest1); + qemu_put_8s(f, &s->stest2); + qemu_put_8s(f, &s->stest3); + qemu_put_8s(f, &s->sidl); + qemu_put_8s(f, &s->stime0); + qemu_put_8s(f, &s->respid0); + qemu_put_8s(f, &s->respid1); + qemu_put_be32s(f, &s->mmrs); + qemu_put_be32s(f, &s->mmws); + qemu_put_be32s(f, &s->sfs); + qemu_put_be32s(f, &s->drs); + qemu_put_be32s(f, &s->sbms); + qemu_put_be32s(f, &s->dbms); + qemu_put_be32s(f, &s->dnad64); + qemu_put_be32s(f, &s->pmjad1); + qemu_put_be32s(f, &s->pmjad2); + qemu_put_be32s(f, &s->rbc); + qemu_put_be32s(f, &s->ua); + qemu_put_be32s(f, &s->ia); + qemu_put_be32s(f, &s->sbc); + qemu_put_be32s(f, &s->csbc); + qemu_put_buffer(f, (uint8_t *)s->scratch, sizeof (s->scratch)); + qemu_put_8s(f, &s->sbr); + + qemu_put_buffer(f, (uint8_t *)s->script_ram, sizeof (s->script_ram)); +} + +static int lsi_scsi_load(QEMUFile *f, void *opaque, int version_id) +{ + LSIState *s = opaque; + int ret; + + if (version_id > 0) { + return -EINVAL; + } + + if ((ret = pci_device_load(&s->pci_dev, f)) < 0) + return ret; + + qemu_get_sbe32s(f, &s->carry); + qemu_get_sbe32s(f, &s->sense); + qemu_get_sbe32s(f, &s->msg_action); + qemu_get_sbe32s(f, &s->msg_len); + qemu_get_buffer(f, s->msg, sizeof (s->msg)); + qemu_get_sbe32s(f, &s->waiting); + + qemu_get_be32s(f, &s->dsa); + qemu_get_be32s(f, &s->temp); + qemu_get_be32s(f, &s->dnad); + qemu_get_be32s(f, &s->dbc); + qemu_get_8s(f, &s->istat0); + qemu_get_8s(f, &s->istat1); + qemu_get_8s(f, &s->dcmd); + qemu_get_8s(f, &s->dstat); + qemu_get_8s(f, &s->dien); + qemu_get_8s(f, &s->sist0); + qemu_get_8s(f, &s->sist1); + qemu_get_8s(f, &s->sien0); + qemu_get_8s(f, &s->sien1); + qemu_get_8s(f, &s->mbox0); + qemu_get_8s(f, &s->mbox1); + qemu_get_8s(f, &s->dfifo); + qemu_get_8s(f, &s->ctest2); + qemu_get_8s(f, &s->ctest3); + qemu_get_8s(f, &s->ctest4); + qemu_get_8s(f, &s->ctest5); + qemu_get_8s(f, &s->ccntl0); + qemu_get_8s(f, &s->ccntl1); + qemu_get_be32s(f, &s->dsp); + qemu_get_be32s(f, &s->dsps); + qemu_get_8s(f, &s->dmode); + qemu_get_8s(f, &s->dcntl); + qemu_get_8s(f, &s->scntl0); + qemu_get_8s(f, &s->scntl1); + qemu_get_8s(f, &s->scntl2); + qemu_get_8s(f, &s->scntl3); + qemu_get_8s(f, &s->sstat0); + qemu_get_8s(f, &s->sstat1); + qemu_get_8s(f, &s->scid); + qemu_get_8s(f, &s->sxfer); + qemu_get_8s(f, &s->socl); + qemu_get_8s(f, &s->sdid); + qemu_get_8s(f, &s->ssid); + qemu_get_8s(f, &s->sfbr); + qemu_get_8s(f, &s->stest1); + qemu_get_8s(f, &s->stest2); + qemu_get_8s(f, &s->stest3); + qemu_get_8s(f, &s->sidl); + qemu_get_8s(f, &s->stime0); + qemu_get_8s(f, &s->respid0); + qemu_get_8s(f, &s->respid1); + qemu_get_be32s(f, &s->mmrs); + qemu_get_be32s(f, &s->mmws); + qemu_get_be32s(f, &s->sfs); + qemu_get_be32s(f, &s->drs); + qemu_get_be32s(f, &s->sbms); + qemu_get_be32s(f, &s->dbms); + qemu_get_be32s(f, &s->dnad64); + qemu_get_be32s(f, &s->pmjad1); + qemu_get_be32s(f, &s->pmjad2); + qemu_get_be32s(f, &s->rbc); + qemu_get_be32s(f, &s->ua); + qemu_get_be32s(f, &s->ia); + qemu_get_be32s(f, &s->sbc); + qemu_get_be32s(f, &s->csbc); + qemu_get_buffer(f, (uint8_t *)s->scratch, sizeof (s->scratch)); + qemu_get_8s(f, &s->sbr); + + qemu_get_buffer(f, (uint8_t *)s->script_ram, sizeof (s->script_ram)); + + return 0; +} + static int lsi_scsi_uninit(PCIDevice *d) { LSIState *s = (LSIState *) d; @@ -2033,6 +2203,8 @@ static void lsi_scsi_init(PCIDevice *dev) lsi_soft_reset(s); scsi_bus_new(&dev->qdev, lsi_scsi_attach); + + register_savevm("lsiscsi", -1, 0, lsi_scsi_save, lsi_scsi_load, s); } static PCIDeviceInfo lsi_info = { |