KVM, just like plain QEMU, does not allow debugging of SMP guests reliably because the debugged CPU is fixed and, even worse, breakpoints only have effect on that single CPU. Patch below overcomes this by exploiting the attached carrier patch for QEMU (which couples the monitor with the debugger focus). Furthermore, the patch ensures that KVM_SET_GUEST_DEBUG is properly updated for all vcpus if the first soft breakpoint is added or the last one is removed. This patch is RFC as it depends on that "carrier" patch which needs more work (SMP debugging with plain QEMU is still borken) and only applies to KVM right now (QEMU trunk contains a few interesting debugger extensions, and even more are queued). However, if you want to play with SMP debugging under KVM, you may like these two. --- qemu/monitor.c | 1 + qemu/qemu-kvm.c | 29 ++++++++++++++++++++++------- 2 files changed, 23 insertions(+), 7 deletions(-) Index: b/qemu/monitor.c =================================================================== --- a/qemu/monitor.c +++ b/qemu/monitor.c @@ -319,6 +319,7 @@ static void do_info_cpus(void) mon_set_cpu(first_cpu); for(env = first_cpu; env != NULL; env = env->next_cpu) { + kvm_save_registers(env); term_printf("%c CPU #%d:", (env == mon_cpu) ? '*' : ' ', env->cpu_index); Index: b/qemu/qemu-kvm.c =================================================================== --- a/qemu/qemu-kvm.c +++ b/qemu/qemu-kvm.c @@ -19,6 +19,7 @@ int kvm_pit = 1; #include "qemu-common.h" #include "console.h" #include "block.h" +#include "monitor.h" #include "qemu-kvm.h" #include @@ -58,7 +59,7 @@ pthread_t io_thread; static int io_thread_fd = -1; static int io_thread_sigfd = -1; -static int kvm_debug_stop_requested; +static CPUState *kvm_debug_cpu_requested; struct kvm_sw_breakpoint *first_sw_breakpoint; @@ -548,9 +549,10 @@ int kvm_main_loop(void) qemu_system_powerdown(); else if (qemu_reset_requested()) qemu_kvm_system_reset(); - else if (kvm_debug_stop_requested) { - kvm_debug_stop_requested = 0; + else if (kvm_debug_cpu_requested) { + mon_set_cpu(kvm_debug_cpu_requested); vm_stop(EXCP_DEBUG); + kvm_debug_cpu_requested = NULL; } } @@ -576,7 +578,7 @@ static int kvm_debug(void *opaque, int v break; } if (handle) { - kvm_debug_stop_requested = 1; + kvm_debug_cpu_requested = cpu_single_env; vcpu_info[vcpu].stopped = 1; } else kvm_update_guest_debug(cpu_single_env, break_type); @@ -855,8 +857,15 @@ int kvm_insert_breakpoint(CPUState *env, first_sw_breakpoint = bp; if (bp->next) bp->next->prev = bp; - - return kvm_update_guest_debug(env, KVM_GDB_BREAKPOINT_NONE); + else { + /* Just added the first breakpoint, so update the kernel state. */ + foreach_cpu(env) { + err = kvm_update_guest_debug(env, KVM_GDB_BREAKPOINT_NONE); + if (err) + break; + } + } + return err; #else return -EINVAL; #endif @@ -894,7 +903,13 @@ int kvm_remove_breakpoint(CPUState *env, free(bp); - return kvm_update_guest_debug(env, KVM_GDB_BREAKPOINT_NONE); + if (!first_sw_breakpoint) + foreach_cpu(env) { + err = kvm_update_guest_debug(env, KVM_GDB_BREAKPOINT_NONE); + if (err) + break; + } + return err; #else return -EINVAL; #endif