From 8f275077b00643b62d090da218d1e5e66094a6cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 14 Jan 2020 08:24:37 -0500 Subject: [PATCH] target/arm: only update pc after semihosting completes Before we introduce blocking semihosting calls we need to ensure we can restart the system on semi hosting exception. To be able to do this the EXCP_SEMIHOST operation should be idempotent until it finally completes. Practically this means ensureing we only update the pc after the semihosting call has completed. Backports commit 4ff5ef9e911c670ca10cdd36dd27c5395ec2c753 from qemu --- qemu/target/arm/helper.c | 8 ++++++++ qemu/target/arm/m_helper.c | 21 +++++++-------------- qemu/target/arm/translate-a64.c | 2 +- qemu/target/arm/translate.c | 2 +- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/qemu/target/arm/helper.c b/qemu/target/arm/helper.c index 7c793d71..64b7c2c5 100644 --- a/qemu/target/arm/helper.c +++ b/qemu/target/arm/helper.c @@ -7755,6 +7755,12 @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx, return target_el; } +target_ulong do_arm_semihosting(CPUARMState *env) +{ + /* Unicorn: We don't handle semihosting */ + g_assert_not_reached(); +} + /* * Function used to synchronize QEMU's AArch64 register set with AArch32 * register set. This is necessary when switching between AArch32 and AArch64 @@ -8385,6 +8391,7 @@ static inline bool check_for_semihosting(CPUState *cs) "...handling as semihosting call 0x%" PRIx64 "\n", env->xregs[0]); env->xregs[0] = do_arm_semihosting(env); + env->pc += 4; return true; } return false; @@ -8444,6 +8451,7 @@ static inline bool check_for_semihosting(CPUState *cs) "...handling as semihosting call 0x%x\n", env->regs[0]); env->regs[0] = do_arm_semihosting(env); + env->regs[15] += env->thumb ? 2 : 4; return true; } #else diff --git a/qemu/target/arm/m_helper.c b/qemu/target/arm/m_helper.c index 146bd0e5..4340e317 100644 --- a/qemu/target/arm/m_helper.c +++ b/qemu/target/arm/m_helper.c @@ -2115,21 +2115,14 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) break; } break; + case EXCP_SEMIHOST: + qemu_log_mask(CPU_LOG_INT, + "...handling as semihosting call 0x%x\n", + env->regs[0]); + env->regs[0] = do_arm_semihosting(env); + env->regs[15] += env->thumb ? 2 : 4; + break; case EXCP_BKPT: -#if 0 - if (semihosting_enabled) { - int nr; - nr = arm_lduw_code(env, env->regs[15], arm_sctlr_b(env)) & 0xff; - if (nr == 0xab) { - env->regs[15] += 2; - qemu_log_mask(CPU_LOG_INT, - "...handling as semihosting call 0x%x\n", - env->regs[0]); - env->regs[0] = do_arm_semihosting(env); - return; - } - } -#endif //armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG, false); break; case EXCP_IRQ: diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index 26896f48..65430f85 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -2131,7 +2131,7 @@ static void disas_exc(DisasContext *s, uint32_t insn) break; } #endif - gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST); + gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); } else { unsupported_encoding(s, insn); } diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index e8b599b9..bc0c9ca7 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -1174,7 +1174,7 @@ static inline void gen_hlt(DisasContext *s, int imm) s->current_el != 0 && #endif (imm == (s->thumb ? 0x3c : 0xf000))) { - gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST); + gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); return; }