aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2020-02-07 14:04:27 +0000
committerPeter Maydell <peter.maydell@linaro.org>2020-02-07 14:04:27 +0000
commitd63d0ec59d87a698de5ed843288f90a23470cf2e (patch)
tree105ff5302c5441e63bdf0050568b0110457accb9
parent16e07f78df002067bc4bfb115ba1ee0ce278e9e5 (diff)
target/arm: Raise only one interrupt in arm_cpu_exec_interrupt
The fall through organization of this function meant that we would raise an interrupt, then might overwrite that with another. Since interrupt prioritization is IMPLEMENTATION DEFINED, we can recognize these in any order we choose. Unify the code to raise the interrupt in a block at the end. Tested-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20200206105448.4726-42-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--target/arm/cpu.c30
1 files changed, 12 insertions, 18 deletions
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 4ffc09909d..b0762a76c4 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -535,17 +535,15 @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
uint64_t hcr_el2 = arm_hcr_el2_eff(env);
uint32_t target_el;
uint32_t excp_idx;
- bool ret = false;
+
+ /* The prioritization of interrupts is IMPLEMENTATION DEFINED. */
if (interrupt_request & CPU_INTERRUPT_FIQ) {
excp_idx = EXCP_FIQ;
target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
if (arm_excp_unmasked(cs, excp_idx, target_el,
cur_el, secure, hcr_el2)) {
- cs->exception_index = excp_idx;
- env->exception.target_el = target_el;
- cc->do_interrupt(cs);
- ret = true;
+ goto found;
}
}
if (interrupt_request & CPU_INTERRUPT_HARD) {
@@ -553,10 +551,7 @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
if (arm_excp_unmasked(cs, excp_idx, target_el,
cur_el, secure, hcr_el2)) {
- cs->exception_index = excp_idx;
- env->exception.target_el = target_el;
- cc->do_interrupt(cs);
- ret = true;
+ goto found;
}
}
if (interrupt_request & CPU_INTERRUPT_VIRQ) {
@@ -564,10 +559,7 @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
target_el = 1;
if (arm_excp_unmasked(cs, excp_idx, target_el,
cur_el, secure, hcr_el2)) {
- cs->exception_index = excp_idx;
- env->exception.target_el = target_el;
- cc->do_interrupt(cs);
- ret = true;
+ goto found;
}
}
if (interrupt_request & CPU_INTERRUPT_VFIQ) {
@@ -575,14 +567,16 @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
target_el = 1;
if (arm_excp_unmasked(cs, excp_idx, target_el,
cur_el, secure, hcr_el2)) {
- cs->exception_index = excp_idx;
- env->exception.target_el = target_el;
- cc->do_interrupt(cs);
- ret = true;
+ goto found;
}
}
+ return false;
- return ret;
+ found:
+ cs->exception_index = excp_idx;
+ env->exception.target_el = target_el;
+ cc->do_interrupt(cs);
+ return true;
}
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)