@samitouri / QOSamiQemu / commits / 539421a428

tcg: Pass host-endian values to plugin_gen_mem_callbacks_*

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> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Tested-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Link: https://lore.kernel.org/qemu-devel/20260325024252.3369186-2-pierrick.bouvier@linaro.org Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>

Richard Henderson committed Mar 24, 2026 at 19:42 UTC 539421a428fd4b8231d9be042143f2d09c719e2a
1 file changed +27 -25
tcg/tcg-op-ldst.c
+27 -25
@@ -262,9 +262,6 @@ static void tcg_gen_qemu_ld_i32_int(TCGv_i32 val, TCGTemp *addr,
262 addr_new = tci_extend_addr(addr);
263 copy_addr = plugin_maybe_preserve_addr(addr);
264 gen_ldst1(INDEX_op_qemu_ld, TCG_TYPE_I32, tcgv_i32_temp(val), addr_new, oi);
265 - plugin_gen_mem_callbacks_i32(val, copy_addr, addr, orig_oi,
266 - QEMU_PLUGIN_MEM_R);
267 - maybe_free_addr(addr, addr_new);
265
266 if ((orig_memop ^ memop) & MO_BSWAP) {
267 switch (orig_memop & MO_SIZE) {
@@ -280,6 +277,10 @@ static void tcg_gen_qemu_ld_i32_int(TCGv_i32 val, TCGTemp *addr,
277 g_assert_not_reached();
278 }
279 }
280 +
281 + plugin_gen_mem_callbacks_i32(val, copy_addr, addr, orig_oi,
282 + QEMU_PLUGIN_MEM_R);
283 + maybe_free_addr(addr, addr_new);
284 }
285
286 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,
291 tcg_gen_qemu_ld_i32_int(val, addr, idx, memop);
292 }
293
293 -static void tcg_gen_qemu_st_i32_int(TCGv_i32 val, TCGTemp *addr,
294 +static void tcg_gen_qemu_st_i32_int(TCGv_i32 orig_val, TCGTemp *addr,
295 TCGArg idx, MemOp memop)
296 {
296 - TCGv_i32 swap = NULL;
297 + TCGv_i32 val = orig_val;
298 MemOpIdx orig_oi, oi;
299 TCGTemp *addr_new;
300
@@ -302,29 +303,29 @@ static void tcg_gen_qemu_st_i32_int(TCGv_i32 val, TCGTemp *addr,
303 orig_oi = oi = make_memop_idx(memop, idx);
304
305 if ((memop & MO_BSWAP) && !tcg_target_has_memory_bswap(memop)) {
305 - swap = tcg_temp_ebb_new_i32();
306 + val = tcg_temp_ebb_new_i32();
307 switch (memop & MO_SIZE) {
308 case MO_16:
308 - tcg_gen_bswap16_i32(swap, val, 0);
309 + tcg_gen_bswap16_i32(val, orig_val, 0);
310 break;
311 case MO_32:
311 - tcg_gen_bswap32_i32(swap, val);
312 + tcg_gen_bswap32_i32(val, orig_val);
313 break;
314 default:
315 g_assert_not_reached();
316 }
316 - val = swap;
317 memop &= ~MO_BSWAP;
318 oi = make_memop_idx(memop, idx);
319 }
320
321 addr_new = tci_extend_addr(addr);
322 gen_ldst1(INDEX_op_qemu_st, TCG_TYPE_I32, tcgv_i32_temp(val), addr_new, oi);
323 - plugin_gen_mem_callbacks_i32(val, NULL, addr, orig_oi, QEMU_PLUGIN_MEM_W);
323 + plugin_gen_mem_callbacks_i32(orig_val, NULL, addr, orig_oi,
324 + QEMU_PLUGIN_MEM_W);
325 maybe_free_addr(addr, addr_new);
326
326 - if (swap) {
327 - tcg_temp_free_i32(swap);
327 + if (val != orig_val) {
328 + tcg_temp_free_i32(val);
329 }
330 }
331
@@ -360,9 +361,6 @@ static void tcg_gen_qemu_ld_i64_int(TCGv_i64 val, TCGTemp *addr,
361 addr_new = tci_extend_addr(addr);
362 copy_addr = plugin_maybe_preserve_addr(addr);
363 gen_ld_i64(val, addr_new, oi);
363 - plugin_gen_mem_callbacks_i64(val, copy_addr, addr, orig_oi,
364 - QEMU_PLUGIN_MEM_R);
365 - maybe_free_addr(addr, addr_new);
364
365 if ((orig_memop ^ memop) & MO_BSWAP) {
366 int flags = (orig_memop & MO_SIGN
@@ -382,6 +380,10 @@ static void tcg_gen_qemu_ld_i64_int(TCGv_i64 val, TCGTemp *addr,
380 g_assert_not_reached();
381 }
382 }
383 +
384 + plugin_gen_mem_callbacks_i64(val, copy_addr, addr, orig_oi,
385 + QEMU_PLUGIN_MEM_R);
386 + maybe_free_addr(addr, addr_new);
387 }
388
389 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,
394 tcg_gen_qemu_ld_i64_int(val, addr, idx, memop);
395 }
396
395 -static void tcg_gen_qemu_st_i64_int(TCGv_i64 val, TCGTemp *addr,
397 +static void tcg_gen_qemu_st_i64_int(TCGv_i64 orig_val, TCGTemp *addr,
398 TCGArg idx, MemOp memop)
399 {
398 - TCGv_i64 swap = NULL;
400 + TCGv_i64 val = orig_val;
401 MemOpIdx orig_oi, oi;
402 TCGTemp *addr_new;
403
@@ -404,32 +406,32 @@ static void tcg_gen_qemu_st_i64_int(TCGv_i64 val, TCGTemp *addr,
406 orig_oi = oi = make_memop_idx(memop, idx);
407
408 if ((memop & MO_BSWAP) && !tcg_target_has_memory_bswap(memop)) {
407 - swap = tcg_temp_ebb_new_i64();
409 + val = tcg_temp_ebb_new_i64();
410 switch (memop & MO_SIZE) {
411 case MO_16:
410 - tcg_gen_bswap16_i64(swap, val, 0);
412 + tcg_gen_bswap16_i64(val, orig_val, 0);
413 break;
414 case MO_32:
413 - tcg_gen_bswap32_i64(swap, val, 0);
415 + tcg_gen_bswap32_i64(val, orig_val, 0);
416 break;
417 case MO_64:
416 - tcg_gen_bswap64_i64(swap, val);
418 + tcg_gen_bswap64_i64(val, orig_val);
419 break;
420 default:
421 g_assert_not_reached();
422 }
421 - val = swap;
423 memop &= ~MO_BSWAP;
424 oi = make_memop_idx(memop, idx);
425 }
426
427 addr_new = tci_extend_addr(addr);
428 gen_st_i64(val, addr_new, oi);
428 - plugin_gen_mem_callbacks_i64(val, NULL, addr, orig_oi, QEMU_PLUGIN_MEM_W);
429 + plugin_gen_mem_callbacks_i64(orig_val, NULL, addr, orig_oi,
430 + QEMU_PLUGIN_MEM_W);
431 maybe_free_addr(addr, addr_new);
432
431 - if (swap) {
432 - tcg_temp_free_i64(swap);
433 + if (val != orig_val) {
434 + tcg_temp_free_i64(val);
435 }
436 }
437