]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
accel/tcg: create a thread-kick function for TCG
authorPaolo Bonzini <pbonzini@redhat.com>
Mon, 11 Aug 2025 06:28:31 +0000 (08:28 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 17 Sep 2025 17:00:55 +0000 (19:00 +0200)
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>
accel/tcg/cpu-exec.c
accel/tcg/tcg-accel-ops-mttcg.c
accel/tcg/tcg-accel-ops-mttcg.h
accel/tcg/tcg-accel-ops-rr.c
accel/tcg/tcg-accel-ops.c
accel/tcg/tcg-accel-ops.h
accel/tcg/user-exec.c
bsd-user/main.c
docs/devel/tcg-icount.rst
linux-user/main.c

index f838535d111faaeb58bdec4f0cb18dd9f8da89b0..9241bcadb5f1336ee4aa356fde2f766de7c3630c 100644 (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()) {
index b12b7a36b5df6487275a92a94d57aac3f946fa66..1148ebcaae5ef74c0314d222cf122880da738d30 100644 (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];
index 8ffa7a9a9fe0d23f0f166b595a967a9781086b44..5c145cc85955a79eb0907b2135f6aee7457ee513 100644 (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);
 
index d13e0d8b44dc1b85968402af53e20179342202fe..a1d75fd34194858fb3a812f2ea88e4ab8856c73a 100644 (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);
     };
 }
 
index 9c37266c1e046b1fb0699c6ea3b04e99a98a9273..1f662a9c7452bfe2316848c95911ed6c7bd4194f 100644 (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;
index 6feeb3f3e9b20f8f5bbde92b43e090fe30931234..aecce605d7b7a27101789158d9d6a5685665d3a9 100644 (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 */
index 66c25fba7dde6d52821c79de3f9267b0e66ee830..3c072fd868fb1dca3fddefe45c95e5b62b82e665 100644 (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.
  */
index 9ba69642f500d97cacc046857ced50561e95a594..73aae8c3274d94bbf9ed3ee5c0fed8db338f8bcc 100644 (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)
 {
index 7df883446a74f567727cf6e0157a88ca12862e73..a1dcd79e0fdd5142d6e876466e397cf8a25d6d89 100644 (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.
 
index 7b0ccb6fd6090fce840a4a725ee58ce9f8d81c84..4ddfc9a619cbbfab7b80fefd0e17985910571897 100644 (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) {