Liu Yu wrote:
Signed-off-by: Liu Yu yu.liu-kzfg59tc24xl57midrc...@public.gmane.org
---
target-ppc/kvm.c | 197
++
1 files changed, 197 insertions(+), 0 deletions(-)
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index b53d6e9..d8dbdb4 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -8,6 +8,9 @@
* Christian Ehrhardt
ehrhardt-23vcf4htsmix0ybbhkvfkdbpr1lh4...@public.gmane.org
* Hollis Blanchard hollisb-r/jw6+rmf7hqt0dzr+a...@public.gmane.org
*
+ * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
+ * Yu Liu yu.liu-kzfg59tc24xl57midrc...@public.gmane.org
+ *
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
@@ -18,6 +21,7 @@
#include sys/mman.h
#include linux/kvm.h
+#include asm/kvm_asm.h
#include qemu-common.h
#include qemu-timer.h
@@ -26,6 +30,7 @@
#include kvm_ppc.h
#include cpu.h
#include device_tree.h
+#include gdbstub.h
//#define DEBUG_KVM
@@ -216,3 +221,195 @@ 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)
+{
+uint32_t sc = tswap32(KVM_INST_GUESTGDB);
+uint32_t tmp;
+
+if (cpu_memory_rw_debug(env, bp-pc, (uint8_t *)bp-saved_insn, 4, 0) ||
+cpu_memory_rw_debug(env, bp-pc, (uint8_t *)sc, 4, 1))
+return -EINVAL;
+cpu_memory_rw_debug(env, bp-pc, (uint8_t *)tmp, 4, 0);
+return 0;
+}
+
+int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint
*bp)
+{
+uint32_t sc;
+
+if (cpu_memory_rw_debug(env, bp-pc, (uint8_t *)sc, 4, 0) ||
+sc != tswap32(KVM_INST_GUESTGDB) ||
+cpu_memory_rw_debug(env, bp-pc, (uint8_t *)bp-saved_insn, 4, 1))
+return -EINVAL;
+return 0;
+}
+
+static struct {
+target_ulong addr;
+int type;
+} hw_breakpoint[6];
+
+static int nb_hw_breakpoint;
+static int nb_hw_watchpoint;
+static int max_hw_breakpoint;
+static int max_hw_watchpoint;
+
+void kvmppc_debug_init(int max_hw_bp, int max_hw_wp)
+{
+max_hw_breakpoint = max_hw_bp 4? 4 : max_hw_bp;
+max_hw_watchpoint = max_hw_wp 2? 2 : max_hw_wp;
+}
+
+static int find_hw_breakpoint(target_ulong addr, int type)
+{
+int n;
+
+for (n = 0; n nb_hw_breakpoint + nb_hw_watchpoint; n++)
+if (hw_breakpoint[n].addr == addr hw_breakpoint[n].type == type)
+return n;
+return -1;
+}
+
+int kvm_arch_insert_hw_breakpoint(target_ulong addr,
+ target_ulong len, int type)
+{
+hw_breakpoint[nb_hw_breakpoint + nb_hw_watchpoint].addr = addr;
+hw_breakpoint[nb_hw_breakpoint + nb_hw_watchpoint].type = type;
+
+switch (type) {
+case GDB_BREAKPOINT_HW:
+if (nb_hw_breakpoint = max_hw_breakpoint)
+return -ENOBUFS;
+
+if (find_hw_breakpoint(addr, type) = 0)
+return -EEXIST;
+
+nb_hw_breakpoint++;
+break;
+
+case GDB_WATCHPOINT_WRITE:
+case GDB_WATCHPOINT_ACCESS:
+if (nb_hw_watchpoint = max_hw_watchpoint)
+return -ENOBUFS;
+
+if (find_hw_breakpoint(addr, type) = 0)
+return -EEXIST;
+
+nb_hw_watchpoint++;
+break;
+
+default:
+return -ENOSYS;
+}
+
+return 0;
+}
+
+int kvm_arch_remove_hw_breakpoint(target_ulong addr,
+ target_ulong len, int type)
+{
+int n;
+
+n = find_hw_breakpoint(addr, type);
+if (n 0)
+return -ENOENT;
+
+switch (type) {
+case GDB_BREAKPOINT_HW:
+nb_hw_breakpoint--;
+break;
+
+case GDB_WATCHPOINT_WRITE:
+case GDB_WATCHPOINT_ACCESS:
+nb_hw_watchpoint--;
+break;
+
+default:
+return -ENOSYS;
+}
+hw_breakpoint[n] = hw_breakpoint[nb_hw_breakpoint + nb_hw_watchpoint];
+
+return 0;
+}
+
+void kvm_arch_remove_all_hw_breakpoints(void)
+{
+nb_hw_breakpoint = nb_hw_watchpoint = 0;
+}
+
+static CPUWatchpoint hw_watchpoint;
+
+int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info)
+{
+int handle = 0;
+int n;
+
+if (cpu_single_env-singlestep_enabled) {
+handle = 1;
+
+} else if (arch_info-status) {
+if (arch_info-status == KVMPPC_DEBUG_BREAKPOINT) {
+n = find_hw_breakpoint(arch_info-pc, GDB_BREAKPOINT_HW);
+if (n = 0)
+handle = 1;
+
+} else if (arch_info-status == KVMPPC_DEBUG_WATCH_ACCESS) {
+n = find_hw_breakpoint(arch_info-pc, GDB_WATCHPOINT_ACCESS);
+if (n = 0) {
+handle = 1;
+cpu_single_env-watchpoint_hit = hw_watchpoint;
+hw_watchpoint.vaddr =