public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@web.de>
To: kvm-devel <kvm@vger.kernel.org>
Cc: Avi Kivity <avi@qumranet.com>,
	Hollis Blanchard <hollisb@us.ibm.com>,
	Jerone Young <jyoung5@us.ibm.com>,
	Joerg Roedel <joerg.roedel@amd.com>
Subject: [PATCH 7/11] QEMU/KVM: New guest debugging interface
Date: Tue, 27 May 2008 00:10:19 +0200	[thread overview]
Message-ID: <483B354B.3090801@web.de> (raw)
In-Reply-To: <4839B14A.3010406@web.de>

This patch switches both libkvm as well as the qemu pieces over to the
new guest debug interface. It comes with full support for software-based
breakpoints (via guest code modification), hardware-assisted breakpoints
and watchpoints (x86-only so far).

Breakpoint management is done inside qemu-kvm, transparent to gdbstub,
and also avoiding that the gdb frontend takes over. This allows for
running debuggers inside the guest while guest debugging it active,
because the host can cleanly tell apart host- and guest-originated
breakpoint events.

Yet improvable are x86 corner cases when using single-step ("forgotten"
debug flags on the guest's stack). And, of courese, the yet empty
non-x86 helper functions have to be populated.

Signed-off-by: Jan Kiszka <jan.kiszka@web.de>
---
 libkvm/libkvm.c         |   14 +++-
 libkvm/libkvm.h         |    9 ++
 qemu/exec.c             |   31 +++++---
 qemu/qemu-kvm-ia64.c    |   33 +++++++++
 qemu/qemu-kvm-powerpc.c |   33 +++++++++
 qemu/qemu-kvm-x86.c     |  167 ++++++++++++++++++++++++++++++++++++++++++++++++
 qemu/qemu-kvm.c         |  157 ++++++++++++++++++++++++++++++++++++++-------
 qemu/qemu-kvm.h         |   33 ++++++++-
 user/main.c             |    7 +-
 9 files changed, 442 insertions(+), 42 deletions(-)

Index: b/libkvm/libkvm.c
===================================================================
--- a/libkvm/libkvm.c
+++ b/libkvm/libkvm.c
@@ -740,7 +740,13 @@ static int handle_io(kvm_context_t kvm, 
 
 int handle_debug(kvm_context_t kvm, int vcpu)
 {
-	return kvm->callbacks->debug(kvm->opaque, vcpu);
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+	struct kvm_run *run = kvm->run[vcpu];
+
+	return kvm->callbacks->debug(kvm->opaque, vcpu, &run->debug.arch);
+#else
+	return 0;
+#endif
 }
 
 int kvm_get_regs(kvm_context_t kvm, int vcpu, struct kvm_regs *regs)
@@ -945,10 +951,12 @@ int kvm_inject_irq(kvm_context_t kvm, in
 	return ioctl(kvm->vcpu_fd[vcpu], KVM_INTERRUPT, &intr);
 }
 
-int kvm_guest_debug(kvm_context_t kvm, int vcpu, struct kvm_debug_guest *dbg)
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+int kvm_set_guest_debug(kvm_context_t kvm, int vcpu, struct kvm_guest_debug *dbg)
 {
-	return ioctl(kvm->vcpu_fd[vcpu], KVM_DEBUG_GUEST, dbg);
+	return ioctl(kvm->vcpu_fd[vcpu], KVM_SET_GUEST_DEBUG, dbg);
 }
+#endif
 
 int kvm_set_signal_mask(kvm_context_t kvm, int vcpu, const sigset_t *sigset)
 {
Index: b/qemu/exec.c
===================================================================
--- a/qemu/exec.c
+++ b/qemu/exec.c
@@ -1110,6 +1110,9 @@ int cpu_watchpoint_insert(CPUState *env,
     CPUState *env_iter;
     int i;
 
+    if (kvm_enabled())
+        return kvm_insert_breakpoint(env, addr, len, type);
+
     if (type != GDB_WATCHPOINT_WRITE)
         return -ENOSYS;
 
@@ -1139,6 +1142,9 @@ int cpu_watchpoint_remove(CPUState *env,
     CPUState *env_iter;
     int i;
 
+    if (kvm_enabled())
+        return kvm_remove_breakpoint(env, addr, len, type);
+
     if (type != GDB_WATCHPOINT_WRITE)
         return -ENOSYS;
 
@@ -1165,6 +1171,9 @@ int cpu_breakpoint_insert(CPUState *env,
     CPUState *env_iter;
     int i;
 
+    if (kvm_enabled())
+        return kvm_insert_breakpoint(env, pc, len, type);
+
     for(i = 0; i < env->nb_breakpoints; i++) {
         if (env->breakpoints[i] == pc)
             return 0;
@@ -1175,9 +1184,6 @@ int cpu_breakpoint_insert(CPUState *env,
     foreach_cpu(env_iter)
         env_iter->breakpoints[env_iter->nb_breakpoints++] = pc;
 
-    if (kvm_enabled())
-	kvm_update_debugger(env);
-
     breakpoint_invalidate(env, pc);
     return 0;
 #else
@@ -1192,6 +1198,10 @@ int cpu_breakpoint_remove(CPUState *env,
 #if defined(TARGET_HAS_ICE)
     CPUState *env_iter;
     int i;
+
+    if (kvm_enabled())
+        return kvm_remove_breakpoint(env, pc, len, type);
+
     for(i = 0; i < env->nb_breakpoints; i++) {
         if (env->breakpoints[i] == pc)
             goto found;
@@ -1204,9 +1214,6 @@ int cpu_breakpoint_remove(CPUState *env,
             env_iter->breakpoints[env_iter->nb_breakpoints];
     }
 
-    if (kvm_enabled())
-	kvm_update_debugger(env);
-
     breakpoint_invalidate(env, pc);
     return 0;
 #else
@@ -1221,12 +1228,14 @@ void cpu_single_step(CPUState *env, int 
 #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);
+        }
     }
-    if (kvm_enabled())
-	kvm_update_debugger(env);
 #endif
 }
 
Index: b/qemu/qemu-kvm.c
===================================================================
--- a/qemu/qemu-kvm.c
+++ b/qemu/qemu-kvm.c
@@ -546,14 +546,18 @@ int kvm_main_loop(void)
     return 0;
 }
 
-static int kvm_debug(void *opaque, int vcpu)
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+int kvm_debug(void *opaque, int vcpu, struct kvm_debug_exit_arch *arch_info)
 {
-    CPUState *env = cpu_single_env;
+    int handle = kvm_arch_debug(arch_info);
 
-    kvm_debug_stop_requested = 1;
-    vcpu_info[vcpu].stopped = 1;
-    return 1;
+    if (handle) {
+	kvm_debug_stop_requested = 1;
+	vcpu_info[vcpu].stopped = 1;
+    }
+    return handle;
 }
+#endif
 
 static int kvm_inb(void *opaque, uint16_t addr, uint8_t *data)
 {
@@ -655,7 +659,9 @@ static int kvm_shutdown(void *opaque, in
 }
  
 static struct kvm_callbacks qemu_kvm_ops = {
+#ifdef KVM_CAP_SET_GUEST_DEBUG
     .debug = kvm_debug,
+#endif
     .inb   = kvm_inb,
     .inw   = kvm_inw,
     .inl   = kvm_inl,
@@ -767,30 +773,137 @@ int kvm_qemu_init_env(CPUState *cenv)
     return kvm_arch_qemu_init_env(cenv);
 }
 
-int kvm_update_debugger(CPUState *env)
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+struct kvm_sw_breakpoint *first_sw_breakpoint;
+
+struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(target_ulong pc)
+{
+    struct kvm_sw_breakpoint *bp = first_sw_breakpoint;
+
+    while (bp) {
+	if (bp->pc == pc)
+	    break;
+	bp = bp->next;
+    }
+    return bp;
+}
+
+int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
 {
-    struct kvm_debug_guest dbg;
-    int i, r;
+    struct kvm_guest_debug dbg;
+    int err;
+
+    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;
+
+    assert(!cpu_single_env || cpu_single_env == env);
 
-    memset(dbg.breakpoints, 0, sizeof(dbg.breakpoints));
+    if (!cpu_single_env && vm_running) {
+	pause_vcpu_thread(env->cpu_index);
+	err = kvm_set_guest_debug(kvm_context, env->cpu_index, &dbg);
+	resume_vcpu_thread(env->cpu_index);
+    } else
+	err = kvm_set_guest_debug(kvm_context, env->cpu_index, &dbg);
+    return err;
+}
+
+int kvm_insert_breakpoint(CPUState *env, target_ulong addr,
+			  target_ulong len, int type)
+{
+    struct kvm_sw_breakpoint *bp;
+    int err;
 
-    dbg.enabled = 0;
-    if (env->nb_breakpoints || env->singlestep_enabled) {
-	dbg.enabled = 1;
-	for (i = 0; i < 4 && i < env->nb_breakpoints; ++i) {
-	    dbg.breakpoints[i].enabled = 1;
-	    dbg.breakpoints[i].address = env->breakpoints[i];
+    if (type == GDB_BREAKPOINT_SW) {
+	bp = kvm_find_sw_breakpoint(addr);
+	if (bp) {
+	    bp->usecount++;
+	    return 0;
 	}
-	dbg.singlestep = env->singlestep_enabled;
+
+	bp = qemu_malloc(sizeof(struct kvm_sw_breakpoint));
+	if (!bp)
+	    return -ENOMEM;
+
+	bp->pc = addr;
+	bp->usecount = 1;
+	bp->prev = NULL;
+	bp->next = first_sw_breakpoint;
+	err = kvm_arch_insert_sw_breakpoint(env, bp);
+	if (err) {
+	    free(bp);
+	    return err;
+	}
+
+	first_sw_breakpoint = bp;
+	if (bp->next)
+	    bp->next->prev = bp;
+    } else {
+	err = kvm_arch_insert_hw_breakpoint(addr, len, type);
+	if (err)
+	    return err;
+    }
+    return kvm_update_guest_debug(env, 0);
+}
+
+int kvm_remove_breakpoint(CPUState *env, target_ulong addr,
+			  target_ulong len, int type)
+{
+    struct kvm_sw_breakpoint *bp;
+    int err;
+
+    if (type == GDB_BREAKPOINT_SW) {
+	bp = kvm_find_sw_breakpoint(addr);
+	if (!bp)
+	    return -ENOENT;
+
+	if (bp->usecount > 1) {
+	    bp->usecount--;
+	    return 0;
+	}
+
+	err = kvm_arch_remove_sw_breakpoint(env, bp);
+	if (err)
+	    return err;
+
+	if (bp->prev)
+	    bp->prev->next = bp->next;
+	else
+	    first_sw_breakpoint = bp->next;
+	if (bp->next)
+	    bp->next->prev = bp->prev;
+
+	qemu_free(bp);
+    } else {
+	err = kvm_arch_remove_hw_breakpoint(addr, len, type);
+	if (err)
+	    return err;
     }
-    if (vm_running)
-        pause_all_threads();
-    r = kvm_guest_debug(kvm_context, env->cpu_index, &dbg);
-    if (vm_running)
-        resume_all_threads();
-    return r;
+    return 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 *env, target_ulong addr,
+			  target_ulong len, int type)
+{
+    return -EINVAL;
+}
+
+int kvm_remove_breakpoint(CPUState *env, target_ulong addr,
+			  target_ulong len, int type)
+{
+    return -EINVAL;
+}
+#endif /* !KVM_CAP_SET_GUEST_DEBUG */
 
 /*
  * dirty pages logging
Index: b/libkvm/libkvm.h
===================================================================
--- a/libkvm/libkvm.h
+++ b/libkvm/libkvm.h
@@ -51,7 +51,10 @@ struct kvm_callbacks {
 	/// generic memory writes to unmapped memory (For MMIO devices)
     int (*mmio_write)(void *opaque, uint64_t addr, uint8_t *data,
 					int len);
-    int (*debug)(void *opaque, int vcpu);
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+    int (*debug)(void *opaque, int vcpu,
+		 struct kvm_debug_exit_arch *arch_info);
+#endif
 	/*!
 	 * \brief Called when the VCPU issues an 'hlt' instruction.
 	 *
@@ -337,7 +340,9 @@ static inline int kvm_reset_mpstate(kvm_
  */
 int kvm_inject_irq(kvm_context_t kvm, int vcpu, unsigned irq);
 
-int kvm_guest_debug(kvm_context_t, int vcpu, struct kvm_debug_guest *dbg);
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+int kvm_set_guest_debug(kvm_context_t, int vcpu, struct kvm_guest_debug *dbg);
+#endif
 
 #if defined(__i386__) || defined(__x86_64__)
 /*!
Index: b/qemu/qemu-kvm.h
===================================================================
--- a/qemu/qemu-kvm.h
+++ b/qemu/qemu-kvm.h
@@ -12,8 +12,6 @@
 
 #include <signal.h>
 
-#include <signal.h>
-
 int kvm_main_loop(void);
 int kvm_qemu_init(void);
 int kvm_qemu_create_context(void);
@@ -25,7 +23,11 @@ void kvm_save_registers(CPUState *env);
 void kvm_load_mpstate(CPUState *env);
 void kvm_save_mpstate(CPUState *env);
 int kvm_cpu_exec(CPUState *env);
-int kvm_update_debugger(CPUState *env);
+int kvm_insert_breakpoint(CPUState *env, target_ulong addr,
+			  target_ulong len, int type);
+int kvm_remove_breakpoint(CPUState *env, target_ulong addr,
+			  target_ulong len, int type);
+int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap);
 int kvm_qemu_init_env(CPUState *env);
 int kvm_qemu_check_extension(int ext);
 void kvm_apic_init(CPUState *env);
@@ -61,6 +63,31 @@ int kvm_arch_try_push_interrupts(void *o
 void kvm_arch_update_regs_for_sipi(CPUState *env);
 void kvm_arch_cpu_reset(CPUState *env);
 
+struct kvm_guest_debug;
+struct kvm_debug_exit_arch;
+
+struct kvm_sw_breakpoint {
+	target_ulong pc;
+	target_ulong saved_insn;
+	int usecount;
+	struct kvm_sw_breakpoint *prev;
+	struct kvm_sw_breakpoint *next;
+};
+
+extern struct kvm_sw_breakpoint *first_sw_breakpoint;
+
+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 *env,
+				  struct kvm_sw_breakpoint *bp);
+int kvm_arch_remove_sw_breakpoint(CPUState *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_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg);
+
 CPUState *qemu_kvm_cpu_env(int index);
 
 void qemu_kvm_aio_wait_start(void);
Index: b/qemu/qemu-kvm-ia64.c
===================================================================
--- a/qemu/qemu-kvm-ia64.c
+++ b/qemu/qemu-kvm-ia64.c
@@ -65,3 +65,36 @@ void kvm_arch_update_regs_for_sipi(CPUSt
 void kvm_arch_cpu_reset(CPUState *env)
 {
 }
+
+int kvm_arch_insert_sw_breakpoint(CPUState *env,
+				  struct kvm_sw_breakpoint *bp)
+{
+    return -EINVAL;
+}
+
+int kvm_arch_remove_sw_breakpoint(CPUState *env,
+				  struct kvm_sw_breakpoint *bp)
+{
+    return -EINVAL;
+}
+
+int kvm_arch_insert_hw_breakpoint(target_ulong addr,
+				  target_ulong len, int type)
+{
+    return -ENOSYS;
+}
+
+int kvm_arch_remove_hw_breakpoint(target_ulong addr,
+				  target_ulong len, int type)
+{
+    return -ENOSYS;
+}
+
+int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info)
+{
+    return 0;
+}
+
+void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
+{
+}
Index: b/qemu/qemu-kvm-powerpc.c
===================================================================
--- a/qemu/qemu-kvm-powerpc.c
+++ b/qemu/qemu-kvm-powerpc.c
@@ -217,3 +217,36 @@ int handle_powerpc_dcr_write(int vcpu, u
 void kvm_arch_cpu_reset(CPUState *env)
 {
 }
+
+int kvm_arch_insert_sw_breakpoint(CPUState *env,
+				  struct kvm_sw_breakpoint *bp)
+{
+    return -EINVAL;
+}
+
+int kvm_arch_remove_sw_breakpoint(CPUState *env,
+				  struct kvm_sw_breakpoint *bp)
+{
+    return -EINVAL;
+}
+
+int kvm_arch_insert_hw_breakpoint(target_ulong addr,
+				  target_ulong len, int type)
+{
+    return -ENOSYS;
+}
+
+int kvm_arch_remove_hw_breakpoint(target_ulong addr,
+				  target_ulong len, int type)
+{
+    return -ENOSYS;
+}
+
+int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info)
+{
+    return 0;
+}
+
+void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
+{
+}
Index: b/qemu/qemu-kvm-x86.c
===================================================================
--- a/qemu/qemu-kvm-x86.c
+++ b/qemu/qemu-kvm-x86.c
@@ -687,3 +687,170 @@ void kvm_arch_cpu_reset(CPUState *env)
 	}
     }
 }
+
+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)
+{
+    if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1))
+	return -EINVAL;
+    return 0;
+}
+
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+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;
+}
+
+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 = 1;
+			cpu_single_env->watchpoint[0].vaddr =
+			    hw_breakpoint[n].addr;
+			cpu_single_env->watchpoint[0].type =
+			    GDB_WATCHPOINT_WRITE;
+			break;
+		    case 0x3:
+			handle = 1;
+			cpu_single_env->watchpoint_hit = 1;
+			cpu_single_env->watchpoint[0].vaddr =
+			    hw_breakpoint[n].addr;
+			cpu_single_env->watchpoint[0].type =
+			    GDB_WATCHPOINT_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 (first_sw_breakpoint)
+	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
Index: b/user/main.c
===================================================================
--- a/user/main.c
+++ b/user/main.c
@@ -284,11 +284,14 @@ static int test_outl(void *opaque, uint1
 	return 0;
 }
 
-static int test_debug(void *opaque, int vcpu)
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+static int test_debug(void *opaque, int vcpu,
+		      struct kvm_debug_exit_arch *arch_info)
 {
 	printf("test_debug\n");
 	return 0;
 }
+#endif
 
 static int test_halt(void *opaque, int vcpu)
 {
@@ -343,7 +346,9 @@ static struct kvm_callbacks test_callbac
 	.outl        = test_outl,
 	.mmio_read   = test_mem_read,
 	.mmio_write  = test_mem_write,
+#ifdef KVM_CAP_SET_GUEST_DEBUG
 	.debug       = test_debug,
+#endif
 	.halt        = test_halt,
 	.io_window = test_io_window,
 	.try_push_interrupts = test_try_push_interrupts,


  parent reply	other threads:[~2008-05-26 22:10 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-05-26 22:05 [PATCH 0/11] Rework guest debug interface / x86 debug register support -v2 Jan Kiszka
2008-05-26 22:09 ` [PATCH 1/11] QEMU/KVM: Fix deadlocks in monitor and debugger Jan Kiszka
2008-05-27  9:36   ` Avi Kivity
2008-05-27 13:00     ` Jan Kiszka
2008-05-27 13:09       ` Avi Kivity
2008-05-26 22:09 ` [PATCH 2/11] QEMU/KVM: Cleanup and improve kvm_load/save_registers usage Jan Kiszka
2008-06-09 19:16   ` Anthony Liguori
2008-06-12 12:38     ` Avi Kivity
2008-05-26 22:09 ` [PATCH 3/11] QEMU/KVM: Proper vm_stop on debug events Jan Kiszka
2008-05-26 22:09 ` [PATCH 4/11] QEMU: Enhance cpu_break/watchpoint API and gdbstub integration Jan Kiszka
2008-05-26 22:10 ` [PATCH 5/11] QEMU: Improve SMP debugging support Jan Kiszka
2008-05-26 22:10 ` [PATCH 6/11] QEMU/KVM: Introduce single vcpu pause/resume Jan Kiszka
2008-05-26 22:10 ` Jan Kiszka [this message]
2008-05-27 18:31   ` [PATCH 7/11] QEMU/KVM: New guest debugging interface Jan Kiszka
2008-05-26 22:10 ` [PATCH 8/11] QEMU/KVM: Support for SMP guest debugging Jan Kiszka
2008-05-26 22:10 ` [PATCH 9/11] KVM: New guest debugging interface Jan Kiszka
2008-05-26 22:10 ` [PATCH 10/11] KVM-x86: Properly virtualize debug registers Jan Kiszka
2008-05-26 22:10 ` [PATCH 11/11] KVM-x86: Wire up host-managed " Jan Kiszka
2008-05-27  9:50 ` [PATCH 0/11] Rework guest debug interface / x86 debug register support -v2 Avi Kivity
2008-05-27 10:44   ` Jan Kiszka
2008-05-27 18:46   ` Hollis Blanchard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=483B354B.3090801@web.de \
    --to=jan.kiszka@web.de \
    --cc=avi@qumranet.com \
    --cc=hollisb@us.ibm.com \
    --cc=joerg.roedel@amd.com \
    --cc=jyoung5@us.ibm.com \
    --cc=kvm@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox