aboutsummaryrefslogtreecommitdiff
path: root/accel/tcg/translate-all.c
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2022-11-01 09:36:13 -0400
committerStefan Hajnoczi <stefanha@redhat.com>2022-11-01 09:36:13 -0400
commit18cd31ff30883707408c7d6d952310189903939e (patch)
treecf0d18ede8d3bd6d0cf1fe38f4a2ab997df77b6b /accel/tcg/translate-all.c
parent7ef1d48763d6c6e90d1a4e1dc04b1125e77c2aee (diff)
parent83d92559cdf0ce842e52e5bbf230f7f62a6206aa (diff)
Merge tag 'pull-tcg-20221031-2' of https://gitlab.com/rth7680/qemu into staging
Remove sparc32plus support from tcg/sparc. target/i386: Use cpu_unwind_state_data for tpr access. target/i386: Expand eflags updates inline Complete cpu initialization before registration # -----BEGIN PGP SIGNATURE----- # # iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmNgQvIdHHJpY2hhcmQu # aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV9bxAf/X6904X+2I55LTMP7 # jLCxMAlSgFiwaWW4sQLvfUS2qjjMNw7dtljF0HaYVJCawABI4tIY3nEYL8dhLiGU # WpMTmDIY/cBrQ0aMWfUTGRIFZOIpCLsZwiG6zW6w5KxfKUaakeZSgxqhzgFFcM2k # UDb9HYC6jwEDDZJYTRpcTIsnYHjaiu/ofKjbjWoslq9DIrThLr1UZgoOxzZ9w2Rh # xEDBNnD42Kzb0Lbc5B1cX4tla43g9KfHkfG6Ww3fJVYZcFxFhAp40y1chtq5qaia # 64cPOfSdjoHWaZKdXop3hDYvqRTour56S+e1n1VxHVhbsVRh0KKYBvzAZtiN4FEu # w8E8bA== # =fxqA # -----END PGP SIGNATURE----- # gpg: Signature made Mon 31 Oct 2022 17:49:38 EDT # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full] # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * tag 'pull-tcg-20221031-2' of https://gitlab.com/rth7680/qemu: tests/tcg/multiarch: Add munmap-pthread.c accel/tcg: Complete cpu initialization before registration target/i386: Expand eflags updates inline accel/tcg: Remove reset_icount argument from cpu_restore_state_from_tb accel/tcg: Remove will_exit argument from cpu_restore_state target/openrisc: Use cpu_unwind_state_data for mfspr target/openrisc: Always exit after mtspr npc target/i386: Use cpu_unwind_state_data for tpr access accel/tcg: Introduce cpu_unwind_state_data tcg/tci: fix logic error when registering helpers via FFI tcg/sparc64: Remove sparc32plus constraints tcg/sparc64: Rename from tcg/sparc tcg/sparc: Remove support for sparc32plus Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'accel/tcg/translate-all.c')
-rw-r--r--accel/tcg/translate-all.c107
1 files changed, 60 insertions, 47 deletions
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index f185356a36..921944a5ab 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -247,52 +247,65 @@ static int encode_search(TranslationBlock *tb, uint8_t *block)
return p - block;
}
-/* The cpu state corresponding to 'searched_pc' is restored.
- * When reset_icount is true, current TB will be interrupted and
- * icount should be recalculated.
- */
-int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
- uintptr_t searched_pc, bool reset_icount)
+static int cpu_unwind_data_from_tb(TranslationBlock *tb, uintptr_t host_pc,
+ uint64_t *data)
{
- uint64_t data[TARGET_INSN_START_WORDS];
- uintptr_t host_pc = (uintptr_t)tb->tc.ptr;
+ uintptr_t iter_pc = (uintptr_t)tb->tc.ptr;
const uint8_t *p = tb->tc.ptr + tb->tc.size;
int i, j, num_insns = tb->icount;
-#ifdef CONFIG_PROFILER
- TCGProfile *prof = &tcg_ctx->prof;
- int64_t ti = profile_getclock();
-#endif
- searched_pc -= GETPC_ADJ;
+ host_pc -= GETPC_ADJ;
- if (searched_pc < host_pc) {
+ if (host_pc < iter_pc) {
return -1;
}
- memset(data, 0, sizeof(data));
+ memset(data, 0, sizeof(uint64_t) * TARGET_INSN_START_WORDS);
if (!TARGET_TB_PCREL) {
data[0] = tb_pc(tb);
}
- /* Reconstruct the stored insn data while looking for the point at
- which the end of the insn exceeds the searched_pc. */
+ /*
+ * Reconstruct the stored insn data while looking for the point
+ * at which the end of the insn exceeds host_pc.
+ */
for (i = 0; i < num_insns; ++i) {
for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
data[j] += decode_sleb128(&p);
}
- host_pc += decode_sleb128(&p);
- if (host_pc > searched_pc) {
- goto found;
+ iter_pc += decode_sleb128(&p);
+ if (iter_pc > host_pc) {
+ return num_insns - i;
}
}
return -1;
+}
+
+/*
+ * The cpu state corresponding to 'host_pc' is restored in
+ * preparation for exiting the TB.
+ */
+void cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
+ uintptr_t host_pc)
+{
+ uint64_t data[TARGET_INSN_START_WORDS];
+#ifdef CONFIG_PROFILER
+ TCGProfile *prof = &tcg_ctx->prof;
+ int64_t ti = profile_getclock();
+#endif
+ int insns_left = cpu_unwind_data_from_tb(tb, host_pc, data);
+
+ if (insns_left < 0) {
+ return;
+ }
- found:
- if (reset_icount && (tb_cflags(tb) & CF_USE_ICOUNT)) {
+ if (tb_cflags(tb) & CF_USE_ICOUNT) {
assert(icount_enabled());
- /* Reset the cycle counter to the start of the block
- and shift if to the number of actually executed instructions */
- cpu_neg(cpu)->icount_decr.u16.low += num_insns - i;
+ /*
+ * Reset the cycle counter to the start of the block and
+ * shift if to the number of actually executed instructions.
+ */
+ cpu_neg(cpu)->icount_decr.u16.low += insns_left;
}
cpu->cc->tcg_ops->restore_state_to_opc(cpu, tb, data);
@@ -302,20 +315,11 @@ int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
prof->restore_time + profile_getclock() - ti);
qatomic_set(&prof->restore_count, prof->restore_count + 1);
#endif
- return 0;
}
-bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit)
+bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc)
{
/*
- * The pc update associated with restore without exit will
- * break the relative pc adjustments performed by TARGET_TB_PCREL.
- */
- if (TARGET_TB_PCREL) {
- assert(will_exit);
- }
-
- /*
* The host_pc has to be in the rx region of the code buffer.
* If it is not we will not be able to resolve it here.
* The two cases where host_pc will not be correct are:
@@ -328,13 +332,24 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit)
if (in_code_gen_buffer((const void *)(host_pc - tcg_splitwx_diff))) {
TranslationBlock *tb = tcg_tb_lookup(host_pc);
if (tb) {
- cpu_restore_state_from_tb(cpu, tb, host_pc, will_exit);
+ cpu_restore_state_from_tb(cpu, tb, host_pc);
return true;
}
}
return false;
}
+bool cpu_unwind_state_data(CPUState *cpu, uintptr_t host_pc, uint64_t *data)
+{
+ if (in_code_gen_buffer((const void *)(host_pc - tcg_splitwx_diff))) {
+ TranslationBlock *tb = tcg_tb_lookup(host_pc);
+ if (tb) {
+ return cpu_unwind_data_from_tb(tb, host_pc, data) >= 0;
+ }
+ }
+ return false;
+}
+
void page_init(void)
{
page_size_init();
@@ -1016,7 +1031,7 @@ void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr)
tb = tcg_tb_lookup(retaddr);
if (tb) {
/* We can use retranslation to find the PC. */
- cpu_restore_state_from_tb(cpu, tb, retaddr, true);
+ cpu_restore_state_from_tb(cpu, tb, retaddr);
tb_phys_invalidate(tb, -1);
} else {
/* The exception probably happened in a helper. The CPU state should
@@ -1052,7 +1067,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
cpu_abort(cpu, "cpu_io_recompile: could not find TB for pc=%p",
(void *)retaddr);
}
- cpu_restore_state_from_tb(cpu, tb, retaddr, true);
+ cpu_restore_state_from_tb(cpu, tb, retaddr);
/*
* Some guests must re-execute the branch when re-executing a delay
@@ -1565,15 +1580,13 @@ void tcg_flush_jmp_cache(CPUState *cpu)
{
CPUJumpCache *jc = cpu->tb_jmp_cache;
- if (likely(jc)) {
- for (int i = 0; i < TB_JMP_CACHE_SIZE; i++) {
- qatomic_set(&jc->array[i].tb, NULL);
- }
- } else {
- /* This should happen once during realize, and thus never race. */
- jc = g_new0(CPUJumpCache, 1);
- jc = qatomic_xchg(&cpu->tb_jmp_cache, jc);
- assert(jc == NULL);
+ /* During early initialization, the cache may not yet be allocated. */
+ if (unlikely(jc == NULL)) {
+ return;
+ }
+
+ for (int i = 0; i < TB_JMP_CACHE_SIZE; i++) {
+ qatomic_set(&jc->array[i].tb, NULL);
}
}