Commit 0026348b authored by David Hildenbrand's avatar David Hildenbrand Committed by Richard Henderson
Browse files

exec: Factor out core logic of check_watchpoint()



We want to perform the same checks in probe_write() to trigger a cpu
exit before doing any modifications. We'll have to pass a PC.

Signed-off-by: default avatarDavid Hildenbrand <david@redhat.com>
Reviewed-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Message-Id: <20190823100741.9621-9-david@redhat.com>
[rth: Use vaddr for len, like other watchpoint functions;
Move user-only stub to static inline.]
Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
parent 74841f04
Loading
Loading
Loading
Loading
+18 −8
Original line number Diff line number Diff line
@@ -2789,11 +2789,10 @@ static const MemoryRegionOps notdirty_mem_ops = {
};

/* Generate a debug exception if a watchpoint has been hit.  */
static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
                          MemTxAttrs attrs, int flags, uintptr_t ra)
{
    CPUState *cpu = current_cpu;
    CPUClass *cc = CPU_GET_CLASS(cpu);
    target_ulong vaddr;
    CPUWatchpoint *wp;

    assert(tcg_enabled());
@@ -2804,17 +2803,17 @@ static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
        cpu_interrupt(cpu, CPU_INTERRUPT_DEBUG);
        return;
    }
    vaddr = (cpu->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
    vaddr = cc->adjust_watchpoint_address(cpu, vaddr, len);

    addr = cc->adjust_watchpoint_address(cpu, addr, len);
    QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
        if (cpu_watchpoint_address_matches(wp, vaddr, len)
        if (cpu_watchpoint_address_matches(wp, addr, len)
            && (wp->flags & flags)) {
            if (flags == BP_MEM_READ) {
                wp->flags |= BP_WATCHPOINT_HIT_READ;
            } else {
                wp->flags |= BP_WATCHPOINT_HIT_WRITE;
            }
            wp->hitaddr = vaddr;
            wp->hitaddr = MAX(addr, wp->vaddr);
            wp->hitattrs = attrs;
            if (!cpu->watchpoint_hit) {
                if (wp->flags & BP_CPU &&
@@ -2829,11 +2828,14 @@ static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
                if (wp->flags & BP_STOP_BEFORE_ACCESS) {
                    cpu->exception_index = EXCP_DEBUG;
                    mmap_unlock();
                    cpu_loop_exit(cpu);
                    cpu_loop_exit_restore(cpu, ra);
                } else {
                    /* Force execution of one insn next time.  */
                    cpu->cflags_next_tb = 1 | curr_cflags();
                    mmap_unlock();
                    if (ra) {
                        cpu_restore_state(cpu, ra, true);
                    }
                    cpu_loop_exit_noexc(cpu);
                }
            }
@@ -2843,6 +2845,14 @@ static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
    }
}

static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
{
    CPUState *cpu = current_cpu;
    vaddr addr = (cpu->mem_io_vaddr & TARGET_PAGE_MASK) + offset;

    cpu_check_watchpoint(cpu, addr, len, attrs, flags, 0);
}

/* Watchpoint access routines.  Watchpoints are inserted using TLB tricks,
   so these check for a hit then pass through to the normal out-of-line
   phys routines.  */
+7 −0
Original line number Diff line number Diff line
@@ -1091,6 +1091,11 @@ static inline void cpu_watchpoint_remove_by_ref(CPUState *cpu,
static inline void cpu_watchpoint_remove_all(CPUState *cpu, int mask)
{
}

static inline void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
                                        MemTxAttrs atr, int fl, uintptr_t ra)
{
}
#else
int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
                          int flags, CPUWatchpoint **watchpoint);
@@ -1098,6 +1103,8 @@ int cpu_watchpoint_remove(CPUState *cpu, vaddr addr,
                          vaddr len, int flags);
void cpu_watchpoint_remove_by_ref(CPUState *cpu, CPUWatchpoint *watchpoint);
void cpu_watchpoint_remove_all(CPUState *cpu, int mask);
void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
                          MemTxAttrs attrs, int flags, uintptr_t ra);
#endif

/**