@@ -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(¤t_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(¤t_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(¤t_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(¤t_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(¤t_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(¤t_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, ¤t_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 */
/*
@@ -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;