public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@web.de>
To: kvm-devel <kvm-devel@lists.sourceforge.net>
Cc: Hollis Blanchard <hollisb@us.ibm.com>
Subject: [RFC][PATCH 4/4] kvm-userspace: use soft-BPs for guest debugging
Date: Fri, 16 May 2008 18:02:13 +0200	[thread overview]
Message-ID: <482DB005.4010509@web.de> (raw)
In-Reply-To: <482D9198.7040801@web.de>

With this patch applied, kvm is able to ignore breakpoint requests of an
attached gdb frontend so that the latter is motivated to insert soft
breakpoints into the guest code. All we need to do for this is to catch
and forward #BP exceptions which are now provided by the kernel module.

Along this, the patch makes vm_stop-on-breakpoint start to work.

Limitations:
 - only takes care of x86 so far
 - gdbstub state tracking is broken (artificially incrementing
   nb_breakpoints won't fly, as we'll have no chance to decrement it),
   we need an enhanced interface to the stub

---
 libkvm/kvm-common.h |    2 ++
 libkvm/libkvm-x86.c |   16 ++++++++++++++++
 libkvm/libkvm.c     |    5 -----
 libkvm/libkvm.h     |    8 +++++++-
 qemu/exec.c         |   19 +++++++++++++------
 qemu/qemu-kvm.c     |   22 +++++++++++++---------
 6 files changed, 51 insertions(+), 21 deletions(-)

Index: b/libkvm/kvm-common.h
===================================================================
--- a/libkvm/kvm-common.h
+++ b/libkvm/kvm-common.h
@@ -85,4 +85,6 @@ int handle_io_window(kvm_context_t kvm);
 int handle_debug(kvm_context_t kvm, int vcpu);
 int try_push_interrupts(kvm_context_t kvm);
 
+int handle_debug(kvm_context_t kvm, int vcpu);
+
 #endif
Index: b/libkvm/libkvm-x86.c
===================================================================
--- a/libkvm/libkvm-x86.c
+++ b/libkvm/libkvm-x86.c
@@ -661,3 +661,19 @@ int kvm_disable_tpr_access_reporting(kvm
 }
 
 #endif
+
+int handle_debug(kvm_context_t kvm, int vcpu)
+{
+	struct kvm_run *run = kvm->run[vcpu];
+	unsigned long watchpoint = 0;
+	int break_type;
+
+	if (run->debug.arch.exception == 1) {
+		/* TODO: fully process run->debug.arch */
+		break_type = KVM_GDB_BREAKPOINT_HW;
+	} else
+		break_type = KVM_GDB_BREAKPOINT_SW;
+
+	return kvm->callbacks->debug(kvm->opaque, vcpu, break_type,
+				     watchpoint);
+}
Index: b/libkvm/libkvm.c
===================================================================
--- a/libkvm/libkvm.c
+++ b/libkvm/libkvm.c
@@ -738,11 +738,6 @@ static int handle_io(kvm_context_t kvm, 
 	return 0;
 }
 
