accel/tcg: create a thread-kick function for TCG

Round-robin TCG is calling into cpu_exit() directly.  In preparation
for making cpu_exit() usable from all accelerators, define a generic
thread-kick function for TCG which is used directly in the multi-threaded
case, and through CPU_FOREACH in the round-robin case.

Use it also for user-mode emulation, and take the occasion to move
the implementation to accel/tcg/user-exec.c.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2025-08-11 08:28:31 +02:00
parent f084ff128b
commit 9cf342b491
10 changed files with 16 additions and 21 deletions

View file

@ -40,6 +40,7 @@
#include "exec/replay-core.h"
#include "system/tcg.h"
#include "exec/helper-proto-common.h"
#include "tcg-accel-ops.h"
#include "tb-jmp-cache.h"
#include "tb-hash.h"
#include "tb-context.h"
@ -748,6 +749,11 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
return false;
}
void tcg_kick_vcpu_thread(CPUState *cpu)
{
cpu_exit(cpu);
}
static inline bool icount_exit_request(CPUState *cpu)
{
if (!icount_enabled()) {

View file

@ -123,11 +123,6 @@ static void *mttcg_cpu_thread_fn(void *arg)
return NULL;
}
void mttcg_kick_vcpu_thread(CPUState *cpu)
{
cpu_exit(cpu);
}
void mttcg_start_vcpu_thread(CPUState *cpu)
{
char thread_name[VCPU_THREAD_NAME_SIZE];

View file

@ -10,9 +10,6 @@
#ifndef TCG_ACCEL_OPS_MTTCG_H
#define TCG_ACCEL_OPS_MTTCG_H
/* kick MTTCG vCPU thread */
void mttcg_kick_vcpu_thread(CPUState *cpu);
/* start an mttcg vCPU thread */
void mttcg_start_vcpu_thread(CPUState *cpu);

View file

@ -43,7 +43,7 @@ void rr_kick_vcpu_thread(CPUState *unused)
CPUState *cpu;
CPU_FOREACH(cpu) {
cpu_exit(cpu);
tcg_kick_vcpu_thread(cpu);
};
}

View file

@ -206,7 +206,7 @@ static void tcg_accel_ops_init(AccelClass *ac)
if (qemu_tcg_mttcg_enabled()) {
ops->create_vcpu_thread = mttcg_start_vcpu_thread;
ops->kick_vcpu_thread = mttcg_kick_vcpu_thread;
ops->kick_vcpu_thread = tcg_kick_vcpu_thread;
ops->handle_interrupt = tcg_handle_interrupt;
} else {
ops->create_vcpu_thread = rr_start_vcpu_thread;

View file

@ -18,5 +18,6 @@ void tcg_cpu_destroy(CPUState *cpu);
int tcg_cpu_exec(CPUState *cpu);
void tcg_handle_interrupt(CPUState *cpu, int mask);
void tcg_cpu_init_cflags(CPUState *cpu, bool parallel);
void tcg_kick_vcpu_thread(CPUState *cpu);
#endif /* TCG_ACCEL_OPS_H */

View file

@ -38,6 +38,7 @@
#include "qemu/int128.h"
#include "trace.h"
#include "tcg/tcg-ldst.h"
#include "tcg-accel-ops.h"
#include "backend-ldst.h"
#include "internal-common.h"
#include "tb-internal.h"
@ -46,6 +47,11 @@ __thread uintptr_t helper_retaddr;
//#define DEBUG_SIGNAL
void qemu_cpu_kick(CPUState *cpu)
{
tcg_kick_vcpu_thread(cpu);
}
/*
* Adjust the pc to pass to cpu_restore_state; return the memop type.
*/

View file

@ -214,11 +214,6 @@ bool qemu_cpu_is_self(CPUState *cpu)
return thread_cpu == cpu;
}
void qemu_cpu_kick(CPUState *cpu)
{
cpu_exit(cpu);
}
/* Assumes contents are already zeroed. */
static void init_task_state(TaskState *ts)
{

View file

@ -37,7 +37,7 @@ translator starts by allocating a budget of instructions to be
executed. The budget of instructions is limited by how long it will be
until the next timer will expire. We store this budget as part of a
vCPU icount_decr field which shared with the machinery for handling
cpu_exit(). The whole field is checked at the start of every
qemu_cpu_kick(). The whole field is checked at the start of every
translated block and will cause a return to the outer loop to deal
with whatever caused the exit.

View file

@ -189,11 +189,6 @@ bool qemu_cpu_is_self(CPUState *cpu)
return thread_cpu == cpu;
}
void qemu_cpu_kick(CPUState *cpu)
{
cpu_exit(cpu);
}
void task_settid(TaskState *ts)
{
if (ts->ts_tid == 0) {