Commit 1ca38f84e1 for qemu.org
commit 1ca38f84e19427c462f077390492f971f9eb11eb
Author: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri Mar 27 18:32:17 2026 +0100
lsi53c895a: keep lsi_request and SCSIRequest in local variables
Protect against changes from reentrant device MMIO during DMA, by always
operating on the same request.
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index 81b4f93f4d..1180e60181 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);
}
}