Commit b3e88abb20 for qemu.org

commit b3e88abb200c357235ae1de34cd17b0b1fb24d78
Author: Philippe Mathieu-Daudé <philmd@linaro.org>
Date:   Wed Mar 11 00:20:40 2026 +0100

    gdbstub: Consider GDBFeature::base_reg in gdb_register_coprocessor()

    When a feature XML file provides a "regnum=" tag to indicate
    the registers base index, respect it, as it might not be the
    same as our current number of registered entries, in particular
    when there are gaps.

    This fixes a bug with the "power-fpu.xml" file [*] which was
    loaded at index 70 while the base register is 71. This latent
    bug was exposed by commit 1ec0fbe2dda ("target/ppc: Fix
    CPUClass::gdb_num_core_regs value").

    [*] https://lore.kernel.org/qemu-devel/e44df309-d40d-46f0-88a8-7ac55f9a3634@fhofhammer.de/

    Reported-by: Florian Hofhammer <florian.hofhammer@fhofhammer.de>
    Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
    Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
    Tested-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
    Link: https://lore.kernel.org/qemu-devel/20260310232045.58440-13-philmd@linaro.org
    Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>

diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 69038c66f2..c3c944e965 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -601,6 +601,7 @@ void gdb_init_cpu(CPUState *cpu)
     if (xmlfile) {
         assert(!cc->gdb_num_core_regs);
         feature = gdb_find_static_feature(xmlfile);
+        assert(feature->base_reg == 0);
         gdb_register_feature(cpu, 0,
                              cc->gdb_read_register, cc->gdb_write_register,
                              feature);
@@ -630,6 +631,11 @@ void gdb_register_coprocessor(CPUState *cpu,
         }
     }

+    if (base_reg < feature->base_reg) {
+        trace_gdbxml_register_coprocessor_gap(base_reg,
+                                              feature->base_reg);
+        base_reg = feature->base_reg;
+    }
     gdb_register_feature(cpu, base_reg, get_reg, set_reg, feature);

     /* Add to end of list.  */
diff --git a/gdbstub/trace-events b/gdbstub/trace-events
index 8caee36c24..5bc8394674 100644
--- a/gdbstub/trace-events
+++ b/gdbstub/trace-events
@@ -29,6 +29,7 @@ gdbstub_err_checksum_incorrect(uint8_t expected, uint8_t got) "got command packe
 gdbstub_err_unexpected_runpkt(uint8_t ch) "unexpected packet (0x%02x) while target running"

 gdbxml_init_cpu(const char *typename, unsigned id, unsigned gdb_num_regs, unsigned gdb_num_g_regs, unsigned gdb_num_core_regs) "%s:%d regs:%u g_regs:%u core_regs:%u"
+gdbxml_register_coprocessor_gap(unsigned gdb_num_regs, unsigned base_reg) "regs %u -> %u"
 gdbxml_register_feature(const char *featname, const char *xmlname, unsigned base_reg, unsigned num_regs) "%s (%s) @%u +%u"
 gdbxml_feature_builder_header(const char *name, const char *xmlname, int num_regs) "%s (%s) regs:%d"
 gdbxml_feature_builder_content(const char *xml) "%s"