From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LNDQm-0005VQ-Fp for qemu-devel@nongnu.org; Wed, 14 Jan 2009 16:37:44 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LNDQk-0005Rv-99 for qemu-devel@nongnu.org; Wed, 14 Jan 2009 16:37:42 -0500 Received: from [199.232.76.173] (port=56121 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LNDQk-0005Re-27 for qemu-devel@nongnu.org; Wed, 14 Jan 2009 16:37:42 -0500 Received: from phong.sigbus.net ([65.49.35.42]:43829) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LNDQj-0000RW-Cx for qemu-devel@nongnu.org; Wed, 14 Jan 2009 16:37:41 -0500 Received: from [192.168.0.3] (c-67-188-86-149.hsd1.ca.comcast.net [67.188.86.149]) by phong.sigbus.net (Postfix) with ESMTP id B7D1395C0C3 for ; Wed, 14 Jan 2009 13:37:36 -0800 (PST) From: Nolan Content-Type: text/plain Date: Wed, 14 Jan 2009 13:37:36 -0800 Message-Id: <1231969056.15230.65.camel@voxel> Mime-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH] save/restore for LSI SCSI. Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org This patch adds save and restore to the LSIlogic SCSI model. It works fine if the adapter is idle when suspending. After resume, subsequent IO operations complete normally. I have only tested on a debian etch guest, no windows. There is a bug if there is IO in flight. Sometimes it results in the guest freezing hard, other times in the guest unsuccessfully reseting the adapter. Oddly, I saw at least one case where restore failed (with the "reset the adapter" case), but a second restore from the same snapshot worked. I've not much further time to dedicate to this code, so I'm sending it to the list in the hopes that others might. Signed-off-by: Nolan Leake diff --git a/qemu/hw/lsi53c895a.c b/qemu/hw/lsi53c895a.c index c65ff90..c44f289 100644 --- a/qemu/hw/lsi53c895a.c +++ b/qemu/hw/lsi53c895a.c @@ -10,6 +10,8 @@ /* ??? Need to check if the {read,write}[wl] routines work properly on big-endian targets. */ +#include \ + #include "hw.h" #include "pci.h" #include "scsi-disk.h" @@ -1973,6 +1975,170 @@ int lsi_scsi_uninit(PCIDevice *d) return 0; } +static void lsi_scsi_save(QEMUFile *f, void *opaque) +{ + LSIState *s = opaque; + + assert(s->active_commands == 0); + assert(s->dma_buf == NULL); + +#if 0 + /* XXX Do we need to save any of these? */ + 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); +#endif + + 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_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; + + if (version_id > 0) { + return -EINVAL; + } + +#if 0 + 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); +#endif + + 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_buffer(f, (uint8_t *)s->script_ram, sizeof (s->script_ram)); + + return 0; +} + void *lsi_scsi_init(PCIBus *bus, int devfn) { LSIState *s; @@ -2018,5 +2184,7 @@ void *lsi_scsi_init(PCIBus *bus, int devfn) lsi_soft_reset(s); + register_savevm("lsiscsi", -1, 0, lsi_scsi_save, lsi_scsi_load, s); + return s; }