-int handle_debug(kvm_context_t kvm, int vcpu)
-{
-	return kvm->callbacks->debug(kvm->opaque, vcpu);
-}
-
 int kvm_get_regs(kvm_context_t kvm, int vcpu, struct kvm_regs *regs)
 {
     return ioctl(kvm->vcpu_fd[vcpu], KVM_GET_REGS, regs);
Index: b/qemu/exec.c
===================================================================
--- a/qemu/exec.c
+++ b/qemu/exec.c
@@ -1157,6 +1157,12 @@ int cpu_breakpoint_insert(CPUState *env,
 #if defined(TARGET_HAS_ICE)
     int i;
 
+    if (kvm_enabled()) {
+        env->nb_breakpoints++;
+        kvm_update_debugger(env);
+        return -ENOSYS;
+    }
+
     for(i = 0; i < env->nb_breakpoints; i++) {
         if (env->breakpoints[i] == pc)
             return 0;
@@ -1166,9 +1172,6 @@ int cpu_breakpoint_insert(CPUState *env,
         return -ENOBUFS;
     env->breakpoints[env->nb_breakpoints++] = pc;
 
-    if (kvm_enabled())
-	kvm_update_debugger(env);
-
     breakpoint_invalidate(env, pc);
     return 0;
 #else
@@ -1182,6 +1185,13 @@ int cpu_breakpoint_remove(CPUState *env,
 {
 #if defined(TARGET_HAS_ICE)
     int i;
+
+    if (kvm_enabled()) {
+        env->nb_breakpoints--;
+        kvm_update_debugger(env);
+        return -ENOSYS;
+    }
+
     for(i = 0; i < env->nb_breakpoints; i++) {
         if (env->breakpoints[i] == pc)
             goto found;
@@ -1192,9 +1202,6 @@ int cpu_breakpoint_remove(CPUState *env,
     if (i < env->nb_breakpoints)
       env->breakpoints[i] = env->breakpoints[env->nb_breakpoints];
 
-    if (kvm_enabled())
-	kvm_update_debugger(env);
-    
     breakpoint_invalidate(env, pc);
     return 0;
 #else
Index: b/qemu/qemu-kvm.c
===================================================================
--- a/qemu/qemu-kvm.c
+++ b/qemu/qemu-kvm.c
@@ -58,6 +58,8 @@ pthread_t io_thread;
 static int io_thread_fd = -1;
 static int io_thread_sigfd = -1;
 
+static int kvm_debug_stop_requested;
+
 static inline unsigned long kvm_get_thread_id(void)
 {
     return syscall(SYS_gettid);
@@ -517,6 +519,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;
+	    vm_stop(EXCP_DEBUG);
+	}
     }
 
     pause_all_threads();
@@ -525,11 +531,12 @@ int kvm_main_loop(void)
     return 0;
 }
 
-static int kvm_debug(void *opaque, int vcpu)
+static int kvm_debug(void *opaque, int vcpu, int break_type,
+                     uint64_t watchpoint_addr)
 {
-    CPUState *env = cpu_single_env;
-
-    env->exception_index = EXCP_DEBUG;
+    /* TODO: process break_type */
+    kvm_debug_stop_requested = 1;
+    vcpu_info[vcpu].stopped = 1;
     return 1;
 }
 
@@ -748,15 +755,12 @@ int kvm_qemu_init_env(CPUState *cenv)
 int kvm_update_debugger(CPUState *env)
 {
     struct kvm_debug_guest dbg;
-    int i, r;
+    int r;
 
     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];
-	}
+	memset(dbg.breakpoints, 0, sizeof(dbg.breakpoints));
 	dbg.singlestep = env->singlestep_enabled;
     }
     if (vm_running)
Index: b/libkvm/libkvm.h
===================================================================
--- a/libkvm/libkvm.h
+++ b/libkvm/libkvm.h
@@ -25,6 +25,12 @@ int kvm_get_msrs(kvm_context_t, int vcpu
 int kvm_set_msrs(kvm_context_t, int vcpu, struct kvm_msr_entry *msrs, int n);
 #endif
 
+#define KVM_GDB_BREAKPOINT_SW		0
+#define KVM_GDB_BREAKPOINT_HW		1
+#define KVM_GDB_WATCHPOINT_WRITE	2
+#define KVM_GDB_WATCHPOINT_READ		3
+#define KVM_GDB_WATCHPOINT_ACCESS	4
+
 /*!
  * \brief KVM callbacks structure
  *
@@ -51,7 +57,7 @@ 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);
+    int (*debug)(void *opaque, int vcpu, int break_type, uint64_t watchpoint);
 	/*!
 	 * \brief Called when the VCPU issues an 'hlt' instruction.
 	 *

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft 
Defy all challenges. Microsoft(R) Visual Studio 2008. 
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

      parent reply	other threads:[~2008-05-16 16:02 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <482D9198.7040801@web.de>
2008-05-16 16:01 ` [RFC][PATCH 1/4] qemu: refactor cpu_watch/breakpoint API Jan Kiszka
2008-05-16 16:01 ` [RFC][PATCH 2/4] kvm: Arch-specifc KVM_EXIT_DEBUG payload Jan Kiszka
2008-05-21 15:59   ` [kvm-devel] " Avi Kivity
2008-05-22 13:27     ` Jan Kiszka
2008-05-21 16:04   ` Avi Kivity
2008-05-22 13:42     ` Jan Kiszka
2008-05-22 13:59       ` Avi Kivity
2008-05-22 14:32         ` Jan Kiszka
2008-05-22 14:35           ` Avi Kivity
2008-05-16 16:02 ` [RFC][PATCH 3/4] kvm-vmx: KVM_EXIT_DEBUG on #BP exceptions Jan Kiszka
2008-05-21 16:01   ` [kvm-devel] " Avi Kivity
2008-05-22 13:31     ` Jan Kiszka
2008-05-22 13:58       ` Avi Kivity
2008-05-22 14:24         ` Jan Kiszka
2008-05-22 14:31           ` Avi Kivity
2008-05-22 14:26       ` Hollis Blanchard
2008-05-22 14:34         ` Avi Kivity
2008-05-22 18:27           ` Hollis Blanchard
2008-05-25 10:24             ` Avi Kivity
2008-05-16 16:02 ` Jan Kiszka [this message]

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=482DB005.4010509@web.de \
    --to=jan.kiszka@web.de \
    --cc=hollisb@us.ibm.com \
    --cc=kvm-devel@lists.sourceforge.net \
    /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