diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2021-11-03 00:03:49 -0400 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-12-15 10:35:26 +0000 |
commit | ee03027a2cef00f977a3d28242c0a250b8552495 (patch) | |
tree | 42e74225bdb97be6a66025ec7a5b6eb519ef34ba /target/arm/translate-a64.c | |
parent | 936a6b86030a0db172b09a1ea953091a1555611e (diff) |
target/arm: Take an exception if PC is misaligned
For A64, any input to an indirect branch can cause this.
For A32, many indirect branch paths force the branch to be aligned,
but BXWritePC does not. This includes the BX instruction but also
other interworking changes to PC. Prior to v8, this case is UNDEFINED.
With v8, this is CONSTRAINED UNPREDICTABLE and may either raise an
exception or force align the PC.
We choose to raise an exception because we have the infrastructure,
it makes the generated code for gen_bx simpler, and it has the
possibility of catching more guest bugs.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/translate-a64.c')
-rw-r--r-- | target/arm/translate-a64.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 2986fe1393..130a9ff8d5 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -14753,6 +14753,7 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) uint64_t pc = s->base.pc_next; uint32_t insn; + /* Singlestep exceptions have the highest priority. */ if (s->ss_active && !s->pstate_ss) { /* Singlestep state is Active-pending. * If we're in this state at the start of a TB then either @@ -14771,6 +14772,20 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) return; } + if (pc & 3) { + /* + * PC alignment fault. This has priority over the instruction abort + * that we would receive from a translation fault via arm_ldl_code. + * This should only be possible after an indirect branch, at the + * start of the TB. + */ + assert(s->base.num_insns == 1); + gen_helper_exception_pc_alignment(cpu_env, tcg_constant_tl(pc)); + s->base.is_jmp = DISAS_NORETURN; + s->base.pc_next = QEMU_ALIGN_UP(pc, 4); + return; + } + s->pc_curr = pc; insn = arm_ldl_code(env, &s->base, pc, s->sctlr_b); s->insn = insn; |