summaryrefslogtreecommitdiffstats
path: root/target/openrisc
diff options
context:
space:
mode:
authorStafford Horne2022-06-23 22:44:56 +0200
committerStafford Horne2022-09-04 08:02:57 +0200
commit66564c31e4e012c65c84d403c2dc14c0a754047f (patch)
tree104bce2af89bda10fbd2c2a0dc802dd124df7032 /target/openrisc
parenttarget/openrisc: Enable MTTCG (diff)
downloadqemu-66564c31e4e012c65c84d403c2dc14c0a754047f.tar.gz
qemu-66564c31e4e012c65c84d403c2dc14c0a754047f.tar.xz
qemu-66564c31e4e012c65c84d403c2dc14c0a754047f.zip
target/openrisc: Interrupt handling fixes
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>
Diffstat (limited to 'target/openrisc')
-rw-r--r--target/openrisc/cpu.c1
-rw-r--r--target/openrisc/sys_helper.c7
2 files changed, 7 insertions, 1 deletions
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 41d1b2a24a..cb9f35f408 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -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
diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index da88ad9e77..09b3c97d7c 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -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;