public inbox for qemu-devel@nongnu.org
 help / color / mirror / Atom feed
From: Pierrick Bouvier <pierrick.bouvier@linaro.org>
To: Richard Henderson <richard.henderson@linaro.org>, qemu-devel@nongnu.org
Subject: Re: [PATCH for-11.0] tcg: Pass host-endian values to plugin_gen_mem_callbacks_*
Date: Tue, 24 Mar 2026 18:39:14 -0700	[thread overview]
Message-ID: <456faa09-4889-43e2-a35a-449888f9249e@linaro.org> (raw)
In-Reply-To: <20260325004052.1026892-1-richard.henderson@linaro.org>

Hi Richard,

On 3/24/26 5:40 PM, Richard Henderson wrote:
> If the host does not support swapped-endian loads and stores,
> then we emulate those within the tcg expanders with explicit
> bswap operations.
> 
> However, we were passing values to the plugin interface in
> the middle of those bswap operations, which meant that we
> would pass values of the wrong endianness to plugins when
> running on hosts without swapped-endian loads and stores.
> 
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3351
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> 
> Hi Pierrick,
> 
> On IRC I expressed the opinion that there was an additional
> big-endian bug with how we treat neg.plugin_mem_value_low,
> but I now see that isn't true, because of how we adjust the
> store address in plugin_gen_mem_callbacks_i32.
>

Yes, we store the value directly swapped, so there is no further 
transformation needed.

