Commit 8c60f7f38e for qemu.org

commit 8c60f7f38ed97c11a49649bf746dc572ebcbea00
Author: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Date:   Fri Jun 26 12:10:32 2026 +0200

    accel: Have each implementation return their AccelGdbConfig

    Hold the per-accelerator AccelGdbConfig in AccelState, set its
    single @sstep_flags field in AccelClass::init_machine handlers.

    Remove the AccelClass::gdbstub_supported_sstep_flags() getter
    and inline the single accel_supported_gdbstub_sstep_flags() call
    in gdb_init_gdbserver_state().

    Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
    Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
    Message-ID: <20260705215729.62196-15-philmd@oss.qualcomm.com>

diff --git a/accel/accel-common.c b/accel/accel-common.c
index 62590a7d9a..f31d68a9b7 100644
--- a/accel/accel-common.c
+++ b/accel/accel-common.c
@@ -113,16 +113,6 @@ void accel_cpu_common_unrealize(CPUState *cpu)
     }
 }

-int accel_supported_gdbstub_sstep_flags(void)
-{
-    AccelState *accel = current_accel();
-    AccelClass *acc = ACCEL_GET_CLASS(accel);
-    if (acc->gdbstub_supported_sstep_flags) {
-        return acc->gdbstub_supported_sstep_flags(accel);
-    }
-    return 0;
-}
-
 static const TypeInfo accel_types[] = {
     {
         .name           = TYPE_ACCEL,
diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c
index 21b9b71a6d..8bd9154a50 100644
--- a/accel/hvf/hvf-all.c
+++ b/accel/hvf/hvf-all.c
@@ -220,6 +220,8 @@ static int hvf_accel_init(AccelState *as, MachineState *ms)
     }
     assert_hvf_ok(ret);

+    as->gdbstub.sstep_flags = SSTEP_ENABLE | SSTEP_NOIRQ;
+
     QTAILQ_INIT(&s->hvf_sw_breakpoints);

     hvf_state = s;
@@ -228,11 +230,6 @@ static int hvf_accel_init(AccelState *as, MachineState *ms)
     return hvf_arch_init();
 }

-static int hvf_gdbstub_sstep_flags(AccelState *as)
-{
-    return SSTEP_ENABLE | SSTEP_NOIRQ;
-}
-
 static void hvf_set_kernel_irqchip(Object *obj, Visitor *v,
                                    const char *name, void *opaque,
                                    Error **errp)
@@ -278,7 +275,6 @@ static void hvf_accel_class_init(ObjectClass *oc, const void *data)
     ac->name = "HVF";
     ac->init_machine = hvf_accel_init;
     ac->allowed = &hvf_allowed;
-    ac->gdbstub_supported_sstep_flags = hvf_gdbstub_sstep_flags;
     hvf_kernel_irqchip_override = false;
     hvf_kernel_irqchip = false;
     object_class_property_add(oc, "kernel-irqchip", "on|off|split",
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index b6125125f8..ceb0b33abd 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -104,7 +104,6 @@ bool kvm_readonly_mem_allowed;
 bool kvm_vm_attributes_allowed;
 bool kvm_msi_use_devid;
 bool kvm_pre_fault_memory_supported;
-static int kvm_sstep_flags;
 static bool kvm_immediate_exit;
 static uint64_t kvm_supported_memory_attributes;
 static bool kvm_guest_memfd_supported;
@@ -3041,13 +3040,13 @@ static int kvm_init(AccelState *as, MachineState *ms)
         (kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG) > 0);

     if (s->have_guest_debug) {
-        kvm_sstep_flags = SSTEP_ENABLE;
+        as->gdbstub.sstep_flags = SSTEP_ENABLE;

         int guest_debug_flags =
             kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG2);

         if (guest_debug_flags & KVM_GUESTDBG_BLOCKIRQ) {
-            kvm_sstep_flags |= SSTEP_NOIRQ;
+            as->gdbstub.sstep_flags |= SSTEP_NOIRQ;
         }
     }
 #endif
@@ -4279,17 +4278,6 @@ static void kvm_accel_instance_init(Object *obj)
     s->honor_guest_pat = ON_OFF_AUTO_OFF;
 }

