@@ -951,10 +951,6 @@ static void kvm_invoke_set_guest_debug(void *data)
struct kvm_set_guest_debug_data *dbg_data = data;
CPUState *env = dbg_data->env;
- if (env->kvm_vcpu_dirty) {
- kvm_arch_put_registers(env);
- env->kvm_vcpu_dirty = 0;
- }
dbg_data->err = kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &dbg_data->dbg);
}
@@ -962,12 +958,12 @@ 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;
+ data.dbg.control = reinject_trap;
+ 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;
data.env = env;
on_vcpu(env, kvm_invoke_set_guest_debug, &data);
@@ -21,6 +21,10 @@
#include "config.h"
+#ifdef CONFIG_KVM
+#include <linux/kvm.h> /* for kvm_guest_debug */
+#endif
+
#ifdef TARGET_X86_64
#define TARGET_LONG_BITS 64
#else
@@ -718,7 +722,10 @@ typedef struct CPUX86State {
uint8_t has_error_code;
uint32_t sipi_vector;
uint32_t cpuid_kvm_features;
-
+#if defined(CONFIG_KVM) && defined(KVM_CAP_SET_GUEST_DEBUG)
+ struct kvm_guest_debug kvm_guest_debug;
+#endif
+
/* in order to simplify APIC support, we leave this pointer to the
user */
struct APICState *apic_state;
@@ -865,6 +865,15 @@ int kvm_arch_put_registers(CPUState *env)
if (ret < 0)
return ret;
+ /*
+ * 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.
+ */
+ ret = kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &env->kvm_guest_debug);
+ if (ret < 0)
+ return ret;
+
ret = kvm_put_fpu(env);
if (ret < 0)
return ret;
@@ -1163,6 +1172,8 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
(len_code[hw_breakpoint[n].len] << (18 + n*4));
}
}
+ /* Keep a copy for the writeback workaround in kvm_arch_put_registers */
+ memcpy(&env->kvm_guest_debug, dbg, sizeof(env->kvm_guest_debug));
}
#endif /* KVM_CAP_SET_GUEST_DEBUG */
#endif