90 lines
3.2 KiB
Diff
90 lines
3.2 KiB
Diff
Pending upstream inclusion
|
|
|
|
Link: https://lists.gnu.org/archive/html/qemu-devel/2015-09/msg03573.html
|
|
Patchwork: https://patchwork.ozlabs.org/patch/517392/
|
|
X-Gentoo-Bug: 563162
|
|
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=563162
|
|
|
|
Signed-off-by: Markos Chandras <hwoarang@gentoo.org>
|
|
|
|
diff --git a/target-mips/cpu.c b/target-mips/cpu.c
|
|
index 4027d0f..144eea9 100644
|
|
--- a/target-mips/cpu.c
|
|
+++ b/target-mips/cpu.c
|
|
@@ -58,7 +58,9 @@ static bool mips_cpu_has_work(CPUState *cs)
|
|
check for interrupts that can be taken. */
|
|
if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
|
|
cpu_mips_hw_interrupts_pending(env)) {
|
|
- has_work = true;
|
|
+ if (cpu_mips_hw_interrupts_enabled(env)) {
|
|
+ has_work = true;
|
|
+ }
|
|
}
|
|
|
|
/* MIPS-MT has the ability to halt the CPU. */
|
|
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
|
|
index c91883d..210370e 100644
|
|
--- a/target-mips/cpu.h
|
|
+++ b/target-mips/cpu.h
|
|
@@ -639,23 +639,24 @@ static inline int cpu_mmu_index (CPUMIPSState *env)
|
|
return env->hflags & MIPS_HFLAG_KSU;
|
|
}
|
|
|
|
-static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
|
|
+static inline bool cpu_mips_hw_interrupts_enabled(CPUMIPSState *env)
|
|
{
|
|
- int32_t pending;
|
|
- int32_t status;
|
|
- int r;
|
|
-
|
|
- if (!(env->CP0_Status & (1 << CP0St_IE)) ||
|
|
- (env->CP0_Status & (1 << CP0St_EXL)) ||
|
|
- (env->CP0_Status & (1 << CP0St_ERL)) ||
|
|
+ return (env->CP0_Status & (1 << CP0St_IE)) &&
|
|
+ !(env->CP0_Status & (1 << CP0St_EXL)) &&
|
|
+ !(env->CP0_Status & (1 << CP0St_ERL)) &&
|
|
+ !(env->hflags & MIPS_HFLAG_DM) &&
|
|
/* Note that the TCStatus IXMT field is initialized to zero,
|
|
and only MT capable cores can set it to one. So we don't
|
|
need to check for MT capabilities here. */
|
|
- (env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT)) ||
|
|
- (env->hflags & MIPS_HFLAG_DM)) {
|
|
- /* Interrupts are disabled */
|
|
- return 0;
|
|
- }
|
|
+ !(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT));
|
|
+}
|
|
+
|
|
+/* Check if there is pending and not masked out interrupt */
|
|
+static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
|
|
+{
|
|
+ int32_t pending;
|
|
+ int32_t status;
|
|
+ bool r;
|
|
|
|
pending = env->CP0_Cause & CP0Ca_IP_mask;
|
|
status = env->CP0_Status & CP0Ca_IP_mask;
|
|
@@ -669,7 +670,7 @@ static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
|
|
/* A MIPS configured with compatibility or VInt (Vectored Interrupts)
|
|
treats the pending lines as individual interrupt lines, the status
|
|
lines are individual masks. */
|
|
- r = pending & status;
|
|
+ r = (pending & status) != 0;
|
|
}
|
|
return r;
|
|
}
|
|
diff --git a/target-mips/helper.c b/target-mips/helper.c
|
|
index 01c4461..2d86323 100644
|
|
--- a/target-mips/helper.c
|
|
+++ b/target-mips/helper.c
|
|
@@ -759,7 +759,8 @@ bool mips_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
|
MIPSCPU *cpu = MIPS_CPU(cs);
|
|
CPUMIPSState *env = &cpu->env;
|
|
|
|
- if (cpu_mips_hw_interrupts_pending(env)) {
|
|
+ if (cpu_mips_hw_interrupts_enabled(env) &&
|
|
+ cpu_mips_hw_interrupts_pending(env)) {
|
|
/* Raise it */
|
|
cs->exception_index = EXCP_EXT_INTERRUPT;
|
|
env->error_code = 0;
|