Patchwork [RFC,qom-cpu,16/41] cpu: Move breakpoints field from CPU_COMMON to CPUState

login
register
mail settings
Submitter Andreas Färber
Date Sept. 4, 2013, 9:04 a.m.
Message ID <1378285521-3230-17-git-send-email-afaerber@suse.de>
Download mbox | patch
Permalink /patch/272515/
State New
Headers show

Comments

Andreas Färber - Sept. 4, 2013, 9:04 a.m.
Most targets were using offsetof(CPUFooState, breakpoints) to determine
how much of CPUFooState to clear on reset. Use the next field after
CPU_COMMON instead, if any, or sizeof(CPUFooState) otherwise.

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 exec.c                        | 21 +++++++++++++--------
 include/exec/cpu-defs.h       | 10 ----------
 include/qom/cpu.h             |  9 +++++++++
 linux-user/main.c             |  4 ++--
 target-alpha/translate.c      |  4 ++--
 target-arm/cpu.c              |  2 +-
 target-arm/translate.c        |  4 ++--
 target-cris/cpu.c             |  2 +-
 target-cris/cpu.h             |  4 ++--
 target-cris/translate.c       |  5 +++--
 target-i386/cpu.c             |  2 +-
 target-i386/cpu.h             |  3 ++-
 target-i386/helper.c          |  3 ++-
 target-i386/translate.c       |  4 ++--
 target-lm32/cpu.c             |  2 +-
 target-lm32/cpu.h             |  1 +
 target-lm32/translate.c       |  5 +++--
 target-m68k/cpu.c             |  2 +-
 target-m68k/cpu.h             |  1 +
 target-m68k/translate.c       |  4 ++--
 target-microblaze/cpu.c       |  2 +-
 target-microblaze/translate.c |  5 +++--
 target-mips/cpu.c             |  2 +-
 target-mips/cpu.h             |  1 +
 target-mips/translate.c       |  4 ++--
 target-moxie/cpu.c            |  2 +-
 target-moxie/translate.c      |  4 ++--
 target-openrisc/cpu.c         |  6 +++++-
 target-openrisc/cpu.h         |  1 +
 target-openrisc/translate.c   |  5 +++--
 target-ppc/translate.c        |  4 ++--
 target-s390x/cpu.c            |  4 ++--
 target-s390x/translate.c      |  4 ++--
 target-sh4/cpu.c              |  2 +-
 target-sh4/cpu.h              |  1 +
 target-sh4/translate.c        |  4 ++--
 target-sparc/cpu.c            |  2 +-
 target-sparc/cpu.h            |  1 +
 target-sparc/translate.c      |  4 ++--
 target-unicore32/translate.c  |  4 ++--
 target-xtensa/translate.c     |  5 +++--
 41 files changed, 90 insertions(+), 69 deletions(-)
