@@ -962,7 +962,9 @@ static void on_vcpu(CPUState *env, void (*func)(void *data), void *data)
#endif
func(data);
}
-#endif /* KVM_UPSTREAM */
+#else /* !KVM_UPSTREAM */
+static void on_vcpu(CPUState *env, void (*func)(void *data), void *data);
+#endif /* !KVM_UPSTREAM */
struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
target_ulong pc)
@@ -981,8 +983,6 @@ int kvm_sw_breakpoints_active(CPUState *env)
return !QTAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints);
}
-#ifdef KVM_UPSTREAM
-
struct kvm_set_guest_debug_data {
struct kvm_guest_debug dbg;
CPUState *env;
@@ -1012,7 +1012,6 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
on_vcpu(env, kvm_invoke_set_guest_debug, &data);
return data.err;
}
-#endif
int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
target_ulong len, int type)
@@ -54,14 +54,12 @@ int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
void kvm_flush_coalesced_mmio_buffer(void);
-#ifdef KVM_UPSTREAM
int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
target_ulong len, int type);
int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
target_ulong len, int type);
void kvm_remove_all_breakpoints(CPUState *current_env);
int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap);
-#endif /* KVM_UPSTREAM */
int kvm_pit_in_kernel(void);
int kvm_irqchip_in_kernel(void);
@@ -94,7 +92,6 @@ int kvm_arch_init(KVMState *s, int smp_cpus);
int kvm_arch_init_vcpu(CPUState *env);
void kvm_arch_reset_vcpu(CPUState *env);
-#ifdef KVM_UPSTREAM
struct kvm_guest_debug;
struct kvm_debug_exit_arch;
@@ -126,7 +123,6 @@ int kvm_arch_remove_hw_breakpoint(target_ulong addr,
void kvm_arch_remove_all_hw_breakpoints(void);
void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg);
-#endif
int kvm_check_extension(KVMState *s, unsigned int extension);
@@ -921,6 +921,32 @@ void kvm_arch_load_regs(CPUState *env)
rc = kvm_set_msrs(env, msrs, n);
if (rc == -1)
perror("kvm_set_msrs FAILED");
+
+ /*
+ * Kernels before 2.6.33 (which correlates with !kvm_has_vcpu_events())
+ * overwrote flags.TF injected via SET_GUEST_DEBUG while updating GP regs.
+ * Work around this by updating the debug state once again if
+ * single-stepping is on.
+ * Another reason to call kvm_update_guest_debug here is a pending debug
+ * trap raise by the guest. On kernels without SET_VCPU_EVENTS we have to
+ * reinject them via SET_GUEST_DEBUG.
+ */
+ if (!kvm_has_vcpu_events() &&
+ (env->exception_injected != -1 || env->singlestep_enabled)) {
+ unsigned long reinject_trap = 0;
+
+ if (env->exception_injected == 1) {
+ reinject_trap = KVM_GUESTDBG_INJECT_DB;
+ } else if (env->exception_injected == 3) {
+ reinject_trap = KVM_GUESTDBG_INJECT_BP;
+ }
+ env->exception_injected = -1;
+
+ rc = kvm_update_guest_debug(env, reinject_trap);
+ if (rc < 0) {
+ perror("kvm_update_guest_debug FAILED");
+ }
+ }
}
void kvm_load_tsc(CPUState *env)
@@ -1376,177 +1402,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
-
#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
void kvm_arch_do_ioperm(void *_data)
{
@@ -1025,13 +1025,6 @@ int kvm_inject_irq(CPUState *env, unsigned irq)
return kvm_vcpu_ioctl(env, KVM_INTERRUPT, &intr);
}
-#ifdef KVM_CAP_SET_GUEST_DEBUG
-int kvm_set_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
-{
- return kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, dbg);
-}
-#endif
-
int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset)
{
struct kvm_signal_mask *sigmask;
@@ -2312,43 +2305,6 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
return;
}
-#ifdef KVM_CAP_SET_GUEST_DEBUG
-
-struct kvm_set_guest_debug_data {
- struct kvm_guest_debug dbg;
- int err;
-};
-
-static void kvm_invoke_set_guest_debug(void *data)
-{
- struct kvm_set_guest_debug_data *dbg_data = data;
-
- if (cpu_single_env->kvm_vcpu_dirty) {
- kvm_arch_save_regs(cpu_single_env);
- cpu_single_env->kvm_vcpu_dirty = 0;
- }
- dbg_data->err =
- kvm_set_guest_debug(cpu_single_env,
- &dbg_data->dbg);
-}
-
-int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
-{
- struct kvm_set_guest_debug_data data;
-
- data.dbg.control = 0;
- if (env->singlestep_enabled)
- data.dbg.control = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
-
- kvm_arch_update_guest_debug(env, &data.dbg);
- data.dbg.control |= reinject_trap;
-
- on_vcpu(env, kvm_invoke_set_guest_debug, &data);
- return data.err;
-}
-
-#endif
-
/*
* dirty pages logging
*/
@@ -323,10 +323,6 @@ static inline int kvm_reset_mpstate(CPUState *env)
*/
int kvm_inject_irq(CPUState *env, unsigned irq);
-#ifdef KVM_CAP_SET_GUEST_DEBUG
-int kvm_set_guest_debug(CPUState *env, struct kvm_guest_debug *dbg);
-#endif
-
#if defined(__i386__) || defined(__x86_64__)
/*!
* \brief Setup a vcpu's cpuid instruction emulation
@@ -880,12 +876,6 @@ int kvm_init_ap(void);
int kvm_vcpu_inited(CPUState *env);
void kvm_load_mpstate(CPUState *env);
void kvm_save_mpstate(CPUState *env);
-int kvm_insert_breakpoint(CPUState * current_env, target_ulong addr,
- target_ulong len, int type);
-int kvm_remove_breakpoint(CPUState * current_env, target_ulong addr,
- target_ulong len, int type);
-void kvm_remove_all_breakpoints(CPUState * current_env);
-int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap);
void kvm_apic_init(CPUState *env);
/* called from vcpu initialization */
void qemu_kvm_load_lapic(CPUState *env);
@@ -928,33 +918,6 @@ void kvm_arch_push_nmi(void *opaque);
void kvm_arch_cpu_reset(CPUState *env);
int kvm_set_boot_cpu_id(uint32_t id);
-struct kvm_guest_debug;
-struct kvm_debug_exit_arch;
-
-struct kvm_sw_breakpoint {
- target_ulong pc;
- target_ulong saved_insn;
- int use_count;
- QTAILQ_ENTRY(kvm_sw_breakpoint) entry;
-};
-
-QTAILQ_HEAD(kvm_sw_breakpoint_head, kvm_sw_breakpoint);
-
-int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info);
-int kvm_sw_breakpoints_active(CPUState *env);
-struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
- target_ulong pc);
-int kvm_arch_insert_sw_breakpoint(CPUState * current_env,
- struct kvm_sw_breakpoint *bp);
-int kvm_arch_remove_sw_breakpoint(CPUState * current_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_remove_all_hw_breakpoints(void);
-void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg);
-
void qemu_kvm_aio_wait_start(void);
void qemu_kvm_aio_wait(void);
void qemu_kvm_aio_wait_end(void);
@@ -1020,6 +1020,7 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
return ret;
}
+#endif
#ifdef KVM_CAP_SET_GUEST_DEBUG
int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
@@ -1194,6 +1195,5 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
}
}
#endif /* KVM_CAP_SET_GUEST_DEBUG */
-#endif
#include "qemu-kvm-x86.c"