qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] target/arm: Don't assert() for ISB/SB inside IT block
@ 2025-05-01 12:55 Peter Maydell
  2025-05-01 14:24 ` Richard Henderson
  2025-05-08  7:31 ` Michael Tokarev
  0 siblings, 2 replies; 4+ messages in thread
From: Peter Maydell @ 2025-05-01 12:55 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: qemu-stable

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>
---
 target/arm/tcg/translate.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index 88df9c482ab..e773ab72685 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -7760,7 +7760,8 @@ static bool arm_check_ss_active(DisasContext *dc)
 
 static void arm_post_translate_insn(DisasContext *dc)
 {
-    if (dc->condjmp && dc->base.is_jmp == DISAS_NEXT) {
+    if (dc->condjmp &&
+        (dc->base.is_jmp == DISAS_NEXT || dc->base.is_jmp == DISAS_TOO_MANY)) {
         if (dc->pc_save != dc->condlabel.pc_save) {
             gen_update_pc(dc, dc->condlabel.pc_save - dc->pc_save);
         }
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] target/arm: Don't assert() for ISB/SB inside IT block
  2025-05-01 12:55 [PATCH] target/arm: Don't assert() for ISB/SB inside IT block Peter Maydell
@ 2025-05-01 14:24 ` Richard Henderson
  2025-05-08  7:31 ` Michael Tokarev
  1 sibling, 0 replies; 4+ messages in thread
From: Richard Henderson @ 2025-05-01 14:24 UTC (permalink / raw)
  To: qemu-devel

On 5/1/25 05:55, Peter Maydell wrote:
> (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.)

Heh.  For some reason I only fold unconditional branch-to-next.
I'll fix this.  Anyway,

> 
> Cc: qemu-stable@nongnu.org
> Fixes: https://gitlab.com/qemu-project/qemu/-/issues/2942
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>   target/arm/tcg/translate.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
> index 88df9c482ab..e773ab72685 100644
> --- a/target/arm/tcg/translate.c
> +++ b/target/arm/tcg/translate.c
> @@ -7760,7 +7760,8 @@ static bool arm_check_ss_active(DisasContext *dc)
>   
>   static void arm_post_translate_insn(DisasContext *dc)
>   {
> -    if (dc->condjmp && dc->base.is_jmp == DISAS_NEXT) {
> +    if (dc->condjmp &&
> +        (dc->base.is_jmp == DISAS_NEXT || dc->base.is_jmp == DISAS_TOO_MANY)) {
>           if (dc->pc_save != dc->condlabel.pc_save) {
>               gen_update_pc(dc, dc->condlabel.pc_save - dc->pc_save);
>           }

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] target/arm: Don't assert() for ISB/SB inside IT block
  2025-05-01 12:55 [PATCH] target/arm: Don't assert() for ISB/SB inside IT block Peter Maydell
  2025-05-01 14:24 ` Richard Henderson
@ 2025-05-08  7:31 ` Michael Tokarev
  2025-05-08 10:18   ` Peter Maydell
  1 sibling, 1 reply; 4+ messages in thread
From: Michael Tokarev @ 2025-05-08  7:31 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: qemu-stable

On 01.05.2025 15:55, Peter Maydell wrote:
> 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

Hi!

Is this change applicable for older stable releases, besides 10.0
(currently 9.2 and 7.2)?  It applies cleanly but I wonder if it is
actually needed..

Thanks,

/mjt


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] target/arm: Don't assert() for ISB/SB inside IT block
  2025-05-08  7:31 ` Michael Tokarev
@ 2025-05-08 10:18   ` Peter Maydell
  0 siblings, 0 replies; 4+ messages in thread
From: Peter Maydell @ 2025-05-08 10:18 UTC (permalink / raw)
  To: Michael Tokarev; +Cc: qemu-arm, qemu-devel, qemu-stable

On Thu, 8 May 2025 at 08:31, Michael Tokarev <mjt@tls.msk.ru> wrote:
>
> On 01.05.2025 15:55, Peter Maydell wrote:
> > If the guest code has an ISB or SB insn inside an IT block, we
> > generate incorrect code which trips a TCG assertion:

> Is this change applicable for older stable releases, besides 10.0
> (currently 9.2 and 7.2)?  It applies cleanly but I wonder if it is
> actually needed..

I think any branch with commit 73fce314dbbf2d ("target/arm: Use
DISAS_TOO_MANY for ISB and SB") needs the fix. That would
include both 9.2 and 7.2, unless I got my git rune wrong.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-05-08 10:19 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-01 12:55 [PATCH] target/arm: Don't assert() for ISB/SB inside IT block Peter Maydell
2025-05-01 14:24 ` Richard Henderson
2025-05-08  7:31 ` Michael Tokarev
2025-05-08 10:18   ` Peter Maydell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).