Skip to content

Commit

Permalink
sparc/sparc64: grab BQL before calling cpu_check_irqs
Browse files Browse the repository at this point in the history
IRQ modification is part of device emulation and should be done while
the BQL is held to prevent races when MTTCG is enabled. This adds
assertions in the hw emulation layer and wraps the calls from helpers
in the BQL.

Reported-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
  • Loading branch information
stsquad committed Mar 9, 2017
1 parent c34c762 commit 5ee5993
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 0 deletions.
3 changes: 3 additions & 0 deletions hw/sparc/sun4m.c
Expand Up @@ -142,6 +142,9 @@ void cpu_check_irqs(CPUSPARCState *env)
{
CPUState *cs;

/* We should be holding the BQL before we mess with IRQs */
g_assert(qemu_mutex_iothread_locked());

if (env->pil_in && (env->interrupt_index == 0 ||
(env->interrupt_index & ~15) == TT_EXTINT)) {
unsigned int i;
Expand Down
3 changes: 3 additions & 0 deletions hw/sparc64/sparc64.c
Expand Up @@ -55,6 +55,9 @@ void cpu_check_irqs(CPUSPARCState *env)
uint32_t pil = env->pil_in |
(env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));

/* We should be holding the BQL before we mess with IRQs */
g_assert(qemu_mutex_iothread_locked());

/* TT_IVEC has a higher priority (16) than TT_EXTINT (31..17) */
if (env->ivec_status & 0x20) {
return;
Expand Down
3 changes: 3 additions & 0 deletions target/sparc/int64_helper.c
Expand Up @@ -18,6 +18,7 @@
*/

#include "qemu/osdep.h"
#include "qemu/main-loop.h"
#include "cpu.h"
#include "exec/helper-proto.h"
#include "exec/log.h"
Expand Down Expand Up @@ -208,7 +209,9 @@ static bool do_modify_softint(CPUSPARCState *env, uint32_t value)
env->softint = value;
#if !defined(CONFIG_USER_ONLY)
if (cpu_interrupts_enabled(env)) {
qemu_mutex_lock_iothread();
cpu_check_irqs(env);
qemu_mutex_unlock_iothread();
}
#endif
return true;
Expand Down
13 changes: 13 additions & 0 deletions target/sparc/win_helper.c
Expand Up @@ -18,6 +18,7 @@
*/

#include "qemu/osdep.h"
#include "qemu/main-loop.h"
#include "cpu.h"
#include "exec/exec-all.h"
#include "exec/helper-proto.h"
Expand Down Expand Up @@ -82,6 +83,7 @@ void cpu_put_psr_raw(CPUSPARCState *env, target_ulong val)
#endif
}

/* Called with BQL held */
void cpu_put_psr(CPUSPARCState *env, target_ulong val)
{
cpu_put_psr_raw(env, val);
Expand Down Expand Up @@ -153,7 +155,10 @@ void helper_wrpsr(CPUSPARCState *env, target_ulong new_psr)
if ((new_psr & PSR_CWP) >= env->nwindows) {
cpu_raise_exception_ra(env, TT_ILL_INSN, GETPC());
} else {
/* cpu_put_psr may trigger interrupts, hence BQL */
qemu_mutex_lock_iothread();
cpu_put_psr(env, new_psr);
qemu_mutex_unlock_iothread();
}
}

Expand Down Expand Up @@ -368,7 +373,9 @@ void helper_wrpstate(CPUSPARCState *env, target_ulong new_state)

#if !defined(CONFIG_USER_ONLY)
if (cpu_interrupts_enabled(env)) {
qemu_mutex_lock_iothread();
cpu_check_irqs(env);
qemu_mutex_unlock_iothread();
}
#endif
}
Expand All @@ -381,7 +388,9 @@ void helper_wrpil(CPUSPARCState *env, target_ulong new_pil)
env->psrpil = new_pil;

if (cpu_interrupts_enabled(env)) {
qemu_mutex_lock_iothread();
cpu_check_irqs(env);
qemu_mutex_unlock_iothread();
}
#endif
}
Expand All @@ -408,7 +417,9 @@ void helper_done(CPUSPARCState *env)

#if !defined(CONFIG_USER_ONLY)
if (cpu_interrupts_enabled(env)) {
qemu_mutex_lock_iothread();
cpu_check_irqs(env);
qemu_mutex_unlock_iothread();
}
#endif
}
Expand All @@ -435,7 +446,9 @@ void helper_retry(CPUSPARCState *env)

#if !defined(CONFIG_USER_ONLY)
if (cpu_interrupts_enabled(env)) {
qemu_mutex_lock_iothread();
cpu_check_irqs(env);
qemu_mutex_unlock_iothread();
}
#endif
}
Expand Down

0 comments on commit 5ee5993

Please sign in to comment.