When using qemu-system-arm from CVS or 0.9.1 I've noticed that the emulator locks up occasionally on heavy disk access. Forcing a fsck on start up is normally enough to trigger it. The root cause is that scsi_read_data can be reentered before updating sector and sector_count:
lsi_do_dma calls scsi_read_data, which calls scsi_read_complete, lsi_command_complete, lsi_do_dma, scsi_read_data without updating sector and sector_count, and so on... This results in an unending series of reads: scsi-disk: Command: lun=0 tag=0x10049 data=0x28 0x00 0x00 0x24 0x24 0x97 0x00 0x00 0x90 0x00 scsi-disk: Read (sector 2368663, count 144) scsi-disk: Read tag=0x10049 sector_count=144 scsi-disk: Data ready tag=0x10049 len=65536 scsi-disk: Read tag=0x10049 sector_count=16 scsi-disk: Data ready tag=0x10049 len=8192 scsi-disk: Read tag=0x10049 sector_count=16 scsi-disk: Data ready tag=0x10049 len=8192 scsi-disk: Read tag=0x10049 sector_count=-16 scsi-disk: Data ready tag=0x10049 len=65536 scsi-disk: Read tag=0x10049 sector_count=-144 scsi-disk: Data ready tag=0x10049 len=65536 scsi-disk: Read tag=0x10049 sector_count=-272 scsi-disk: Data ready tag=0x10049 len=65536 The attached patch ensures that the scsi_read_complete call occurs at the end on scsi_read_data. I'm not sure if this is how it was intended to work -- an alternative would be to prevent lsi_command_complete calling lsi_do_dma. But the patch does prevent the hanging.
Index: hw/scsi-disk.c =================================================================== RCS file: /sources/qemu/qemu/hw/scsi-disk.c,v retrieving revision 1.20 diff -u -r1.20 scsi-disk.c --- hw/scsi-disk.c 3 Feb 2008 04:05:50 -0000 1.20 +++ hw/scsi-disk.c 26 Feb 2008 22:31:03 -0000 @@ -171,6 +171,7 @@ SCSIDeviceState *s = d->state; SCSIRequest *r; uint32_t n; + int sector; r = scsi_find_request(s, tag); if (!r) { @@ -191,17 +192,19 @@ return; } + sector = r->sector; + n = r->sector_count; if (n > SCSI_DMA_BUF_SIZE / 512) n = SCSI_DMA_BUF_SIZE / 512; + r->sector += n; + r->sector_count -= n; r->buf_len = n * 512; - r->aiocb = bdrv_aio_read(s->bdrv, r->sector, r->dma_buf, n, + r->aiocb = bdrv_aio_read(s->bdrv, sector, r->dma_buf, n, scsi_read_complete, r); if (r->aiocb == NULL) scsi_command_complete(r, SENSE_HARDWARE_ERROR); - r->sector += n; - r->sector_count -= n; } static void scsi_write_complete(void * opaque, int ret)
Brian