qemu/target/arm
Peter Maydell 7407d2319d target/arm: Don't assert() for ISB/SB inside IT block
If the guest code has an ISB or SB insn inside an IT block, we
generate incorrect code which trips a TCG assertion:

qemu-system-arm: ../tcg/tcg-op.c:3343: void tcg_gen_goto_tb(unsigned int): Assertion `(tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0' failed.

This is because we call gen_goto_tb(dc, 1, ...) twice:

 brcond_i32 ZF,$0x0,ne,$L1
 add_i32 pc,pc,$0x4
 goto_tb $0x1
 exit_tb $0x73d948001b81
 set_label $L1
 add_i32 pc,pc,$0x4
 goto_tb $0x1
 exit_tb $0x73d948001b81

Both calls are in arm_tr_tb_stop(), one for the
DISAS_NEXT/DISAS_TOO_MANY handling, and one for the dc->condjump
condition-failed codepath.  The DISAS_NEXT handling doesn't have this
problem because arm_post_translate_insn() does the handling of "emit
the label for the condition-failed conditional execution" and so
arm_tr_tb_stop() doesn't have dc->condjump set.  But for
DISAS_TOO_MANY we don't do that.

Fix the bug by making arm_post_translate_insn() handle the
DISAS_TOO_MANY case.  This only affects the SB and ISB insns when
used in Thumb mode inside an IT block: only these insns specifically
set is_jmp to TOO_MANY, and their A32 encodings are unconditional.

For the major TOO_MANY case (breaking the TB because it would cross a
page boundary) we do that check and set is_jmp to TOO_MANY only after
the call to arm_post_translate_insn(); so arm_post_translate_insn()
sees is_jmp == DISAS_NEXT, and  we emit the correct code for that
situation.

With this fix we generate the somewhat more sensible set of TCG ops:
 brcond_i32 ZF,$0x0,ne,$L1
 set_label $L1
 add_i32 pc,pc,$0x4
 goto_tb $0x1
 exit_tb $0x7c5434001b81

(NB: the TCG optimizer doesn't optimize out the jump-to-next, but
we can't really avoid emitting it because we don't know at the
point we're emitting the handling for the condexec check whether
this insn is going to happen to be a nop for us or not.)

Cc: qemu-stable@nongnu.org
Fixes: https://gitlab.com/qemu-project/qemu/-/issues/2942
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20250501125544.727038-1-peter.maydell@linaro.org
(cherry picked from commit 8ed7c0b648)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-08 10:22:26 +03:00
..
hvf target/arm/hvf: sign extend the data for a load operation when SSE=1 2025-03-18 09:02:47 +03:00
tcg target/arm: Don't assert() for ISB/SB inside IT block 2025-05-08 10:22:26 +03:00
arch_dump.c target/arm: Move feature test functions to their own header 2023-10-27 11:44:32 +01:00
arm-powerctl.c target/arm: Expose arm_cpu_mp_affinity() in 'multiprocessing.h' header 2024-01-26 11:30:48 +00:00
arm-powerctl.h target/arm/arm-powerctl: Add new arm_set_cpu_on_and_reset() 2019-02-28 11:03:04 +00:00
arm-qmp-cmds.c target: Improve error reporting for CpuModelInfo member @props 2024-03-12 14:03:00 +01:00
common-semi-target.h target/arm/common-semi-target.h: Remove unnecessary boot.h include 2023-10-19 14:32:13 +01:00
cortex-regs.c target/arm: Saturate L2CTLR_EL1 core count field rather than overflowing 2023-05-18 11:39:33 +01:00
cpregs.h target/arm/cpregs: Include missing 'kvm-consts.h' header 2024-01-26 11:30:48 +00:00
cpu-features.h target/arm: Enable FEAT_CMOW for -cpu max 2024-11-05 10:10:00 +00:00
cpu-param.h license: Update deprecated SPDX tag LGPL-2.0+ to LGPL-2.0-or-later 2024-09-20 10:11:59 +03:00
cpu-qom.h target/arm: Add support for Non-maskable Interrupt 2024-04-25 10:21:04 +01:00
cpu.c target/arm: Implement SEL2 physical and virtual timers 2025-03-18 09:02:48 +03:00
cpu.h target/arm: Implement SEL2 physical and virtual timers 2025-03-18 09:02:48 +03:00
cpu64.c target/arm/tcg: refine cache descriptions with a wrapper 2024-09-13 15:31:47 +01:00
debug_helper.c target/arm: Honour SDCR.TDCC and SCR.TERR in AArch32 EL3 non-Monitor modes 2025-02-25 09:12:51 +03:00
gdbstub.c gdbstub: Re-factor gdb command extensions 2024-07-22 09:37:44 +01:00
gdbstub64.c gdbstub: Add support for MTE in system mode 2024-09-10 23:33:51 +01:00
gtimer.h target/arm: Implement SEL2 physical and virtual timers 2025-03-18 09:02:48 +03:00
helper.c target/arm: Implement SEL2 physical and virtual timers 2025-03-18 09:02:48 +03:00
helper.h target/arm: Widen NeonGenNarrowEnvFn return to 64 bits 2024-09-19 12:58:58 +01:00
hvf_arm.h hvf: arm: Implement and use hvf_get_physical_address_range 2024-09-13 15:31:47 +01:00
hyp_gdbstub.c target/arm: remove break after g_assert_not_reached() 2024-09-24 13:53:35 +02:00
idau.h Use DECLARE_*CHECKER* macros 2020-09-09 09:27:09 -04:00
internals.h target/arm: Refactor handling of timer offset for direct register accesses 2025-03-18 09:02:48 +03:00
Kconfig kconfig: express dependency of individual boards on libfdt 2024-05-10 15:45:15 +02:00
kvm-consts.h exec: Rename NEED_CPU_H -> COMPILING_PER_TARGET 2024-04-26 09:49:51 +02:00
kvm-stub.c target/arm: Avoid bare abort() or assert(0) 2022-05-05 09:35:51 +01:00
kvm.c target/arm: kvm: require KVM_CAP_DEVICE_CTRL 2024-10-29 15:04:47 +00:00
kvm_arm.h target/arm: kvm: require KVM_CAP_DEVICE_CTRL 2024-10-29 15:04:47 +00:00
machine.c target/arm: Rename FPSR_MASK and FPCR_MASK and define them symbolically 2024-07-11 11:41:33 +01:00
meson.build target/arm: Move v7m-related code from cpu32.c into a separate file 2024-03-08 14:45:03 +00:00
multiprocessing.h target/arm: Expose arm_cpu_mp_affinity() in 'multiprocessing.h' header 2024-01-26 11:30:48 +00:00
op_addsub.h Move target-* CPU file into a target/ folder 2016-12-20 21:52:12 +01:00
ptw.c arm/ptw: Honour WXN/UWXN and SIF in short-format descriptors 2024-11-19 13:02:06 +00:00
syndrome.h target/arm: fix exception syndrome for AArch32 bkpt insn 2024-02-02 13:51:57 +00:00
tcg-stubs.c target/arm: Move hflags code into the tcg directory 2023-02-27 13:27:04 +00:00
trace-events target/arm: Implement FEAT_ECV CNTPOFF_EL2 handling 2024-03-07 12:19:03 +00:00
trace.h trace: switch position of headers to what Meson requires 2020-08-21 06:18:24 -04:00
vfp_helper.c target/arm: Store FPSR cumulative exception bits in env->vfp.fpsr 2024-10-29 15:04:46 +00:00