qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] Guest debugging support for KVM
@ 2009-01-14 14:43 Jan Kiszka
  2009-01-15 20:19 ` Anthony Liguori
  0 siblings, 1 reply; 3+ messages in thread
From: Jan Kiszka @ 2009-01-14 14:43 UTC (permalink / raw)
  To: qemu-devel@nongnu.org

[ Also available via git://git.kiszka.org/qemu.git queue/gdb ]

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

Open issues: Writing soft breakpoints to BIOS code. cpu_memory_rw_debug
does not work here. Suggestion to fix this cleanly are welcome.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 configure         |    4 +
 exec.c            |   10 ++-
 gdbstub.c         |   29 +++++++--
 gdbstub.h         |    7 ++
 kvm-all.c         |  172 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 kvm.h             |   41 +++++++++++++
 target-i386/kvm.c |  172 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 423 insertions(+), 12 deletions(-)

diff --git a/configure b/configure
index a8ea55a..afbe1e0 100755
--- a/configure
+++ b/configure
@@ -479,11 +479,11 @@ case "$cpu" in
            ARCH_CFLAGS="-march=z900"
            ;;
     i386)
-           ARCH_CFLAGS="-m32"
+           ARCH_CFLAGS="-m32 -DCONFIG_X86"
            ARCH_LDFLAGS="-m32"
            ;;
     x86_64)
-           ARCH_CFLAGS="-m64"
+           ARCH_CFLAGS="-m64 -DCONFIG_X86"
            ARCH_LDFLAGS="-m64"
            ;;
 esac
diff --git a/exec.c b/exec.c
index d6fa977..89f457a 100644
--- a/exec.c
+++ b/exec.c
@@ -1458,9 +1458,13 @@ void cpu_single_step(CPUState *env, int enabled)
 #if defined(TARGET_HAS_ICE)
     if (env->singlestep_enabled != enabled) {
         env->singlestep_enabled = enabled;
-        /* must flush all the translated code to avoid inconsistancies */
-        /* XXX: only flush what is necessary */
-        tb_flush(env);
+        if (kvm_enabled())
+            kvm_update_guest_debug(env, 0);
+        else {
+            /* must flush all the translated code to avoid inconsistancies */
+            /* XXX: only flush what is necessary */
+            tb_flush(env);
+        }
     }
 #endif
 }
diff --git a/gdbstub.c b/gdbstub.c
index a3ff07a..0bcd5d5 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -38,6 +38,7 @@
 #define MAX_PACKET_LENGTH 4096
 
 #include "qemu_socket.h"
+#include "kvm.h"
 
 
 enum {
@@ -1389,13 +1390,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,
@@ -1409,6 +1403,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:
@@ -1440,6 +1437,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:
@@ -1469,6 +1469,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
@@ -1509,6 +1514,8 @@ 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;
+            if (kvm_enabled())
+                kvm_put_registers(s->c_cpu);
 #elif defined (TARGET_PPC)
             s->c_cpu->nip = addr;
 #elif defined (TARGET_SPARC)
@@ -1550,6 +1557,8 @@ 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;
+            if (kvm_enabled())
+                kvm_put_registers(s->c_cpu);
 #elif defined (TARGET_PPC)
             s->c_cpu->nip = addr;
 #elif defined (TARGET_SPARC)
@@ -1595,6 +1604,8 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
         }
         break;
     case 'g':
+        if (kvm_enabled())
+            kvm_get_registers(s->g_cpu);
         len = 0;
         for (addr = 0; addr < num_g_regs; addr++) {
             reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr);
@@ -1612,6 +1623,8 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
             len -= reg_size;
             registers += reg_size;
         }
+        if (kvm_enabled())
+            kvm_put_registers(s->g_cpu);
         put_packet(s, "OK");
         break;
     case 'm':
@@ -1770,6 +1783,8 @@ 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) {
+                    if (kvm_enabled())
+                        kvm_get_registers(env);
                     len = snprintf((char *)mem_buf, sizeof(mem_buf),
                                    "CPU#%d [%s]", env->cpu_index,
                                    env->halted ? "halted " : "running");
diff --git a/gdbstub.h b/gdbstub.h
index c7d1c4b..5740041 100644
--- a/gdbstub.h
+++ b/gdbstub.h
@@ -3,6 +3,13 @@
 
 #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 void (*gdb_syscall_complete_cb)(CPUState *env,
                                         target_ulong ret, target_ulong err);
 
diff --git a/kvm-all.c b/kvm-all.c
index 9fb295c..51bb6e3 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -22,6 +22,7 @@
 
 #include "qemu-common.h"
 #include "sysemu.h"
+#include "gdbstub.h"
 #include "kvm.h"
 
 /* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */
@@ -156,6 +157,16 @@ int kvm_sync_vcpus(void)
     return 0;
 }
 
+void kvm_put_registers(CPUState *env)
+{
+    kvm_arch_put_registers(env);
+}
+
+void kvm_get_registers(CPUState *env)
+{
+    kvm_arch_get_registers(env);
+}
+
 /*
  * dirty pages logging control
  */
@@ -511,6 +522,16 @@ int kvm_cpu_exec(CPUState *env)
             break;
         case KVM_EXIT_DEBUG:
             dprintf("kvm_exit_debug\n");
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+            if (kvm_arch_debug(&run->debug.arch)) {
+                gdb_set_stop_cpu(env);
+                vm_stop(EXCP_DEBUG);
+                env->exception_index = EXCP_DEBUG;
+                return 0;
+            }
+            /* re-enter, this exception was guest-internal */
+            ret = 1;
+#endif /* KVM_CAP_SET_GUEST_DEBUG */
             break;
         default:
             dprintf("kvm_arch_handle_exit\n");
@@ -663,3 +684,154 @@ int kvm_has_sync_mmu(void)
 
     return 0;
 }
+
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+struct kvm_sw_breakpoint_head kvm_sw_breakpoints =
+    TAILQ_HEAD_INITIALIZER(kvm_sw_breakpoints);
+
+struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(target_ulong pc)
+{
+    struct kvm_sw_breakpoint *bp;
+
+    TAILQ_FOREACH(bp, &kvm_sw_breakpoints, entry) {
+        if (bp->pc == pc)
+            return bp;
+    }
+    return NULL;
+}
+
+int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
+{
+    struct kvm_guest_debug dbg;
+
+    dbg.control = 0;
+    if (env->singlestep_enabled)
+        dbg.control = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
+
+    kvm_arch_update_guest_debug(env, &dbg);
+    dbg.control |= reinject_trap;
+
+    return kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &dbg);
+}
+
+int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
+                          target_ulong len, int type)
+{
+    struct kvm_sw_breakpoint *bp;
+    CPUState *env;
+    int err;
+
+    if (type == GDB_BREAKPOINT_SW) {
+        bp = kvm_find_sw_breakpoint(addr);
+        if (bp) {
+            bp->use_count++;
+            return 0;
+        }
+
+        bp = qemu_malloc(sizeof(struct kvm_sw_breakpoint));
+        if (!bp)
+            return -ENOMEM;
+
+        bp->pc = addr;
+        bp->use_count = 1;
+        err = kvm_arch_insert_sw_breakpoint(current_env, bp);
+        if (err) {
+            free(bp);
+            return err;
+        }
+
+        TAILQ_INSERT_HEAD(&kvm_sw_breakpoints, bp, entry);
+    } else {
+        err = kvm_arch_insert_hw_breakpoint(addr, len, type);
+        if (err)
+            return err;
+    }
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        err = kvm_update_guest_debug(env, 0);
+        if (err)
+            return err;
+    }
+    return 0;
+}
+
+int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
+                          target_ulong len, int type)
+{
+    struct kvm_sw_breakpoint *bp;
+    CPUState *env;
+    int err;
+
+    if (type == GDB_BREAKPOINT_SW) {
+        bp = kvm_find_sw_breakpoint(addr);
+        if (!bp)
+            return -ENOENT;
+
+        if (bp->use_count > 1) {
+            bp->use_count--;
+            return 0;
+        }
+
+        err = kvm_arch_remove_sw_breakpoint(current_env, bp);
+        if (err)
+            return err;
+
+        TAILQ_REMOVE(&kvm_sw_breakpoints, bp, entry);
+        qemu_free(bp);
+    } else {
+        err = kvm_arch_remove_hw_breakpoint(addr, len, type);
+        if (err)
+            return err;
+    }
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        err = kvm_update_guest_debug(env, 0);
+        if (err)
+            return err;
+    }
+    return 0;
+}
+
+void kvm_remove_all_breakpoints(CPUState *current_env)
+{
+    struct kvm_sw_breakpoint *bp, *next;
+    CPUState *env;
+
+    TAILQ_FOREACH_SAFE(bp, &kvm_sw_breakpoints, entry, next) {
+        if (kvm_arch_remove_sw_breakpoint(current_env, bp) != 0) {
+            /* Try harder to find a CPU that currently sees the breakpoint. */
+            for (env = first_cpu; env != NULL; env = env->next_cpu) {
+                if (kvm_arch_remove_sw_breakpoint(env, bp) == 0)
+                    break;
+            }
+        }
+    }
+    kvm_arch_remove_all_hw_breakpoints();
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu)
+        kvm_update_guest_debug(env, 0);
+}
+
+#else /* !KVM_CAP_SET_GUEST_DEBUG */
+
+int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
+{
+    return -EINVAL;
+}
+
+int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
+                          target_ulong len, int type)
+{
+    return -EINVAL;
+}
+
+int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
+                          target_ulong len, int type)
+{
+    return -EINVAL;
+}
+
+void kvm_remove_all_breakpoints(CPUState *current_env)
+{
+}
+#endif /* !KVM_CAP_SET_GUEST_DEBUG */
diff --git a/kvm.h b/kvm.h
index efce145..0f5f612 100644
--- a/kvm.h
+++ b/kvm.h
@@ -15,6 +15,7 @@
 #define QEMU_KVM_H
 
 #include "config.h"
+#include "sys-queue.h"
 
 #ifdef CONFIG_KVM
 extern int kvm_allowed;
@@ -49,6 +50,16 @@ int kvm_has_sync_mmu(void);
 int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
 int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
 
+void kvm_get_registers(CPUState *env);
+void kvm_put_registers(CPUState *env);
+
+int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
+                          target_ulong len, int type);
+int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
+                          target_ulong len, int type);
+void kvm_remove_all_breakpoints(CPUState *current_env);
+int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap);
+
 /* internal API */
 
 struct KVMState;
@@ -76,4 +87,34 @@ int kvm_arch_init(KVMState *s, int smp_cpus);
 
 int kvm_arch_init_vcpu(CPUState *env);
 
+struct kvm_guest_debug;
+struct kvm_debug_exit_arch;
+
+struct kvm_sw_breakpoint {
+    target_ulong pc;
+    target_ulong saved_insn;
+    int use_count;
+    TAILQ_ENTRY(kvm_sw_breakpoint) entry;
+};
+
+TAILQ_HEAD(kvm_sw_breakpoint_head, kvm_sw_breakpoint);
+
+extern struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
+
+int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info);
+
+struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(target_ulong pc);
+
+int kvm_arch_insert_sw_breakpoint(CPUState *current_env,
+                                  struct kvm_sw_breakpoint *bp);
+int kvm_arch_remove_sw_breakpoint(CPUState *current_env,
+                                  struct kvm_sw_breakpoint *bp);
+int kvm_arch_insert_hw_breakpoint(target_ulong addr,
+                                  target_ulong len, int type);
+int kvm_arch_remove_hw_breakpoint(target_ulong addr,
+                                  target_ulong len, int type);
+void kvm_arch_remove_all_hw_breakpoints(void);
+
+void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg);
+
 #endif
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 2412ae4..1490e38 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -22,6 +22,7 @@
 #include "sysemu.h"
 #include "kvm.h"
 #include "cpu.h"
+#include "gdbstub.h"
 
 //#define DEBUG_KVM
 
@@ -637,3 +638,174 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
 
     return ret;
 }
+
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
+{
+    uint8_t int3 = 0xcc;
+
+    if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 0) ||
+        cpu_memory_rw_debug(env, bp->pc, &int3, 1, 1))
+        return -EINVAL;
+    return 0;
+}
+
+int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
+{
+    uint8_t int3;
+
+    if (cpu_memory_rw_debug(env, bp->pc, &int3, 1, 0) || int3 != 0xcc ||
+        cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1))
+        return -EINVAL;
+    return 0;
+}
+
+static struct {
+    target_ulong addr;
+    int len;
+    int type;
+} hw_breakpoint[4];
+
+static int nb_hw_breakpoint;
+
+static int find_hw_breakpoint(target_ulong addr, int len, int type)
+{
+    int n;
+
+    for (n = 0; n < nb_hw_breakpoint; n++)
+        if (hw_breakpoint[n].addr == addr && hw_breakpoint[n].type == type &&
+            (hw_breakpoint[n].len == len || len == -1))
+            return n;
+    return -1;
+}
+
+int kvm_arch_insert_hw_breakpoint(target_ulong addr,
+                                  target_ulong len, int type)
+{
+    switch (type) {
+    case GDB_BREAKPOINT_HW:
+        len = 1;
+        break;
+    case GDB_WATCHPOINT_WRITE:
+    case GDB_WATCHPOINT_ACCESS:
+        switch (len) {
+        case 1:
+            break;
+        case 2:
+        case 4:
+        case 8:
+            if (addr & (len - 1))
+                return -EINVAL;
+            break;
+        default:
+            return -EINVAL;
+        }
+        break;
+    default:
+        return -ENOSYS;
+    }
+
+    if (nb_hw_breakpoint == 4)
+        return -ENOBUFS;
+
+    if (find_hw_breakpoint(addr, len, type) >= 0)
+        return -EEXIST;
+
+    hw_breakpoint[nb_hw_breakpoint].addr = addr;
+    hw_breakpoint[nb_hw_breakpoint].len = len;
+    hw_breakpoint[nb_hw_breakpoint].type = type;
+    nb_hw_breakpoint++;
+
+    return 0;
+}
+
+int kvm_arch_remove_hw_breakpoint(target_ulong addr,
+                                  target_ulong len, int type)
+{
+    int n;
+
+    n = find_hw_breakpoint(addr, (type == GDB_BREAKPOINT_HW) ? 1 : len, type);
+    if (n < 0)
+        return -ENOENT;
+
+    nb_hw_breakpoint--;
+    hw_breakpoint[n] = hw_breakpoint[nb_hw_breakpoint];
+
+    return 0;
+}
+
+void kvm_arch_remove_all_hw_breakpoints(void)
+{
+    nb_hw_breakpoint = 0;
+}
+
+static CPUWatchpoint hw_watchpoint;
+
+int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info)
+{
+    int handle = 0;
+    int n;
+
+    if (arch_info->exception == 1) {
+        if (arch_info->dr6 & (1 << 14)) {
+            if (cpu_single_env->singlestep_enabled)
+                handle = 1;
+        } else {
+            for (n = 0; n < 4; n++)
+                if (arch_info->dr6 & (1 << n))
+                    switch ((arch_info->dr7 >> (16 + n*4)) & 0x3) {
+                    case 0x0:
+                        handle = 1;
+                        break;
+                    case 0x1:
+                        handle = 1;
+                        cpu_single_env->watchpoint_hit = &hw_watchpoint;
+                        hw_watchpoint.vaddr = hw_breakpoint[n].addr;
+                        hw_watchpoint.flags = BP_MEM_WRITE;
+                        break;
+                    case 0x3:
+                        handle = 1;
+                        cpu_single_env->watchpoint_hit = &hw_watchpoint;
+                        hw_watchpoint.vaddr = hw_breakpoint[n].addr;
+                        hw_watchpoint.flags = BP_MEM_ACCESS;
+                        break;
+                    }
+        }
+    } else if (kvm_find_sw_breakpoint(arch_info->pc))
+        handle = 1;
+
+    if (!handle)
+        kvm_update_guest_debug(cpu_single_env,
+                        (arch_info->exception == 1) ?
+                        KVM_GUESTDBG_INJECT_DB : KVM_GUESTDBG_INJECT_BP);
+
+    return handle;
+}
+
+void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
+{
+    const uint8_t type_code[] = {
+        [GDB_BREAKPOINT_HW] = 0x0,
+        [GDB_WATCHPOINT_WRITE] = 0x1,
+        [GDB_WATCHPOINT_ACCESS] = 0x3
+    };
+    const uint8_t len_code[] = {
+        [1] = 0x0, [2] = 0x1, [4] = 0x3, [8] = 0x2
+    };
+    int n;
+
+    if (!TAILQ_EMPTY(&kvm_sw_breakpoints))
+        dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
+
+    if (nb_hw_breakpoint > 0) {
+        dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP;
+        dbg->arch.debugreg[7] = 0x0600;
+        for (n = 0; n < nb_hw_breakpoint; n++) {
+            dbg->arch.debugreg[n] = hw_breakpoint[n].addr;
+            dbg->arch.debugreg[7] |= (2 << (n * 2)) |
+                (type_code[hw_breakpoint[n].type] << (16 + n*4)) |
+                (len_code[hw_breakpoint[n].len] << (18 + n*4));
+        }
+    }
+}
+#endif /* KVM_CAP_SET_GUEST_DEBUG */

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [Qemu-devel] [PATCH] Guest debugging support for KVM
  2009-01-14 14:43 [Qemu-devel] [PATCH] Guest debugging support for KVM Jan Kiszka
@ 2009-01-15 20:19 ` Anthony Liguori
  2009-01-15 21:26   ` [Qemu-devel] " Jan Kiszka
  0 siblings, 1 reply; 3+ messages in thread
From: Anthony Liguori @ 2009-01-15 20:19 UTC (permalink / raw)
  To: qemu-devel

Jan Kiszka wrote:
> [ Also available via git://git.kiszka.org/qemu.git queue/gdb ]
>
> 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
>
> Open issues: Writing soft breakpoints to BIOS code. cpu_memory_rw_debug
> does not work here. Suggestion to fix this cleanly are welcome.
>
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
>
>  configure         |    4 +
>  exec.c            |   10 ++-
>  gdbstub.c         |   29 +++++++--
>  gdbstub.h         |    7 ++
>  kvm-all.c         |  172 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  kvm.h             |   41 +++++++++++++
>  target-i386/kvm.c |  172 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  7 files changed, 423 insertions(+), 12 deletions(-)
>
> diff --git a/configure b/configure
> index a8ea55a..afbe1e0 100755
> --- a/configure
> +++ b/configure
> @@ -479,11 +479,11 @@ case "$cpu" in
>             ARCH_CFLAGS="-march=z900"
>             ;;
>      i386)
> -           ARCH_CFLAGS="-m32"
> +           ARCH_CFLAGS="-m32 -DCONFIG_X86"
>             ARCH_LDFLAGS="-m32"
>             ;;
>      x86_64)
> -           ARCH_CFLAGS="-m64"
> +           ARCH_CFLAGS="-m64 -DCONFIG_X86"
>             ARCH_LDFLAGS="-m64"
>             ;;
>  esac
>   

This seems unnecessary, no?

The rest looks good.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [Qemu-devel] Re: [PATCH] Guest debugging support for KVM
  2009-01-15 20:19 ` Anthony Liguori
