target/openrisc: Interrupt handling fixes
authorStafford Horne <shorne@gmail.com>
Thu, 23 Jun 2022 20:44:56 +0000 (05:44 +0900)
committerStafford Horne <shorne@gmail.com>
Sun, 4 Sep 2022 06:02:57 +0000 (07:02 +0100)
When running SMP systems we sometimes were seeing lockups where
IPI interrupts were being raised by never handled.

This looks to be caused by 2 issues in the openrisc interrupt handling
logic.

 1. After clearing an interrupt the openrisc_cpu_set_irq handler will
    always clear PICSR.  This is not correct as masked interrupts
    should still be visible in PICSR.
 2. After setting PICMR (mask register) and exposed interrupts should
    cause an interrupt to be raised.  This was not being done so add it.

This patch fixes both issues.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Stafford Horne <shorne@gmail.com>
target/openrisc/cpu.c
target/openrisc/sys_helper.c

index 41d1b2a24a6936d51b9441d009d8fff556c3c978..cb9f35f4087a0da76feec0e7f8bb3c0831eadd15 100644 (file)
@@ -98,7 +98,6 @@ static void openrisc_cpu_set_irq(void *opaque, int irq, int level)
         cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
-        cpu->env.picsr = 0;
     }
 }
 #endif
index da88ad9e7780e73f2c1b2862df5b8f3d122d97ab..09b3c97d7c1ac408e5852ddc1d723c938c3e6e2f 100644 (file)
@@ -139,6 +139,13 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb)
         break;
     case TO_SPR(9, 0):  /* PICMR */
         env->picmr = rb;
+        qemu_mutex_lock_iothread();
+        if (env->picsr & env->picmr) {
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+        } else {
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+        }
+        qemu_mutex_unlock_iothread();
         break;
     case TO_SPR(9, 2):  /* PICSR */
         env->picsr &= ~rb;