accel/tcg: Return TCGTBCPUState from cpu_get_tb_cpu_state

Combine 3 different pointer returns into one structure return.

Include a cflags field in TCGTBCPUState, not filled in by
cpu_get_tb_cpu_state, but used by all callers.  This fills
a hole in the structure and is useful in some subroutines.

Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2025-04-27 15:32:11 -07:00
parent 5b1c93be57
commit 4759aae432
23 changed files with 218 additions and 176 deletions

View file

@ -385,9 +385,6 @@ const void *HELPER(lookup_tb_ptr)(CPUArchState *env)
{
CPUState *cpu = env_cpu(env);
TranslationBlock *tb;
vaddr pc;
uint64_t cs_base;
uint32_t flags, cflags;
/*
* By definition we've just finished a TB, so I/O is OK.
@ -397,20 +394,21 @@ const void *HELPER(lookup_tb_ptr)(CPUArchState *env)
* The next TB, if we chain to it, will clear the flag again.
*/
cpu->neg.can_do_io = true;
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
cflags = curr_cflags(cpu);
if (check_for_breakpoints(cpu, pc, &cflags)) {
TCGTBCPUState s = cpu_get_tb_cpu_state(cpu);
s.cflags = curr_cflags(cpu);
if (check_for_breakpoints(cpu, s.pc, &s.cflags)) {
cpu_loop_exit(cpu);
}
tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
tb = tb_lookup(cpu, s.pc, s.cs_base, s.flags, s.cflags);
if (tb == NULL) {
return tcg_code_gen_epilogue;
}
if (qemu_loglevel_mask(CPU_LOG_TB_CPU | CPU_LOG_EXEC)) {
log_cpu_exec(pc, cpu, tb);
log_cpu_exec(s.pc, cpu, tb);
}
return tb->tc.ptr;
@ -560,11 +558,7 @@ static void cpu_exec_longjmp_cleanup(CPUState *cpu)
void cpu_exec_step_atomic(CPUState *cpu)
{
CPUArchState *env = cpu_env(cpu);
TranslationBlock *tb;
vaddr pc;
uint64_t cs_base;
uint32_t flags, cflags;
int tb_exit;
if (sigsetjmp(cpu->jmp_env, 0) == 0) {
@ -573,13 +567,13 @@ void cpu_exec_step_atomic(CPUState *cpu)
g_assert(!cpu->running);
cpu->running = true;
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
TCGTBCPUState s = cpu_get_tb_cpu_state(cpu);
s.cflags = curr_cflags(cpu);
cflags = curr_cflags(cpu);
/* Execute in a serial context. */
cflags &= ~CF_PARALLEL;
s.cflags &= ~CF_PARALLEL;
/* After 1 insn, return and release the exclusive lock. */
cflags |= CF_NO_GOTO_TB | CF_NO_GOTO_PTR | 1;
s.cflags |= CF_NO_GOTO_TB | CF_NO_GOTO_PTR | 1;
/*
* No need to check_for_breakpoints here.
* We only arrive in cpu_exec_step_atomic after beginning execution
@ -587,16 +581,16 @@ void cpu_exec_step_atomic(CPUState *cpu)
* Any breakpoint for this insn will have been recognized earlier.
*/
tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
tb = tb_lookup(cpu, s.pc, s.cs_base, s.flags, s.cflags);
if (tb == NULL) {
mmap_lock();
tb = tb_gen_code(cpu, pc, cs_base, flags, cflags);
tb = tb_gen_code(cpu, s.pc, s.cs_base, s.flags, s.cflags);
mmap_unlock();
}
cpu_exec_enter(cpu);
/* execute the generated code */
trace_exec_tb(tb, pc);
trace_exec_tb(tb, s.pc);
cpu_tb_exec(cpu, tb, &tb_exit);
cpu_exec_exit(cpu);
} else {
@ -941,11 +935,8 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
while (!cpu_handle_interrupt(cpu, &last_tb)) {
TranslationBlock *tb;
vaddr pc;
uint64_t cs_base;
uint32_t flags, cflags;
cpu_get_tb_cpu_state(cpu_env(cpu), &pc, &cs_base, &flags);
TCGTBCPUState s = cpu_get_tb_cpu_state(cpu);
s.cflags = cpu->cflags_next_tb;
/*
* When requested, use an exact setting for cflags for the next
@ -954,33 +945,32 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
* have CF_INVALID set, -1 is a convenient invalid value that
* does not require tcg headers for cpu_common_reset.
*/
cflags = cpu->cflags_next_tb;
if (cflags == -1) {
cflags = curr_cflags(cpu);
if (s.cflags == -1) {
s.cflags = curr_cflags(cpu);
} else {
cpu->cflags_next_tb = -1;
}
if (check_for_breakpoints(cpu, pc, &cflags)) {
if (check_for_breakpoints(cpu, s.pc, &s.cflags)) {
break;
}
tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
tb = tb_lookup(cpu, s.pc, s.cs_base, s.flags, s.cflags);
if (tb == NULL) {
CPUJumpCache *jc;
uint32_t h;
mmap_lock();
tb = tb_gen_code(cpu, pc, cs_base, flags, cflags);
tb = tb_gen_code(cpu, s.pc, s.cs_base, s.flags, s.cflags);
mmap_unlock();
/*
* We add the TB in the virtual pc hash table
* for the fast lookup
*/
h = tb_jmp_cache_hash_func(pc);
h = tb_jmp_cache_hash_func(s.pc);
jc = cpu->tb_jmp_cache;
jc->array[h].pc = pc;
jc->array[h].pc = s.pc;
qatomic_set(&jc->array[h].tb, tb);
}
@ -1000,7 +990,7 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
tb_add_jump(last_tb, tb_exit, tb);
}
cpu_loop_exec_tb(cpu, tb, pc, &last_tb, &tb_exit);
cpu_loop_exec_tb(cpu, tb, s.pc, &last_tb, &tb_exit);
/* Try to align the host and virtual clocks
if the guest is in advance */

View file

@ -590,13 +590,9 @@ void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr)
/* The exception probably happened in a helper. The CPU state should
have been saved before calling it. Fetch the PC from there. */
CPUArchState *env = cpu_env(cpu);
vaddr pc;
uint64_t cs_base;
tb_page_addr_t addr;
uint32_t flags;
TCGTBCPUState s = cpu_get_tb_cpu_state(cpu);
tb_page_addr_t addr = get_page_addr_code(env, s.pc);
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
addr = get_page_addr_code(env, pc);
if (addr != -1) {
tb_invalidate_phys_range(cpu, addr, addr);
}