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>
This commit is contained in:
		
							parent
							
								
									6e5d97d01d
								
							
						
					
					
						commit
						777aec7ac9
					
				
							
								
								
									
										172
									
								
								hw/lsi53c895a.c
								
								
								
								
							
							
						
						
									
										172
									
								
								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 = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue