From 65339110b74b80757a209b78a9af1a3550737fed Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sat, 27 Jun 2026 18:05:43 +0200 Subject: cpu: Constify CPUState::cc (cached CPUClass pointer) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Various CPUState can share the same CPUClass parent, and must not update its fields. Protect the CPUClass by marking the CPUState pointer const. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Reviewed-by: Chao Liu Message-ID: <20260705215729.62196-2-philmd@oss.qualcomm.com> --- accel/tcg/cpu-exec.c | 2 +- accel/tcg/translate-all.c | 3 +-- gdbstub/gdbstub.c | 2 +- include/hw/core/cpu.h | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 9c754b0365..d7f91dce9d 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -460,7 +460,7 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit) * counter hit zero); we must restore the guest PC to the address * of the start of the TB. */ - CPUClass *cc = cpu->cc; + const CPUClass *cc = cpu->cc; const TCGCPUOps *tcg_ops = cc->tcg_ops; if (tcg_ops->synchronize_from_tb) { diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 3f1a3a2843..328d96aba3 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -575,7 +575,7 @@ void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr) void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr) { TranslationBlock *tb; - CPUClass *cc; + const CPUClass *cc = cpu->cc; uint32_t n; tb = tcg_tb_lookup(retaddr); @@ -591,7 +591,6 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr) * to account for the re-execution of the branch. */ n = 1; - cc = cpu->cc; if (cc->tcg_ops->io_recompile_replay_branch && cc->tcg_ops->io_recompile_replay_branch(cpu, tb)) { cpu->neg.icount_decr.u16.low++; diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index c3c944e965..26366acb67 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -578,7 +578,7 @@ static void gdb_register_feature(CPUState *cpu, int base_reg, static const char *gdb_get_core_xml_file(CPUState *cpu) { - CPUClass *cc = cpu->cc; + const CPUClass *cc = cpu->cc; /* * The CPU class can provide the XML filename via a method, diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 59d601465b..60a23d6f38 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -480,7 +480,7 @@ struct CPUState { /*< private >*/ DeviceState parent_obj; /* cache to avoid expensive CPU_GET_CLASS */ - CPUClass *cc; + const CPUClass *cc; /*< public >*/ int nr_threads; -- cgit v1.2.3 From c1b47f48eb539ed45053eb281a53147fd23323bd Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Tue, 30 Jun 2026 13:12:23 +0200 Subject: target/i386: Remove duplicate tlb_flush() call in cpu_post_load() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Common vCPU cpu_common_post_load() handler calls tlb_flush() since commit 9656f324d25 ("Move interrupt_request and user_mode_only to common cpu state..."), no need to call it twice. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Chao Liu Message-ID: <20260705215729.62196-3-philmd@oss.qualcomm.com> --- target/i386/machine.c | 1 - 1 file changed, 1 deletion(-) diff --git a/target/i386/machine.c b/target/i386/machine.c index 1f5c517e56..df0e0c178e 100644 --- a/target/i386/machine.c +++ b/target/i386/machine.c @@ -401,7 +401,6 @@ static int cpu_post_load(void *opaque, int version_id) env->dr[7] = dr7 & ~(DR7_GLOBAL_BP_MASK | DR7_LOCAL_BP_MASK); cpu_x86_update_dr7(env, dr7); } - tlb_flush(cs); return 0; } -- cgit v1.2.3 From cadee08114719304e8c662fb54a88b6c3b01c304 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Tue, 30 Jun 2026 13:11:52 +0200 Subject: accel/tcg: Restrict tlb_protect/unprotect_code() to TCG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both tlb_protect() and tlb_unprotect_code() are only used within accel/tcg/. Avoid exposing them to the whole code base, declare them in a new "system-page-protection.h" local header (maintaining the previous LGPL-2.1-or-later license). Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Reviewed-by: Chao Liu Message-ID: <20260705215729.62196-4-philmd@oss.qualcomm.com> --- accel/tcg/cputlb.c | 3 ++- accel/tcg/system-page-protection.h | 17 +++++++++++++++++ accel/tcg/tb-maint.c | 1 + include/exec/cputlb.h | 8 ++------ 4 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 accel/tcg/system-page-protection.h diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 6e66f3c6e9..7f7c208ba1 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1,5 +1,5 @@ /* - * Common CPU TLB handling + * Common CPU TLB handling (system emulation) * * Copyright (c) 2003 Fabrice Bellard * @@ -47,6 +47,7 @@ #include "tb-hash.h" #include "tlb-bounds.h" #include "internal-common.h" +#include "system-page-protection.h" #ifdef CONFIG_PLUGIN #include "qemu/plugin-memory.h" #endif diff --git a/accel/tcg/system-page-protection.h b/accel/tcg/system-page-protection.h new file mode 100644 index 0000000000..52896c6d24 --- /dev/null +++ b/accel/tcg/system-page-protection.h @@ -0,0 +1,17 @@ +/* + * QEMU page protection (system emulation) + * + * Copyright (c) 2003 Fabrice Bellard + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#ifndef SYSTEM_PAGE_PROTECTION_H +#define SYSTEM_PAGE_PROTECTION_H + +#include "system/ram_addr.h" + +void tlb_protect_code(ram_addr_t ram_addr); +void tlb_unprotect_code(ram_addr_t ram_addr); + +#endif + diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c index c33dbf65e7..4313864d2c 100644 --- a/accel/tcg/tb-maint.c +++ b/accel/tcg/tb-maint.c @@ -38,6 +38,7 @@ #include "user/page-protection.h" #define runstate_is_running() true #else +#include "system-page-protection.h" #include "system/runstate.h" #endif #include "trace.h" diff --git a/include/exec/cputlb.h b/include/exec/cputlb.h index 3a9603a696..f7f7020382 100644 --- a/include/exec/cputlb.h +++ b/include/exec/cputlb.h @@ -24,14 +24,10 @@ #include "exec/hwaddr.h" #include "exec/memattrs.h" #include "exec/vaddr.h" -#include "system/ram_addr.h" - -#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) -void tlb_protect_code(ram_addr_t ram_addr); -void tlb_unprotect_code(ram_addr_t ram_addr); -#endif #ifndef CONFIG_USER_ONLY +#include "system/ram_addr.h" + void tlb_reset_dirty(CPUState *cpu, uintptr_t start, uintptr_t length); void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t length); #endif -- cgit v1.2.3 From 586a25c492def6a2f4a895440fc4170cfed6da31 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Tue, 30 Jun 2026 17:55:08 +0200 Subject: accel/hvf: Remove left-over comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Missed in commit 6bf331164c5 ("accel/hvf: Drop hvf_slot and hvf_find_overlap_slot"). Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-5-philmd@oss.qualcomm.com> --- accel/hvf/hvf-accel-ops.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c index b74a5779c3..dd2b45b7cb 100644 --- a/accel/hvf/hvf-accel-ops.c +++ b/accel/hvf/hvf-accel-ops.c @@ -62,8 +62,6 @@ HVFState *hvf_state; -/* Memory slots */ - static void do_hvf_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg) { if (!cpu->vcpu_dirty) { -- cgit v1.2.3 From abdd572a4380739b8eb8461bda9f720905dcf56c Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Tue, 30 Jun 2026 14:44:30 +0200 Subject: accel/mshv: Replace @dirty field by generic CPUState::vcpu_dirty field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need for accel-specific @dirty field when we have a generic one in CPUState. (Other accelerators already did that in commits 6f13a0ada01..36ab216b81d). Signed-off-by: Philippe Mathieu-Daudé Tested-by: Magnus Kulke Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-6-philmd@oss.qualcomm.com> --- accel/mshv/mshv-all.c | 18 +++++++++--------- include/system/mshv_int.h | 1 - target/i386/mshv/mshv-cpu.c | 6 +++--- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/accel/mshv/mshv-all.c b/accel/mshv/mshv-all.c index 9452504ac2..1959baf667 100644 --- a/accel/mshv/mshv-all.c +++ b/accel/mshv/mshv-all.c @@ -531,7 +531,7 @@ static int mshv_init_vcpu(CPUState *cpu) } mshv_arch_init_vcpu(cpu); - cpu->accel->dirty = true; + cpu->vcpu_dirty = true; return 0; } @@ -617,7 +617,7 @@ static int mshv_cpu_exec(CPUState *cpu) cpu_exec_start(cpu); do { - if (cpu->accel->dirty) { + if (cpu->vcpu_dirty) { ret = mshv_arch_store_vcpu_state(cpu); if (ret) { error_report("Failed to put registers after init: %s", @@ -625,7 +625,7 @@ static int mshv_cpu_exec(CPUState *cpu) ret = -1; break; } - cpu->accel->dirty = false; + cpu->vcpu_dirty = false; } ret = mshv_run_vcpu(mshv_state->vm, cpu, &mshv_msg, &exit_reason); @@ -746,7 +746,7 @@ static void do_mshv_cpu_synchronize_post_init(CPUState *cpu, abort(); } - cpu->accel->dirty = false; + cpu->vcpu_dirty = false; } static void mshv_cpu_synchronize_post_init(CPUState *cpu) @@ -763,13 +763,13 @@ static void mshv_cpu_synchronize_post_reset(CPUState *cpu) cpu_dump_state(cpu, stderr, CPU_DUMP_CODE); vm_stop(RUN_STATE_INTERNAL_ERROR); } - cpu->accel->dirty = false; + cpu->vcpu_dirty = false; } static void do_mshv_cpu_synchronize_pre_loadvm(CPUState *cpu, run_on_cpu_data arg) { - cpu->accel->dirty = true; + cpu->vcpu_dirty = true; } static void mshv_cpu_synchronize_pre_loadvm(CPUState *cpu) @@ -779,7 +779,7 @@ static void mshv_cpu_synchronize_pre_loadvm(CPUState *cpu) static void do_mshv_cpu_synchronize(CPUState *cpu, run_on_cpu_data arg) { - if (!cpu->accel->dirty) { + if (!cpu->vcpu_dirty) { int ret = mshv_arch_load_vcpu_state(cpu); if (ret < 0) { error_report("Failed to load registers for vcpu %d", @@ -789,13 +789,13 @@ static void do_mshv_cpu_synchronize(CPUState *cpu, run_on_cpu_data arg) vm_stop(RUN_STATE_INTERNAL_ERROR); } - cpu->accel->dirty = true; + cpu->vcpu_dirty = true; } } static void mshv_cpu_synchronize(CPUState *cpu) { - if (!cpu->accel->dirty) { + if (!cpu->vcpu_dirty) { run_on_cpu(cpu, do_mshv_cpu_synchronize, RUN_ON_CPU_NULL); } } diff --git a/include/system/mshv_int.h b/include/system/mshv_int.h index ba3073888a..b91c4d661a 100644 --- a/include/system/mshv_int.h +++ b/include/system/mshv_int.h @@ -43,7 +43,6 @@ typedef struct MshvHvCallArgs { struct AccelCPUState { int cpufd; - bool dirty; MshvHvCallArgs hvcall_args; }; diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c index 126ca40b48..1c433c408c 100644 --- a/target/i386/mshv/mshv-cpu.c +++ b/target/i386/mshv/mshv-cpu.c @@ -1692,7 +1692,7 @@ static int pio_write(uint64_t port, const uint8_t *data, uintptr_t size, return ret; } -static int handle_pio_non_str(const CPUState *cpu, +static int handle_pio_non_str(CPUState *cpu, hv_x64_io_port_intercept_message *info) { size_t len = info->access_info.access_size; @@ -1748,7 +1748,7 @@ static int handle_pio_non_str(const CPUState *cpu, return -1; } - cpu->accel->dirty = false; + cpu->vcpu_dirty = false; return 0; } @@ -1909,7 +1909,7 @@ static int handle_pio_str(CPUState *cpu, hv_x64_io_port_intercept_message *info) return -1; } - cpu->accel->dirty = false; + cpu->vcpu_dirty = false; return 0; } -- cgit v1.2.3 From ce0b7a15bc1f44f1d788f0a6aaa36244fa95a662 Mon Sep 17 00:00:00 2001 From: Magnus Kulke Date: Wed, 1 Jul 2026 15:03:35 +0200 Subject: accel/mshv: Fix pointer to proc feature bitfield MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Processor features are stored in a union containing two "banks": union hv_partition_processor_features { uint64_t as_uint[2]; struct { uint64_t sse3_support:1; ... } } get_proc_features() to retrieve the 2nd bank was passing a pointer that steps over the whole union (+16B) instead of picking the 2nd bank _in_ the union. This manifests in mismatching feature bits for the 2nd bank and possibly other side-effects caused by writing beyond the union. We need to step over the first bank (+8B) by using as_uint64[0/1] to correct this behaviour. Resolves: Coverity CID 1660876 Fixes: 2f6da91e8a ("accel/mshv: store partition proc features") Signed-off-by: Magnus Kulke Reviewed-by: Doru Blânzeanu Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Maydell Message-ID: <20260701130335.418156-1-magnuskulke@linux.microsoft.com> Signed-off-by: Philippe Mathieu-Daudé --- accel/mshv/mshv-all.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accel/mshv/mshv-all.c b/accel/mshv/mshv-all.c index 1959baf667..72721d0f0d 100644 --- a/accel/mshv/mshv-all.c +++ b/accel/mshv/mshv-all.c @@ -167,7 +167,7 @@ static int get_proc_features(int vm_fd, ret = get_partition_property(vm_fd, HV_PARTITION_PROPERTY_PROCESSOR_FEATURES0, - features[0].as_uint64); + &features->as_uint64[0]); if (ret < 0) { error_report("Failed to get processor features bank 0"); return -1; @@ -175,7 +175,7 @@ static int get_proc_features(int vm_fd, ret = get_partition_property(vm_fd, HV_PARTITION_PROPERTY_PROCESSOR_FEATURES1, - features[1].as_uint64); + &features->as_uint64[1]); if (ret < 0) { error_report("Failed to get processor features bank 1"); return -1; -- cgit v1.2.3 From 32822e389871d2596ccce1f25ec713356c5c0280 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 26 Jun 2026 14:32:46 +0200 Subject: gdbstub: Add trace event for STEP packet handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Acked-by: Alex Bennée Message-ID: <20260705215729.62196-7-philmd@oss.qualcomm.com> --- gdbstub/gdbstub.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index 26366acb67..246e774630 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -1369,6 +1369,7 @@ static void handle_step(GArray *params, void *user_ctx) gdb_set_cpu_pc(gdb_get_cmd_param(params, 0)->val_ull); } + trace_gdbstub_op_stepping(gdbserver_state.c_cpu->cpu_index); cpu_single_step(gdbserver_state.c_cpu, gdbserver_state.sstep_flags); gdb_continue(); } -- cgit v1.2.3 From 82d97eeda8593aca32756e7ddaf0b8f12d015893 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 26 Jun 2026 12:16:31 +0200 Subject: gdbstub: Only return E22 when reverse GDB is not supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to keep processing the arguments when we know reverse debugging is not available. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Reviewed-by: Alex Bennée Message-ID: <20260705215729.62196-8-philmd@oss.qualcomm.com> --- gdbstub/gdbstub.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index 246e774630..f54415a9db 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -1378,6 +1378,7 @@ static void handle_backward(GArray *params, void *user_ctx) { if (!gdb_can_reverse()) { gdb_put_packet("E22"); + return; } if (params->len == 1) { switch (gdb_get_cmd_param(params, 0)->opcode) { -- cgit v1.2.3 From 67ae20cc4ab407d6ce826420be6e838bba99045d Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 3 Jul 2026 15:24:47 +0200 Subject: accel/whpx: Implement missing AccelClass::gdbstub_supported_sstep_flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correct gdbstub support requires some gdbstub_supported_sstep_flags. Apparently missed in commit d7482ffe975 ("whpx: Added support for breakpoints and stepping"), even with the recent 19b48084f71 ("whpx: i386: re-enable guest debug support") fixes. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-9-philmd@oss.qualcomm.com> --- accel/whpx/whpx-common.c | 1 + include/system/whpx-all.h | 1 + target/arm/whpx/whpx-all.c | 5 +++++ target/i386/whpx/whpx-all.c | 5 +++++ 4 files changed, 12 insertions(+) diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c index 247e12db81..e3f93efc61 100644 --- a/accel/whpx/whpx-common.c +++ b/accel/whpx/whpx-common.c @@ -527,6 +527,7 @@ 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/include/system/whpx-all.h b/include/system/whpx-all.h index 4022571fff..0e2d333e91 100644 --- a/include/system/whpx-all.h +++ b/include/system/whpx-all.h @@ -23,6 +23,7 @@ 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 3079c6293c..5208d7e1df 100644 --- a/target/arm/whpx/whpx-all.c +++ b/target/arm/whpx/whpx-all.c @@ -295,6 +295,11 @@ 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 e626acef2f..f6e1636a4e 100644 --- a/target/i386/whpx/whpx-all.c +++ b/target/i386/whpx/whpx-all.c @@ -1853,6 +1853,11 @@ void whpx_apply_breakpoints( } } +int whpx_arch_gdbstub_sstep_flags(AccelState *as) +{ + return SSTEP_ENABLE; +} + bool whpx_arch_supports_guest_debug(void) { return true; -- cgit v1.2.3 From 0f66a691727a9d4d32081e62d9d2ee8a84b104f2 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 26 Jun 2026 13:15:09 +0200 Subject: accel/kvm: Always define AccelOpsClass::supports_guest_debug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Whether TARGET_KVM_HAVE_GUEST_DEBUG is defined or not, kvm_supports_guest_debug() still exists and can be called. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-10-philmd@oss.qualcomm.com> --- accel/kvm/kvm-accel-ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accel/kvm/kvm-accel-ops.c b/accel/kvm/kvm-accel-ops.c index 6d9140e549..d7967bc922 100644 --- a/accel/kvm/kvm-accel-ops.c +++ b/accel/kvm/kvm-accel-ops.c @@ -105,9 +105,9 @@ static void kvm_accel_ops_class_init(ObjectClass *oc, const void *data) ops->synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm; ops->handle_interrupt = generic_handle_interrupt; + ops->supports_guest_debug = kvm_supports_guest_debug; #ifdef TARGET_KVM_HAVE_GUEST_DEBUG ops->update_guest_debug = kvm_update_guest_debug_ops; - ops->supports_guest_debug = kvm_supports_guest_debug; ops->insert_breakpoint = kvm_insert_breakpoint; ops->remove_breakpoint = kvm_remove_breakpoint; ops->remove_all_breakpoints = kvm_remove_all_breakpoints; -- cgit v1.2.3 From e32e858cf8090b4351021cd997b719258999784f Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 26 Jun 2026 12:30:15 +0200 Subject: accel/kvm: Simplify kvm_init() w.r.t. TARGET_KVM_HAVE_GUEST_DEBUG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify #ifdef'ry using TARGET_KVM_HAVE_GUEST_DEBUG in kvm_init(). No need to zero-initialize kvm_sstep_flags again. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-11-philmd@oss.qualcomm.com> --- accel/kvm/kvm-all.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 5d55cb45cf..304467704e 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -3040,21 +3040,18 @@ static int kvm_init(AccelState *as, MachineState *ms) #ifdef TARGET_KVM_HAVE_GUEST_DEBUG kvm_has_guest_debug = (kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG) > 0); -#endif - kvm_sstep_flags = 0; if (kvm_has_guest_debug) { kvm_sstep_flags = SSTEP_ENABLE; -#if defined TARGET_KVM_HAVE_GUEST_DEBUG 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; } -#endif } +#endif kvm_state = s; -- cgit v1.2.3 From f2468e2f4996e60723884e36f527a3e7d535aa66 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 26 Jun 2026 12:33:30 +0200 Subject: accel/kvm: Hold have_guest_debug in KVMState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefer to store per-accelerator variables in the per-accelerator state, rather than as static variables. This is a good practice to allow concurrent accelerators in the future. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-12-philmd@oss.qualcomm.com> --- accel/kvm/kvm-all.c | 9 +++++---- include/system/kvm_int.h | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 304467704e..b6125125f8 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 bool kvm_has_guest_debug; static int kvm_sstep_flags; static bool kvm_immediate_exit; static uint64_t kvm_supported_memory_attributes; @@ -3038,10 +3037,10 @@ static int kvm_init(AccelState *as, MachineState *ms) (kvm_check_extension(s, KVM_CAP_VM_ATTRIBUTES) > 0); #ifdef TARGET_KVM_HAVE_GUEST_DEBUG - kvm_has_guest_debug = + s->have_guest_debug = (kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG) > 0); - if (kvm_has_guest_debug) { + if (s->have_guest_debug) { kvm_sstep_flags = SSTEP_ENABLE; int guest_debug_flags = @@ -3833,8 +3832,10 @@ int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap) bool kvm_supports_guest_debug(void) { + KVMState *s = KVM_STATE(as); + /* probed during kvm_init() */ - return kvm_has_guest_debug; + return s->have_guest_debug; } int kvm_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len) diff --git a/include/system/kvm_int.h b/include/system/kvm_int.h index 0876aac938..53bb0fcf18 100644 --- a/include/system/kvm_int.h +++ b/include/system/kvm_int.h @@ -118,6 +118,7 @@ struct KVMState #endif int max_nested_state_len; int kvm_shadow_mem; + bool have_guest_debug; bool kernel_irqchip_allowed; bool kernel_irqchip_required; OnOffAuto kernel_irqchip_split; -- cgit v1.2.3 From 5ba4a7d02b4ac07f01815185873afd28330f04ba Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 3 Jul 2026 15:09:49 +0200 Subject: gdbstub: Reduce gdb_supports_guest_debug() scope MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gdb_supports_guest_debug() is only required for system emulation, reduce its scope by making it private; remove the user emulation variant. Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20260705215729.62196-13-philmd@oss.qualcomm.com> --- gdbstub/internals.h | 1 - gdbstub/system.c | 4 +++- gdbstub/user.c | 6 ------ 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/gdbstub/internals.h b/gdbstub/internals.h index 9b25bf58b8..60ddc14666 100644 --- a/gdbstub/internals.h +++ b/gdbstub/internals.h @@ -217,7 +217,6 @@ void gdb_syscall_handling(const char *syscall_packet); * Break/Watch point support - there is an implementation for system * and user mode. */ -bool gdb_supports_guest_debug(void); int gdb_breakpoint_insert(CPUState *cs, int type, vaddr addr, vaddr len); int gdb_breakpoint_remove(CPUState *cs, int type, vaddr addr, vaddr len); void gdb_breakpoint_remove_all(CPUState *cs); diff --git a/gdbstub/system.c b/gdbstub/system.c index 2063b63b2f..1179c82cb8 100644 --- a/gdbstub/system.c +++ b/gdbstub/system.c @@ -331,6 +331,8 @@ static void create_processes(GDBState *s) gdb_create_default_process(s); } +static bool gdb_supports_guest_debug(void); + bool gdbserver_start(const char *device, Error **errp) { Chardev *chr = NULL; @@ -627,7 +629,7 @@ int gdb_signal_to_target(int sig) * Break/Watch point helpers */ -bool gdb_supports_guest_debug(void) +static bool gdb_supports_guest_debug(void) { const AccelOpsClass *ops = cpus_get_accel(); if (ops->supports_guest_debug) { diff --git a/gdbstub/user.c b/gdbstub/user.c index 97eb13e796..f7bc4e63df 100644 --- a/gdbstub/user.c +++ b/gdbstub/user.c @@ -796,12 +796,6 @@ bool gdb_can_reverse(void) * Break/Watch point helpers */ -bool gdb_supports_guest_debug(void) -{ - /* user-mode == TCG == supported */ - return true; -} - int gdb_breakpoint_insert(CPUState *cs, int type, vaddr addr, vaddr len) { CPUState *cpu; -- cgit v1.2.3 From e9c5654035834eb5b8f8ae53cb01376f6d8dd222 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 3 Jul 2026 10:51:39 +0200 Subject: gdbstub: Move supported_sstep_flags in AccelGdbConfig structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit supported_sstep_flags are per-accelerators. Move them to a new AccelGdbConfig structure, still in GDBState. Suggested-by: Alex Bennée Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-14-philmd@oss.qualcomm.com> --- gdbstub/gdbstub.c | 10 +++++----- gdbstub/internals.h | 3 ++- include/qemu/accel.h | 9 +++++++++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index f54415a9db..06b712562c 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -72,9 +72,9 @@ 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.supported_sstep_flags = accel_supported_gdbstub_sstep_flags(); + gdbserver_state.accel_config.sstep_flags = accel_supported_gdbstub_sstep_flags(); gdbserver_state.sstep_flags = SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER; - gdbserver_state.sstep_flags &= gdbserver_state.supported_sstep_flags; + gdbserver_state.sstep_flags &= gdbserver_state.accel_config.sstep_flags; } /* writes 2*len+1 bytes in buf */ @@ -1537,12 +1537,12 @@ static void handle_query_qemu_sstepbits(GArray *params, void *user_ctx) { g_string_printf(gdbserver_state.str_buf, "ENABLE=%x", SSTEP_ENABLE); - if (gdbserver_state.supported_sstep_flags & SSTEP_NOIRQ) { + if (gdbserver_state.accel_config.sstep_flags & SSTEP_NOIRQ) { g_string_append_printf(gdbserver_state.str_buf, ",NOIRQ=%x", SSTEP_NOIRQ); } - if (gdbserver_state.supported_sstep_flags & SSTEP_NOTIMER) { + if (gdbserver_state.accel_config.sstep_flags & SSTEP_NOTIMER) { g_string_append_printf(gdbserver_state.str_buf, ",NOTIMER=%x", SSTEP_NOTIMER); } @@ -1560,7 +1560,7 @@ static void handle_set_qemu_sstep(GArray *params, void *user_ctx) new_sstep_flags = gdb_get_cmd_param(params, 0)->val_ul; - if (new_sstep_flags & ~gdbserver_state.supported_sstep_flags) { + if (new_sstep_flags & ~gdbserver_state.accel_config.sstep_flags) { gdb_put_packet("E22"); return; } diff --git a/gdbstub/internals.h b/gdbstub/internals.h index 60ddc14666..0444dee224 100644 --- a/gdbstub/internals.h +++ b/gdbstub/internals.h @@ -9,6 +9,7 @@ #ifndef GDBSTUB_INTERNALS_H #define GDBSTUB_INTERNALS_H +#include "qemu/accel.h" #include "exec/cpu-common.h" /* @@ -83,8 +84,8 @@ typedef struct GDBState { int process_num; GString *str_buf; GByteArray *mem_buf; + AccelGdbConfig accel_config; int sstep_flags; - int supported_sstep_flags; /* * Whether we are allowed to send a stop reply packet at this moment. * Must be set off after sending the stop reply itself. diff --git a/include/qemu/accel.h b/include/qemu/accel.h index d3638c7bfd..052b4c5931 100644 --- a/include/qemu/accel.h +++ b/include/qemu/accel.h @@ -73,6 +73,15 @@ bool accel_cpu_common_realize(CPUState *cpu, Error **errp); */ void accel_cpu_common_unrealize(CPUState *cpu); +/** + * struct AccelGdbConfig - gdbstub configuration for an accelerator. + * + * @sstep_flags: Set SSTEP_* flags that accelerator supports for guest debug. + */ +typedef struct AccelGdbConfig { + unsigned sstep_flags; +} AccelGdbConfig; + /** * accel_supported_gdbstub_sstep_flags: * -- cgit v1.2.3 From 8c60f7f38ed97c11a49649bf746dc572ebcbea00 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 26 Jun 2026 12:10:32 +0200 Subject: accel: Have each implementation return their AccelGdbConfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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é Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-15-philmd@oss.qualcomm.com> --- accel/accel-common.c | 10 ---------- accel/hvf/hvf-all.c | 8 ++------ accel/kvm/kvm-all.c | 17 ++--------------- accel/tcg/tcg-all.c | 27 +++++++++++---------------- accel/whpx/whpx-common.c | 1 - gdbstub/gdbstub.c | 2 +- include/accel/accel-ops.h | 5 ++--- include/qemu/accel.h | 8 -------- include/system/whpx-all.h | 1 - target/arm/whpx/whpx-all.c | 5 ----- target/i386/whpx/whpx-all.c | 7 ++----- 11 files changed, 20 insertions(+), 71 deletions(-) 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: -- cgit v1.2.3 From d1286e29336815305f016adf8ed6ae181e68a532 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 26 Jun 2026 12:39:28 +0200 Subject: gdbstub: Make default replay_mode value explicit in stubs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make explicit @replay_mode is stubbed as REPLAY_MODE_NONE. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-16-philmd@oss.qualcomm.com> --- stubs/replay-mode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stubs/replay-mode.c b/stubs/replay-mode.c index 439d97e4a8..5bc8f7d658 100644 --- a/stubs/replay-mode.c +++ b/stubs/replay-mode.c @@ -1,4 +1,4 @@ #include "qemu/osdep.h" #include "system/replay.h" -ReplayMode replay_mode; +ReplayMode replay_mode = REPLAY_MODE_NONE; -- cgit v1.2.3 From 2aaa8ee7dec5a8a10ec2c69ea774971e940f26d3 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 26 Jun 2026 12:41:49 +0200 Subject: accel: Hold @can_reverse information in AccelGdbConfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hold @can_reverse in AccelGdbConfig, set it when initializing AccelState in AccelClass::init_machine handlers (only TCG sets it). Remove gdb_can_reverse() as now unused. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Manos Pitsidianakis Message-ID: <20260705215729.62196-17-philmd@oss.qualcomm.com> --- accel/tcg/tcg-all.c | 3 +++ gdbstub/gdbstub.c | 4 ++-- gdbstub/internals.h | 1 - gdbstub/system.c | 5 ----- gdbstub/user.c | 6 ------ include/qemu/accel.h | 2 ++ 6 files changed, 7 insertions(+), 14 deletions(-) diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c index d30b53cd3b..7186c10cf0 100644 --- a/accel/tcg/tcg-all.c +++ b/accel/tcg/tcg-all.c @@ -159,6 +159,9 @@ static int tcg_init_machine(AccelState *as, MachineState *ms) */ as->gdbstub.sstep_flags |= SSTEP_NOIRQ | SSTEP_NOTIMER; } + if (replay_mode == REPLAY_MODE_PLAY) { + as->gdbstub.can_reverse = true; + } page_init(); tb_htable_init(); diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index 6c4fa06563..0a328b0dd4 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -1376,7 +1376,7 @@ static void handle_step(GArray *params, void *user_ctx) static void handle_backward(GArray *params, void *user_ctx) { - if (!gdb_can_reverse()) { + if (!gdbserver_state.accel_config.can_reverse) { gdb_put_packet("E22"); return; } @@ -1684,7 +1684,7 @@ static void handle_query_supported(GArray *params, void *user_ctx) g_string_append(gdbserver_state.str_buf, ";qXfer:features:read+"); } - if (gdb_can_reverse()) { + if (gdbserver_state.accel_config.can_reverse) { g_string_append(gdbserver_state.str_buf, ";ReverseStep+;ReverseContinue+"); } diff --git a/gdbstub/internals.h b/gdbstub/internals.h index 0444dee224..0b74ea4000 100644 --- a/gdbstub/internals.h +++ b/gdbstub/internals.h @@ -154,7 +154,6 @@ CPUState *gdb_first_attached_cpu(void); void gdb_append_thread_id(CPUState *cpu, GString *buf); int gdb_get_cpu_index(CPUState *cpu); unsigned int gdb_get_max_cpus(void); /* both */ -bool gdb_can_reverse(void); /* system emulation, stub for user */ int gdb_target_sigtrap(void); /* user */ void gdb_create_default_process(GDBState *s); diff --git a/gdbstub/system.c b/gdbstub/system.c index 1179c82cb8..2e8c457097 100644 --- a/gdbstub/system.c +++ b/gdbstub/system.c @@ -479,11 +479,6 @@ unsigned int gdb_get_max_cpus(void) return ms->smp.max_cpus; } -bool gdb_can_reverse(void) -{ - return replay_mode == REPLAY_MODE_PLAY; -} - /* * Softmmu specific command helpers */ diff --git a/gdbstub/user.c b/gdbstub/user.c index f7bc4e63df..299388b9f7 100644 --- a/gdbstub/user.c +++ b/gdbstub/user.c @@ -786,12 +786,6 @@ unsigned int gdb_get_max_cpus(void) return max_cpus; } -/* replay not supported for user-mode */ -bool gdb_can_reverse(void) -{ - return false; -} - /* * Break/Watch point helpers */ diff --git a/include/qemu/accel.h b/include/qemu/accel.h index 3b01d55741..8e0c3dfe08 100644 --- a/include/qemu/accel.h +++ b/include/qemu/accel.h @@ -77,9 +77,11 @@ void accel_cpu_common_unrealize(CPUState *cpu); * struct AccelGdbConfig - gdbstub configuration for an accelerator. * * @sstep_flags: Set SSTEP_* flags that accelerator supports for guest debug. + * @can_reverse: Whether reverse mode is supported. */ typedef struct AccelGdbConfig { unsigned sstep_flags; + bool can_reverse; } AccelGdbConfig; #endif /* QEMU_ACCEL_H */ -- cgit v1.2.3 From 0533f0841378ae17b96169a2ddafe8b1b010b09b Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 3 Jul 2026 15:06:57 +0200 Subject: accel: Remove AccelOpsClass::supports_guest_debug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now accelerators hold the 'guest debug supported' information in their state, accessible by the common code. No need to call a per-accelerator handler, simply check for the SSTEP_ENABLE in AccelGdbConfig::sstep_flags. Remove all AccelOpsClass::supports_guest_debug implementations, inline gdb_supports_guest_debug() and remove the now unnecessary KVMState::have_guest_debug field. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-18-philmd@oss.qualcomm.com> --- accel/accel-common.c | 5 +++++ accel/hvf/hvf-accel-ops.c | 1 - accel/kvm/kvm-accel-ops.c | 1 - accel/kvm/kvm-all.c | 13 +------------ accel/kvm/kvm-cpus.h | 1 - accel/tcg/tcg-accel-ops.c | 6 ------ accel/whpx/whpx-accel-ops.c | 6 ------ docs/system/gdb.rst | 2 +- gdbstub/system.c | 13 +------------ include/accel/accel-cpu-ops.h | 1 - include/qemu/accel.h | 2 ++ include/system/hvf_int.h | 5 ----- include/system/kvm_int.h | 1 - include/system/whpx-all.h | 3 --- target/arm/hvf/hvf.c | 5 ----- target/arm/whpx/whpx-all.c | 5 ----- target/i386/hvf/hvf.c | 5 ----- target/i386/whpx/whpx-all.c | 5 ----- 18 files changed, 10 insertions(+), 70 deletions(-) diff --git a/accel/accel-common.c b/accel/accel-common.c index f31d68a9b7..00a400243f 100644 --- a/accel/accel-common.c +++ b/accel/accel-common.c @@ -70,6 +70,11 @@ void accel_init_interfaces(AccelClass *ac) accel_init_cpu_interfaces(ac); } +bool accel_supports_guest_debug(AccelState *accel) +{ + return accel->gdbstub.sstep_flags & SSTEP_ENABLE; +} + void accel_cpu_instance_init(CPUState *cpu) { if (cpu->cc->accel_cpu && cpu->cc->accel_cpu->cpu_instance_init) { diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c index dd2b45b7cb..ecc0cd1b55 100644 --- a/accel/hvf/hvf-accel-ops.c +++ b/accel/hvf/hvf-accel-ops.c @@ -369,7 +369,6 @@ static void hvf_accel_ops_class_init(ObjectClass *oc, const void *data) ops->remove_breakpoint = hvf_remove_breakpoint; ops->remove_all_breakpoints = hvf_remove_all_breakpoints; ops->update_guest_debug = hvf_update_guest_debug; - ops->supports_guest_debug = hvf_arch_supports_guest_debug; ops->get_vcpu_stats = hvf_get_vcpu_stats; }; diff --git a/accel/kvm/kvm-accel-ops.c b/accel/kvm/kvm-accel-ops.c index d7967bc922..4533032790 100644 --- a/accel/kvm/kvm-accel-ops.c +++ b/accel/kvm/kvm-accel-ops.c @@ -105,7 +105,6 @@ static void kvm_accel_ops_class_init(ObjectClass *oc, const void *data) ops->synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm; ops->handle_interrupt = generic_handle_interrupt; - ops->supports_guest_debug = kvm_supports_guest_debug; #ifdef TARGET_KVM_HAVE_GUEST_DEBUG ops->update_guest_debug = kvm_update_guest_debug_ops; ops->insert_breakpoint = kvm_insert_breakpoint; diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index ceb0b33abd..b03488ebac 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -3036,10 +3036,7 @@ static int kvm_init(AccelState *as, MachineState *ms) (kvm_check_extension(s, KVM_CAP_VM_ATTRIBUTES) > 0); #ifdef TARGET_KVM_HAVE_GUEST_DEBUG - s->have_guest_debug = - (kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG) > 0); - - if (s->have_guest_debug) { + if (kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG) > 0) { as->gdbstub.sstep_flags = SSTEP_ENABLE; int guest_debug_flags = @@ -3829,14 +3826,6 @@ int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap) return data.err; } -bool kvm_supports_guest_debug(void) -{ - KVMState *s = KVM_STATE(as); - - /* probed during kvm_init() */ - return s->have_guest_debug; -} - int kvm_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len) { struct kvm_sw_breakpoint *bp; diff --git a/accel/kvm/kvm-cpus.h b/accel/kvm/kvm-cpus.h index 688511151c..3185659562 100644 --- a/accel/kvm/kvm-cpus.h +++ b/accel/kvm/kvm-cpus.h @@ -16,7 +16,6 @@ void kvm_destroy_vcpu(CPUState *cpu); void kvm_cpu_synchronize_post_reset(CPUState *cpu); void kvm_cpu_synchronize_post_init(CPUState *cpu); void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu); -bool kvm_supports_guest_debug(void); int kvm_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len); int kvm_remove_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len); void kvm_remove_all_breakpoints(CPUState *cpu); diff --git a/accel/tcg/tcg-accel-ops.c b/accel/tcg/tcg-accel-ops.c index c179cd4ade..927af6c1db 100644 --- a/accel/tcg/tcg-accel-ops.c +++ b/accel/tcg/tcg-accel-ops.c @@ -109,11 +109,6 @@ void tcg_handle_interrupt(CPUState *cpu, int mask) } } -static bool tcg_supports_guest_debug(void) -{ - return true; -} - /* Translate GDB watchpoint type to a flags value for cpu_watchpoint_* */ static inline int xlat_gdb_type(CPUState *cpu, int gdbtype) { @@ -221,7 +216,6 @@ static void tcg_accel_ops_init(AccelClass *ac) } ops->cpu_reset_hold = tcg_cpu_reset_hold; - ops->supports_guest_debug = tcg_supports_guest_debug; ops->insert_breakpoint = tcg_insert_breakpoint; ops->remove_breakpoint = tcg_remove_breakpoint; ops->remove_all_breakpoints = tcg_remove_all_breakpoints; diff --git a/accel/whpx/whpx-accel-ops.c b/accel/whpx/whpx-accel-ops.c index b8f41544cb..ca5a119521 100644 --- a/accel/whpx/whpx-accel-ops.c +++ b/accel/whpx/whpx-accel-ops.c @@ -82,11 +82,6 @@ static bool whpx_vcpu_thread_is_idle(CPUState *cpu) return !whpx_irqchip_in_kernel(); } -static bool whpx_supports_guest_debug(void) -{ - return whpx_arch_supports_guest_debug(); -} - static void whpx_accel_ops_class_init(ObjectClass *oc, const void *data) { @@ -96,7 +91,6 @@ static void whpx_accel_ops_class_init(ObjectClass *oc, const void *data) ops->kick_vcpu_thread = whpx_kick_vcpu_thread; ops->cpu_thread_is_idle = whpx_vcpu_thread_is_idle; ops->handle_interrupt = generic_handle_interrupt; - ops->supports_guest_debug = whpx_supports_guest_debug; ops->synchronize_post_reset = whpx_cpu_synchronize_post_reset; ops->synchronize_post_init = whpx_cpu_synchronize_post_init; diff --git a/docs/system/gdb.rst b/docs/system/gdb.rst index d50470b135..b6d8f8e77d 100644 --- a/docs/system/gdb.rst +++ b/docs/system/gdb.rst @@ -54,7 +54,7 @@ While GDB can always fall back to inserting breakpoints into memory accelerator. For TCG system emulation we advertise an infinite number of hardware assisted breakpoints and watchpoints. For other accelerators it will depend on if support has been added (see -supports_guest_debug and related hooks in AccelOpsClass). +the AccelGdbConfig structure). As TCG cannot track all memory accesses in user-mode there is no support for watchpoints. diff --git a/gdbstub/system.c b/gdbstub/system.c index 2e8c457097..bf7aa1ac23 100644 --- a/gdbstub/system.c +++ b/gdbstub/system.c @@ -331,8 +331,6 @@ static void create_processes(GDBState *s) gdb_create_default_process(s); } -static bool gdb_supports_guest_debug(void); - bool gdbserver_start(const char *device, Error **errp) { Chardev *chr = NULL; @@ -345,7 +343,7 @@ bool gdbserver_start(const char *device, Error **errp) return false; } - if (!gdb_supports_guest_debug()) { + if (!accel_supports_guest_debug(current_accel())) { error_setg(errp, "gdbstub: current accelerator doesn't " "support guest debugging"); return false; @@ -624,15 +622,6 @@ int gdb_signal_to_target(int sig) * Break/Watch point helpers */ -static bool gdb_supports_guest_debug(void) -{ - const AccelOpsClass *ops = cpus_get_accel(); - if (ops->supports_guest_debug) { - return ops->supports_guest_debug(); - } - return false; -} - int gdb_breakpoint_insert(CPUState *cs, int type, vaddr addr, vaddr len) { const AccelOpsClass *ops = cpus_get_accel(); diff --git a/include/accel/accel-cpu-ops.h b/include/accel/accel-cpu-ops.h index 9c07a903ea..b23a0606c7 100644 --- a/include/accel/accel-cpu-ops.h +++ b/include/accel/accel-cpu-ops.h @@ -84,7 +84,6 @@ struct AccelOpsClass { int64_t (*get_elapsed_ticks)(void); /* gdbstub hooks */ - bool (*supports_guest_debug)(void); int (*update_guest_debug)(CPUState *cpu); int (*insert_breakpoint)(CPUState *cpu, int type, vaddr addr, vaddr len); int (*remove_breakpoint)(CPUState *cpu, int type, vaddr addr, vaddr len); diff --git a/include/qemu/accel.h b/include/qemu/accel.h index 8e0c3dfe08..6f65f1cb89 100644 --- a/include/qemu/accel.h +++ b/include/qemu/accel.h @@ -84,4 +84,6 @@ typedef struct AccelGdbConfig { bool can_reverse; } AccelGdbConfig; +bool accel_supports_guest_debug(AccelState *accel); + #endif /* QEMU_ACCEL_H */ diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h index 58fb865eba..d64f494255 100644 --- a/include/system/hvf_int.h +++ b/include/system/hvf_int.h @@ -104,11 +104,6 @@ void hvf_arch_remove_all_hw_breakpoints(void); */ int hvf_update_guest_debug(CPUState *cpu); -/* - * Return whether the guest supports debugging. - */ -bool hvf_arch_supports_guest_debug(void); - bool hvf_arch_cpu_realize(CPUState *cpu, Error **errp); uint32_t hvf_arch_get_default_ipa_bit_size(void); uint32_t hvf_arch_get_max_ipa_bit_size(void); diff --git a/include/system/kvm_int.h b/include/system/kvm_int.h index 53bb0fcf18..0876aac938 100644 --- a/include/system/kvm_int.h +++ b/include/system/kvm_int.h @@ -118,7 +118,6 @@ struct KVMState #endif int max_nested_state_len; int kvm_shadow_mem; - bool have_guest_debug; bool kernel_irqchip_allowed; bool kernel_irqchip_required; OnOffAuto kernel_irqchip_split; diff --git a/include/system/whpx-all.h b/include/system/whpx-all.h index 4022571fff..d018e67e4f 100644 --- a/include/system/whpx-all.h +++ b/include/system/whpx-all.h @@ -22,7 +22,4 @@ void whpx_translate_cpu_breakpoints( void whpx_arch_destroy_vcpu(CPUState *cpu); void whpx_arch_accel_class_init(ObjectClass *oc); -/* called by whpx-accel-ops */ -bool whpx_arch_supports_guest_debug(void); - #endif diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index 8b902c6882..e16457c3cf 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -2900,8 +2900,3 @@ void hvf_arch_update_guest_debug(CPUState *cpu) hvf_arch_set_traps(cpu); } - -bool hvf_arch_supports_guest_debug(void) -{ - return true; -} diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c index 3079c6293c..00a5de8cdc 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 */ } -bool whpx_arch_supports_guest_debug(void) -{ - return false; -} - void whpx_arch_destroy_vcpu(CPUState *cpu) { /* currently empty on Arm */ diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 2d1a943b96..19ad64a1d9 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -1066,8 +1066,3 @@ void hvf_arch_remove_all_hw_breakpoints(void) void hvf_arch_update_guest_debug(CPUState *cpu) { } - -bool hvf_arch_supports_guest_debug(void) -{ - return false; -} diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c index 467ac6bed4..11b5d1fc60 100644 --- a/target/i386/whpx/whpx-all.c +++ b/target/i386/whpx/whpx-all.c @@ -1853,11 +1853,6 @@ void whpx_apply_breakpoints( } } -bool whpx_arch_supports_guest_debug(void) -{ - return true; -} - void whpx_arch_destroy_vcpu(CPUState *cpu) { X86CPU *x86cpu = X86_CPU(cpu); -- cgit v1.2.3 From 032731dbafb6a21173205230270dadfa01080af3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 30 Jun 2026 20:04:29 -0700 Subject: cpu: Move cpu_breakpoint_test out of line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the function to cpu-common.c, with the other breakpoint functions. Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20260705215729.62196-19-philmd@oss.qualcomm.com> --- cpu-common.c | 15 +++++++++++++++ include/hw/core/cpu.h | 16 +--------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/cpu-common.c b/cpu-common.c index 988d057d84..adb76b3a78 100644 --- a/cpu-common.c +++ b/cpu-common.c @@ -388,6 +388,21 @@ void process_queued_cpu_work(CPUState *cpu) qemu_cond_broadcast(&qemu_work_cond); } +/* Return true if PC matches an installed breakpoint. */ +bool cpu_breakpoint_test(CPUState *cpu, vaddr pc, int mask) +{ + CPUBreakpoint *bp; + + if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) { + QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { + if (bp->pc == pc && (bp->flags & mask)) { + return true; + } + } + } + return false; +} + /* Add a breakpoint. */ int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, CPUBreakpoint **breakpoint) diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 60a23d6f38..31753f331f 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -1157,21 +1157,7 @@ int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags); void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint); void cpu_breakpoint_remove_all(CPUState *cpu, int mask); - -/* Return true if PC matches an installed breakpoint. */ -static inline bool cpu_breakpoint_test(CPUState *cpu, vaddr pc, int mask) -{ - CPUBreakpoint *bp; - - if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) { - QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { - if (bp->pc == pc && (bp->flags & mask)) { - return true; - } - } - } - return false; -} +bool cpu_breakpoint_test(CPUState *cpu, vaddr pc, int mask); /** * cpu_get_address_space: -- cgit v1.2.3 From fe90b5f15b4523e8def87a1a703dba86601d1f67 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Mon, 29 Jun 2026 08:55:13 +0200 Subject: cpu: Move BREAKPOINT definitions to 'exec/breakpoint.h' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-20-philmd@oss.qualcomm.com> --- include/exec/breakpoint.h | 14 ++++++++++++++ include/hw/core/cpu.h | 14 -------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/exec/breakpoint.h b/include/exec/breakpoint.h index 95f0482e6d..cc6fedd09f 100644 --- a/include/exec/breakpoint.h +++ b/include/exec/breakpoint.h @@ -12,6 +12,20 @@ #include "exec/vaddr.h" #include "exec/memattrs.h" +/* Breakpoint/watchpoint flags */ +#define BP_MEM_READ 0x01 +#define BP_MEM_WRITE 0x02 +#define BP_MEM_ACCESS (BP_MEM_READ | BP_MEM_WRITE) +#define BP_STOP_BEFORE_ACCESS 0x04 +/* 0x08 currently unused */ +#define BP_GDB 0x10 +#define BP_CPU 0x20 +#define BP_ANY (BP_GDB | BP_CPU) +#define BP_HIT_SHIFT 6 +#define BP_WATCHPOINT_HIT_READ (BP_MEM_READ << BP_HIT_SHIFT) +#define BP_WATCHPOINT_HIT_WRITE (BP_MEM_WRITE << BP_HIT_SHIFT) +#define BP_WATCHPOINT_HIT (BP_MEM_ACCESS << BP_HIT_SHIFT) + typedef struct CPUBreakpoint { vaddr pc; int flags; /* BP_* */ diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 31753f331f..e5b68bced3 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -1138,20 +1138,6 @@ void qemu_init_vcpu(CPUState *cpu); */ void cpu_single_step(CPUState *cpu, int enabled); -/* Breakpoint/watchpoint flags */ -#define BP_MEM_READ 0x01 -#define BP_MEM_WRITE 0x02 -#define BP_MEM_ACCESS (BP_MEM_READ | BP_MEM_WRITE) -#define BP_STOP_BEFORE_ACCESS 0x04 -/* 0x08 currently unused */ -#define BP_GDB 0x10 -#define BP_CPU 0x20 -#define BP_ANY (BP_GDB | BP_CPU) -#define BP_HIT_SHIFT 6 -#define BP_WATCHPOINT_HIT_READ (BP_MEM_READ << BP_HIT_SHIFT) -#define BP_WATCHPOINT_HIT_WRITE (BP_MEM_WRITE << BP_HIT_SHIFT) -#define BP_WATCHPOINT_HIT (BP_MEM_ACCESS << BP_HIT_SHIFT) - int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, CPUBreakpoint **breakpoint); int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags); -- cgit v1.2.3 From 9dfa834009e14c85da93db7f767aad53a189c815 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 26 Jun 2026 16:40:06 +0200 Subject: accel: Remove unnecessary 'inline' qualifier in remove_all_breakpoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-22-philmd@oss.qualcomm.com> --- accel/tcg/tcg-accel-ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accel/tcg/tcg-accel-ops.c b/accel/tcg/tcg-accel-ops.c index 927af6c1db..1043fc6187 100644 --- a/accel/tcg/tcg-accel-ops.c +++ b/accel/tcg/tcg-accel-ops.c @@ -188,7 +188,7 @@ static int tcg_remove_breakpoint(CPUState *cs, int type, vaddr addr, vaddr len) } } -static inline void tcg_remove_all_breakpoints(CPUState *cpu) +static void tcg_remove_all_breakpoints(CPUState *cpu) { cpu_breakpoint_remove_all(cpu, BP_GDB); cpu_watchpoint_remove_all(cpu, BP_GDB); -- cgit v1.2.3 From 9285f1a2159e87a3caecd594fd7c02616984f5fc Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 26 Jun 2026 16:44:36 +0200 Subject: gdbstub/user: Directly call gdb_breakpoint_remove_all() in user mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to deref external methods with unused argument to end up calling a method defined in the same unit file, call it directly. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-23-philmd@oss.qualcomm.com> --- gdbstub/user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gdbstub/user.c b/gdbstub/user.c index 299388b9f7..90d6ee49fb 100644 --- a/gdbstub/user.c +++ b/gdbstub/user.c @@ -557,7 +557,7 @@ static void disable_gdbstub(CPUState *thread_cpu) close(gdbserver_user_state.fd); gdbserver_user_state.fd = -1; CPU_FOREACH(cpu) { - cpu_breakpoint_remove_all(cpu, BP_GDB); + gdb_breakpoint_remove_all(cpu); /* no cpu_watchpoint_remove_all for user-mode */ cpu_single_step(cpu, 0); } -- cgit v1.2.3 From 85b6e24fa2a84ab980c5e26f8524b1f1b8649d54 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Tue, 30 Jun 2026 12:22:44 +0200 Subject: gdbstub: Reduce @type variable scope MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-24-philmd@oss.qualcomm.com> --- gdbstub/system.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gdbstub/system.c b/gdbstub/system.c index bf7aa1ac23..9c4bd8ebcb 100644 --- a/gdbstub/system.c +++ b/gdbstub/system.c @@ -125,7 +125,6 @@ static void gdb_vm_state_change(void *opaque, bool running, RunState state) CPUState *cpu = gdbserver_state.c_cpu; g_autoptr(GString) buf = g_string_new(NULL); g_autoptr(GString) tid = g_string_new(NULL); - const char *type; int ret; if (running || gdbserver_state.state == RS_INACTIVE) { @@ -151,6 +150,8 @@ static void gdb_vm_state_change(void *opaque, bool running, RunState state) switch (state) { case RUN_STATE_DEBUG: if (cpu->watchpoint_hit) { + const char *type; + switch (cpu->watchpoint_hit->flags & BP_MEM_ACCESS) { case BP_MEM_READ: type = "r"; -- cgit v1.2.3 From af97fe2eafe4acebf13bdcb64de32d67a2e5a237 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 26 Jun 2026 17:30:59 +0200 Subject: gdbstub: Introduce GdbBreakpointType enumerator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce the GdbBreakpointType enumerator to better follow code related to GDB protocol handling. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-25-philmd@oss.qualcomm.com> --- gdbstub/internals.h | 7 +++++-- gdbstub/system.c | 6 ++++-- gdbstub/user.c | 6 ++++-- include/gdbstub/enums.h | 12 +++++++----- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/gdbstub/internals.h b/gdbstub/internals.h index 0b74ea4000..33f68672d1 100644 --- a/gdbstub/internals.h +++ b/gdbstub/internals.h @@ -11,6 +11,7 @@ #include "qemu/accel.h" #include "exec/cpu-common.h" +#include "gdbstub/enums.h" /* * Most "large" transfers (e.g. memory reads, feature XML @@ -217,8 +218,10 @@ void gdb_syscall_handling(const char *syscall_packet); * Break/Watch point support - there is an implementation for system * and user mode. */ -int gdb_breakpoint_insert(CPUState *cs, int type, vaddr addr, vaddr len); -int gdb_breakpoint_remove(CPUState *cs, int type, vaddr addr, vaddr len); +int gdb_breakpoint_insert(CPUState *cs, GdbBreakpointType type, + vaddr addr, vaddr len); +int gdb_breakpoint_remove(CPUState *cs, GdbBreakpointType type, + vaddr addr, vaddr len); void gdb_breakpoint_remove_all(CPUState *cs); /** diff --git a/gdbstub/system.c b/gdbstub/system.c index 9c4bd8ebcb..6e2dbc823e 100644 --- a/gdbstub/system.c +++ b/gdbstub/system.c @@ -623,7 +623,8 @@ int gdb_signal_to_target(int sig) * Break/Watch point helpers */ -int gdb_breakpoint_insert(CPUState *cs, int type, vaddr addr, vaddr len) +int gdb_breakpoint_insert(CPUState *cs, GdbBreakpointType type, + vaddr addr, vaddr len) { const AccelOpsClass *ops = cpus_get_accel(); if (ops->insert_breakpoint) { @@ -632,7 +633,8 @@ int gdb_breakpoint_insert(CPUState *cs, int type, vaddr addr, vaddr len) return -ENOSYS; } -int gdb_breakpoint_remove(CPUState *cs, int type, vaddr addr, vaddr len) +int gdb_breakpoint_remove(CPUState *cs, GdbBreakpointType type, + vaddr addr, vaddr len) { const AccelOpsClass *ops = cpus_get_accel(); if (ops->remove_breakpoint) { diff --git a/gdbstub/user.c b/gdbstub/user.c index 90d6ee49fb..9e6f9a6f37 100644 --- a/gdbstub/user.c +++ b/gdbstub/user.c @@ -790,7 +790,8 @@ unsigned int gdb_get_max_cpus(void) * Break/Watch point helpers */ -int gdb_breakpoint_insert(CPUState *cs, int type, vaddr addr, vaddr len) +int gdb_breakpoint_insert(CPUState *cs, GdbBreakpointType type, + vaddr addr, vaddr len) { CPUState *cpu; int err = 0; @@ -811,7 +812,8 @@ int gdb_breakpoint_insert(CPUState *cs, int type, vaddr addr, vaddr len) } } -int gdb_breakpoint_remove(CPUState *cs, int type, vaddr addr, vaddr len) +int gdb_breakpoint_remove(CPUState *cs, GdbBreakpointType type, + vaddr addr, vaddr len) { CPUState *cpu; int err = 0; diff --git a/include/gdbstub/enums.h b/include/gdbstub/enums.h index c4d54a1d08..e4e2043d92 100644 --- a/include/gdbstub/enums.h +++ b/include/gdbstub/enums.h @@ -12,10 +12,12 @@ #define DEFAULT_GDBSTUB_PORT "1234" /* GDB breakpoint/watchpoint types */ -#define GDB_BREAKPOINT_SW 0 -#define GDB_BREAKPOINT_HW 1 -#define GDB_WATCHPOINT_WRITE 2 -#define GDB_WATCHPOINT_READ 3 -#define GDB_WATCHPOINT_ACCESS 4 +typedef enum GdbBreakpointType { + GDB_BREAKPOINT_SW = 0, + GDB_BREAKPOINT_HW = 1, + GDB_WATCHPOINT_WRITE = 2, + GDB_WATCHPOINT_READ = 3, + GDB_WATCHPOINT_ACCESS = 4, +} GdbBreakpointType; #endif /* GDBSTUB_ENUMS_H */ -- cgit v1.2.3 From 0c4f68b2e340d52d2878fac1cd21c43e661f5c6b Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 26 Jun 2026 17:30:59 +0200 Subject: accel: Use GdbBreakpointType enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include '_gdbstub_' in the AccelOpsClass handlers to emphasize we are handling gdbstub-related requests. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-26-philmd@oss.qualcomm.com> --- accel/hvf/hvf-accel-ops.c | 20 +++++++++++--------- accel/kvm/kvm-accel-ops.c | 6 +++--- accel/kvm/kvm-all.c | 14 ++++++++------ accel/kvm/kvm-cpus.h | 11 ++++++++--- accel/tcg/tcg-accel-ops.c | 16 +++++++++------- gdbstub/system.c | 12 ++++++------ include/accel/accel-cpu-ops.h | 9 ++++++--- include/system/hvf_int.h | 9 ++++++--- include/system/kvm.h | 9 ++++++--- target/arm/hvf/hvf.c | 12 +++++++----- target/arm/hyp_gdbstub.c | 8 ++++---- target/arm/internals.h | 5 +++-- target/arm/kvm.c | 12 +++++++----- target/i386/hvf/hvf.c | 8 +++++--- target/i386/kvm/kvm.c | 12 +++++++----- target/loongarch/kvm/kvm.c | 8 +++++--- target/ppc/kvm.c | 12 +++++++----- target/riscv/kvm/kvm-cpu.c | 8 +++++--- target/s390x/kvm/kvm.c | 8 +++++--- 19 files changed, 118 insertions(+), 81 deletions(-) diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c index ecc0cd1b55..d2276d8513 100644 --- a/accel/hvf/hvf-accel-ops.c +++ b/accel/hvf/hvf-accel-ops.c @@ -233,7 +233,8 @@ int hvf_update_guest_debug(CPUState *cpu) return 0; } -static int hvf_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len) +static int hvf_insert_gdbstub_breakpoint(CPUState *cpu, GdbBreakpointType type, + vaddr addr, vaddr len) { struct hvf_sw_breakpoint *bp; int err; @@ -256,7 +257,7 @@ static int hvf_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len) QTAILQ_INSERT_HEAD(&hvf_state->hvf_sw_breakpoints, bp, entry); } else { - err = hvf_arch_insert_hw_breakpoint(addr, len, type); + err = hvf_arch_insert_gdbstub_hw_breakpoint(addr, len, type); if (err) { return err; } @@ -271,7 +272,8 @@ static int hvf_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len) return 0; } -static int hvf_remove_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len) +static int hvf_remove_gdbstub_breakpoint(CPUState *cpu, GdbBreakpointType type, + vaddr addr, vaddr len) { struct hvf_sw_breakpoint *bp; int err; @@ -295,7 +297,7 @@ static int hvf_remove_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len) QTAILQ_REMOVE(&hvf_state->hvf_sw_breakpoints, bp, entry); g_free(bp); } else { - err = hvf_arch_remove_hw_breakpoint(addr, len, type); + err = hvf_arch_remove_gdbstub_hw_breakpoint(addr, len, type); if (err) { return err; } @@ -310,7 +312,7 @@ static int hvf_remove_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len) return 0; } -static void hvf_remove_all_breakpoints(CPUState *cpu) +static void hvf_remove_all_gdbstub_breakpoints(CPUState *cpu) { struct hvf_sw_breakpoint *bp, *next; CPUState *tmpcpu; @@ -328,7 +330,7 @@ static void hvf_remove_all_breakpoints(CPUState *cpu) QTAILQ_REMOVE(&hvf_state->hvf_sw_breakpoints, bp, entry); g_free(bp); } - hvf_arch_remove_all_hw_breakpoints(); + hvf_arch_remove_all_gdbstub_hw_breakpoints(); CPU_FOREACH(cpu) { hvf_update_guest_debug(cpu); @@ -365,9 +367,9 @@ static void hvf_accel_ops_class_init(ObjectClass *oc, const void *data) ops->synchronize_state = hvf_cpu_synchronize_state; ops->synchronize_pre_loadvm = hvf_cpu_synchronize_pre_loadvm; - ops->insert_breakpoint = hvf_insert_breakpoint; - ops->remove_breakpoint = hvf_remove_breakpoint; - ops->remove_all_breakpoints = hvf_remove_all_breakpoints; + ops->insert_gdbstub_breakpoint = hvf_insert_gdbstub_breakpoint; + ops->remove_gdbstub_breakpoint = hvf_remove_gdbstub_breakpoint; + ops->remove_all_gdbstub_breakpoints = hvf_remove_all_gdbstub_breakpoints; ops->update_guest_debug = hvf_update_guest_debug; ops->get_vcpu_stats = hvf_get_vcpu_stats; diff --git a/accel/kvm/kvm-accel-ops.c b/accel/kvm/kvm-accel-ops.c index 4533032790..c8e7aa3870 100644 --- a/accel/kvm/kvm-accel-ops.c +++ b/accel/kvm/kvm-accel-ops.c @@ -107,9 +107,9 @@ static void kvm_accel_ops_class_init(ObjectClass *oc, const void *data) #ifdef TARGET_KVM_HAVE_GUEST_DEBUG ops->update_guest_debug = kvm_update_guest_debug_ops; - ops->insert_breakpoint = kvm_insert_breakpoint; - ops->remove_breakpoint = kvm_remove_breakpoint; - ops->remove_all_breakpoints = kvm_remove_all_breakpoints; + ops->insert_gdbstub_breakpoint = kvm_insert_gdbstub_breakpoint; + ops->remove_gdbstub_breakpoint = kvm_remove_gdbstub_breakpoint; + ops->remove_all_gdbstub_breakpoints = kvm_remove_all_gdbstub_breakpoints; #endif } diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index b03488ebac..feffca0d82 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -3826,7 +3826,8 @@ int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap) return data.err; } -int kvm_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len) +int kvm_insert_gdbstub_breakpoint(CPUState *cpu, GdbBreakpointType type, + vaddr addr, vaddr len) { struct kvm_sw_breakpoint *bp; int err; @@ -3849,7 +3850,7 @@ int kvm_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len) QTAILQ_INSERT_HEAD(&cpu->kvm_state->kvm_sw_breakpoints, bp, entry); } else { - err = kvm_arch_insert_hw_breakpoint(addr, len, type); + err = kvm_arch_insert_gdbstub_hw_breakpoint(addr, len, type); if (err) { return err; } @@ -3864,7 +3865,8 @@ int kvm_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len) return 0; } -int kvm_remove_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len) +int kvm_remove_gdbstub_breakpoint(CPUState *cpu, GdbBreakpointType type, + vaddr addr, vaddr len) { struct kvm_sw_breakpoint *bp; int err; @@ -3888,7 +3890,7 @@ int kvm_remove_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len) QTAILQ_REMOVE(&cpu->kvm_state->kvm_sw_breakpoints, bp, entry); g_free(bp); } else { - err = kvm_arch_remove_hw_breakpoint(addr, len, type); + err = kvm_arch_remove_gdbstub_hw_breakpoint(addr, len, type); if (err) { return err; } @@ -3903,7 +3905,7 @@ int kvm_remove_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len) return 0; } -void kvm_remove_all_breakpoints(CPUState *cpu) +void kvm_remove_all_gdbstub_breakpoints(CPUState *cpu) { struct kvm_sw_breakpoint *bp, *next; KVMState *s = cpu->kvm_state; @@ -3921,7 +3923,7 @@ void kvm_remove_all_breakpoints(CPUState *cpu) QTAILQ_REMOVE(&s->kvm_sw_breakpoints, bp, entry); g_free(bp); } - kvm_arch_remove_all_hw_breakpoints(); + kvm_arch_remove_all_gdbstub_hw_breakpoints(); CPU_FOREACH(cpu) { kvm_update_guest_debug(cpu, 0); diff --git a/accel/kvm/kvm-cpus.h b/accel/kvm/kvm-cpus.h index 3185659562..bc2dd82e68 100644 --- a/accel/kvm/kvm-cpus.h +++ b/accel/kvm/kvm-cpus.h @@ -10,13 +10,18 @@ #ifndef KVM_CPUS_H #define KVM_CPUS_H +#include "gdbstub/enums.h" + int kvm_init_vcpu(CPUState *cpu, Error **errp); int kvm_cpu_exec(CPUState *cpu); void kvm_destroy_vcpu(CPUState *cpu); void kvm_cpu_synchronize_post_reset(CPUState *cpu); void kvm_cpu_synchronize_post_init(CPUState *cpu); void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu); -int kvm_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len); -int kvm_remove_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len); -void kvm_remove_all_breakpoints(CPUState *cpu); +int kvm_insert_gdbstub_breakpoint(CPUState *cpu, GdbBreakpointType type, + vaddr addr, vaddr len); +int kvm_remove_gdbstub_breakpoint(CPUState *cpu, GdbBreakpointType type, + vaddr addr, vaddr len); +void kvm_remove_all_gdbstub_breakpoints(CPUState *cpu); + #endif /* KVM_CPUS_H */ diff --git a/accel/tcg/tcg-accel-ops.c b/accel/tcg/tcg-accel-ops.c index 1043fc6187..560fe2554b 100644 --- a/accel/tcg/tcg-accel-ops.c +++ b/accel/tcg/tcg-accel-ops.c @@ -110,7 +110,7 @@ void tcg_handle_interrupt(CPUState *cpu, int mask) } /* Translate GDB watchpoint type to a flags value for cpu_watchpoint_* */ -static inline int xlat_gdb_type(CPUState *cpu, int gdbtype) +static inline int xlat_gdb_type(CPUState *cpu, GdbBreakpointType gdbtype) { static const int xlat[] = { [GDB_WATCHPOINT_WRITE] = BP_GDB | BP_MEM_WRITE, @@ -126,7 +126,8 @@ static inline int xlat_gdb_type(CPUState *cpu, int gdbtype) return cputype; } -static int tcg_insert_breakpoint(CPUState *cs, int type, vaddr addr, vaddr len) +static int tcg_insert_gdbstub_breakpoint(CPUState *cs, GdbBreakpointType type, + vaddr addr, vaddr len) { CPUState *cpu; int err = 0; @@ -157,7 +158,8 @@ static int tcg_insert_breakpoint(CPUState *cs, int type, vaddr addr, vaddr len) } } -static int tcg_remove_breakpoint(CPUState *cs, int type, vaddr addr, vaddr len) +static int tcg_remove_gdbstub_breakpoint(CPUState *cs, GdbBreakpointType type, + vaddr addr, vaddr len) { CPUState *cpu; int err = 0; @@ -188,7 +190,7 @@ static int tcg_remove_breakpoint(CPUState *cs, int type, vaddr addr, vaddr len) } } -static void tcg_remove_all_breakpoints(CPUState *cpu) +static void tcg_remove_all_gdbstub_breakpoints(CPUState *cpu) { cpu_breakpoint_remove_all(cpu, BP_GDB); cpu_watchpoint_remove_all(cpu, BP_GDB); @@ -216,9 +218,9 @@ static void tcg_accel_ops_init(AccelClass *ac) } ops->cpu_reset_hold = tcg_cpu_reset_hold; - ops->insert_breakpoint = tcg_insert_breakpoint; - ops->remove_breakpoint = tcg_remove_breakpoint; - ops->remove_all_breakpoints = tcg_remove_all_breakpoints; + ops->insert_gdbstub_breakpoint = tcg_insert_gdbstub_breakpoint; + ops->remove_gdbstub_breakpoint = tcg_remove_gdbstub_breakpoint; + ops->remove_all_gdbstub_breakpoints = tcg_remove_all_gdbstub_breakpoints; } static void tcg_accel_ops_class_init(ObjectClass *oc, const void *data) diff --git a/gdbstub/system.c b/gdbstub/system.c index 6e2dbc823e..3098fd5574 100644 --- a/gdbstub/system.c +++ b/gdbstub/system.c @@ -627,8 +627,8 @@ int gdb_breakpoint_insert(CPUState *cs, GdbBreakpointType type, vaddr addr, vaddr len) { const AccelOpsClass *ops = cpus_get_accel(); - if (ops->insert_breakpoint) { - return ops->insert_breakpoint(cs, type, addr, len); + if (ops->insert_gdbstub_breakpoint) { + return ops->insert_gdbstub_breakpoint(cs, type, addr, len); } return -ENOSYS; } @@ -637,8 +637,8 @@ int gdb_breakpoint_remove(CPUState *cs, GdbBreakpointType type, vaddr addr, vaddr len) { const AccelOpsClass *ops = cpus_get_accel(); - if (ops->remove_breakpoint) { - return ops->remove_breakpoint(cs, type, addr, len); + if (ops->remove_gdbstub_breakpoint) { + return ops->remove_gdbstub_breakpoint(cs, type, addr, len); } return -ENOSYS; } @@ -646,8 +646,8 @@ int gdb_breakpoint_remove(CPUState *cs, GdbBreakpointType type, void gdb_breakpoint_remove_all(CPUState *cs) { const AccelOpsClass *ops = cpus_get_accel(); - if (ops->remove_all_breakpoints) { - ops->remove_all_breakpoints(cs); + if (ops->remove_all_gdbstub_breakpoints) { + ops->remove_all_gdbstub_breakpoints(cs); } } diff --git a/include/accel/accel-cpu-ops.h b/include/accel/accel-cpu-ops.h index b23a0606c7..f0c7ee7542 100644 --- a/include/accel/accel-cpu-ops.h +++ b/include/accel/accel-cpu-ops.h @@ -13,6 +13,7 @@ #include "qemu/accel.h" #include "exec/vaddr.h" #include "qom/object.h" +#include "gdbstub/enums.h" #define ACCEL_OPS_SUFFIX "-ops" #define TYPE_ACCEL_OPS "accel" ACCEL_OPS_SUFFIX @@ -85,9 +86,11 @@ struct AccelOpsClass { /* gdbstub hooks */ int (*update_guest_debug)(CPUState *cpu); - int (*insert_breakpoint)(CPUState *cpu, int type, vaddr addr, vaddr len); - int (*remove_breakpoint)(CPUState *cpu, int type, vaddr addr, vaddr len); - void (*remove_all_breakpoints)(CPUState *cpu); + int (*insert_gdbstub_breakpoint)(CPUState *cpu, GdbBreakpointType type, + vaddr addr, vaddr len); + int (*remove_gdbstub_breakpoint)(CPUState *cpu, GdbBreakpointType type, + vaddr addr, vaddr len); + void (*remove_all_gdbstub_breakpoints)(CPUState *cpu); }; void generic_handle_interrupt(CPUState *cpu, int mask); diff --git a/include/system/hvf_int.h b/include/system/hvf_int.h index d64f494255..a01691ce17 100644 --- a/include/system/hvf_int.h +++ b/include/system/hvf_int.h @@ -13,6 +13,7 @@ #include "qemu/queue.h" #include "exec/vaddr.h" +#include "gdbstub/enums.h" #include "qom/object.h" #include "accel/accel-ops.h" @@ -91,9 +92,11 @@ int hvf_sw_breakpoints_active(CPUState *cpu); int hvf_arch_insert_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp); int hvf_arch_remove_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp); -int hvf_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type); -int hvf_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type); -void hvf_arch_remove_all_hw_breakpoints(void); +int hvf_arch_insert_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type); +int hvf_arch_remove_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type); +void hvf_arch_remove_all_gdbstub_hw_breakpoints(void); /* * hvf_update_guest_debug: diff --git a/include/system/kvm.h b/include/system/kvm.h index cdd1856ac5..714b8c7b01 100644 --- a/include/system/kvm.h +++ b/include/system/kvm.h @@ -17,6 +17,7 @@ #define QEMU_KVM_H #include "exec/memattrs.h" +#include "gdbstub/enums.h" #include "qemu/accel.h" #include "accel/accel-route.h" #include "qom/object.h" @@ -412,9 +413,11 @@ int kvm_arch_insert_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp); int kvm_arch_remove_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp); -int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type); -int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type); -void kvm_arch_remove_all_hw_breakpoints(void); +int kvm_arch_insert_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type); +int kvm_arch_remove_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type); +void kvm_arch_remove_all_gdbstub_hw_breakpoints(void); void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg); diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index e16457c3cf..d5b1966a86 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -2726,7 +2726,8 @@ int hvf_arch_remove_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp) return 0; } -int hvf_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type) +int hvf_arch_insert_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type) { switch (type) { case GDB_BREAKPOINT_HW: @@ -2734,13 +2735,14 @@ int hvf_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type) case GDB_WATCHPOINT_READ: case GDB_WATCHPOINT_WRITE: case GDB_WATCHPOINT_ACCESS: - return insert_hw_watchpoint(addr, len, type); + return insert_gdbstub_hw_watchpoint(addr, len, type); default: return -ENOSYS; } } -int hvf_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type) +int hvf_arch_remove_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type) { switch (type) { case GDB_BREAKPOINT_HW: @@ -2748,13 +2750,13 @@ int hvf_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type) case GDB_WATCHPOINT_READ: case GDB_WATCHPOINT_WRITE: case GDB_WATCHPOINT_ACCESS: - return delete_hw_watchpoint(addr, len, type); + return delete_gdbstub_hw_watchpoint(addr, len, type); default: return -ENOSYS; } } -void hvf_arch_remove_all_hw_breakpoints(void) +void hvf_arch_remove_all_gdbstub_hw_breakpoints(void) { if (cur_hw_wps > 0) { g_array_remove_range(hw_watchpoints, 0, cur_hw_wps); diff --git a/target/arm/hyp_gdbstub.c b/target/arm/hyp_gdbstub.c index bb5969720c..dda6946dda 100644 --- a/target/arm/hyp_gdbstub.c +++ b/target/arm/hyp_gdbstub.c @@ -94,7 +94,7 @@ int delete_hw_breakpoint(vaddr pc) } /** - * insert_hw_watchpoint() + * insert_gdbstub_hw_watchpoint() * @addr: address of watch point * @len: size of area * @type: type of watch point @@ -125,7 +125,7 @@ int delete_hw_breakpoint(vaddr pc) * need to ensure you mask the address as required and set BAS=0xff */ -int insert_hw_watchpoint(vaddr addr, vaddr len, int type) +int insert_gdbstub_hw_watchpoint(vaddr addr, vaddr len, GdbBreakpointType type) { HWWatchpoint wp = { .wcr = R_DBGWCR_E_MASK, /* E=1, enable */ @@ -208,13 +208,13 @@ bool check_watchpoint_in_range(int i, vaddr addr) } /** - * delete_hw_watchpoint() + * delete_gdbstub_hw_watchpoint() * @addr: address of breakpoint * * Delete a breakpoint and shuffle any above down */ -int delete_hw_watchpoint(vaddr addr, vaddr len, int type) +int delete_gdbstub_hw_watchpoint(vaddr addr, vaddr len, GdbBreakpointType type) { int i; for (i = 0; i < cur_hw_wps; i++) { diff --git a/target/arm/internals.h b/target/arm/internals.h index fcce3804f3..067c3f2b8b 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -29,6 +29,7 @@ #include "exec/vaddr.h" #include "exec/breakpoint.h" #include "exec/memop.h" +#include "gdbstub/enums.h" #ifdef CONFIG_TCG #include "accel/tcg/tb-cpu-state.h" #include "tcg/tcg-gvec-desc.h" @@ -1968,8 +1969,8 @@ int delete_hw_breakpoint(vaddr pc); bool check_watchpoint_in_range(int i, vaddr addr); CPUWatchpoint *find_hw_watchpoint(CPUState *cpu, vaddr addr); -int insert_hw_watchpoint(vaddr addr, vaddr len, int type); -int delete_hw_watchpoint(vaddr addr, vaddr len, int type); +int insert_gdbstub_hw_watchpoint(vaddr addr, vaddr len, GdbBreakpointType type); +int delete_gdbstub_hw_watchpoint(vaddr addr, vaddr len, GdbBreakpointType type); /* Return the current value of the system counter in ticks */ uint64_t gt_get_countervalue(CPUARMState *env); diff --git a/target/arm/kvm.c b/target/arm/kvm.c index a54ef51ec2..01f42f4253 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -1784,7 +1784,8 @@ void kvm_arch_accel_class_init(ObjectClass *oc) "Eager Page Split chunk size for hugepages. (default: 0, disabled)"); } -int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type) +int kvm_arch_insert_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type) { switch (type) { case GDB_BREAKPOINT_HW: @@ -1793,13 +1794,14 @@ int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type) case GDB_WATCHPOINT_READ: case GDB_WATCHPOINT_WRITE: case GDB_WATCHPOINT_ACCESS: - return insert_hw_watchpoint(addr, len, type); + return insert_gdbstub_hw_watchpoint(addr, len, type); default: return -ENOSYS; } } -int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type) +int kvm_arch_remove_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type) { switch (type) { case GDB_BREAKPOINT_HW: @@ -1807,13 +1809,13 @@ int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type) case GDB_WATCHPOINT_READ: case GDB_WATCHPOINT_WRITE: case GDB_WATCHPOINT_ACCESS: - return delete_hw_watchpoint(addr, len, type); + return delete_gdbstub_hw_watchpoint(addr, len, type); default: return -ENOSYS; } } -void kvm_arch_remove_all_hw_breakpoints(void) +void kvm_arch_remove_all_gdbstub_hw_breakpoints(void) { if (cur_hw_wps > 0) { g_array_remove_range(hw_watchpoints, 0, cur_hw_wps); diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 19ad64a1d9..150598418e 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -1049,17 +1049,19 @@ int hvf_arch_remove_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp) return -ENOSYS; } -int hvf_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type) +int hvf_arch_insert_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type) { return -ENOSYS; } -int hvf_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type) +int hvf_arch_remove_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type) { return -ENOSYS; } -void hvf_arch_remove_all_hw_breakpoints(void) +void hvf_arch_remove_all_gdbstub_hw_breakpoints(void) { } diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 64cc421abe..1e09155e92 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -6159,12 +6159,12 @@ int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) static struct { target_ulong addr; int len; - int type; + GdbBreakpointType type; } hw_breakpoint[4]; static int nb_hw_breakpoint; -static int find_hw_breakpoint(target_ulong addr, int len, int type) +static int find_hw_breakpoint(target_ulong addr, int len, GdbBreakpointType type) { int n; @@ -6177,7 +6177,8 @@ static int find_hw_breakpoint(target_ulong addr, int len, int type) return -1; } -int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type) +int kvm_arch_insert_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type) { switch (type) { case GDB_BREAKPOINT_HW: @@ -6217,7 +6218,8 @@ int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type) return 0; } -int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type) +int kvm_arch_remove_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type) { int n; @@ -6231,7 +6233,7 @@ int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type) return 0; } -void kvm_arch_remove_all_hw_breakpoints(void) +void kvm_arch_remove_all_gdbstub_hw_breakpoints(void) { nb_hw_breakpoint = 0; } diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c index d6539c12ac..beda6965f8 100644 --- a/target/loongarch/kvm/kvm.c +++ b/target/loongarch/kvm/kvm.c @@ -1418,17 +1418,19 @@ int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) return 0; } -int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type) +int kvm_arch_insert_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type) { return -ENOSYS; } -int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type) +int kvm_arch_remove_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type) { return -ENOSYS; } -void kvm_arch_remove_all_hw_breakpoints(void) +void kvm_arch_remove_all_gdbstub_hw_breakpoints(void) { } diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index b94c2997a0..93ec0cf6a7 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -455,7 +455,7 @@ unsigned long kvm_arch_vcpu_id(CPUState *cpu) static struct HWBreakpoint { target_ulong addr; - int type; + GdbBreakpointType type; } hw_debug_points[MAX_HW_BKPTS]; static CPUWatchpoint hw_watchpoint; @@ -1412,7 +1412,7 @@ int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) return 0; } -static int find_hw_breakpoint(target_ulong addr, int type) +static int find_hw_breakpoint(target_ulong addr, GdbBreakpointType type) { int n; @@ -1454,7 +1454,8 @@ static int find_hw_watchpoint(target_ulong addr, int *flag) return -1; } -int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type) +int kvm_arch_insert_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type) { const unsigned breakpoint_index = nb_hw_breakpoint + nb_hw_watchpoint; if (breakpoint_index >= ARRAY_SIZE(hw_debug_points)) { @@ -1498,7 +1499,8 @@ int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type) return 0; } -int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type) +int kvm_arch_remove_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type) { int n; @@ -1526,7 +1528,7 @@ int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type) return 0; } -void kvm_arch_remove_all_hw_breakpoints(void) +void kvm_arch_remove_all_gdbstub_hw_breakpoints(void) { nb_hw_breakpoint = nb_hw_watchpoint = 0; } diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 39d48a9db4..2a5440d584 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -2215,19 +2215,21 @@ int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) return 0; } -int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type) +int kvm_arch_insert_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type) { /* TODO; To be implemented later. */ return -EINVAL; } -int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type) +int kvm_arch_remove_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type) { /* TODO; To be implemented later. */ return -EINVAL; } -void kvm_arch_remove_all_hw_breakpoints(void) +void kvm_arch_remove_all_gdbstub_hw_breakpoints(void) { /* TODO; To be implemented later. */ } diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c index fdef8f9e8a..195e39df03 100644 --- a/target/s390x/kvm/kvm.c +++ b/target/s390x/kvm/kvm.c @@ -907,7 +907,8 @@ static int insert_hw_breakpoint(vaddr addr, int len, int type) return 0; } -int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type) +int kvm_arch_insert_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type) { switch (type) { case GDB_BREAKPOINT_HW: @@ -925,7 +926,8 @@ int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type) return insert_hw_breakpoint(addr, len, type); } -int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type) +int kvm_arch_remove_gdbstub_hw_breakpoint(vaddr addr, vaddr len, + GdbBreakpointType type) { int size; struct kvm_hw_breakpoint *bp = find_hw_breakpoint(addr, len, type); @@ -954,7 +956,7 @@ int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type) return 0; } -void kvm_arch_remove_all_hw_breakpoints(void) +void kvm_arch_remove_all_gdbstub_hw_breakpoints(void) { nb_hw_breakpoints = 0; g_free(hw_breakpoints); -- cgit v1.2.3 From 0b55b519c6f8c905d545412568e47e06bf34d918 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sat, 27 Jun 2026 17:02:29 +0200 Subject: target/arm: Inline check_watchpoints() in arm_debug_check_watchpoint() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit check_watchpoints() is called once, by arm_debug_check_watchpoint(), which doesn't do more than this call. Merge both. No logical change intended. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-27-philmd@oss.qualcomm.com> --- target/arm/tcg/debug.c | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/target/arm/tcg/debug.c b/target/arm/tcg/debug.c index 07a52643e7..528d2889c3 100644 --- a/target/arm/tcg/debug.c +++ b/target/arm/tcg/debug.c @@ -351,28 +351,6 @@ static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp) return true; } -static bool check_watchpoints(ARMCPU *cpu) -{ - CPUARMState *env = &cpu->env; - int n; - - /* - * If watchpoints are disabled globally or we can't take debug - * exceptions here then watchpoint firings are ignored. - */ - if (extract32(env->cp15.mdscr_el1, 15, 1) == 0 - || !arm_generate_debug_exceptions(env)) { - return false; - } - - for (n = 0; n < ARRAY_SIZE(env->cpu_watchpoint); n++) { - if (bp_wp_matches(cpu, n, true)) { - return true; - } - } - return false; -} - bool arm_debug_check_breakpoint(CPUState *cs) { ARMCPU *cpu = ARM_CPU(cs); @@ -426,8 +404,24 @@ bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) * is also an architectural watchpoint match. */ ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + int n; - return check_watchpoints(cpu); + /* + * If watchpoints are disabled globally or we can't take debug + * exceptions here then watchpoint firings are ignored. + */ + if (extract32(env->cp15.mdscr_el1, 15, 1) == 0 + || !arm_generate_debug_exceptions(env)) { + return false; + } + + for (n = 0; n < ARRAY_SIZE(env->cpu_watchpoint); n++) { + if (bp_wp_matches(cpu, n, true)) { + return true; + } + } + return false; } /* -- cgit v1.2.3 From cbdbbfaf761be3eedcc8cae1f6c08b747d1642a6 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Tue, 30 Jun 2026 06:42:41 +0200 Subject: target/ppc: Ensure TCG is used in ppc_update_daw() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per commit d5ee641cfc5 ("target/ppc: Implement watchpoint debug facility for v2.07S"), only TCG is implemented: ISA v2.07S introduced the watchpoint facility based on the DAWR0 and DAWRX0 SPRs. Implement this in TCG. ^^^^^^^^^^^^^^^^^^^^^ Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Message-ID: <20260705215729.62196-28-philmd@oss.qualcomm.com> --- target/ppc/cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c index 41edb18643..47467ee163 100644 --- a/target/ppc/cpu.c +++ b/target/ppc/cpu.c @@ -147,6 +147,8 @@ void ppc_update_daw(CPUPPCState *env, int rid) vaddr len; int flags; + assert(tcg_enabled()); + if (env->dawr_watchpoint[rid]) { cpu_watchpoint_remove_by_ref(cs, env->dawr_watchpoint[rid]); env->dawr_watchpoint[rid] = NULL; -- cgit v1.2.3 From 93e7ca71d7bc5987e65d1c99b0944b084e9b15b7 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Tue, 30 Jun 2026 18:13:50 +0200 Subject: accel/tcg: Improve docstrings around TCGCPUOps::*watchpoint* handlers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit d5ee641cfc5 ("target/ppc: Implement watchpoint debug facility for v2.07S") also implemented TCGCPUOps::debug_check_watchpoint for PPC: make the comment generic. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-29-philmd@oss.qualcomm.com> --- include/accel/tcg/cpu-ops.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/accel/tcg/cpu-ops.h b/include/accel/tcg/cpu-ops.h index 710da12b82..3ff6e6810e 100644 --- a/include/accel/tcg/cpu-ops.h +++ b/include/accel/tcg/cpu-ops.h @@ -250,14 +250,13 @@ struct TCGCPUOps { int mmu_idx, uintptr_t retaddr); /** - * @adjust_watchpoint_address: hack for cpu_check_watchpoint used by ARM + * @adjust_watchpoint_address: hack for cpu_check_watchpoint (used by ARM) */ vaddr (*adjust_watchpoint_address)(CPUState *cpu, vaddr addr, int len); /** * @debug_check_watchpoint: return true if the architectural - * watchpoint whose address has matched should really fire, used by ARM - * and RISC-V + * watchpoint whose address has matched should really fire. */ bool (*debug_check_watchpoint)(CPUState *cpu, CPUWatchpoint *wp); -- cgit v1.2.3 From d682cd181c57797cd0d5e5d4d9a4895f90129c7c Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 26 Jun 2026 16:06:19 +0200 Subject: cpu: Better name cpu_single_step() trace event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cpu_single_step() is not related to breakpoints. Rename the trace event. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Message-ID: <20260705215729.62196-30-philmd@oss.qualcomm.com> --- cpu-target.c | 4 ++-- trace-events | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cpu-target.c b/cpu-target.c index f030e2c642..019906b32e 100644 --- a/cpu-target.c +++ b/cpu-target.c @@ -31,6 +31,8 @@ void cpu_single_step(CPUState *cpu, int enabled) { if (cpu->singlestep_enabled != enabled) { + trace_cpu_change_singlestep_flags(cpu->cpu_index, + cpu->singlestep_enabled, enabled); cpu->singlestep_enabled = enabled; #if !defined(CONFIG_USER_ONLY) @@ -39,8 +41,6 @@ void cpu_single_step(CPUState *cpu, int enabled) ops->update_guest_debug(cpu); } #endif - - trace_breakpoint_singlestep(cpu->cpu_index, enabled); } } diff --git a/trace-events b/trace-events index faeba6242f..ea1d2b11a2 100644 --- a/trace-events +++ b/trace-events @@ -28,7 +28,7 @@ # cpu.c breakpoint_insert(int cpu_index, uint64_t pc, int flags) "cpu=%d pc=0x%" PRIx64 " flags=0x%x" breakpoint_remove(int cpu_index, uint64_t pc, int flags) "cpu=%d pc=0x%" PRIx64 " flags=0x%x" -breakpoint_singlestep(int cpu_index, int enabled) "cpu=%d enable=%d" +cpu_change_singlestep_flags(int cpu_index, int old_flags, int new_flags) "cpu=%d flags=0x%x -> 0x%x" cpu_exec_start(int cpu_index) "cpu=%d" cpu_exec_end(int cpu_index) "cpu=%d" -- cgit v1.2.3 From 0a8bc0f25151d8d83e193bffc4811b4631460fc5 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 26 Jun 2026 14:18:03 +0200 Subject: cpu: Introduce cpu_single_stepping() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Access CPUState::@singlestep_enabled field with a helper. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-31-philmd@oss.qualcomm.com> --- accel/kvm/kvm-all.c | 2 +- accel/tcg/cpu-exec-common.c | 2 +- accel/tcg/cpu-exec.c | 8 ++++---- include/hw/core/cpu.h | 11 +++++++++++ linux-user/riscv/cpu_loop.c | 2 +- linux-user/s390x/cpu_loop.c | 2 +- system/cpus.c | 2 +- target/arm/hvf/hvf.c | 8 ++++---- target/arm/kvm.c | 2 +- target/i386/kvm/kvm.c | 2 +- target/i386/whpx/whpx-all.c | 6 +++--- target/loongarch/kvm/kvm.c | 2 +- target/microblaze/translate.c | 2 +- target/ppc/kvm.c | 2 +- target/s390x/kvm/kvm.c | 2 +- 15 files changed, 33 insertions(+), 22 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index feffca0d82..963a4edd26 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -3812,7 +3812,7 @@ int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap) data.dbg.control = reinject_trap; - if (cpu->singlestep_enabled) { + if (cpu_single_stepping(cpu)) { data.dbg.control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP; if (cpu->singlestep_enabled & SSTEP_NOIRQ) { diff --git a/accel/tcg/cpu-exec-common.c b/accel/tcg/cpu-exec-common.c index e48ea31373..44e84344f3 100644 --- a/accel/tcg/cpu-exec-common.c +++ b/accel/tcg/cpu-exec-common.c @@ -47,7 +47,7 @@ uint32_t curr_cflags(CPUState *cpu) * For singlestep and -d nochain, suppress goto_tb so that * we can log -d cpu,exec after every TB. */ - if (unlikely(cpu->singlestep_enabled)) { + if (unlikely(cpu_single_stepping(cpu))) { cflags |= CF_NO_GOTO_TB | CF_NO_GOTO_PTR | CF_SINGLE_STEP | 1; } else if (qatomic_read(&one_insn_per_tb)) { cflags |= CF_NO_GOTO_TB | 1; diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index d7f91dce9d..0386ac4955 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -308,7 +308,7 @@ static bool check_for_breakpoints_slow(CPUState *cpu, vaddr pc, * so that one could (gdb) singlestep into the guest kernel's * architectural breakpoint handler. */ - if (cpu->singlestep_enabled) { + if (cpu_single_stepping(cpu)) { return false; } @@ -485,7 +485,7 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit) * raise a debug exception. Single-step with another exception * is handled in cpu_handle_exception. */ - if (unlikely(cpu->singlestep_enabled) && cpu->exception_index == -1) { + if (unlikely(cpu_single_stepping(cpu)) && cpu->exception_index == -1) { cpu->exception_index = EXCP_DEBUG; cpu_loop_exit(cpu); } @@ -732,7 +732,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret) bql_unlock(); cpu->exception_index = -1; - if (unlikely(cpu->singlestep_enabled)) { + if (unlikely(cpu_single_stepping(cpu))) { /* * After processing the exception, ensure an EXCP_DEBUG is * raised when single-stepping so that GDB doesn't miss the @@ -849,7 +849,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, * raised when single-stepping so that GDB doesn't miss the * next instruction. */ - if (unlikely(cpu->singlestep_enabled)) { + if (unlikely(cpu_single_stepping(cpu))) { cpu->exception_index = EXCP_DEBUG; bql_unlock(); return true; diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index e5b68bced3..00f6c5d5de 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -1138,6 +1138,17 @@ void qemu_init_vcpu(CPUState *cpu); */ void cpu_single_step(CPUState *cpu, int enabled); +/** + * cpu_single_stepping: + * @cpu: The vCPU to check + * + * Returns whether the vCPU has single-stepping enabled. + */ +static inline bool cpu_single_stepping(const CPUState *cpu) +{ + return cpu->singlestep_enabled; +} + int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, CPUBreakpoint **breakpoint); int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags); diff --git a/linux-user/riscv/cpu_loop.c b/linux-user/riscv/cpu_loop.c index eecc8d1517..6f27a06da4 100644 --- a/linux-user/riscv/cpu_loop.c +++ b/linux-user/riscv/cpu_loop.c @@ -68,7 +68,7 @@ void cpu_loop(CPURISCVState *env) } else if (ret != -QEMU_ESIGRETURN && ret != -QEMU_ESETPC) { env->gpr[xA0] = ret; } - if (cs->singlestep_enabled) { + if (cpu_single_stepping(cs)) { goto gdbstep; } break; diff --git a/linux-user/s390x/cpu_loop.c b/linux-user/s390x/cpu_loop.c index 67d2a803fb..25f19f725e 100644 --- a/linux-user/s390x/cpu_loop.c +++ b/linux-user/s390x/cpu_loop.c @@ -87,7 +87,7 @@ void cpu_loop(CPUS390XState *env) env->regs[2] = ret; } - if (unlikely(cs->singlestep_enabled)) { + if (unlikely(cpu_single_stepping(cs))) { /* * cpu_tb_exec() did not raise EXCP_DEBUG, because it has seen * that EXCP_SVC was already pending. diff --git a/system/cpus.c b/system/cpus.c index b31c825b46..97e5a5edee 100644 --- a/system/cpus.c +++ b/system/cpus.c @@ -344,7 +344,7 @@ bool cpu_can_run(CPUState *cpu) void cpu_handle_guest_debug(CPUState *cpu) { if (replay_running_debug()) { - if (!cpu->singlestep_enabled) { + if (!cpu_single_stepping(cpu)) { /* * Report about the breakpoint and * make a single step to skip it diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index d5b1966a86..640ef66559 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -2340,7 +2340,7 @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp) case EC_SOFTWARESTEP: { ret = EXCP_DEBUG; - if (!cpu->singlestep_enabled) { + if (!cpu_single_stepping(cpu)) { error_report("EC_SOFTWARESTEP but single-stepping not enabled"); } break; @@ -2549,7 +2549,7 @@ static int hvf_handle_exception(CPUState *cpu, hv_vcpu_exit_exception_t *excp) assert_hvf_ok(r); /* Handle single-stepping over instructions which trigger a VM exit */ - if (cpu->singlestep_enabled) { + if (cpu_single_stepping(cpu)) { ret = EXCP_DEBUG; } } @@ -2868,7 +2868,7 @@ void hvf_arch_update_guest_debug(CPUState *cpu) CPUARMState *env = &arm_cpu->env; /* Check whether guest debugging is enabled */ - cpu->accel->guest_debug_enabled = cpu->singlestep_enabled || + cpu->accel->guest_debug_enabled = cpu_single_stepping(cpu) || hvf_sw_breakpoints_active(cpu) || hvf_arm_hw_debug_active(cpu); @@ -2882,7 +2882,7 @@ void hvf_arch_update_guest_debug(CPUState *cpu) cpu_synchronize_state(cpu); /* Enable/disable single-stepping */ - if (cpu->singlestep_enabled) { + if (cpu_single_stepping(cpu)) { env->cp15.mdscr_el1 = deposit64(env->cp15.mdscr_el1, MDSCR_EL1_SS_SHIFT, 1, 1); pstate_write(env, pstate_read(env) | PSTATE_SS); diff --git a/target/arm/kvm.c b/target/arm/kvm.c index 01f42f4253..d40a6a9859 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -1492,7 +1492,7 @@ static bool kvm_arm_handle_debug(ARMCPU *cpu, switch (hsr_ec) { case EC_SOFTWARESTEP: - if (cs->singlestep_enabled) { + if (cpu_single_stepping(cs)) { return true; } else { /* diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 1e09155e92..4272b6770c 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -6250,7 +6250,7 @@ static int kvm_handle_debug(X86CPU *cpu, if (arch_info->exception == EXCP01_DB) { if (arch_info->dr6 & DR6_BS) { - if (cs->singlestep_enabled) { + if (cpu_single_stepping(cs)) { ret = EXCP_DEBUG; } } else { diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c index 11b5d1fc60..634d542821 100644 --- a/target/i386/whpx/whpx-all.c +++ b/target/i386/whpx/whpx-all.c @@ -2266,7 +2266,7 @@ int whpx_vcpu_run(CPUState *cpu) } } - if (exclusive_step_mode != WHPX_STEP_NONE || cpu->singlestep_enabled) { + if (exclusive_step_mode != WHPX_STEP_NONE || cpu_single_stepping(cpu)) { whpx_vcpu_configure_single_stepping(cpu, true, NULL); } @@ -2283,7 +2283,7 @@ int whpx_vcpu_run(CPUState *cpu) break; } - if (exclusive_step_mode != WHPX_STEP_NONE || cpu->singlestep_enabled) { + if (exclusive_step_mode != WHPX_STEP_NONE || cpu_single_stepping(cpu)) { whpx_vcpu_configure_single_stepping(cpu, false, &vcpu->exit_ctx.VpContext.Rflags); @@ -2648,7 +2648,7 @@ int whpx_vcpu_run(CPUState *cpu) cpu->exception_index = EXCP_DEBUG; } else if ((vcpu->exit_ctx.VpException.ExceptionType == WHvX64ExceptionTypeDebugTrapOrFault) && - !cpu->singlestep_enabled) { + !cpu_single_stepping(cpu)) { /* * Just finished stepping over a breakpoint, but the * gdb does not expect us to do single-stepping. diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c index beda6965f8..48cdb78a4c 100644 --- a/target/loongarch/kvm/kvm.c +++ b/target/loongarch/kvm/kvm.c @@ -1440,7 +1440,7 @@ static bool kvm_loongarch_handle_debug(CPUState *cs, struct kvm_run *run) CPULoongArchState *env = &cpu->env; kvm_cpu_synchronize_state(cs); - if (cs->singlestep_enabled) { + if (cpu_single_stepping(cs)) { return true; } diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c index a93f14d6e0..8b219afb5d 100644 --- a/target/microblaze/translate.c +++ b/target/microblaze/translate.c @@ -1772,7 +1772,7 @@ static void mb_tr_tb_stop(DisasContextBase *dcb, CPUState *cs) } /* Finish DISAS_EXIT_* */ - if (unlikely(cs->singlestep_enabled)) { + if (unlikely(cpu_single_stepping(cs))) { gen_raise_exception(dc, EXCP_DEBUG); } else { tcg_gen_exit_tb(NULL, 0); diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 93ec0cf6a7..19d41c8e91 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -1615,7 +1615,7 @@ static int kvm_handle_debug(PowerPCCPU *cpu, struct kvm_run *run) CPUPPCState *env = &cpu->env; struct kvm_debug_exit_arch *arch_info = &run->debug.arch; - if (cs->singlestep_enabled) { + if (cpu_single_stepping(cs)) { return kvm_handle_singlestep(); } diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c index 195e39df03..19ddf59e00 100644 --- a/target/s390x/kvm/kvm.c +++ b/target/s390x/kvm/kvm.c @@ -1874,7 +1874,7 @@ static int kvm_arch_handle_debug_exit(S390CPU *cpu) } break; case KVM_SINGLESTEP: - if (cs->singlestep_enabled) { + if (cpu_single_stepping(cs)) { ret = EXCP_DEBUG; } break; -- cgit v1.2.3 From 7e28b7c8970ce2740a665156927f3c3cda82fc2e Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 26 Jun 2026 14:25:28 +0200 Subject: cpu: Rename CPUState @singlestep_enabled -> @singlestep_flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPUState::singlestep_enabled contains multiple flags since commit 60897d369f1 ("Debugger single step without interrupts"). Use an unsigned type and rename the field to avoid mistakes. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-32-philmd@oss.qualcomm.com> --- accel/kvm/kvm-all.c | 2 +- accel/tcg/cpu-exec.c | 2 +- accel/tcg/tcg-accel-ops-rr.c | 2 +- cpu-target.c | 8 ++++---- include/hw/core/cpu.h | 10 +++++----- target/arm/hvf/hvf.c | 2 +- target/ppc/translate.c | 16 ++++++++-------- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 963a4edd26..83cbd120a8 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -3815,7 +3815,7 @@ int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap) if (cpu_single_stepping(cpu)) { data.dbg.control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP; - if (cpu->singlestep_enabled & SSTEP_NOIRQ) { + if (cpu->singlestep_flags & SSTEP_NOIRQ) { data.dbg.control |= KVM_GUESTDBG_BLOCKIRQ; } } diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 0386ac4955..257211235d 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -828,7 +828,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, return true; } - if (unlikely(cpu->singlestep_enabled & SSTEP_NOIRQ)) { + if (unlikely(cpu->singlestep_flags & SSTEP_NOIRQ)) { /* Mask out external interrupts for this step. */ interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK; } diff --git a/accel/tcg/tcg-accel-ops-rr.c b/accel/tcg/tcg-accel-ops-rr.c index 5b132d3d5d..cdaa3e1180 100644 --- a/accel/tcg/tcg-accel-ops-rr.c +++ b/accel/tcg/tcg-accel-ops-rr.c @@ -274,7 +274,7 @@ static void *rr_cpu_thread_fn(void *arg) current_cpu = cpu; qemu_clock_enable(QEMU_CLOCK_VIRTUAL, - (cpu->singlestep_enabled & SSTEP_NOTIMER) == 0); + (cpu->singlestep_flags & SSTEP_NOTIMER) == 0); if (cpu_can_run(cpu)) { int r; diff --git a/cpu-target.c b/cpu-target.c index 019906b32e..4783845c9b 100644 --- a/cpu-target.c +++ b/cpu-target.c @@ -28,12 +28,12 @@ /* enable or disable single step mode. EXCP_DEBUG is returned by the CPU loop after each instruction */ -void cpu_single_step(CPUState *cpu, int enabled) +void cpu_single_step(CPUState *cpu, unsigned flags) { - if (cpu->singlestep_enabled != enabled) { + if (cpu->singlestep_flags != flags) { trace_cpu_change_singlestep_flags(cpu->cpu_index, - cpu->singlestep_enabled, enabled); - cpu->singlestep_enabled = enabled; + cpu->singlestep_flags, flags); + cpu->singlestep_flags = flags; #if !defined(CONFIG_USER_ONLY) const AccelOpsClass *ops = cpus_get_accel(); diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 00f6c5d5de..db4865bd63 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -440,7 +440,7 @@ struct qemu_work_item; * @stopped: Indicates the CPU has been artificially stopped. * @unplug: Indicates a pending CPU unplug request. * @crash_occurred: Indicates the OS reported a crash (panic) for this CPU - * @singlestep_enabled: Flags for single-stepping. + * @singlestep_flags: Flags for single-stepping. * @icount_extra: Instructions until next timer event. * @cpu_ases: Pointer to array of CPUAddressSpaces (which define the * AddressSpaces this CPU has) @@ -505,7 +505,7 @@ struct CPUState { int exclusive_context_count; uint32_t cflags_next_tb; uint32_t interrupt_request; - int singlestep_enabled; + unsigned singlestep_flags; int64_t icount_budget; int64_t icount_extra; uint64_t random_seed; @@ -1132,11 +1132,11 @@ void qemu_init_vcpu(CPUState *cpu); /** * cpu_single_step: * @cpu: CPU to the flags for. - * @enabled: Flags to enable. + * @flags: Flags to enable. * * Enables or disables single-stepping for @cpu. */ -void cpu_single_step(CPUState *cpu, int enabled); +void cpu_single_step(CPUState *cpu, unsigned flags); /** * cpu_single_stepping: @@ -1146,7 +1146,7 @@ void cpu_single_step(CPUState *cpu, int enabled); */ static inline bool cpu_single_stepping(const CPUState *cpu) { - return cpu->singlestep_enabled; + return cpu->singlestep_flags; } int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index 640ef66559..f5dd7e8e02 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -2603,7 +2603,7 @@ int hvf_arch_vcpu_exec(CPUState *cpu) flush_cpu_state(cpu); do { - if (!(cpu->singlestep_enabled & SSTEP_NOIRQ) && + if (!(cpu->singlestep_flags & SSTEP_NOIRQ) && hvf_inject_interrupts(cpu)) { return EXCP_INTERRUPT; } diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 3f6d326cef..06ed2adf10 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -198,7 +198,7 @@ struct DisasContext { bool pmu_insn_cnt; bool bhrb_enable; ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */ - int singlestep_enabled; + int singlestep_flags; uint32_t flags; uint64_t insns_flags; uint64_t insns_flags2; @@ -367,7 +367,7 @@ static void gen_debug_exception(DisasContext *ctx, bool rfi_type) #if !defined(CONFIG_USER_ONLY) if (ctx->flags & POWERPC_FLAG_DE) { target_ulong dbsr = 0; - if (ctx->singlestep_enabled & CPU_SINGLE_STEP) { + if (ctx->singlestep_flags & CPU_SINGLE_STEP) { dbsr = DBCR0_ICMP; } else { /* Must have been branch */ @@ -3645,7 +3645,7 @@ static void pmu_count_insns(DisasContext *ctx) static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest) { - if (unlikely(ctx->singlestep_enabled)) { + if (unlikely(ctx->singlestep_flags)) { return false; } return translator_use_goto_tb(&ctx->base, dest); @@ -3653,7 +3653,7 @@ static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest) static void gen_lookup_and_goto_ptr(DisasContext *ctx) { - if (unlikely(ctx->singlestep_enabled)) { + if (unlikely(ctx->singlestep_flags)) { gen_debug_exception(ctx, false); } else { /* @@ -6559,13 +6559,13 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->pmu_insn_cnt = (hflags >> HFLAGS_INSN_CNT) & 1; ctx->bhrb_enable = (hflags >> HFLAGS_BHRB_ENABLE) & 1; - ctx->singlestep_enabled = 0; + ctx->singlestep_flags = 0; if ((hflags >> HFLAGS_SE) & 1) { - ctx->singlestep_enabled |= CPU_SINGLE_STEP; + ctx->singlestep_flags |= CPU_SINGLE_STEP; ctx->base.max_insns = 1; } if ((hflags >> HFLAGS_BE) & 1) { - ctx->singlestep_enabled |= CPU_BRANCH_STEP; + ctx->singlestep_flags |= CPU_BRANCH_STEP; } } @@ -6641,7 +6641,7 @@ static void ppc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) } /* Honor single stepping. */ - if (unlikely(ctx->singlestep_enabled & CPU_SINGLE_STEP)) { + if (unlikely(ctx->singlestep_flags & CPU_SINGLE_STEP)) { bool rfi_type = false; switch (is_jmp) { -- cgit v1.2.3 From c0df53752c86e5f51e12e7b99501b6f4d2e52c01 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 26 Jun 2026 15:16:02 +0200 Subject: cpu: Only check SSTEP_ENABLE flag in cpu_single_stepping() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only the SSTEP_ENABLE bitmask means single-step is enabled. Fixes: 60897d369f1 ("Debugger single step without interrupts") Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Message-ID: <20260705215729.62196-33-philmd@oss.qualcomm.com> --- include/hw/core/cpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index db4865bd63..b54035fb13 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -1146,7 +1146,7 @@ void cpu_single_step(CPUState *cpu, unsigned flags); */ static inline bool cpu_single_stepping(const CPUState *cpu) { - return cpu->singlestep_flags; + return cpu->singlestep_flags & SSTEP_ENABLE; } int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, -- cgit v1.2.3