From: Paolo Bonzini <[email protected]> Protect against changes from reentrant device MMIO during DMA, by always operating on the same request.
Cc: [email protected] Signed-off-by: Paolo Bonzini <[email protected]> (cherry picked from commit 1ca38f84e19427c462f077390492f971f9eb11eb) Signed-off-by: Michael Tokarev <[email protected]> diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index a5598931f9..be9bff02b0 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -626,6 +626,8 @@ static void lsi_do_dma(LSIState *s, int out) uint32_t count; dma_addr_t addr; SCSIDevice *dev; + SCSIRequest *req; + lsi_request *p; if (!s->current || !s->current->dma_len) { /* Wait until data is available. */ @@ -633,12 +635,14 @@ static void lsi_do_dma(LSIState *s, int out) return; } - dev = s->current->req->dev; + p = s->current; + req = s->current->req; + dev = req->dev; assert(dev); count = s->dbc; - if (count > s->current->dma_len) - count = s->current->dma_len; + if (count > p->dma_len) + count = p->dma_len; addr = s->dnad; /* both 40 and Table Indirect 64-bit DMAs store upper bits in dnad64 */ @@ -653,21 +657,22 @@ static void lsi_do_dma(LSIState *s, int out) s->csbc += count; s->dnad += count; s->dbc -= count; - if (s->current->dma_buf == NULL) { - s->current->dma_buf = scsi_req_get_buf(s->current->req); + if (p->dma_buf == NULL) { + p->dma_buf = scsi_req_get_buf(req); } /* ??? Set SFBR to first data byte. */ if (out) { - lsi_mem_read(s, addr, s->current->dma_buf, count); + lsi_mem_read(s, addr, p->dma_buf, count); } else { - lsi_mem_write(s, addr, s->current->dma_buf, count); + lsi_mem_write(s, addr, p->dma_buf, count); } - s->current->dma_len -= count; - if (s->current->dma_len == 0) { - s->current->dma_buf = NULL; - scsi_req_continue(s->current->req); + + p->dma_len -= count; + if (p->dma_len == 0) { + p->dma_buf = NULL; + scsi_req_continue(req); } else { - s->current->dma_buf += count; + p->dma_buf += count; lsi_resume_script(s); } } -- 2.47.3
