diff mbox

[v2,11/21] KVM: Rework of guest debug state writing

Message ID cfdf9a4cba34649027c99bce17c4b7a77d678c02.1265187223.git.jan.kiszka@siemens.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jan Kiszka Feb. 3, 2010, 8:53 a.m. UTC
None
diff mbox

Patch

diff --git a/kvm-all.c b/kvm-all.c
index 3516f01..9c921cc 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -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);
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 7d0bbd0..7787fb1 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -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;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 8743f32..5ac12a8 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -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