qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [5741] Restore pc on watchpoint hits (Jan Kiszka)


From: Anthony Liguori
Subject: [Qemu-devel] [5741] Restore pc on watchpoint hits (Jan Kiszka)
Date: Tue, 18 Nov 2008 20:24:07 +0000

Revision: 5741
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=5741
Author:   aliguori
Date:     2008-11-18 20:24:06 +0000 (Tue, 18 Nov 2008)

Log Message:
-----------
Restore pc on watchpoint hits (Jan Kiszka)

In order to provide accurate information about the triggering
instruction, this patch adds the required bits to restore the pc if the
access happened inside a TB. With the BP_STOP_BEFORE_ACCESS flag, the
watchpoint user can control if the debug trap should be issued on or
after the accessing instruction.

Signed-off-by: Jan Kiszka <address@hidden>
Signed-off-by: Anthony Liguori <address@hidden>

Modified Paths:
--------------
    trunk/cpu-all.h
    trunk/exec.c

Modified: trunk/cpu-all.h
===================================================================
--- trunk/cpu-all.h     2008-11-18 20:14:20 UTC (rev 5740)
+++ trunk/cpu-all.h     2008-11-18 20:24:06 UTC (rev 5741)
@@ -765,6 +765,7 @@
 #define BP_MEM_READ           0x01
 #define BP_MEM_WRITE          0x02
 #define BP_MEM_ACCESS         (BP_MEM_READ | BP_MEM_WRITE)
+#define BP_STOP_BEFORE_ACCESS 0x04
 #define BP_GDB                0x10
 
 int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,

Modified: trunk/exec.c
===================================================================
--- trunk/exec.c        2008-11-18 20:14:20 UTC (rev 5740)
+++ trunk/exec.c        2008-11-18 20:24:06 UTC (rev 5741)
@@ -2506,16 +2506,38 @@
 static void check_watchpoint(int offset, int len_mask, int flags)
 {
     CPUState *env = cpu_single_env;
+    target_ulong pc, cs_base;
+    TranslationBlock *tb;
     target_ulong vaddr;
     CPUWatchpoint *wp;
+    int cpu_flags;
 
+    if (env->watchpoint_hit) {
+        /* We re-entered the check after replacing the TB. Now raise
+         * the debug interrupt so that is will trigger after the
+         * current instruction. */
+        cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
+        return;
+    }
     vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
     for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
         if ((vaddr == (wp->vaddr & len_mask) ||
              (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
             env->watchpoint_hit = wp;
-            cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
-            break;
+            tb = tb_find_pc(env->mem_io_pc);
+            if (!tb) {
+                cpu_abort(env, "check_watchpoint: could not find TB for pc=%p",
+                         (void *)env->mem_io_pc);
+            }
+            cpu_restore_state(tb, env, env->mem_io_pc, NULL);
+            tb_phys_invalidate(tb, -1);
+            if (wp->flags & BP_STOP_BEFORE_ACCESS) {
+                env->exception_index = EXCP_DEBUG;
+            } else {
+                cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
+                tb_gen_code(env, pc, cs_base, cpu_flags, 1);
+            }
+            cpu_resume_from_signal(env, NULL);
         }
     }
 }






reply via email to

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