@@ -919,7 +919,9 @@ static void on_vcpu(CPUState *env, void (*func)(void *data), void *data)
func(data);
#endif
}
-#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)
@@ -938,8 +940,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;
@@ -969,7 +969,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)
@@ -61,14 +61,12 @@ void kvm_setup_guest_memory(void *start, size_t size);
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);
-#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);
@@ -101,7 +99,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;
@@ -133,7 +130,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);
@@ -835,6 +835,13 @@ void kvm_arch_load_regs(CPUState *env)
kvm_set_regs(env, ®s);
+ /*
+ * Kernels before 2.6.33 overwrote flags.TF injected via SET_GUEST_DEBUG
+ * while updating GP regs. Work around this by updating the debug state
+ * once again.
+ */
+ kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &env->kvm_guest_debug);
+
memset(&fpu, 0, sizeof fpu);
fpu.fsw = env->fpus & ~(7 << 11);
fpu.fsw |= (env->fpstt & 7) << 11;
@@ -1372,177 +1379,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)
{
@@ -1016,13 +1016,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;
@@ -2318,43 +2311,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);
@@ -1003,6 +1003,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)
@@ -1176,6 +1177,5 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
memcpy(&env->kvm_guest_debug, dbg, sizeof(env->kvm_guest_debug));
}
#endif /* KVM_CAP_SET_GUEST_DEBUG */
-#endif
#include "qemu-kvm-x86.c"