summaryrefslogtreecommitdiffstats
path: root/target/arm/translate.c
diff options
context:
space:
mode:
authorRichard Henderson2021-11-03 05:03:49 +0100
committerPeter Maydell2021-12-15 11:35:26 +0100
commitee03027a2cef00f977a3d28242c0a250b8552495 (patch)
tree42e74225bdb97be6a66025ec7a5b6eb519ef34ba /target/arm/translate.c
parenttarget/arm: Split compute_fsr_fsc out of arm_deliver_fault (diff)
downloadqemu-ee03027a2cef00f977a3d28242c0a250b8552495.tar.gz
qemu-ee03027a2cef00f977a3d28242c0a250b8552495.tar.xz
qemu-ee03027a2cef00f977a3d28242c0a250b8552495.zip
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.c')
-rw-r--r--target/arm/translate.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 0103c75a27..45917c3a6d 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9555,7 +9555,27 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
uint32_t pc = dc->base.pc_next;
unsigned int insn;
- if (arm_check_ss_active(dc) || arm_check_kernelpage(dc)) {
+ /* Singlestep exceptions have the highest priority. */
+ if (arm_check_ss_active(dc)) {
+ dc->base.pc_next = pc + 4;
+ 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
+ * (or the execution of the kernelpage entrypoint). This should only
+ * be possible after an indirect branch, at the start of the TB.
+ */
+ assert(dc->base.num_insns == 1);
+ gen_helper_exception_pc_alignment(cpu_env, tcg_constant_tl(pc));
+ dc->base.is_jmp = DISAS_NORETURN;
+ dc->base.pc_next = QEMU_ALIGN_UP(pc, 4);
+ return;
+ }
+
+ if (arm_check_kernelpage(dc)) {
dc->base.pc_next = pc + 4;
return;
}