summaryrefslogtreecommitdiffstats
path: root/target/arm
diff options
context:
space:
mode:
authorAlex Bennée2019-12-17 16:08:57 +0100
committerAlex Bennée2020-01-09 12:41:29 +0100
commit4ff5ef9e911c670ca10cdd36dd27c5395ec2c753 (patch)
tree5abc54db219c91ed383e48bbfaad767b8628b1e9 /target/arm
parenttarget/arm: remove unused EXCP_SEMIHOST leg (diff)
downloadqemu-4ff5ef9e911c670ca10cdd36dd27c5395ec2c753.tar.gz
qemu-4ff5ef9e911c670ca10cdd36dd27c5395ec2c753.tar.xz
qemu-4ff5ef9e911c670ca10cdd36dd27c5395ec2c753.zip
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. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Keith Packard <keithp@keithp.com> Tested-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'target/arm')
-rw-r--r--target/arm/helper.c2
-rw-r--r--target/arm/m_helper.c1
-rw-r--r--target/arm/translate-a64.c2
-rw-r--r--target/arm/translate.c6
4 files changed, 7 insertions, 4 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c
index da22c19800..19a57a17da 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8614,11 +8614,13 @@ static void handle_semihosting(CPUState *cs)
"...handling as semihosting call 0x%" PRIx64 "\n",
env->xregs[0]);
env->xregs[0] = do_arm_semihosting(env);
+ env->pc += 4;
} else {
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;
}
}
#endif
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
index 76de317e6a..33d414a684 100644
--- a/target/arm/m_helper.c
+++ b/target/arm/m_helper.c
@@ -2185,6 +2185,7 @@ void arm_v7m_cpu_do_interrupt(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;
case EXCP_BKPT:
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG, false);
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index d4bebbe629..972c28c3c9 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1937,7 +1937,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/target/arm/translate.c b/target/arm/translate.c
index 2b6c1f91bf..5185e08641 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1124,7 +1124,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;
}
@@ -8457,7 +8457,7 @@ static bool trans_BKPT(DisasContext *s, arg_BKPT *a)
!IS_USER(s) &&
#endif
(a->imm == 0xab)) {
- gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST);
+ gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
} else {
gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false));
}
@@ -10266,7 +10266,7 @@ static bool trans_SVC(DisasContext *s, arg_SVC *a)
!IS_USER(s) &&
#endif
(a->imm == semihost_imm)) {
- gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST);
+ gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
} else {
gen_set_pc_im(s, s->base.pc_next);
s->svc_imm = a->imm;