> 
> r~
> ---
>   tcg/tcg-op-ldst.c | 52 ++++++++++++++++++++++++-----------------------
>   1 file changed, 27 insertions(+), 25 deletions(-)
> 
> diff --git a/tcg/tcg-op-ldst.c b/tcg/tcg-op-ldst.c
> index 354d9968f9..22211ccb45 100644
> --- a/tcg/tcg-op-ldst.c
> +++ b/tcg/tcg-op-ldst.c
> @@ -262,9 +262,6 @@ static void tcg_gen_qemu_ld_i32_int(TCGv_i32 val, TCGTemp *addr,
>       addr_new = tci_extend_addr(addr);
>       copy_addr = plugin_maybe_preserve_addr(addr);
>       gen_ldst1(INDEX_op_qemu_ld, TCG_TYPE_I32, tcgv_i32_temp(val), addr_new, oi);
> -    plugin_gen_mem_callbacks_i32(val, copy_addr, addr, orig_oi,
> -                                 QEMU_PLUGIN_MEM_R);
> -    maybe_free_addr(addr, addr_new);
>   
>       if ((orig_memop ^ memop) & MO_BSWAP) {
>           switch (orig_memop & MO_SIZE) {
> @@ -280,6 +277,10 @@ static void tcg_gen_qemu_ld_i32_int(TCGv_i32 val, TCGTemp *addr,
>               g_assert_not_reached();
>           }
>       }
> +
> +    plugin_gen_mem_callbacks_i32(val, copy_addr, addr, orig_oi,
> +                                 QEMU_PLUGIN_MEM_R);
> +    maybe_free_addr(addr, addr_new);
>   }
>   
>   void tcg_gen_qemu_ld_i32_chk(TCGv_i32 val, TCGTemp *addr, TCGArg idx,
> @@ -290,10 +291,10 @@ void tcg_gen_qemu_ld_i32_chk(TCGv_i32 val, TCGTemp *addr, TCGArg idx,
>       tcg_gen_qemu_ld_i32_int(val, addr, idx, memop);
>   }
>   
> -static void tcg_gen_qemu_st_i32_int(TCGv_i32 val, TCGTemp *addr,
> +static void tcg_gen_qemu_st_i32_int(TCGv_i32 orig_val, TCGTemp *addr,
>                                       TCGArg idx, MemOp memop)
>   {
> -    TCGv_i32 swap = NULL;
> +    TCGv_i32 val = orig_val;
>       MemOpIdx orig_oi, oi;
>       TCGTemp *addr_new;
>   
> @@ -302,29 +303,29 @@ static void tcg_gen_qemu_st_i32_int(TCGv_i32 val, TCGTemp *addr,
>       orig_oi = oi = make_memop_idx(memop, idx);
>   
>       if ((memop & MO_BSWAP) && !tcg_target_has_memory_bswap(memop)) {
> -        swap = tcg_temp_ebb_new_i32();
> +        val = tcg_temp_ebb_new_i32();
>           switch (memop & MO_SIZE) {
>           case MO_16:
> -            tcg_gen_bswap16_i32(swap, val, 0);
> +            tcg_gen_bswap16_i32(val, orig_val, 0);
>               break;
>           case MO_32:
> -            tcg_gen_bswap32_i32(swap, val);
> +            tcg_gen_bswap32_i32(val, orig_val);
>               break;
>           default:
>               g_assert_not_reached();
>           }
> -        val = swap;
>           memop &= ~MO_BSWAP;
>           oi = make_memop_idx(memop, idx);
>       }
>   
>       addr_new = tci_extend_addr(addr);
>       gen_ldst1(INDEX_op_qemu_st, TCG_TYPE_I32, tcgv_i32_temp(val), addr_new, oi);
> -    plugin_gen_mem_callbacks_i32(val, NULL, addr, orig_oi, QEMU_PLUGIN_MEM_W);
> +    plugin_gen_mem_callbacks_i32(orig_val, NULL, addr, orig_oi,
> +                                 QEMU_PLUGIN_MEM_W);

It works, but it is still not clear to me why the value orig_val (which 
is not swapped and in target-endian order) gets stored swapped correctly 
in neg.plugin_mem_value_low.

I would expect it to be in target-endian order, since 
plugin_gen_mem_callbacks_i32 uses tcg_gen_st_i32(val, env, ... 
neg.plugin_mem_value_low) which does not perform any swap.

>       maybe_free_addr(addr, addr_new);
>   
> -    if (swap) {
> -        tcg_temp_free_i32(swap);
> +    if (val != orig_val) {
> +        tcg_temp_free_i32(val);
>       }
>   }
>   
> @@ -360,9 +361,6 @@ static void tcg_gen_qemu_ld_i64_int(TCGv_i64 val, TCGTemp *addr,
>       addr_new = tci_extend_addr(addr);
>       copy_addr = plugin_maybe_preserve_addr(addr);
>       gen_ld_i64(val, addr_new, oi);
> -    plugin_gen_mem_callbacks_i64(val, copy_addr, addr, orig_oi,
> -                                 QEMU_PLUGIN_MEM_R);
> -    maybe_free_addr(addr, addr_new);
>   
>       if ((orig_memop ^ memop) & MO_BSWAP) {
>           int flags = (orig_memop & MO_SIGN
> @@ -382,6 +380,10 @@ static void tcg_gen_qemu_ld_i64_int(TCGv_i64 val, TCGTemp *addr,
>               g_assert_not_reached();
>           }
>       }
> +
> +    plugin_gen_mem_callbacks_i64(val, copy_addr, addr, orig_oi,
> +                                 QEMU_PLUGIN_MEM_R);
> +    maybe_free_addr(addr, addr_new);
>   }
>   
>   void tcg_gen_qemu_ld_i64_chk(TCGv_i64 val, TCGTemp *addr, TCGArg idx,
> @@ -392,10 +394,10 @@ void tcg_gen_qemu_ld_i64_chk(TCGv_i64 val, TCGTemp *addr, TCGArg idx,
>       tcg_gen_qemu_ld_i64_int(val, addr, idx, memop);
>   }
>   
> -static void tcg_gen_qemu_st_i64_int(TCGv_i64 val, TCGTemp *addr,
> +static void tcg_gen_qemu_st_i64_int(TCGv_i64 orig_val, TCGTemp *addr,
>                                       TCGArg idx, MemOp memop)
>   {
> -    TCGv_i64 swap = NULL;
> +    TCGv_i64 val = orig_val;
>       MemOpIdx orig_oi, oi;
>       TCGTemp *addr_new;
>   
> @@ -404,32 +406,32 @@ static void tcg_gen_qemu_st_i64_int(TCGv_i64 val, TCGTemp *addr,
>       orig_oi = oi = make_memop_idx(memop, idx);
>   
>       if ((memop & MO_BSWAP) && !tcg_target_has_memory_bswap(memop)) {
> -        swap = tcg_temp_ebb_new_i64();
> +        val = tcg_temp_ebb_new_i64();
>           switch (memop & MO_SIZE) {
>           case MO_16:
> -            tcg_gen_bswap16_i64(swap, val, 0);
> +            tcg_gen_bswap16_i64(val, orig_val, 0);
>               break;
>           case MO_32:
> -            tcg_gen_bswap32_i64(swap, val, 0);
> +            tcg_gen_bswap32_i64(val, orig_val, 0);
>               break;
>           case MO_64:
> -            tcg_gen_bswap64_i64(swap, val);
> +            tcg_gen_bswap64_i64(val, orig_val);
>               break;
>           default:
>               g_assert_not_reached();
>           }
> -        val = swap;
>           memop &= ~MO_BSWAP;
>           oi = make_memop_idx(memop, idx);
>       }
>   
>       addr_new = tci_extend_addr(addr);
>       gen_st_i64(val, addr_new, oi);
> -    plugin_gen_mem_callbacks_i64(val, NULL, addr, orig_oi, QEMU_PLUGIN_MEM_W);
> +    plugin_gen_mem_callbacks_i64(orig_val, NULL, addr, orig_oi,
> +                                 QEMU_PLUGIN_MEM_W);
>       maybe_free_addr(addr, addr_new);
>   
> -    if (swap) {
> -        tcg_temp_free_i64(swap);
> +    if (val != orig_val) {
> +        tcg_temp_free_i64(val);
>       }
>   }
>   

This solves the problem, thanks!

I'll probably add another patch to document that better in plugin api, 
and remove the additional swapping done in tests/tcg/plugins/mem.c.

Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Tested-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>

Thanks for the patch,
Pierrick


  reply	other threads:[~2026-03-25  1:39 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-25  0:40 [PATCH for-11.0] tcg: Pass host-endian values to plugin_gen_mem_callbacks_* Richard Henderson
2026-03-25  1:39 ` Pierrick Bouvier [this message]
2026-03-25  4:59   ` Richard Henderson
2026-03-25 15:15     ` Pierrick Bouvier
2026-03-25  2:45 ` Pierrick Bouvier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=456faa09-4889-43e2-a35a-449888f9249e@linaro.org \
    --to=pierrick.bouvier@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox