Message ID | 20170711175937.23140-7-alex.bennee@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | arm: fixes for eret, isb and DISAS_UPDATE handling | expand |
On Tue, Jul 11, 2017 at 18:59:37 +0100, Alex Bennée wrote: > Previously DISAS_JUMP did ensure this but with the optimisation of > 8a6b28c7 (optimize indirect branches) we might not leave the loop. > This means if any pending interrupts are cleared by changing IRQ flags > we might never get around to servicing them. You usually notice this > by seeing the lookup_tb_ptr() helper gainfully chaining TBs together > while cpu->interrupt_request remains high and the exit_request has not > been set. > > This breaks amongst other things the OPTEE test suite which executes > an eret from the secure world after a non-secure world IRQ has gone > pending which then never gets serviced. > > Instead of using the previously implied semantics of DISAS_JUMP we use > DISAS_EXIT which will always exit the run-loop. > > CC: Etienne Carriere <etienne.carriere@linaro.org> > CC: Joakim Bech <joakim.bech@linaro.org> > CC: Peter Maydell <peter.maydell@linaro.org> > CC: Emilio G. Cota <cota@braap.org> > Signed-off-by: Alex Bennée <alex.bennee@linaro.org> > Reviewed-by: Richard Henderson <rth@twiddle.net> Reviewed-by: Emilio G. Cota <cota@braap.org> E.
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 2ac565eb10..3fa39023ca 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -1788,7 +1788,8 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn) return; } gen_helper_exception_return(cpu_env); - s->is_jmp = DISAS_JUMP; + /* Must exit loop to check un-masked IRQs */ + s->is_jmp = DISAS_EXIT; return; case 5: /* DRPS */ if (rn != 0x1f) { diff --git a/target/arm/translate.c b/target/arm/translate.c index dbf919cce3..f1023d5263 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -4479,7 +4479,8 @@ static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr) */ gen_helper_cpsr_write_eret(cpu_env, cpsr); tcg_temp_free_i32(cpsr); - s->is_jmp = DISAS_JUMP; + /* Must exit loop to check un-masked IRQs */ + s->is_jmp = DISAS_EXIT; } /* Generate an old-style exception return. Marks pc as dead. */ @@ -9523,7 +9524,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) tmp = load_cpu_field(spsr); gen_helper_cpsr_write_eret(cpu_env, tmp); tcg_temp_free_i32(tmp); - s->is_jmp = DISAS_JUMP; + /* Must exit loop to check un-masked IRQs */ + s->is_jmp = DISAS_EXIT; } } break;