We want the ability to iterate over vCPUs of a specific accelerator. Introduce cpus_get_accel_cpus_queue() to be used by accelerator common code, and expose the get_cpus_queue() in AccelOpsClass, so each accelerator can register its own queue of vCPUs. Signed-off-by: Philippe Mathieu-Daudé <philmd@xxxxxxxxxx> --- include/hw/core/cpu.h | 8 ++++++++ include/system/accel-ops.h | 6 ++++++ accel/tcg/user-exec-stub.c | 5 +++++ cpu-common.c | 10 ++++++++++ system/cpus.c | 5 +++++ 5 files changed, 34 insertions(+) diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 48d90f50a71..5ae9bb64d6e 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -591,6 +591,14 @@ static inline CPUArchState *cpu_env(CPUState *cpu) typedef QTAILQ_HEAD(CPUTailQ, CPUState) CPUTailQ; extern CPUTailQ cpus_queue; +/** + * cpus_get_accel_cpus_queue: + * @cpu: The vCPU to get the accelerator #CPUTailQ. + * + * Returns the #CPUTailQ associated with the accelerator of the vCPU. + */ +CPUTailQ *cpus_get_accel_cpus_queue(CPUState *cpu); + #define first_cpu QTAILQ_FIRST_RCU(&cpus_queue) #define CPU_NEXT(cpu) QTAILQ_NEXT_RCU(cpu, node) #define CPU_FOREACH(cpu) QTAILQ_FOREACH_RCU(cpu, &cpus_queue, node) diff --git a/include/system/accel-ops.h b/include/system/accel-ops.h index 137fb96d444..fe59f728bfc 100644 --- a/include/system/accel-ops.h +++ b/include/system/accel-ops.h @@ -12,6 +12,7 @@ #include "exec/vaddr.h" #include "qom/object.h" +#include "hw/core/cpu.h" #define ACCEL_OPS_SUFFIX "-ops" #define TYPE_ACCEL_OPS "accel" ACCEL_OPS_SUFFIX @@ -37,6 +38,11 @@ struct AccelOpsClass { bool (*cpus_are_resettable)(void); void (*cpu_reset_hold)(CPUState *cpu); + /** + * get_cpus_queue: + * Returns the #CPUTailQ maintained by this accelerator. + */ + CPUTailQ *(*get_cpus_queue)(void); void (*create_vcpu_thread)(CPUState *cpu); /* MANDATORY NON-NULL */ void (*kick_vcpu_thread)(CPUState *cpu); bool (*cpu_thread_is_idle)(CPUState *cpu); diff --git a/accel/tcg/user-exec-stub.c b/accel/tcg/user-exec-stub.c index 4fbe2dbdc88..cb76cec76be 100644 --- a/accel/tcg/user-exec-stub.c +++ b/accel/tcg/user-exec-stub.c @@ -18,6 +18,11 @@ void cpu_exec_reset_hold(CPUState *cpu) { } +CPUTailQ *cpus_get_accel_cpus_queue(CPUState *cpu) +{ + return NULL; +} + /* User mode emulation does not support record/replay yet. */ bool replay_exception(void) diff --git a/cpu-common.c b/cpu-common.c index 4248b2d727e..ff8db9c7f9d 100644 --- a/cpu-common.c +++ b/cpu-common.c @@ -82,6 +82,7 @@ unsigned int cpu_list_generation_id_get(void) void cpu_list_add(CPUState *cpu) { static bool cpu_index_auto_assigned; + CPUTailQ *accel_cpus_queue = cpus_get_accel_cpus_queue(cpu); QEMU_LOCK_GUARD(&qemu_cpu_list_lock); if (cpu->cpu_index == UNASSIGNED_CPU_INDEX) { @@ -92,17 +93,26 @@ void cpu_list_add(CPUState *cpu) assert(!cpu_index_auto_assigned); } QTAILQ_INSERT_TAIL_RCU(&cpus_queue, cpu, node); + if (accel_cpus_queue) { + QTAILQ_INSERT_TAIL_RCU(accel_cpus_queue, cpu, node); + } + cpu_list_generation_id++; } void cpu_list_remove(CPUState *cpu) { + CPUTailQ *accel_cpus_queue = cpus_get_accel_cpus_queue(cpu); + QEMU_LOCK_GUARD(&qemu_cpu_list_lock); if (!QTAILQ_IN_USE(cpu, node)) { /* there is nothing to undo since cpu_exec_init() hasn't been called */ return; } + if (accel_cpus_queue) { + QTAILQ_REMOVE_RCU(accel_cpus_queue, cpu, node); + } QTAILQ_REMOVE_RCU(&cpus_queue, cpu, node); cpu->cpu_index = UNASSIGNED_CPU_INDEX; cpu_list_generation_id++; diff --git a/system/cpus.c b/system/cpus.c index 99f83806c16..972df6ab061 100644 --- a/system/cpus.c +++ b/system/cpus.c @@ -209,6 +209,11 @@ void cpu_exec_reset_hold(CPUState *cpu) } } +CPUTailQ *cpus_get_accel_cpus_queue(CPUState *cpu) +{ + return cpus_accel ? cpus_accel->get_cpus_queue() : NULL; +} + int64_t cpus_get_virtual_clock(void) { /* -- 2.47.1