Skip to content

Commit 5313b1a

Browse files
iii-irth7680
authored andcommitted
accel/tcg: Call tcg_tb_insert() for one-insn TBs
Currently one-insn TBs created from I/O memory are not added to region_trees. Therefore, when they generate exceptions, they are not handled by cpu_restore_state_from_tb(). For x86 this is not a problem, because x86_restore_state_to_opc() only restores pc and cc, which already have the correct values if the first TB instruction causes an exception. However, on several other architectures, restore_state_to_opc() is not stricly limited to state restoration and affects some exception-related registers, where guests can notice incorrect values, for example: - arm's exception.syndrome; - hppa's unwind_breg; - riscv's excp_uw2; - s390x's int_pgm_ilen. Fix by always calling tcg_tb_insert(). This may increase the size of region_trees, but tcg_region_reset_all() clears it once code_gen_buffer fills up, so it will not grow uncontrollably. Do not call tb_link_page(), which would add such TBs to the QHT, to prevent tb_lookup() from finding them. These TBs are single-use, since subsequent reads from I/O memory may return different values; they are not removed from code_gen_buffer only in order to keep things simple. Co-developed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-ID: <20250116213214.5695-2-iii@linux.ibm.com>
1 parent d3203d5 commit 5313b1a

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

accel/tcg/translate-all.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -531,23 +531,32 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
531531
tb_reset_jump(tb, 1);
532532
}
533533

534+
/*
535+
* Insert TB into the corresponding region tree before publishing it
536+
* through QHT. Otherwise rewinding happened in the TB might fail to
537+
* lookup itself using host PC.
538+
*/
539+
tcg_tb_insert(tb);
540+
534541
/*
535542
* If the TB is not associated with a physical RAM page then it must be
536-
* a temporary one-insn TB, and we have nothing left to do. Return early
537-
* before attempting to link to other TBs or add to the lookup table.
543+
* a temporary one-insn TB.
544+
*
545+
* Such TBs must be added to region trees in order to make sure that
546+
* restore_state_to_opc() - which on some architectures is not limited to
547+
* rewinding, but also affects exception handling! - is called when such a
548+
* TB causes an exception.
549+
*
550+
* At the same time, temporary one-insn TBs must be executed at most once,
551+
* because subsequent reads from, e.g., I/O memory may return different
552+
* values. So return early before attempting to link to other TBs or add
553+
* to the QHT.
538554
*/
539555
if (tb_page_addr0(tb) == -1) {
540556
assert_no_pages_locked();
541557
return tb;
542558
}
543559

544-
/*
545-
* Insert TB into the corresponding region tree before publishing it
546-
* through QHT. Otherwise rewinding happened in the TB might fail to
547-
* lookup itself using host PC.
548-
*/
549-
tcg_tb_insert(tb);
550-
551560
/*
552561
* No explicit memory barrier is required -- tb_link_page() makes the
553562
* TB visible in a consistent state.

0 commit comments

Comments
 (0)