@ 2009-01-15 21:26   ` Jan Kiszka
  0 siblings, 0 replies; 3+ messages in thread
From: Jan Kiszka @ 2009-01-15 21:26 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 2322 bytes --]

Anthony Liguori wrote:
> Jan Kiszka wrote:
>> [ Also available via git://git.kiszka.org/qemu.git queue/gdb ]
>>
>> 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
>>
>> Open issues: Writing soft breakpoints to BIOS code. cpu_memory_rw_debug
>> does not work here. Suggestion to fix this cleanly are welcome.
>>
>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
>> ---
>>
>>  configure         |    4 +
>>  exec.c            |   10 ++-
>>  gdbstub.c         |   29 +++++++--
>>  gdbstub.h         |    7 ++
>>  kvm-all.c         |  172
>> +++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  kvm.h             |   41 +++++++++++++
>>  target-i386/kvm.c |  172
>> +++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  7 files changed, 423 insertions(+), 12 deletions(-)
>>
>> diff --git a/configure b/configure
>> index a8ea55a..afbe1e0 100755
>> --- a/configure
>> +++ b/configure
>> @@ -479,11 +479,11 @@ case "$cpu" in
>>             ARCH_CFLAGS="-march=z900"
>>             ;;
>>      i386)
>> -           ARCH_CFLAGS="-m32"
>> +           ARCH_CFLAGS="-m32 -DCONFIG_X86"
>>             ARCH_LDFLAGS="-m32"
>>             ;;
>>      x86_64)
>> -           ARCH_CFLAGS="-m64"
>> +           ARCH_CFLAGS="-m64 -DCONFIG_X86"
>>             ARCH_LDFLAGS="-m64"
>>             ;;
>>  esac
>>   
> 
> This seems unnecessary, no?

Nope. I suggested and Avi merged a patch to define
KVM_CAP_SET_GUEST_DEBUG only for those archs (ie. currently x86) that
really support it. That avoids having to define empty stubs on the other
KVM archs.

So we need to define the proper arch switch to make the CAP appear in
the kernel header. Also note that there are much more conditional CAP
defines queued up or already merged into mainline.

> 
> The rest looks good.
> 
> Regards,
> 
> Anthony Liguori
> 
> 
> 

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-01-15 21:26 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-14 14:43 [Qemu-devel] [PATCH] Guest debugging support for KVM Jan Kiszka
2009-01-15 20:19 ` Anthony Liguori
2009-01-15 21:26   ` [Qemu-devel] " Jan Kiszka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).