Commit 06d55cc19ac84e799d2df8c750049e51798b00a4

Authored by aliguori
1 parent b4051334

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 <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5741 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 25 additions and 2 deletions
cpu-all.h
@@ -765,6 +765,7 @@ void cpu_reset_interrupt(CPUState *env, int mask); @@ -765,6 +765,7 @@ void cpu_reset_interrupt(CPUState *env, int mask);
765 #define BP_MEM_READ 0x01 765 #define BP_MEM_READ 0x01
766 #define BP_MEM_WRITE 0x02 766 #define BP_MEM_WRITE 0x02
767 #define BP_MEM_ACCESS (BP_MEM_READ | BP_MEM_WRITE) 767 #define BP_MEM_ACCESS (BP_MEM_READ | BP_MEM_WRITE)
  768 +#define BP_STOP_BEFORE_ACCESS 0x04
768 #define BP_GDB 0x10 769 #define BP_GDB 0x10
769 770
770 int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags, 771 int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
@@ -2506,16 +2506,38 @@ static CPUWriteMemoryFunc *notdirty_mem_write[3] = { @@ -2506,16 +2506,38 @@ static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
2506 static void check_watchpoint(int offset, int len_mask, int flags) 2506 static void check_watchpoint(int offset, int len_mask, int flags)
2507 { 2507 {
2508 CPUState *env = cpu_single_env; 2508 CPUState *env = cpu_single_env;
  2509 + target_ulong pc, cs_base;
  2510 + TranslationBlock *tb;
2509 target_ulong vaddr; 2511 target_ulong vaddr;
2510 CPUWatchpoint *wp; 2512 CPUWatchpoint *wp;
  2513 + int cpu_flags;
2511 2514
  2515 + if (env->watchpoint_hit) {
  2516 + /* We re-entered the check after replacing the TB. Now raise
  2517 + * the debug interrupt so that is will trigger after the
  2518 + * current instruction. */
  2519 + cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
  2520 + return;
  2521 + }
2512 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset; 2522 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
2513 for (wp = env->watchpoints; wp != NULL; wp = wp->next) { 2523 for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
2514 if ((vaddr == (wp->vaddr & len_mask) || 2524 if ((vaddr == (wp->vaddr & len_mask) ||
2515 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) { 2525 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
2516 env->watchpoint_hit = wp; 2526 env->watchpoint_hit = wp;
2517 - cpu_interrupt(env, CPU_INTERRUPT_DEBUG);  
2518 - break; 2527 + tb = tb_find_pc(env->mem_io_pc);
  2528 + if (!tb) {
  2529 + cpu_abort(env, "check_watchpoint: could not find TB for pc=%p",
  2530 + (void *)env->mem_io_pc);
  2531 + }
  2532 + cpu_restore_state(tb, env, env->mem_io_pc, NULL);
  2533 + tb_phys_invalidate(tb, -1);
  2534 + if (wp->flags & BP_STOP_BEFORE_ACCESS) {
  2535 + env->exception_index = EXCP_DEBUG;
  2536 + } else {
  2537 + cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
  2538 + tb_gen_code(env, pc, cs_base, cpu_flags, 1);
  2539 + }
  2540 + cpu_resume_from_signal(env, NULL);
2519 } 2541 }
2520 } 2542 }
2521 } 2543 }