All of lore.kernel.org
 help / color / mirror / Atom feed
From: Glauber Costa <glommer@redhat.com>
To: kvm@vger.kernel.org
Cc: avi@redhat.com
Subject: [PATCH 8/8] use upstream code for breakpoint handling
Date: Wed,  8 Jul 2009 09:09:02 -0400	[thread overview]
Message-ID: <1247058542-31211-9-git-send-email-glommer@redhat.com> (raw)
In-Reply-To: <1247058542-31211-8-git-send-email-glommer@redhat.com>

---
 kvm-all.c         |  422 +++++++++++++++-----------------------------
 target-i386/kvm.c |  514 ++++++++++++++++++-----------------------------------
 2 files changed, 314 insertions(+), 622 deletions(-)

diff --git a/kvm-all.c b/kvm-all.c
index 6f92874..a364d34 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -63,6 +63,148 @@ struct KVMState
 static KVMState *kvm_state;
 kvm_context_t kvm_context;
 
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
+                                                 target_ulong pc)
+{
+    struct kvm_sw_breakpoint *bp;
+
+    TAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) {
+        if (bp->pc == pc)
+            return bp;
+    }
+    return NULL;
+}
+
+int kvm_sw_breakpoints_active(CPUState *env)
+{
+    return !TAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints);
+}
+
+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(current_env, 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(&current_env->kvm_state->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(current_env, 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(&current_env->kvm_state->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;
+    KVMState *s = current_env->kvm_state;
+    CPUState *env;
+
+    TAILQ_FOREACH_SAFE(bp, &s->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 */
+
 #ifdef CONFIG_KVM
 
 /* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */
@@ -885,24 +1027,6 @@ void kvm_setup_guest_memory(void *start, size_t size)
     }
 }
 
-#ifdef KVM_CAP_SET_GUEST_DEBUG
-struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
-                                                 target_ulong pc)
-{
-    struct kvm_sw_breakpoint *bp;
-
-    TAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) {
-        if (bp->pc == pc)
-            return bp;
-    }
-    return NULL;
-}
-
-int kvm_sw_breakpoints_active(CPUState *env)
-{
-    return !TAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints);
-}
-
 int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
 {
     struct kvm_guest_debug dbg;
@@ -917,129 +1041,6 @@ int kvm_update_guest_debug(CPUState *env, unsigned long 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(current_env, 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(&current_env->kvm_state->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(current_env, 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(&current_env->kvm_state->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;
-    KVMState *s = current_env->kvm_state;
-    CPUState *env;
-
-    TAILQ_FOREACH_SAFE(bp, &s->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 */
 #endif /* CONFIG_KVM */
 
 #ifdef USE_KVM
@@ -3439,18 +3440,6 @@ int kvm_qemu_init_env(CPUState *cenv)
 
 #ifdef KVM_CAP_SET_GUEST_DEBUG
 
-struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
-                                                 target_ulong pc)
-{
-    struct kvm_sw_breakpoint *bp;
-
-    TAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) {
-	if (bp->pc == pc)
-	    return bp;
-    }
-    return NULL;
-}
-
 struct kvm_set_guest_debug_data {
     struct kvm_guest_debug dbg;
     int err;
@@ -3478,133 +3467,6 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
     on_vcpu(env, kvm_invoke_set_guest_debug, &data);
     return data.err;
 }
-
-int kvm_sw_breakpoints_active(CPUState *env)
-{
-    return !TAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints);
-}
-
-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(current_env, 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(&current_env->kvm_state->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(current_env, 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(&current_env->kvm_state->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, &current_env->kvm_state->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/target-i386/kvm.c b/target-i386/kvm.c
index 66da1ba..54fc9dc 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -35,6 +35,178 @@
 #include "libkvm-all.h"
 #include "libkvm.h"
 
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
+{
+    const static 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, (uint8_t *)&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(cpu_single_env, 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 (kvm_sw_breakpoints_active(env))
+        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 */
+
+
 #ifdef CONFIG_KVM
 
 //#define DEBUG_KVM
@@ -802,177 +974,6 @@ 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)
-{
-    const static 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, (uint8_t *)&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(cpu_single_env, 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 (kvm_sw_breakpoints_active(env))
-        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 */
-
 #endif /* CONFIG_KVM */
 #ifdef USE_KVM
 
@@ -2301,177 +2302,6 @@ 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)
-{
-    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;
-}
-
-#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;
-}
-
-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(cpu_single_env, 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 (kvm_sw_breakpoints_active(env))
-	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
-
 void kvm_arch_do_ioperm(void *_data)
 {
     struct ioperm_data *data = _data;
-- 
1.6.2.2


  reply	other threads:[~2009-07-08 13:09 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-07-08 13:08 [PATCH 0/8] Move closer to upstream Glauber Costa
2009-07-08 13:08 ` [PATCH 1/8] Provide KVMState definition outside CONFIG_KVM Glauber Costa
2009-07-08 13:22   ` Avi Kivity
     [not found]   ` <1247058542-31211-3-git-send-email-glommer@redhat.com>
2009-07-08 13:08     ` [PATCH 3/8] put qemu-kvm-x86.c into kvm.c Glauber Costa
2009-07-08 13:08       ` [PATCH 4/8] replace malloc with qemu_malloc Glauber Costa
2009-07-08 13:08         ` [PATCH 5/8] move kvm_context inside KVMState Glauber Costa
2009-07-08 13:09           ` [PATCH 6/8] provide env->kvm_fd Glauber Costa
2009-07-08 13:09             ` [PATCH 7/8] use kvm_upstream sw_breakpoints structure Glauber Costa
2009-07-08 13:09               ` Glauber Costa [this message]
2009-07-08 13:27               ` Avi Kivity
2009-07-08 13:39                 ` Glauber Costa
2009-07-08 13:44                   ` Avi Kivity
2009-07-08 15:23                     ` Jan Kiszka
2009-07-08 19:44                       ` Jan Kiszka
2009-07-08 19:55                         ` Avi Kivity
2009-07-08 13:32             ` [PATCH 6/8] provide env->kvm_fd Gleb Natapov
2009-07-08 13:44               ` Glauber Costa
2009-07-08 13:38                 ` Gleb Natapov
2009-07-08 13:23       ` [PATCH 3/8] put qemu-kvm-x86.c into kvm.c Avi Kivity
2009-07-08 13:28       ` Gleb Natapov
2009-07-08 13:41         ` Glauber Costa
2009-07-08 13:23     ` [PATCH 2/8] move qemu-kvm.c to kvm-all.c Avi Kivity
2009-07-08 13:52       ` Glauber Costa
2009-07-08 13:27 ` [PATCH 0/8] Move closer to upstream Avi Kivity

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=1247058542-31211-9-git-send-email-glommer@redhat.com \
    --to=glommer@redhat.com \
    --cc=avi@redhat.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.