Commit d63d0ec5 authored by Richard Henderson's avatar Richard Henderson Committed by Peter Maydell
Browse files

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: default avatarAlex Bennée <alex.bennee@linaro.org>
Reviewed-by: default avatarPeter Maydell <peter.maydell@linaro.org>
Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Message-id: 20200206105448.4726-42-richard.henderson@linaro.org
Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parent 16e07f78
Loading
Loading
Loading
Loading
+12 −18
Original line number Diff line number Diff line
@@ -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)