diff --git a/cpu-exec.c b/cpu-exec.c index 798dc084d9..d7c21d35e5 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -200,10 +200,11 @@ void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler) static void cpu_handle_debug_exception(CPUArchState *env) { + CPUState *cpu = ENV_GET_CPU(env); CPUWatchpoint *wp; - if (!env->watchpoint_hit) { - QTAILQ_FOREACH(wp, &env->watchpoints, entry) { + if (!cpu->watchpoint_hit) { + QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { wp->flags &= ~BP_WATCHPOINT_HIT; } } diff --git a/exec.c b/exec.c index 26ed9ccd0c..ee5eff7734 100644 --- a/exec.c +++ b/exec.c @@ -485,7 +485,7 @@ void cpu_exec_init(CPUArchState *env) cpu->cpu_index = cpu_index; cpu->numa_node = 0; QTAILQ_INIT(&env->breakpoints); - QTAILQ_INIT(&env->watchpoints); + QTAILQ_INIT(&cpu->watchpoints); #ifndef CONFIG_USER_ONLY cpu->as = &address_space_memory; cpu->thread_id = qemu_get_thread_id(); @@ -542,6 +542,7 @@ int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len, int flags, CPUWatchpoint **watchpoint) { + CPUState *cpu = ENV_GET_CPU(env); target_ulong len_mask = ~(len - 1); CPUWatchpoint *wp; @@ -559,10 +560,11 @@ int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len wp->flags = flags; /* keep all GDB-injected watchpoints in front */ - if (flags & BP_GDB) - QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry); - else - QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry); + if (flags & BP_GDB) { + QTAILQ_INSERT_HEAD(&cpu->watchpoints, wp, entry); + } else { + QTAILQ_INSERT_TAIL(&cpu->watchpoints, wp, entry); + } tlb_flush_page(env, addr); @@ -575,10 +577,11 @@ int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len, int flags) { + CPUState *cpu = ENV_GET_CPU(env); target_ulong len_mask = ~(len - 1); CPUWatchpoint *wp; - QTAILQ_FOREACH(wp, &env->watchpoints, entry) { + QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { if (addr == wp->vaddr && len_mask == wp->len_mask && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) { cpu_watchpoint_remove_by_ref(env, wp); @@ -591,7 +594,9 @@ int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len /* Remove a specific watchpoint by reference. */ void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint) { - QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry); + CPUState *cpu = ENV_GET_CPU(env); + + QTAILQ_REMOVE(&cpu->watchpoints, watchpoint, entry); tlb_flush_page(env, watchpoint->vaddr); @@ -601,9 +606,10 @@ void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint) /* Remove all matching watchpoints. */ void cpu_watchpoint_remove_all(CPUArchState *env, int mask) { + CPUState *cpu = ENV_GET_CPU(env); CPUWatchpoint *wp, *next; - QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) { + QTAILQ_FOREACH_SAFE(wp, &cpu->watchpoints, entry, next) { if (wp->flags & mask) cpu_watchpoint_remove_by_ref(env, wp); } @@ -799,6 +805,7 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env, int prot, target_ulong *address) { + CPUState *cpu = ENV_GET_CPU(env); hwaddr iotlb; CPUWatchpoint *wp; @@ -818,7 +825,7 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env, /* Make accesses to pages with watchpoints go via the watchpoint trap routines. */ - QTAILQ_FOREACH(wp, &env->watchpoints, entry) { + QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) { /* Avoid trapping reads of pages with a write breakpoint. */ if ((prot & PAGE_WRITE) || (wp->flags & BP_MEM_READ)) { @@ -1579,7 +1586,7 @@ static void check_watchpoint(int offset, int len_mask, int flags) CPUWatchpoint *wp; int cpu_flags; - if (env->watchpoint_hit) { + if (cpu->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. */ @@ -1587,12 +1594,12 @@ static void check_watchpoint(int offset, int len_mask, int flags) return; } vaddr = (cpu->mem_io_vaddr & TARGET_PAGE_MASK) + offset; - QTAILQ_FOREACH(wp, &env->watchpoints, entry) { + QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { if ((vaddr == (wp->vaddr & len_mask) || (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) { wp->flags |= BP_WATCHPOINT_HIT; - if (!env->watchpoint_hit) { - env->watchpoint_hit = wp; + if (!cpu->watchpoint_hit) { + cpu->watchpoint_hit = wp; tb_check_watchpoint(env); if (wp->flags & BP_STOP_BEFORE_ACCESS) { cpu->exception_index = EXCP_DEBUG; diff --git a/gdbstub.c b/gdbstub.c index c5ab73fb1d..0176b3f80e 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -1204,8 +1204,8 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) } switch (state) { case RUN_STATE_DEBUG: - if (env->watchpoint_hit) { - switch (env->watchpoint_hit->flags & BP_MEM_ACCESS) { + if (cpu->watchpoint_hit) { + switch (cpu->watchpoint_hit->flags & BP_MEM_ACCESS) { case BP_MEM_READ: type = "r"; break; @@ -1219,8 +1219,8 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) snprintf(buf, sizeof(buf), "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";", GDB_SIGNAL_TRAP, cpu_index(cpu), type, - env->watchpoint_hit->vaddr); - env->watchpoint_hit = NULL; + (target_ulong)cpu->watchpoint_hit->vaddr); + cpu->watchpoint_hit = NULL; goto send_packet; } tb_flush(env); diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index 8af85476fc..31aac691c5 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -120,13 +120,6 @@ typedef struct CPUBreakpoint { QTAILQ_ENTRY(CPUBreakpoint) entry; } CPUBreakpoint; -typedef struct CPUWatchpoint { - target_ulong vaddr; - target_ulong len_mask; - int flags; /* BP_* */ - QTAILQ_ENTRY(CPUWatchpoint) entry; -} CPUWatchpoint; - #define CPU_TEMP_BUF_NLONGS 128 #define CPU_COMMON \ /* soft mmu support */ \ @@ -135,8 +128,5 @@ typedef struct CPUWatchpoint { /* from this point: preserved by CPU reset */ \ /* ice debug support */ \ QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints; \ - \ - QTAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints; \ - CPUWatchpoint *watchpoint_hit; \ #endif diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 4d1ea35ca4..c7420e070b 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -151,6 +151,13 @@ typedef struct icount_decr_u16 { } icount_decr_u16; #endif +typedef struct CPUWatchpoint { + vaddr vaddr; + vaddr len_mask; + int flags; /* BP_* */ + QTAILQ_ENTRY(CPUWatchpoint) entry; +} CPUWatchpoint; + struct KVMState; struct kvm_run; @@ -231,6 +238,9 @@ struct CPUState { int gdb_num_g_regs; QTAILQ_ENTRY(CPUState) node; + QTAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints; + CPUWatchpoint *watchpoint_hit; + void *opaque; /* In order to avoid passing too many arguments to the MMIO helpers, diff --git a/linux-user/main.c b/linux-user/main.c index 6e62b8babd..5a06192ec4 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3435,6 +3435,7 @@ void init_task_state(TaskState *ts) CPUArchState *cpu_copy(CPUArchState *env) { + CPUState *cpu = ENV_GET_CPU(env); CPUArchState *new_env = cpu_init(cpu_model); #if defined(TARGET_HAS_ICE) CPUBreakpoint *bp; @@ -3450,12 +3451,12 @@ CPUArchState *cpu_copy(CPUArchState *env) Note: Once we support ptrace with hw-debug register access, make sure BP_CPU break/watchpoints are handled correctly on clone. */ QTAILQ_INIT(&env->breakpoints); - QTAILQ_INIT(&env->watchpoints); + QTAILQ_INIT(&cpu->watchpoints); #if defined(TARGET_HAS_ICE) QTAILQ_FOREACH(bp, &env->breakpoints, entry) { cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL); } - QTAILQ_FOREACH(wp, &env->watchpoints, entry) { + QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1, wp->flags, NULL); } diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 62641af77e..906018757d 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -876,7 +876,7 @@ typedef struct CPUX86State { target_ulong dr[8]; /* debug registers */ union { CPUBreakpoint *cpu_breakpoint[4]; - CPUWatchpoint *cpu_watchpoint[4]; + struct CPUWatchpoint *cpu_watchpoint[4]; }; /* break/watchpoints for dr[0..3] */ uint32_t smbase; int old_exception; /* exception in flight */ diff --git a/target-i386/helper.c b/target-i386/helper.c index 6d9bd71a3a..bd8da20946 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1088,11 +1088,12 @@ bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update) void breakpoint_handler(CPUX86State *env) { + CPUState *cs = CPU(x86_env_get_cpu(env)); CPUBreakpoint *bp; - if (env->watchpoint_hit) { - if (env->watchpoint_hit->flags & BP_CPU) { - env->watchpoint_hit = NULL; + if (cs->watchpoint_hit) { + if (cs->watchpoint_hit->flags & BP_CPU) { + cs->watchpoint_hit = NULL; if (check_hw_breakpoints(env, false)) { raise_exception(env, EXCP01_DB); } else { diff --git a/target-i386/kvm.c b/target-i386/kvm.c index e555040a97..7a295f6f20 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -2277,13 +2277,13 @@ static int kvm_handle_debug(X86CPU *cpu, break; case 0x1: ret = EXCP_DEBUG; - env->watchpoint_hit = &hw_watchpoint; + cs->watchpoint_hit = &hw_watchpoint; hw_watchpoint.vaddr = hw_breakpoint[n].addr; hw_watchpoint.flags = BP_MEM_WRITE; break; case 0x3: ret = EXCP_DEBUG; - env->watchpoint_hit = &hw_watchpoint; + cs->watchpoint_hit = &hw_watchpoint; hw_watchpoint.vaddr = hw_breakpoint[n].addr; hw_watchpoint.flags = BP_MEM_ACCESS; break; @@ -2291,11 +2291,11 @@ static int kvm_handle_debug(X86CPU *cpu, } } } - } else if (kvm_find_sw_breakpoint(CPU(cpu), arch_info->pc)) { + } else if (kvm_find_sw_breakpoint(cs, arch_info->pc)) { ret = EXCP_DEBUG; } if (ret == 0) { - cpu_synchronize_state(CPU(cpu)); + cpu_synchronize_state(cs); assert(env->exception_injected == -1); /* pass to guest */ diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h index b94d9b007e..d50726bce7 100644 --- a/target-lm32/cpu.h +++ b/target-lm32/cpu.h @@ -167,7 +167,7 @@ struct CPULM32State { uint32_t wp[4]; /* watchpoints */ CPUBreakpoint * cpu_breakpoint[4]; - CPUWatchpoint * cpu_watchpoint[4]; + struct CPUWatchpoint *cpu_watchpoint[4]; CPU_COMMON diff --git a/target-lm32/helper.c b/target-lm32/helper.c index e5536c0ecb..67ba278e27 100644 --- a/target-lm32/helper.c +++ b/target-lm32/helper.c @@ -118,11 +118,12 @@ static bool check_watchpoints(CPULM32State *env) void lm32_debug_excp_handler(CPULM32State *env) { + CPUState *cs = CPU(lm32_env_get_cpu(env)); CPUBreakpoint *bp; - if (env->watchpoint_hit) { - if (env->watchpoint_hit->flags & BP_CPU) { - env->watchpoint_hit = NULL; + if (cs->watchpoint_hit) { + if (cs->watchpoint_hit->flags & BP_CPU) { + cs->watchpoint_hit = NULL; if (check_watchpoints(env)) { raise_exception(env, EXCP_WATCHPOINT); } else { diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h index 4bae693c6d..e210bacdff 100644 --- a/target-xtensa/cpu.h +++ b/target-xtensa/cpu.h @@ -359,7 +359,7 @@ typedef struct CPUXtensaState { int exception_taken; /* Watchpoints for DBREAK registers */ - CPUWatchpoint *cpu_watchpoint[MAX_NDBREAK]; + struct CPUWatchpoint *cpu_watchpoint[MAX_NDBREAK]; CPU_COMMON } CPUXtensaState; diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c index 259878837f..8a9cb0a825 100644 --- a/target-xtensa/helper.c +++ b/target-xtensa/helper.c @@ -81,11 +81,13 @@ static uint32_t check_hw_breakpoints(CPUXtensaState *env) void xtensa_breakpoint_handler(CPUXtensaState *env) { - if (env->watchpoint_hit) { - if (env->watchpoint_hit->flags & BP_CPU) { + CPUState *cs = CPU(xtensa_env_get_cpu(env)); + + if (cs->watchpoint_hit) { + if (cs->watchpoint_hit->flags & BP_CPU) { uint32_t cause; - env->watchpoint_hit = NULL; + cs->watchpoint_hit = NULL; cause = check_hw_breakpoints(env); if (cause) { debug_exception_env(env, cause);