qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 9/9] qemu-kvm: Use upstream guest debug code


From: Jan Kiszka
Subject: [Qemu-devel] [PATCH 9/9] qemu-kvm: Use upstream guest debug code
Date: Fri, 19 Feb 2010 19:22:27 +0100

Code was absolute identical except for previous fixes and cleanup in
upstream.

Signed-off-by: Jan Kiszka <address@hidden>
---
 kvm-all.c         |    7 +-
 kvm.h             |    4 -
 qemu-kvm-x86.c    |  197 +++++++----------------------------------------------
 qemu-kvm.c        |   44 ------------
 qemu-kvm.h        |   37 ----------
 target-i386/kvm.c |    2 +-
 6 files changed, 30 insertions(+), 261 deletions(-)

diff --git a/kvm-all.c b/kvm-all.c
index f0c5cf6..bed562f 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -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)
diff --git a/kvm.h b/kvm.h
index 2f97c64..a78a27f 100644
--- a/kvm.h
+++ b/kvm.h
@@ -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);
 
diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
index 2b36c22..bd3c0ab 100644
--- a/qemu-kvm-x86.c
+++ b/qemu-kvm-x86.c
@@ -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)
 {
diff --git a/qemu-kvm.c b/qemu-kvm.c
index 9821fc5..3a169fc 100644
--- a/qemu-kvm.c
+++ b/qemu-kvm.c
@@ -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
  */
diff --git a/qemu-kvm.h b/qemu-kvm.h
index 17017c4..93b144f 100644
--- a/qemu-kvm.h
+++ b/qemu-kvm.h
@@ -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);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index a4130d4..9e88932 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -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"
-- 
1.6.0.2





reply via email to

[Prev in Thread] Current Thread [Next in Thread]