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 765 #define BP_MEM_READ 0x01
766 766 #define BP_MEM_WRITE 0x02
767 767 #define BP_MEM_ACCESS (BP_MEM_READ | BP_MEM_WRITE)
  768 +#define BP_STOP_BEFORE_ACCESS 0x04
768 769 #define BP_GDB 0x10
769 770  
770 771 int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
... ...
... ... @@ -2506,16 +2506,38 @@ static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
2506 2506 static void check_watchpoint(int offset, int len_mask, int flags)
2507 2507 {
2508 2508 CPUState *env = cpu_single_env;
  2509 + target_ulong pc, cs_base;
  2510 + TranslationBlock *tb;
2509 2511 target_ulong vaddr;
2510 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 2522 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
2513 2523 for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
2514 2524 if ((vaddr == (wp->vaddr & len_mask) ||
2515 2525 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
2516 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 }
... ...