Currently the mptsas reset function clears intr_status, but it
doesn't reset the doorbell state machine. This means that the state
machine and the interrupt state get out of sync, and the guest can
trigger an assertion failure in mptsas_doorbell_read() where
s->doorbell_state is still DOORBELL_READ but s->intr_status does not
have MPI_HIS_DOORBELL_INTERRUPT set.
Fix this by having reset also reset the doorbell state. Strictly
speaking we don't need to also clear doorbell_reply_idx and
doorbell_reply_size, because those are only read when in
DOORBELL_READ state, and the code always sets them up before
transitioning into that state. But it's less confusing to clear them
out on reset.
Cc: qemu-stable@nongnu.org
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/304
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
Disclaimer: this fixes the fuzzer repro case, and I have
run "make check" and "make check-functional", but I'm pretty
sure neither of those actually exercises the mptsas device...
---
hw/scsi/mptsas.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c
index e4a7b2fee4..5df124c0ce 100644
--- a/hw/scsi/mptsas.c
+++ b/hw/scsi/mptsas.c
@@ -811,6 +811,10 @@ static void mptsas_soft_reset(MPTSASState *s)
s->intr_status = 0;
s->intr_mask = save_mask;
+ s->doorbell_state = DOORBELL_NONE;
+ s->doorbell_reply_idx = 0;
+ s->doorbell_reply_size = 0;
+
s->reply_free_tail = 0;
s->reply_free_head = 0;
s->reply_post_tail = 0;
--
2.43.0
On 29/6/26 20:50, Peter Maydell wrote: > Currently the mptsas reset function clears intr_status, but it > doesn't reset the doorbell state machine. This means that the state > machine and the interrupt state get out of sync, and the guest can > trigger an assertion failure in mptsas_doorbell_read() where > s->doorbell_state is still DOORBELL_READ but s->intr_status does not > have MPI_HIS_DOORBELL_INTERRUPT set. > > Fix this by having reset also reset the doorbell state. Strictly > speaking we don't need to also clear doorbell_reply_idx and > doorbell_reply_size, because those are only read when in > DOORBELL_READ state, and the code always sets them up before > transitioning into that state. But it's less confusing to clear them > out on reset. > > Cc: qemu-stable@nongnu.org > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/304 > Signed-off-by: Peter Maydell <peter.maydell@linaro.org> > --- > Disclaimer: this fixes the fuzzer repro case, and I have > run "make check" and "make check-functional", but I'm pretty > sure neither of those actually exercises the mptsas device... > --- > hw/scsi/mptsas.c | 4 ++++ > 1 file changed, 4 insertions(+) Queued via hw-misc tree, thanks.
On 29/6/26 20:50, Peter Maydell wrote: > Currently the mptsas reset function clears intr_status, but it > doesn't reset the doorbell state machine. This means that the state > machine and the interrupt state get out of sync, and the guest can > trigger an assertion failure in mptsas_doorbell_read() where > s->doorbell_state is still DOORBELL_READ but s->intr_status does not > have MPI_HIS_DOORBELL_INTERRUPT set. > > Fix this by having reset also reset the doorbell state. Strictly > speaking we don't need to also clear doorbell_reply_idx and > doorbell_reply_size, because those are only read when in > DOORBELL_READ state, and the code always sets them up before > transitioning into that state. But it's less confusing to clear them > out on reset. > > Cc: qemu-stable@nongnu.org > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/304 > Signed-off-by: Peter Maydell <peter.maydell@linaro.org> > --- > Disclaimer: this fixes the fuzzer repro case, and I have > run "make check" and "make check-functional", but I'm pretty > sure neither of those actually exercises the mptsas device... > --- > hw/scsi/mptsas.c | 4 ++++ > 1 file changed, 4 insertions(+) Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
© 2016 - 2026 Red Hat, Inc.