Jia Liu - Sept. 4, 2013, 12:48 p.m.
On Wed, Sep 4, 2013 at 5:04 PM, Andreas Färber <afaerber@suse.de> wrote:
> Most targets were using offsetof(CPUFooState, breakpoints) to determine
> how much of CPUFooState to clear on reset. Use the next field after
> CPU_COMMON instead, if any, or sizeof(CPUFooState) otherwise.
>
> Signed-off-by: Andreas Färber <afaerber@suse.de>
> ---
>  exec.c                        | 21 +++++++++++++--------
>  include/exec/cpu-defs.h       | 10 ----------
>  include/qom/cpu.h             |  9 +++++++++
>  linux-user/main.c             |  4 ++--
>  target-alpha/translate.c      |  4 ++--
>  target-arm/cpu.c              |  2 +-
>  target-arm/translate.c        |  4 ++--
>  target-cris/cpu.c             |  2 +-
>  target-cris/cpu.h             |  4 ++--
>  target-cris/translate.c       |  5 +++--
>  target-i386/cpu.c             |  2 +-
>  target-i386/cpu.h             |  3 ++-
>  target-i386/helper.c          |  3 ++-
>  target-i386/translate.c       |  4 ++--
>  target-lm32/cpu.c             |  2 +-
>  target-lm32/cpu.h             |  1 +
>  target-lm32/translate.c       |  5 +++--
>  target-m68k/cpu.c             |  2 +-
>  target-m68k/cpu.h             |  1 +
>  target-m68k/translate.c       |  4 ++--
>  target-microblaze/cpu.c       |  2 +-
>  target-microblaze/translate.c |  5 +++--
>  target-mips/cpu.c             |  2 +-
>  target-mips/cpu.h             |  1 +
>  target-mips/translate.c       |  4 ++--
>  target-moxie/cpu.c            |  2 +-
>  target-moxie/translate.c      |  4 ++--
>  target-openrisc/cpu.c         |  6 +++++-
>  target-openrisc/cpu.h         |  1 +
>  target-openrisc/translate.c   |  5 +++--
>  target-ppc/translate.c        |  4 ++--
>  target-s390x/cpu.c            |  4 ++--
>  target-s390x/translate.c      |  4 ++--
>  target-sh4/cpu.c              |  2 +-
>  target-sh4/cpu.h              |  1 +
>  target-sh4/translate.c        |  4 ++--
>  target-sparc/cpu.c            |  2 +-
>  target-sparc/cpu.h            |  1 +
>  target-sparc/translate.c      |  4 ++--
>  target-unicore32/translate.c  |  4 ++--
>  target-xtensa/translate.c     |  5 +++--
>  41 files changed, 90 insertions(+), 69 deletions(-)
>
> diff --git a/exec.c b/exec.c
> index 5b70bf8..6ae5a21 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -378,7 +378,7 @@ void cpu_exec_init(CPUArchState *env)
>      }
>      cpu->cpu_index = cpu_index;
>      cpu->numa_node = 0;
> -    QTAILQ_INIT(&env->breakpoints);
> +    QTAILQ_INIT(&cpu->breakpoints);
>      QTAILQ_INIT(&cpu->watchpoints);
>  #ifndef CONFIG_USER_ONLY
>      cpu->thread_id = qemu_get_thread_id();
> @@ -511,6 +511,7 @@ int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
>                            CPUBreakpoint **breakpoint)
>  {
>  #if defined(TARGET_HAS_ICE)
> +    CPUState *cpu = ENV_GET_CPU(env);
>      CPUBreakpoint *bp;
>
>      bp = g_malloc(sizeof(*bp));
> @@ -520,12 +521,12 @@ int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
>
>      /* keep all GDB-injected breakpoints in front */
>      if (flags & BP_GDB) {
> -        QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
> +        QTAILQ_INSERT_HEAD(&cpu->breakpoints, bp, entry);
>      } else {
> -        QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
> +        QTAILQ_INSERT_TAIL(&cpu->breakpoints, bp, entry);
>      }
>
> -    breakpoint_invalidate(ENV_GET_CPU(env), pc);
> +    breakpoint_invalidate(cpu, pc);
>
>      if (breakpoint) {
>          *breakpoint = bp;
> @@ -540,9 +541,10 @@ int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
>  int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
>  {
>  #if defined(TARGET_HAS_ICE)
> +    CPUState *cpu = ENV_GET_CPU(env);
>      CPUBreakpoint *bp;
>
> -    QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +    QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
>          if (bp->pc == pc && bp->flags == flags) {
>              cpu_breakpoint_remove_by_ref(env, bp);
>              return 0;
> @@ -558,9 +560,11 @@ int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
>  void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
>  {
>  #if defined(TARGET_HAS_ICE)
> -    QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
> +    CPUState *cpu = ENV_GET_CPU(env);
>
> -    breakpoint_invalidate(ENV_GET_CPU(env), breakpoint->pc);
> +    QTAILQ_REMOVE(&cpu->breakpoints, breakpoint, entry);
> +
> +    breakpoint_invalidate(cpu, breakpoint->pc);
>
>      g_free(breakpoint);
>  #endif
> @@ -570,9 +574,10 @@ void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
>  void cpu_breakpoint_remove_all(CPUArchState *env, int mask)
>  {
>  #if defined(TARGET_HAS_ICE)
> +    CPUState *cpu = ENV_GET_CPU(env);
>      CPUBreakpoint *bp, *next;
>
> -    QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
> +    QTAILQ_FOREACH_SAFE(bp, &cpu->breakpoints, entry, next) {
>          if (bp->flags & mask)
>              cpu_breakpoint_remove_by_ref(env, bp);
>      }
> diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
> index 338b8cb..d090594 100644
> --- a/include/exec/cpu-defs.h
> +++ b/include/exec/cpu-defs.h
> @@ -113,19 +113,9 @@ QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
>  #endif
>
>
> -typedef struct CPUBreakpoint {
> -    target_ulong pc;
> -    int flags; /* BP_* */
> -    QTAILQ_ENTRY(CPUBreakpoint) entry;
> -} CPUBreakpoint;
> -
>  #define CPU_TEMP_BUF_NLONGS 128
>  #define CPU_COMMON                                                      \
>      /* soft mmu support */                                              \
>      CPU_COMMON_TLB                                                      \
> -                                                                        \
> -    /* from this point: preserved by CPU reset */                       \
> -    /* ice debug support */                                             \
> -    QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints;            \
>
>  #endif
> diff --git a/include/qom/cpu.h b/include/qom/cpu.h
> index ae6602a..fc3d345 100644
> --- a/include/qom/cpu.h
> +++ b/include/qom/cpu.h
> @@ -154,6 +154,12 @@ typedef struct icount_decr_u16 {
>  } icount_decr_u16;
>  #endif
>
> +typedef struct CPUBreakpoint {
> +    vaddr pc;
> +    int flags; /* BP_* */
> +    QTAILQ_ENTRY(CPUBreakpoint) entry;
> +} CPUBreakpoint;
> +
>  typedef struct CPUWatchpoint {
>      vaddr vaddr;
>      vaddr len_mask;
> @@ -238,6 +244,9 @@ struct CPUState {
>      int gdb_num_g_regs;
>      QTAILQ_ENTRY(CPUState) node;
>
> +    /* ice debug support */
> +    QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints;
> +
>      QTAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints;
>      CPUWatchpoint *watchpoint_hit;
>
> diff --git a/linux-user/main.c b/linux-user/main.c
> index c8723e7..77278c7 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -3206,10 +3206,10 @@ CPUArchState *cpu_copy(CPUArchState *env)
>      /* Clone all break/watchpoints.
>         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(&cpu->breakpoints);
>      QTAILQ_INIT(&cpu->watchpoints);
>  #if defined(TARGET_HAS_ICE)
> -    QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +    QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
>          cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
>      }
>      QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
> diff --git a/target-alpha/translate.c b/target-alpha/translate.c
> index 50b4339..7b2ae0d 100644
> --- a/target-alpha/translate.c
> +++ b/target-alpha/translate.c
> @@ -3486,8 +3486,8 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
>
>      gen_tb_start();
>      do {
> -        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
> -            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
> +            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>                  if (bp->pc == ctx.pc) {
>                      gen_excp(&ctx, EXCP_DEBUG, 0);
>                      break;
> diff --git a/target-arm/cpu.c b/target-arm/cpu.c
> index 4c6fe17..f9f6930 100644
> --- a/target-arm/cpu.c
> +++ b/target-arm/cpu.c
> @@ -114,7 +114,7 @@ static void arm_cpu_reset(CPUState *s)
>
>      acc->parent_reset(s);
>
> -    memset(env, 0, offsetof(CPUARMState, breakpoints));
> +    memset(env, 0, offsetof(CPUARMState, features));
>      g_hash_table_foreach(cpu->cp_regs, cp_reg_reset, cpu);
>      env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid;
>      env->vfp.xregs[ARM_VFP_MVFR0] = cpu->mvfr0;
> diff --git a/target-arm/translate.c b/target-arm/translate.c
> index 4f4a0a9..0eaec9f 100644
> --- a/target-arm/translate.c
> +++ b/target-arm/translate.c
> @@ -10035,8 +10035,8 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
>          }
>  #endif
>
> -        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
> -            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
> +            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>                  if (bp->pc == dc->pc) {
>                      gen_exception_insn(dc, 0, EXCP_DEBUG);
>                      /* Advance PC so that clearing the breakpoint will
> diff --git a/target-cris/cpu.c b/target-cris/cpu.c
> index 504d6a4..b229a10 100644
> --- a/target-cris/cpu.c
> +++ b/target-cris/cpu.c
> @@ -69,7 +69,7 @@ static void cris_cpu_reset(CPUState *s)
>      ccc->parent_reset(s);
>
>      vr = env->pregs[PR_VR];
> -    memset(env, 0, offsetof(CPUCRISState, breakpoints));
> +    memset(env, 0, offsetof(CPUCRISState, load_info));
>      env->pregs[PR_VR] = vr;
>      tlb_flush(env, 1);
>
> diff --git a/target-cris/cpu.h b/target-cris/cpu.h
> index 9e9cb8c..df2a3f0 100644
> --- a/target-cris/cpu.h
> +++ b/target-cris/cpu.h
> @@ -167,8 +167,8 @@ typedef struct CPUCRISState {
>
>         CPU_COMMON
>
> -       /* Members after CPU_COMMON are preserved across resets.  */
> -       void *load_info;
> +    /* Members from load_info on are preserved across resets.  */
> +    void *load_info;
>  } CPUCRISState;
>
>  #include "cpu-qom.h"
> diff --git a/target-cris/translate.c b/target-cris/translate.c
> index 29e9f63..90a4394 100644
> --- a/target-cris/translate.c
> +++ b/target-cris/translate.c
> @@ -3110,10 +3110,11 @@ static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc)
>
>  static void check_breakpoint(CPUCRISState *env, DisasContext *dc)
>  {
> +    CPUState *cs = CPU(cris_env_get_cpu(env));
>      CPUBreakpoint *bp;
>
> -    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
> -        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +    if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
> +        QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>              if (bp->pc == dc->pc) {
>                  cris_evaluate_flags(dc);
>                  tcg_gen_movi_tl(env_pc, dc->pc);
> diff --git a/target-i386/cpu.c b/target-i386/cpu.c
> index 89e3217..b8d0c15 100644
> --- a/target-i386/cpu.c
> +++ b/target-i386/cpu.c
> @@ -2328,7 +2328,7 @@ static void x86_cpu_reset(CPUState *s)
>      xcc->parent_reset(s);
>
>
> -    memset(env, 0, offsetof(CPUX86State, breakpoints));
> +    memset(env, 0, offsetof(CPUX86State, pat));
>
>      tlb_flush(env, 1);
>
> diff --git a/target-i386/cpu.h b/target-i386/cpu.h
> index 36e62b1..b9503d9 100644
> --- a/target-i386/cpu.h
> +++ b/target-i386/cpu.h
> @@ -849,7 +849,7 @@ typedef struct CPUX86State {
>      target_ulong exception_next_eip;
>      target_ulong dr[8]; /* debug registers */
>      union {
> -        CPUBreakpoint *cpu_breakpoint[4];
> +        struct CPUBreakpoint *cpu_breakpoint[4];
>          struct CPUWatchpoint *cpu_watchpoint[4];
>      }; /* break/watchpoints for dr[0..3] */
>      uint32_t smbase;
> @@ -861,6 +861,7 @@ typedef struct CPUX86State {
>
>      CPU_COMMON
>
> +    /* Fields from here on are preserved across CPU reset. */
>      uint64_t pat;
>
>      /* processor features (e.g. for CPUID insn) */
> diff --git a/target-i386/helper.c b/target-i386/helper.c
> index 2a5ffc2..557c94f 100644
> --- a/target-i386/helper.c
> +++ b/target-i386/helper.c
> @@ -1096,7 +1096,7 @@ void breakpoint_handler(CPUX86State *env)
>              }
>          }
>      } else {
> -        QTAILQ_FOREACH(bp, &env->breakpoints, entry)
> +        QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>              if (bp->pc == env->eip) {
>                  if (bp->flags & BP_CPU) {
>                      check_hw_breakpoints(env, true);
> @@ -1104,6 +1104,7 @@ void breakpoint_handler(CPUX86State *env)
>                  }
>                  break;
>              }
> +        }
>      }
>  }
>
> diff --git a/target-i386/translate.c b/target-i386/translate.c
> index 2e8e8d5..6e64551 100644
> --- a/target-i386/translate.c
> +++ b/target-i386/translate.c
> @@ -8340,8 +8340,8 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
>
>      gen_tb_start();
>      for(;;) {
> -        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
> -            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
> +            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>                  if (bp->pc == pc_ptr &&
>                      !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) {
>                      gen_debug(dc, pc_ptr - dc->cs_base);
> diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
> index 607e332..69bc6bb 100644
> --- a/target-lm32/cpu.c
> +++ b/target-lm32/cpu.c
> @@ -54,7 +54,7 @@ static void lm32_cpu_reset(CPUState *s)
>      lcc->parent_reset(s);
>
>      /* reset cpu state */
> -    memset(env, 0, offsetof(CPULM32State, breakpoints));
> +    memset(env, 0, offsetof(CPULM32State, eba));
>
>      tlb_flush(env, 1);
>  }
> diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
> index a94fd79..85c89e8 100644
> --- a/target-lm32/cpu.h
> +++ b/target-lm32/cpu.h
> @@ -164,6 +164,7 @@ struct CPULM32State {
>
>      CPU_COMMON
>
> +    /* Fields from here on are preserved across CPU reset. */
>      uint32_t eba;       /* exception base address */
>      uint32_t deba;      /* debug exception base address */
>
> diff --git a/target-lm32/translate.c b/target-lm32/translate.c
> index 6ea0ecd..2e4951c 100644
> --- a/target-lm32/translate.c
> +++ b/target-lm32/translate.c
> @@ -997,10 +997,11 @@ static inline void decode(DisasContext *dc, uint32_t ir)
>
>  static void check_breakpoint(CPULM32State *env, DisasContext *dc)
>  {
> +    CPUState *cs = CPU(lm32_env_get_cpu(env));
>      CPUBreakpoint *bp;
>
> -    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
> -        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +    if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
> +        QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>              if (bp->pc == dc->pc) {
>                  tcg_gen_movi_tl(cpu_pc, dc->pc);
>                  t_gen_raise_exception(dc, EXCP_DEBUG);
> diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
> index e46b647..b24120d 100644
> --- a/target-m68k/cpu.c
> +++ b/target-m68k/cpu.c
> @@ -69,7 +69,7 @@ static void m68k_cpu_reset(CPUState *s)
>
>      mcc->parent_reset(s);
>
> -    memset(env, 0, offsetof(CPUM68KState, breakpoints));
> +    memset(env, 0, offsetof(CPUM68KState, features));
>  #if !defined(CONFIG_USER_ONLY)
>      env->sr = 0x2700;
>  #endif
> diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
> index b8ad269..9a49bfc 100644
> --- a/target-m68k/cpu.h
> +++ b/target-m68k/cpu.h
> @@ -110,6 +110,7 @@ typedef struct CPUM68KState {
>
>      CPU_COMMON
>
> +    /* Fields from here on are preserved across CPU reset. */
>      uint32_t features;
>  } CPUM68KState;
>
> diff --git a/target-m68k/translate.c b/target-m68k/translate.c
> index f3cdee0..c005e10 100644
> --- a/target-m68k/translate.c
> +++ b/target-m68k/translate.c
> @@ -3016,8 +3016,8 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
>      do {
>          pc_offset = dc->pc - pc_start;
>          gen_throws_exception = NULL;
> -        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
> -            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
> +            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>                  if (bp->pc == dc->pc) {
>                      gen_exception(dc, dc->pc, EXCP_DEBUG);
>                      dc->is_jmp = DISAS_JUMP;
> diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
> index 8b248f4..d724b6e 100644
> --- a/target-microblaze/cpu.c
> +++ b/target-microblaze/cpu.c
> @@ -73,7 +73,7 @@ static void mb_cpu_reset(CPUState *s)
>
>      mcc->parent_reset(s);
>
> -    memset(env, 0, offsetof(CPUMBState, breakpoints));
> +    memset(env, 0, sizeof(CPUMBState));
>      env->res_addr = RES_ADDR_NONE;
>      tlb_flush(env, 1);
>
> diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
> index f4dbe11..31eef0f 100644
> --- a/target-microblaze/translate.c
> +++ b/target-microblaze/translate.c
> @@ -1724,10 +1724,11 @@ static inline void decode(DisasContext *dc, uint32_t ir)
>
>  static void check_breakpoint(CPUMBState *env, DisasContext *dc)
>  {
> +    CPUState *cs = CPU(mb_env_get_cpu(env));
>      CPUBreakpoint *bp;
>
> -    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
> -        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +    if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
> +        QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>              if (bp->pc == dc->pc) {
>                  t_gen_raise_exception(dc, EXCP_DEBUG);
>                  dc->is_jmp = DISAS_UPDATE;
> diff --git a/target-mips/cpu.c b/target-mips/cpu.c
> index 2fd5591..8f26d11 100644
> --- a/target-mips/cpu.c
> +++ b/target-mips/cpu.c
> @@ -101,7 +101,7 @@ static void mips_cpu_reset(CPUState *s)
>
>      mcc->parent_reset(s);
>
> -    memset(env, 0, offsetof(CPUMIPSState, breakpoints));
> +    memset(env, 0, offsetof(CPUMIPSState, mvp));
>      tlb_flush(env, 1);
>
>      cpu_state_reset(env);
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index b71a711..5320a05 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -469,6 +469,7 @@ struct CPUMIPSState {
>
>      CPU_COMMON
>
> +    /* Fields from here on are preserved across CPU reset. */
>      CPUMIPSMVPContext *mvp;
>  #if !defined(CONFIG_USER_ONLY)
>      CPUMIPSTLBContext *tlb;
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index 453918d..f2e6625 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -15601,8 +15601,8 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
>      LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
>      gen_tb_start();
>      while (ctx.bstate == BS_NONE) {
> -        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
> -            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
> +            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>                  if (bp->pc == ctx.pc) {
>                      save_cpu_state(&ctx, 1);
>                      ctx.bstate = BS_BRANCH;
> diff --git a/target-moxie/cpu.c b/target-moxie/cpu.c
> index ab9d2cc..f7d1e6c 100644
> --- a/target-moxie/cpu.c
> +++ b/target-moxie/cpu.c
> @@ -52,7 +52,7 @@ static void moxie_cpu_reset(CPUState *s)
>
>      mcc->parent_reset(s);
>
> -    memset(env, 0, offsetof(CPUMoxieState, breakpoints));
> +    memset(env, 0, sizeof(CPUMoxieState));
>      env->pc = 0x1000;
>
>      tlb_flush(env, 1);
> diff --git a/target-moxie/translate.c b/target-moxie/translate.c
> index a93196f..63f889f 100644
> --- a/target-moxie/translate.c
> +++ b/target-moxie/translate.c
> @@ -845,8 +845,8 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
>
>      gen_tb_start();
>      do {
> -        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
> -            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
> +            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>                  if (ctx.pc == bp->pc) {
>                      tcg_gen_movi_i32(cpu_pc, ctx.pc);
>                      gen_helper_debug(cpu_env);
> diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
> index b7104e3..3eae4e9 100644
> --- a/target-openrisc/cpu.c
> +++ b/target-openrisc/cpu.c
> @@ -62,7 +62,11 @@ static void openrisc_cpu_reset(CPUState *s)
>
>      occ->parent_reset(s);
>
> -    memset(&cpu->env, 0, offsetof(CPUOpenRISCState, breakpoints));
> +#ifndef CONFIG_USER_ONLY
> +    memset(&cpu->env, 0, offsetof(CPUOpenRISCState, tlb));
> +#else
> +    memset(&cpu->env, 0, offsetof(CPUOpenRISCState, irq));
> +#endif
>
>      tlb_flush(&cpu->env, 1);
>      /*tb_flush(&cpu->env);    FIXME: Do we need it?  */
> diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
> index 8745072..441a0ef 100644
> --- a/target-openrisc/cpu.h
> +++ b/target-openrisc/cpu.h
> @@ -304,6 +304,7 @@ typedef struct CPUOpenRISCState {
>
>      CPU_COMMON
>
> +    /* Fields from here on are preserved across CPU reset. */
>  #ifndef CONFIG_USER_ONLY
>      CPUOpenRISCTLBContext * tlb;
>
> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
> index ea242da..a0a633f 100644
> --- a/target-openrisc/translate.c
> +++ b/target-openrisc/translate.c
> @@ -1645,10 +1645,11 @@ static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
>
>  static void check_breakpoint(OpenRISCCPU *cpu, DisasContext *dc)
>  {
> +    CPUState *cs = CPU(cpu);
>      CPUBreakpoint *bp;
>
> -    if (unlikely(!QTAILQ_EMPTY(&cpu->env.breakpoints))) {
> -        QTAILQ_FOREACH(bp, &cpu->env.breakpoints, entry) {
> +    if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
> +        QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>              if (bp->pc == dc->pc) {
>                  tcg_gen_movi_tl(cpu_pc, dc->pc);
>                  gen_exception(dc, EXCP_DEBUG);
> diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> index 2da7bc7..ec12629 100644
> --- a/target-ppc/translate.c
> +++ b/target-ppc/translate.c
> @@ -9787,8 +9787,8 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
>      /* Set env in case of segfault during code fetch */
>      while (ctx.exception == POWERPC_EXCP_NONE
>              && tcg_ctx.gen_opc_ptr < gen_opc_end) {
> -        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
> -            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
> +            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>                  if (bp->pc == ctx.nip) {
>                      gen_debug_exception(ctxp);
>                      break;
> diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
> index ad0d5bc..d9b8470 100644
> --- a/target-s390x/cpu.c
> +++ b/target-s390x/cpu.c
> @@ -131,7 +131,7 @@ static void s390_cpu_initial_reset(CPUState *s)
>
>      s390_cpu_reset(s);
>      /* initial reset does not touch regs,fregs and aregs */
> -    memset(&env->fpc, 0, offsetof(CPUS390XState, breakpoints) -
> +    memset(&env->fpc, 0, offsetof(CPUS390XState, cpu_num) -
>                           offsetof(CPUS390XState, fpc));
>
>      /* architectured initial values for CR 0 and 14 */
> @@ -150,7 +150,7 @@ static void s390_cpu_full_reset(CPUState *s)
>
>      scc->parent_reset(s);
>
> -    memset(env, 0, offsetof(CPUS390XState, breakpoints));
> +    memset(env, 0, offsetof(CPUS390XState, cpu_num));
>
>      /* architectured initial values for CR 0 and 14 */
>      env->cregs[0] = CR0_RESET;
> diff --git a/target-s390x/translate.c b/target-s390x/translate.c
> index afe90eb..d230f2c 100644
> --- a/target-s390x/translate.c
> +++ b/target-s390x/translate.c
> @@ -4799,8 +4799,8 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu,
>          }
>
>          status = NO_EXIT;
> -        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
> -            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
> +            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>                  if (bp->pc == dc.pc) {
>                      status = EXIT_PC_STALE;
>                      do_debug = true;
> diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c
> index 1f1b8fd..fb176bf 100644
> --- a/target-sh4/cpu.c
> +++ b/target-sh4/cpu.c
> @@ -76,7 +76,7 @@ static void superh_cpu_reset(CPUState *s)
>
>      scc->parent_reset(s);
>
> -    memset(env, 0, offsetof(CPUSH4State, breakpoints));
> +    memset(env, 0, offsetof(CPUSH4State, id));
>      tlb_flush(env, 1);
>
>      env->pc = 0xA0000000;
> diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
> index 8abd0cc..1df0842 100644
> --- a/target-sh4/cpu.h
> +++ b/target-sh4/cpu.h
> @@ -178,6 +178,7 @@ typedef struct CPUSH4State {
>
>      CPU_COMMON
>
> +    /* Fields from here on are preserved over CPU reset. */
>      int id;                    /* CPU model */
>
>      void *intc_handle;
> diff --git a/target-sh4/translate.c b/target-sh4/translate.c
> index c06b29f..3fe53b8 100644
> --- a/target-sh4/translate.c
> +++ b/target-sh4/translate.c
> @@ -1880,8 +1880,8 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
>          max_insns = CF_COUNT_MASK;
>      gen_tb_start();
>      while (ctx.bstate == BS_NONE && tcg_ctx.gen_opc_ptr < gen_opc_end) {
> -        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
> -            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
> +            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>                  if (ctx.pc == bp->pc) {
>                     /* We have hit a breakpoint - make sure PC is up-to-date */
>                     tcg_gen_movi_i32(cpu_pc, ctx.pc);
> diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
> index 9443713..6c1ff68 100644
> --- a/target-sparc/cpu.c
> +++ b/target-sparc/cpu.c
> @@ -32,7 +32,7 @@ static void sparc_cpu_reset(CPUState *s)
>
>      scc->parent_reset(s);
>
> -    memset(env, 0, offsetof(CPUSPARCState, breakpoints));
> +    memset(env, 0, offsetof(CPUSPARCState, version));
>      tlb_flush(env, 1);
>      env->cwp = 0;
>  #ifndef TARGET_SPARC64
> diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
> index cfa1e0d..69c6154 100644
> --- a/target-sparc/cpu.h
> +++ b/target-sparc/cpu.h
> @@ -421,6 +421,7 @@ struct CPUSPARCState {
>
>      CPU_COMMON
>
> +    /* Fields from here on are preserved across CPU reset. */
>      target_ulong version;
>      uint32_t nwindows;
>
> diff --git a/target-sparc/translate.c b/target-sparc/translate.c
> index 73f8b9c..bc52c85 100644
> --- a/target-sparc/translate.c
> +++ b/target-sparc/translate.c
> @@ -5254,8 +5254,8 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
>          max_insns = CF_COUNT_MASK;
>      gen_tb_start();
>      do {
> -        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
> -            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
> +            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>                  if (bp->pc == dc->pc) {
>                      if (dc->pc != pc_start)
>                          save_state(dc);
> diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
> index 1246895..b4bee99 100644
> --- a/target-unicore32/translate.c
> +++ b/target-unicore32/translate.c
> @@ -1925,8 +1925,8 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
>
>      gen_tb_start();
>      do {
> -        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
> -            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
> +            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>                  if (bp->pc == dc->pc) {
>                      gen_set_pc_im(dc->pc);
>                      gen_exception(EXCP_DEBUG);
> diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
> index 24343bd..55d4448 100644
> --- a/target-xtensa/translate.c
> +++ b/target-xtensa/translate.c
> @@ -2871,10 +2871,11 @@ invalid_opcode:
>
>  static void check_breakpoint(CPUXtensaState *env, DisasContext *dc)
>  {
> +    CPUState *cs = CPU(xtensa_env_get_cpu(env));
>      CPUBreakpoint *bp;
>
> -    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
> -        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
> +    if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
> +        QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>              if (bp->pc == dc->pc) {
>                  tcg_gen_movi_i32(cpu_pc, dc->pc);
>                  gen_exception(dc, EXCP_DEBUG);

target-openrisc: Tested-by: Jia Liu <proljc@gmail.com>

> --
> 1.8.1.4
>

Patch

diff --git a/exec.c b/exec.c
index 5b70bf8..6ae5a21 100644
--- a/exec.c
+++ b/exec.c
@@ -378,7 +378,7 @@  void cpu_exec_init(CPUArchState *env)
     }
     cpu->cpu_index = cpu_index;
     cpu->numa_node = 0;
-    QTAILQ_INIT(&env->breakpoints);
+    QTAILQ_INIT(&cpu->breakpoints);
     QTAILQ_INIT(&cpu->watchpoints);
 #ifndef CONFIG_USER_ONLY
     cpu->thread_id = qemu_get_thread_id();
@@ -511,6 +511,7 @@  int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
                           CPUBreakpoint **breakpoint)
 {
 #if defined(TARGET_HAS_ICE)
+    CPUState *cpu = ENV_GET_CPU(env);
     CPUBreakpoint *bp;
 
     bp = g_malloc(sizeof(*bp));
@@ -520,12 +521,12 @@  int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
 
     /* keep all GDB-injected breakpoints in front */
     if (flags & BP_GDB) {
-        QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
+        QTAILQ_INSERT_HEAD(&cpu->breakpoints, bp, entry);
     } else {
-        QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
+        QTAILQ_INSERT_TAIL(&cpu->breakpoints, bp, entry);
     }
 
-    breakpoint_invalidate(ENV_GET_CPU(env), pc);
+    breakpoint_invalidate(cpu, pc);
 
     if (breakpoint) {
         *breakpoint = bp;
@@ -540,9 +541,10 @@  int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
 int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
 {
 #if defined(TARGET_HAS_ICE)
+    CPUState *cpu = ENV_GET_CPU(env);
     CPUBreakpoint *bp;
 
-    QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+    QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
         if (bp->pc == pc && bp->flags == flags) {
             cpu_breakpoint_remove_by_ref(env, bp);
             return 0;
@@ -558,9 +560,11 @@  int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
 void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
 {
 #if defined(TARGET_HAS_ICE)
-    QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
+    CPUState *cpu = ENV_GET_CPU(env);
 
-    breakpoint_invalidate(ENV_GET_CPU(env), breakpoint->pc);
+    QTAILQ_REMOVE(&cpu->breakpoints, breakpoint, entry);
+
+    breakpoint_invalidate(cpu, breakpoint->pc);
 
     g_free(breakpoint);
 #endif
@@ -570,9 +574,10 @@  void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
 void cpu_breakpoint_remove_all(CPUArchState *env, int mask)
 {
 #if defined(TARGET_HAS_ICE)
+    CPUState *cpu = ENV_GET_CPU(env);
     CPUBreakpoint *bp, *next;
 
-    QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
+    QTAILQ_FOREACH_SAFE(bp, &cpu->breakpoints, entry, next) {
         if (bp->flags & mask)
             cpu_breakpoint_remove_by_ref(env, bp);
     }
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index 338b8cb..d090594 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -113,19 +113,9 @@  QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
 #endif
 
 
-typedef struct CPUBreakpoint {
-    target_ulong pc;
-    int flags; /* BP_* */
-    QTAILQ_ENTRY(CPUBreakpoint) entry;
-} CPUBreakpoint;
-
 #define CPU_TEMP_BUF_NLONGS 128
 #define CPU_COMMON                                                      \
     /* soft mmu support */                                              \
     CPU_COMMON_TLB                                                      \
-                                                                        \
-    /* from this point: preserved by CPU reset */                       \
-    /* ice debug support */                                             \
-    QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints;            \
 
 #endif
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index ae6602a..fc3d345 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -154,6 +154,12 @@  typedef struct icount_decr_u16 {
 } icount_decr_u16;
 #endif
 
+typedef struct CPUBreakpoint {
+    vaddr pc;
+    int flags; /* BP_* */
+    QTAILQ_ENTRY(CPUBreakpoint) entry;
+} CPUBreakpoint;
+
 typedef struct CPUWatchpoint {
     vaddr vaddr;
     vaddr len_mask;
@@ -238,6 +244,9 @@  struct CPUState {
     int gdb_num_g_regs;
     QTAILQ_ENTRY(CPUState) node;
 
+    /* ice debug support */
+    QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints;
+
     QTAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints;
     CPUWatchpoint *watchpoint_hit;
 
diff --git a/linux-user/main.c b/linux-user/main.c
index c8723e7..77278c7 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3206,10 +3206,10 @@  CPUArchState *cpu_copy(CPUArchState *env)
     /* Clone all break/watchpoints.
        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(&cpu->breakpoints);
     QTAILQ_INIT(&cpu->watchpoints);
 #if defined(TARGET_HAS_ICE)
-    QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+    QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
         cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
     }
     QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 50b4339..7b2ae0d 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3486,8 +3486,8 @@  static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
 
     gen_tb_start();
     do {
-        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
                 if (bp->pc == ctx.pc) {
                     gen_excp(&ctx, EXCP_DEBUG, 0);
                     break;
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 4c6fe17..f9f6930 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -114,7 +114,7 @@  static void arm_cpu_reset(CPUState *s)
 
     acc->parent_reset(s);
 
-    memset(env, 0, offsetof(CPUARMState, breakpoints));
+    memset(env, 0, offsetof(CPUARMState, features));
     g_hash_table_foreach(cpu->cp_regs, cp_reg_reset, cpu);
     env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid;
     env->vfp.xregs[ARM_VFP_MVFR0] = cpu->mvfr0;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 4f4a0a9..0eaec9f 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -10035,8 +10035,8 @@  static inline void gen_intermediate_code_internal(ARMCPU *cpu,
         }
 #endif
 
-        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
                 if (bp->pc == dc->pc) {
                     gen_exception_insn(dc, 0, EXCP_DEBUG);
                     /* Advance PC so that clearing the breakpoint will
diff --git a/target-cris/cpu.c b/target-cris/cpu.c
index 504d6a4..b229a10 100644
--- a/target-cris/cpu.c
+++ b/target-cris/cpu.c
@@ -69,7 +69,7 @@  static void cris_cpu_reset(CPUState *s)
     ccc->parent_reset(s);
 
     vr = env->pregs[PR_VR];
-    memset(env, 0, offsetof(CPUCRISState, breakpoints));
+    memset(env, 0, offsetof(CPUCRISState, load_info));
     env->pregs[PR_VR] = vr;
     tlb_flush(env, 1);
 
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index 9e9cb8c..df2a3f0 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -167,8 +167,8 @@  typedef struct CPUCRISState {
 
 	CPU_COMMON
 
-	/* Members after CPU_COMMON are preserved across resets.  */
-	void *load_info;
+    /* Members from load_info on are preserved across resets.  */
+    void *load_info;
 } CPUCRISState;
 
 #include "cpu-qom.h"
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 29e9f63..90a4394 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3110,10 +3110,11 @@  static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc)
 
 static void check_breakpoint(CPUCRISState *env, DisasContext *dc)
 {
+    CPUState *cs = CPU(cris_env_get_cpu(env));
     CPUBreakpoint *bp;
 
-    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+    if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+        QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
             if (bp->pc == dc->pc) {
                 cris_evaluate_flags(dc);
                 tcg_gen_movi_tl(env_pc, dc->pc);
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 89e3217..b8d0c15 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2328,7 +2328,7 @@  static void x86_cpu_reset(CPUState *s)
     xcc->parent_reset(s);
 
 
-    memset(env, 0, offsetof(CPUX86State, breakpoints));
+    memset(env, 0, offsetof(CPUX86State, pat));
 
     tlb_flush(env, 1);
 
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 36e62b1..b9503d9 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -849,7 +849,7 @@  typedef struct CPUX86State {
     target_ulong exception_next_eip;
     target_ulong dr[8]; /* debug registers */
     union {
-        CPUBreakpoint *cpu_breakpoint[4];
+        struct CPUBreakpoint *cpu_breakpoint[4];
         struct CPUWatchpoint *cpu_watchpoint[4];
     }; /* break/watchpoints for dr[0..3] */
     uint32_t smbase;
@@ -861,6 +861,7 @@  typedef struct CPUX86State {
 
     CPU_COMMON
 
+    /* Fields from here on are preserved across CPU reset. */
     uint64_t pat;
 
     /* processor features (e.g. for CPUID insn) */
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 2a5ffc2..557c94f 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1096,7 +1096,7 @@  void breakpoint_handler(CPUX86State *env)
             }
         }
     } else {
-        QTAILQ_FOREACH(bp, &env->breakpoints, entry)
+        QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
             if (bp->pc == env->eip) {
                 if (bp->flags & BP_CPU) {
                     check_hw_breakpoints(env, true);
@@ -1104,6 +1104,7 @@  void breakpoint_handler(CPUX86State *env)
                 }
                 break;
             }
+        }
     }
 }
 
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 2e8e8d5..6e64551 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -8340,8 +8340,8 @@  static inline void gen_intermediate_code_internal(X86CPU *cpu,
 
     gen_tb_start();
     for(;;) {
-        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
                 if (bp->pc == pc_ptr &&
                     !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) {
                     gen_debug(dc, pc_ptr - dc->cs_base);
diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
index 607e332..69bc6bb 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -54,7 +54,7 @@  static void lm32_cpu_reset(CPUState *s)
     lcc->parent_reset(s);
 
     /* reset cpu state */
-    memset(env, 0, offsetof(CPULM32State, breakpoints));
+    memset(env, 0, offsetof(CPULM32State, eba));
 
     tlb_flush(env, 1);
 }
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index a94fd79..85c89e8 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -164,6 +164,7 @@  struct CPULM32State {
 
     CPU_COMMON
 
+    /* Fields from here on are preserved across CPU reset. */
     uint32_t eba;       /* exception base address */
     uint32_t deba;      /* debug exception base address */
 
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index 6ea0ecd..2e4951c 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -997,10 +997,11 @@  static inline void decode(DisasContext *dc, uint32_t ir)
 
 static void check_breakpoint(CPULM32State *env, DisasContext *dc)
 {
+    CPUState *cs = CPU(lm32_env_get_cpu(env));
     CPUBreakpoint *bp;
 
-    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+    if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+        QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
             if (bp->pc == dc->pc) {
                 tcg_gen_movi_tl(cpu_pc, dc->pc);
                 t_gen_raise_exception(dc, EXCP_DEBUG);
diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index e46b647..b24120d 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -69,7 +69,7 @@  static void m68k_cpu_reset(CPUState *s)
 
     mcc->parent_reset(s);
 
-    memset(env, 0, offsetof(CPUM68KState, breakpoints));
+    memset(env, 0, offsetof(CPUM68KState, features));
 #if !defined(CONFIG_USER_ONLY)
     env->sr = 0x2700;
 #endif
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index b8ad269..9a49bfc 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -110,6 +110,7 @@  typedef struct CPUM68KState {
 
     CPU_COMMON
 
+    /* Fields from here on are preserved across CPU reset. */
     uint32_t features;
 } CPUM68KState;
 
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index f3cdee0..c005e10 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3016,8 +3016,8 @@  gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
     do {
         pc_offset = dc->pc - pc_start;
         gen_throws_exception = NULL;
-        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
                 if (bp->pc == dc->pc) {
                     gen_exception(dc, dc->pc, EXCP_DEBUG);
                     dc->is_jmp = DISAS_JUMP;
diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
index 8b248f4..d724b6e 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -73,7 +73,7 @@  static void mb_cpu_reset(CPUState *s)
 
     mcc->parent_reset(s);
 
-    memset(env, 0, offsetof(CPUMBState, breakpoints));
+    memset(env, 0, sizeof(CPUMBState));
     env->res_addr = RES_ADDR_NONE;
     tlb_flush(env, 1);
 
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index f4dbe11..31eef0f 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1724,10 +1724,11 @@  static inline void decode(DisasContext *dc, uint32_t ir)
 
 static void check_breakpoint(CPUMBState *env, DisasContext *dc)
 {
+    CPUState *cs = CPU(mb_env_get_cpu(env));
     CPUBreakpoint *bp;
 
-    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+    if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+        QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
             if (bp->pc == dc->pc) {
                 t_gen_raise_exception(dc, EXCP_DEBUG);
                 dc->is_jmp = DISAS_UPDATE;
diff --git a/target-mips/cpu.c b/target-mips/cpu.c
index 2fd5591..8f26d11 100644
--- a/target-mips/cpu.c
+++ b/target-mips/cpu.c
@@ -101,7 +101,7 @@  static void mips_cpu_reset(CPUState *s)
 
     mcc->parent_reset(s);
 
-    memset(env, 0, offsetof(CPUMIPSState, breakpoints));
+    memset(env, 0, offsetof(CPUMIPSState, mvp));
     tlb_flush(env, 1);
 
     cpu_state_reset(env);
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index b71a711..5320a05 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -469,6 +469,7 @@  struct CPUMIPSState {
 
     CPU_COMMON
 
+    /* Fields from here on are preserved across CPU reset. */
     CPUMIPSMVPContext *mvp;
 #if !defined(CONFIG_USER_ONLY)
     CPUMIPSTLBContext *tlb;
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 453918d..f2e6625 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15601,8 +15601,8 @@  gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
     LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
     gen_tb_start();
     while (ctx.bstate == BS_NONE) {
-        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
                 if (bp->pc == ctx.pc) {
                     save_cpu_state(&ctx, 1);
                     ctx.bstate = BS_BRANCH;
diff --git a/target-moxie/cpu.c b/target-moxie/cpu.c
index ab9d2cc..f7d1e6c 100644
--- a/target-moxie/cpu.c
+++ b/target-moxie/cpu.c
@@ -52,7 +52,7 @@  static void moxie_cpu_reset(CPUState *s)
 
     mcc->parent_reset(s);
 
-    memset(env, 0, offsetof(CPUMoxieState, breakpoints));
+    memset(env, 0, sizeof(CPUMoxieState));
     env->pc = 0x1000;
 
     tlb_flush(env, 1);
diff --git a/target-moxie/translate.c b/target-moxie/translate.c
index a93196f..63f889f 100644
--- a/target-moxie/translate.c
+++ b/target-moxie/translate.c
@@ -845,8 +845,8 @@  gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
 
     gen_tb_start();
     do {
-        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
                 if (ctx.pc == bp->pc) {
                     tcg_gen_movi_i32(cpu_pc, ctx.pc);
                     gen_helper_debug(cpu_env);
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
index b7104e3..3eae4e9 100644
--- a/target-openrisc/cpu.c
+++ b/target-openrisc/cpu.c
@@ -62,7 +62,11 @@  static void openrisc_cpu_reset(CPUState *s)
 
     occ->parent_reset(s);
 
-    memset(&cpu->env, 0, offsetof(CPUOpenRISCState, breakpoints));
+#ifndef CONFIG_USER_ONLY
+    memset(&cpu->env, 0, offsetof(CPUOpenRISCState, tlb));
+#else
+    memset(&cpu->env, 0, offsetof(CPUOpenRISCState, irq));
+#endif
 
     tlb_flush(&cpu->env, 1);
     /*tb_flush(&cpu->env);    FIXME: Do we need it?  */
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 8745072..441a0ef 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -304,6 +304,7 @@  typedef struct CPUOpenRISCState {
 
     CPU_COMMON
 
+    /* Fields from here on are preserved across CPU reset. */
 #ifndef CONFIG_USER_ONLY
     CPUOpenRISCTLBContext * tlb;
 
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index ea242da..a0a633f 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1645,10 +1645,11 @@  static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
 
 static void check_breakpoint(OpenRISCCPU *cpu, DisasContext *dc)
 {
+    CPUState *cs = CPU(cpu);
     CPUBreakpoint *bp;
 
-    if (unlikely(!QTAILQ_EMPTY(&cpu->env.breakpoints))) {
-        QTAILQ_FOREACH(bp, &cpu->env.breakpoints, entry) {
+    if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+        QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
             if (bp->pc == dc->pc) {
                 tcg_gen_movi_tl(cpu_pc, dc->pc);
                 gen_exception(dc, EXCP_DEBUG);
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 2da7bc7..ec12629 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9787,8 +9787,8 @@  static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
     /* Set env in case of segfault during code fetch */
     while (ctx.exception == POWERPC_EXCP_NONE
             && tcg_ctx.gen_opc_ptr < gen_opc_end) {
-        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
                 if (bp->pc == ctx.nip) {
                     gen_debug_exception(ctxp);
                     break;
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index ad0d5bc..d9b8470 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -131,7 +131,7 @@  static void s390_cpu_initial_reset(CPUState *s)
 
     s390_cpu_reset(s);
     /* initial reset does not touch regs,fregs and aregs */
-    memset(&env->fpc, 0, offsetof(CPUS390XState, breakpoints) -
+    memset(&env->fpc, 0, offsetof(CPUS390XState, cpu_num) -
                          offsetof(CPUS390XState, fpc));
 
     /* architectured initial values for CR 0 and 14 */
@@ -150,7 +150,7 @@  static void s390_cpu_full_reset(CPUState *s)
 
     scc->parent_reset(s);
 
-    memset(env, 0, offsetof(CPUS390XState, breakpoints));
+    memset(env, 0, offsetof(CPUS390XState, cpu_num));
 
     /* architectured initial values for CR 0 and 14 */
     env->cregs[0] = CR0_RESET;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index afe90eb..d230f2c 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -4799,8 +4799,8 @@  static inline void gen_intermediate_code_internal(S390CPU *cpu,
         }
 
         status = NO_EXIT;
-        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
                 if (bp->pc == dc.pc) {
                     status = EXIT_PC_STALE;
                     do_debug = true;
diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c
index 1f1b8fd..fb176bf 100644
--- a/target-sh4/cpu.c
+++ b/target-sh4/cpu.c
@@ -76,7 +76,7 @@  static void superh_cpu_reset(CPUState *s)
 
     scc->parent_reset(s);
 
-    memset(env, 0, offsetof(CPUSH4State, breakpoints));
+    memset(env, 0, offsetof(CPUSH4State, id));
     tlb_flush(env, 1);
 
     env->pc = 0xA0000000;
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 8abd0cc..1df0842 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -178,6 +178,7 @@  typedef struct CPUSH4State {
 
     CPU_COMMON
 
+    /* Fields from here on are preserved over CPU reset. */
     int id;			/* CPU model */
 
     void *intc_handle;
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index c06b29f..3fe53b8 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -1880,8 +1880,8 @@  gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
         max_insns = CF_COUNT_MASK;
     gen_tb_start();
     while (ctx.bstate == BS_NONE && tcg_ctx.gen_opc_ptr < gen_opc_end) {
-        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
                 if (ctx.pc == bp->pc) {
 		    /* We have hit a breakpoint - make sure PC is up-to-date */
 		    tcg_gen_movi_i32(cpu_pc, ctx.pc);
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 9443713..6c1ff68 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -32,7 +32,7 @@  static void sparc_cpu_reset(CPUState *s)
 
     scc->parent_reset(s);
 
-    memset(env, 0, offsetof(CPUSPARCState, breakpoints));
+    memset(env, 0, offsetof(CPUSPARCState, version));
     tlb_flush(env, 1);
     env->cwp = 0;
 #ifndef TARGET_SPARC64
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index cfa1e0d..69c6154 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -421,6 +421,7 @@  struct CPUSPARCState {
 
     CPU_COMMON
 
+    /* Fields from here on are preserved across CPU reset. */
     target_ulong version;
     uint32_t nwindows;
 
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 73f8b9c..bc52c85 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5254,8 +5254,8 @@  static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
         max_insns = CF_COUNT_MASK;
     gen_tb_start();
     do {
-        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
                 if (bp->pc == dc->pc) {
                     if (dc->pc != pc_start)
                         save_state(dc);
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index 1246895..b4bee99 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -1925,8 +1925,8 @@  static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
 
     gen_tb_start();
     do {
-        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
                 if (bp->pc == dc->pc) {
                     gen_set_pc_im(dc->pc);
                     gen_exception(EXCP_DEBUG);
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 24343bd..55d4448 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -2871,10 +2871,11 @@  invalid_opcode:
 
 static void check_breakpoint(CPUXtensaState *env, DisasContext *dc)
 {
+    CPUState *cs = CPU(xtensa_env_get_cpu(env));
     CPUBreakpoint *bp;
 
-    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+    if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+        QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
             if (bp->pc == dc->pc) {
                 tcg_gen_movi_i32(cpu_pc, dc->pc);
                 gen_exception(dc, EXCP_DEBUG);