We can only run a single hardware accelerator at a time, so add a generic hw_accel_get_cpus_queue() helper in accel-system.c, a file common to all HW accelerators.
Register AccelOpsClass::get_cpus_queue() for each HW accelerator. Add a generic CPU_FOREACH_HWACCEL() macro. Signed-off-by: Philippe Mathieu-Daudé <phi...@linaro.org> --- include/system/hw_accel.h | 9 +++++++++ accel/accel-system.c | 8 ++++++++ accel/kvm/kvm-accel-ops.c | 1 + accel/xen/xen-all.c | 1 + target/i386/nvmm/nvmm-accel-ops.c | 1 + target/i386/whpx/whpx-accel-ops.c | 1 + 6 files changed, 21 insertions(+) diff --git a/include/system/hw_accel.h b/include/system/hw_accel.h index 380e9e640b6..12664cac6f9 100644 --- a/include/system/hw_accel.h +++ b/include/system/hw_accel.h @@ -2,6 +2,7 @@ * QEMU Hardware accelerators support * * Copyright 2016 Google, Inc. + * Copyright 2025 Linaro Ltd. * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -17,6 +18,14 @@ #include "system/whpx.h" #include "system/nvmm.h" +/* Guard with qemu_cpu_list_lock */ +extern CPUTailQ hw_accel_cpus_queue; + +#define CPU_FOREACH_HWACCEL(cpu) \ + QTAILQ_FOREACH_RCU(cpu, &hw_accel_cpus_queue, node) + +CPUTailQ *hw_accel_get_cpus_queue(void); + void cpu_synchronize_state(CPUState *cpu); void cpu_synchronize_post_reset(CPUState *cpu); void cpu_synchronize_post_init(CPUState *cpu); diff --git a/accel/accel-system.c b/accel/accel-system.c index a7596aef59d..60877ea7a28 100644 --- a/accel/accel-system.c +++ b/accel/accel-system.c @@ -27,9 +27,17 @@ #include "qemu/accel.h" #include "hw/boards.h" #include "system/cpus.h" +#include "system/hw_accel.h" #include "qemu/error-report.h" #include "accel-system.h" +CPUTailQ hw_accel_cpus_queue = QTAILQ_HEAD_INITIALIZER(hw_accel_cpus_queue); + +CPUTailQ *hw_accel_get_cpus_queue(void) +{ + return &hw_accel_cpus_queue; +} + int accel_init_machine(AccelState *accel, MachineState *ms) { AccelClass *acc = ACCEL_GET_CLASS(accel); diff --git a/accel/kvm/kvm-accel-ops.c b/accel/kvm/kvm-accel-ops.c index a81e8f3b03b..5f4001860d5 100644 --- a/accel/kvm/kvm-accel-ops.c +++ b/accel/kvm/kvm-accel-ops.c @@ -93,6 +93,7 @@ static void kvm_accel_ops_class_init(ObjectClass *oc, void *data) { AccelOpsClass *ops = ACCEL_OPS_CLASS(oc); + ops->get_cpus_queue = hw_accel_get_cpus_queue; ops->create_vcpu_thread = kvm_start_vcpu_thread; ops->cpu_thread_is_idle = kvm_vcpu_thread_is_idle; ops->cpus_are_resettable = kvm_cpus_are_resettable; diff --git a/accel/xen/xen-all.c b/accel/xen/xen-all.c index 852e9fbe5fe..ac5ed2dfb80 100644 --- a/accel/xen/xen-all.c +++ b/accel/xen/xen-all.c @@ -150,6 +150,7 @@ static void xen_accel_ops_class_init(ObjectClass *oc, void *data) { AccelOpsClass *ops = ACCEL_OPS_CLASS(oc); + ops->get_cpus_queue = hw_accel_get_cpus_queue; ops->create_vcpu_thread = dummy_start_vcpu_thread; } diff --git a/target/i386/nvmm/nvmm-accel-ops.c b/target/i386/nvmm/nvmm-accel-ops.c index e7b56662fee..bb407c68e14 100644 --- a/target/i386/nvmm/nvmm-accel-ops.c +++ b/target/i386/nvmm/nvmm-accel-ops.c @@ -84,6 +84,7 @@ static void nvmm_accel_ops_class_init(ObjectClass *oc, void *data) { AccelOpsClass *ops = ACCEL_OPS_CLASS(oc); + ops->get_cpus_queue = hw_accel_get_cpus_queue; ops->create_vcpu_thread = nvmm_start_vcpu_thread; ops->kick_vcpu_thread = nvmm_kick_vcpu_thread; diff --git a/target/i386/whpx/whpx-accel-ops.c b/target/i386/whpx/whpx-accel-ops.c index ab2e014c9ea..191214ca81d 100644 --- a/target/i386/whpx/whpx-accel-ops.c +++ b/target/i386/whpx/whpx-accel-ops.c @@ -86,6 +86,7 @@ static void whpx_accel_ops_class_init(ObjectClass *oc, void *data) { AccelOpsClass *ops = ACCEL_OPS_CLASS(oc); + ops->get_cpus_queue = hw_accel_get_cpus_queue; ops->create_vcpu_thread = whpx_start_vcpu_thread; ops->kick_vcpu_thread = whpx_kick_vcpu_thread; ops->cpu_thread_is_idle = whpx_vcpu_thread_is_idle; -- 2.47.1