-/**
- * kvm_gdbstub_sstep_flags():
- *
- * Returns: SSTEP_* flags that KVM supports for guest debug. The
- * support is probed during kvm_init()
- */
-static int kvm_gdbstub_sstep_flags(AccelState *as)
-{
-    return kvm_sstep_flags;
-}
-
 static void kvm_accel_class_init(ObjectClass *oc, const void *data)
 {
     AccelClass *ac = ACCEL_CLASS(oc);
@@ -4298,7 +4286,6 @@ static void kvm_accel_class_init(ObjectClass *oc, const void *data)
     ac->rebuild_guest = kvm_reset_vmfd;
     ac->has_memory = kvm_accel_has_memory;
     ac->allowed = &kvm_allowed;
-    ac->gdbstub_supported_sstep_flags = kvm_gdbstub_sstep_flags;

     object_class_property_add(oc, "kernel-irqchip", "on|off|split",
         NULL, kvm_set_kernel_irqchip,
diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c
index 8eb4a6b89e..d30b53cd3b 100644
--- a/accel/tcg/tcg-all.c
+++ b/accel/tcg/tcg-all.c
@@ -149,6 +149,17 @@ static int tcg_init_machine(AccelState *as, MachineState *ms)

     tcg_allowed = true;

+    as->gdbstub.sstep_flags = SSTEP_ENABLE;
+    if (replay_mode == REPLAY_MODE_NONE) {
+        /*
+         * In replay mode all events will come from the log and can't be
+         * suppressed otherwise we would break determinism. However as those
+         * events are tied to the number of executed instructions we won't see
+         * them occurring every time we single step.
+         */
+        as->gdbstub.sstep_flags |= SSTEP_NOIRQ | SSTEP_NOTIMER;
+    }
+
     page_init();
     tb_htable_init();
     tcg_init(s->tb_size * MiB, s->splitwx_enabled, max_threads);
@@ -242,21 +253,6 @@ static void tcg_set_one_insn_per_tb(Object *obj, bool value, Error **errp)
     qatomic_set(&one_insn_per_tb, value);
 }

-static int tcg_gdbstub_supported_sstep_flags(AccelState *as)
-{
-    /*
-     * In replay mode all events will come from the log and can't be
-     * suppressed otherwise we would break determinism. However as those
-     * events are tied to the number of executed instructions we won't see
-     * them occurring every time we single step.
-     */
-    if (replay_mode != REPLAY_MODE_NONE) {
-        return SSTEP_ENABLE;
-    } else {
-        return SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER;
-    }
-}
-
 static void tcg_accel_class_init(ObjectClass *oc, const void *data)
 {
     AccelClass *ac = ACCEL_CLASS(oc);
@@ -266,7 +262,6 @@ static void tcg_accel_class_init(ObjectClass *oc, const void *data)
     ac->cpu_common_unrealize = tcg_exec_unrealizefn;
     ac->get_stats = tcg_get_stats;
     ac->allowed = &tcg_allowed;
-    ac->gdbstub_supported_sstep_flags = tcg_gdbstub_supported_sstep_flags;

     object_class_property_add_str(oc, "thread",
                                   tcg_get_thread,
diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
index e3f93efc61..247e12db81 100644
--- a/accel/whpx/whpx-common.c
+++ b/accel/whpx/whpx-common.c
@@ -527,7 +527,6 @@ static void whpx_accel_class_init(ObjectClass *oc, const void *data)
     ac->init_machine = whpx_accel_init;
     ac->pre_resume_vm = whpx_pre_resume_vm;
     ac->allowed = &whpx_allowed;
-    ac->gdbstub_supported_sstep_flags = whpx_arch_gdbstub_sstep_flags;

     object_class_property_add(oc, "kernel-irqchip", "on|off|split",
         NULL, whpx_set_kernel_irqchip,
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 06b712562c..6c4fa06563 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -72,7 +72,7 @@ void gdb_init_gdbserver_state(void)
      * By default try to use no IRQs and no timers while single
      * stepping so as to make single stepping like a typical ICE HW step.
      */
-    gdbserver_state.accel_config.sstep_flags = accel_supported_gdbstub_sstep_flags();
+    gdbserver_state.accel_config = current_accel()->gdbstub;
     gdbserver_state.sstep_flags = SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER;
     gdbserver_state.sstep_flags &= gdbserver_state.accel_config.sstep_flags;
 }
diff --git a/include/accel/accel-ops.h b/include/accel/accel-ops.h
index f46492e3fe..9f3f329c44 100644
--- a/include/accel/accel-ops.h
+++ b/include/accel/accel-ops.h
@@ -13,6 +13,8 @@

 struct AccelState {
     Object parent_obj;
+
+    AccelGdbConfig gdbstub;
 };

 struct AccelClass {
@@ -36,9 +38,6 @@ struct AccelClass {
     bool (*has_memory)(AccelState *accel, AddressSpace *as,
                        hwaddr start_addr, hwaddr size);

-    /* gdbstub related hooks */
-    int (*gdbstub_supported_sstep_flags)(AccelState *as);
-
     bool *allowed;
     /*
      * Array of global properties that would be applied when specific
diff --git a/include/qemu/accel.h b/include/qemu/accel.h
index 052b4c5931..3b01d55741 100644
--- a/include/qemu/accel.h
+++ b/include/qemu/accel.h
@@ -82,12 +82,4 @@ typedef struct AccelGdbConfig {
     unsigned sstep_flags;
 } AccelGdbConfig;

-/**
- * accel_supported_gdbstub_sstep_flags:
- *
- * Returns the supported single step modes for the configured
- * accelerator.
- */
-int accel_supported_gdbstub_sstep_flags(void);
-
 #endif /* QEMU_ACCEL_H */
diff --git a/include/system/whpx-all.h b/include/system/whpx-all.h
index 0e2d333e91..4022571fff 100644
--- a/include/system/whpx-all.h
+++ b/include/system/whpx-all.h
@@ -23,7 +23,6 @@ void whpx_arch_destroy_vcpu(CPUState *cpu);
 void whpx_arch_accel_class_init(ObjectClass *oc);

 /* called by whpx-accel-ops */
-int whpx_arch_gdbstub_sstep_flags(AccelState *as);
 bool whpx_arch_supports_guest_debug(void);

 #endif
diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c
index 5208d7e1df..3079c6293c 100644
--- a/target/arm/whpx/whpx-all.c
+++ b/target/arm/whpx/whpx-all.c
@@ -295,11 +295,6 @@ void whpx_translate_cpu_breakpoints(
     /* Breakpoints aren’t supported on this platform */
 }

-int whpx_arch_gdbstub_sstep_flags(AccelState *as)
-{
-    return 0;
-}
-
 bool whpx_arch_supports_guest_debug(void)
 {
     return false;
diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index f6e1636a4e..467ac6bed4 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -1853,11 +1853,6 @@ void whpx_apply_breakpoints(
     }
 }

-int whpx_arch_gdbstub_sstep_flags(AccelState *as)
-{
-    return SSTEP_ENABLE;
-}
-
 bool whpx_arch_supports_guest_debug(void)
 {
     return true;
@@ -3348,6 +3343,8 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
     whpx_memory_init();
     whpx_init_emu();

+    as->gdbstub.sstep_flags = SSTEP_ENABLE;
+
     return 0;

 error: