summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2009-03-12 20:12:48 +0000
committeraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2009-03-12 20:12:48 +0000
commite22a25c9361c44995c9241c24df0e1e2c47a56c8 (patch)
tree4bf900c761e36db33146e5527baed9663cf9a785 /gdbstub.c
parentDrop internal bdrv_pread()/bdrv_pwrite() APIs (Avi Kivity) (diff)
downloadqemu-kvm-e22a25c9361c44995c9241c24df0e1e2c47a56c8.tar.gz
qemu-kvm-e22a25c9361c44995c9241c24df0e1e2c47a56c8.tar.bz2
qemu-kvm-e22a25c9361c44995c9241c24df0e1e2c47a56c8.zip
Guest debugging support for KVM (Jan Kiszka)
This is a backport of the guest debugging support for the KVM accelerator that is now part of the KVM tree. It implements the reworked KVM kernel API for guest debugging (KVM_CAP_SET_GUEST_DEBUG) which is not yet part of any mainline kernel but will probably be 2.6.30 stuff. So far supported is x86, but PPC is expected to catch up soon. Core features are: - unlimited soft-breakpoints via code patching - hardware-assisted x86 breakpoints and watchpoints Changes in this version: - use generic hook cpu_synchronize_state to transfer registers between user space and kvm - push kvm_sw_breakpoints into KVMState Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6825 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'gdbstub.c')
-rw-r--r--gdbstub.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/gdbstub.c b/gdbstub.c
index addff2ee7..8876c1d9a 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -39,6 +39,7 @@
#define MAX_PACKET_LENGTH 4096
#include "qemu_socket.h"
+#include "kvm.h"
enum {
@@ -1418,13 +1419,6 @@ void gdb_register_coprocessor(CPUState * env,
}
}
-/* 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
-
#ifndef CONFIG_USER_ONLY
static const int xlat_gdb_type[] = {
[GDB_WATCHPOINT_WRITE] = BP_GDB | BP_MEM_WRITE,
@@ -1438,6 +1432,9 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
CPUState *env;
int err = 0;
+ if (kvm_enabled())
+ return kvm_insert_breakpoint(gdbserver_state->c_cpu, addr, len, type);
+
switch (type) {
case GDB_BREAKPOINT_SW:
case GDB_BREAKPOINT_HW:
@@ -1469,6 +1466,9 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
CPUState *env;
int err = 0;
+ if (kvm_enabled())
+ return kvm_remove_breakpoint(gdbserver_state->c_cpu, addr, len, type);
+
switch (type) {
case GDB_BREAKPOINT_SW:
case GDB_BREAKPOINT_HW:
@@ -1498,6 +1498,11 @@ static void gdb_breakpoint_remove_all(void)
{
CPUState *env;
+ if (kvm_enabled()) {
+ kvm_remove_all_breakpoints(gdbserver_state->c_cpu);
+ return;
+ }
+
for (env = first_cpu; env != NULL; env = env->next_cpu) {
cpu_breakpoint_remove_all(env, BP_GDB);
#ifndef CONFIG_USER_ONLY
@@ -1538,6 +1543,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
addr = strtoull(p, (char **)&p, 16);
#if defined(TARGET_I386)
s->c_cpu->eip = addr;
+ cpu_synchronize_state(s->c_cpu, 1);
#elif defined (TARGET_PPC)
s->c_cpu->nip = addr;
#elif defined (TARGET_SPARC)
@@ -1579,6 +1585,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
addr = strtoull(p, (char **)&p, 16);
#if defined(TARGET_I386)
s->c_cpu->eip = addr;
+ cpu_synchronize_state(s->c_cpu, 1);
#elif defined (TARGET_PPC)
s->c_cpu->nip = addr;
#elif defined (TARGET_SPARC)
@@ -1624,6 +1631,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
}
break;
case 'g':
+ cpu_synchronize_state(s->g_cpu, 0);
len = 0;
for (addr = 0; addr < num_g_regs; addr++) {
reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr);
@@ -1641,6 +1649,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
len -= reg_size;
registers += reg_size;
}
+ cpu_synchronize_state(s->g_cpu, 1);
put_packet(s, "OK");
break;
case 'm':
@@ -1799,6 +1808,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
thread = strtoull(p+16, (char **)&p, 16);
for (env = first_cpu; env != NULL; env = env->next_cpu)
if (env->cpu_index + 1 == thread) {
+ cpu_synchronize_state(env, 0);
len = snprintf((char *)mem_buf, sizeof(mem_buf),
"CPU#%d [%s]", env->cpu_index,
env->halted ? "halted " : "running");