qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Fix assertion failure in lsi53c810 emulator


From: Liu Cyrus
Subject: [PATCH] Fix assertion failure in lsi53c810 emulator
Date: Sat, 12 Jun 2021 14:24:38 +0800

From: cyruscyliu <cyruscyliu@gmail.com>

An assertion failure can be triggered in the lsi53c810 emulator by a guest
when ((s->sstat1 & 0x7) == PHASE_DO) || (s->sstat1 & 0x7) == PHASE_DI)) && (!s->current) holds.
Check s->sstat1 and s->current in lsi_reg_writeb before lsi_execute_script()
to discard this MMIO write.

Fixes: 7d8406be69ce ("PCI SCSI HBA emulation.")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/305
Buglink: https://bugs.launchpad.net/qemu/+bug/1908515
Signed-off-by: cyruscyliu <cyruscyliu@gmail.com>
---
 hw/scsi/lsi53c895a.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index e2c1918..5c08f7f 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -1919,6 +1919,10 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
             lsi_update_irq(s);
         }
         if (s->waiting == LSI_WAIT_RESELECT && val & LSI_ISTAT0_SIGP) {
+            if (!(((((s->sstat1 & 0x7) == PHASE_DO)
+                    || (s->sstat1 & 0x7) == PHASE_DI))
+                    && s->current))
+                break;
             trace_lsi_awoken();
             s->waiting = LSI_NOWAIT;
             s->dsp = s->dnad;
@@ -1980,8 +1984,13 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
          * instruction.  Is this correct?
          */
         if ((s->dmode & LSI_DMODE_MAN) == 0
-            && (s->istat1 & LSI_ISTAT1_SRUN) == 0)
+                && (s->istat1 & LSI_ISTAT1_SRUN) == 0) {
+            if (!(((((s->sstat1 & 0x7) == PHASE_DO)
+                    || (s->sstat1 & 0x7) == PHASE_DI))
+                    && s->current))
+                break;
             lsi_execute_script(s);
+        }
         break;
     CASE_SET_REG32(dsps, 0x30)
     CASE_SET_REG32(scratch[0], 0x34)
@@ -2001,8 +2010,13 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
          * FIXME: if s->waiting != LSI_NOWAIT, this will only execute one
          * instruction.  Is this correct?
          */
-        if ((val & LSI_DCNTL_STD) && (s->istat1 & LSI_ISTAT1_SRUN) == 0)
+        if ((val & LSI_DCNTL_STD) && (s->istat1 & LSI_ISTAT1_SRUN) == 0) {
+            if (!(((((s->sstat1 & 0x7) == PHASE_DO)
+                    || (s->sstat1 & 0x7) == PHASE_DI))
+                    && s->current))
+                break;
             lsi_execute_script(s);
+        }
         break;
     case 0x40: /* SIEN0 */
         s->sien0 = val;
--
2.7.4

Hi folks, this is a suggestion for fixing this bug. 
I'm willing to discuss this with you because I'm new to contribute to QEMU.

Best,
Qiang Liu

reply via email to

[Prev in Thread] Current Thread [Next in Thread]