Patchwork [RFC,qom-cpu,01/41] cpu: Turn cpu_has_work() into a CPUClass hook

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

Comments

Andreas Färber - Sept. 4, 2013, 9:04 a.m.
Default to false.

Tidy variable naming and inline cast uses while at it.

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 cpu-exec.c                  |  5 -----
 cpus.c                      |  2 +-
 include/qom/cpu.h           | 12 ++++++++++--
 qom/cpu.c                   |  6 ++++++
 target-alpha/cpu.c          | 16 ++++++++++++++++
 target-alpha/cpu.h          | 15 ---------------
 target-arm/cpu.c            |  7 +++++++
 target-arm/cpu.h            |  6 ------
 target-cris/cpu.c           |  6 ++++++
 target-cris/cpu.h           |  5 -----
 target-i386/cpu.c           | 15 +++++++++++++++
 target-i386/cpu.h           | 14 --------------
 target-lm32/cpu.c           |  6 ++++++
 target-lm32/cpu.h           |  5 -----
 target-m68k/cpu.c           |  6 ++++++
 target-m68k/cpu.h           |  5 -----
 target-microblaze/cpu.c     |  6 ++++++
 target-microblaze/cpu.h     |  5 -----
 target-mips/cpu.c           | 30 ++++++++++++++++++++++++++++++
 target-mips/cpu.h           | 28 ----------------------------
 target-moxie/cpu.c          |  6 ++++++
 target-moxie/cpu.h          |  5 -----
 target-openrisc/cpu.c       |  7 +++++++
 target-openrisc/cpu.h       |  5 -----
 target-ppc/cpu.h            |  8 --------
 target-ppc/translate_init.c |  9 +++++++++
 target-s390x/cpu.c          | 10 ++++++++++
 target-s390x/cpu.h          |  9 ---------
 target-sh4/cpu.c            |  6 ++++++
 target-sh4/cpu.h            |  5 -----
 target-sparc/cpu.c          | 10 ++++++++++
 target-sparc/cpu.h          |  9 ---------
 target-unicore32/cpu.c      |  7 +++++++
 target-unicore32/cpu.h      |  6 ------
 target-xtensa/cpu.c         |  8 ++++++++
 target-xtensa/cpu.h         |  7 -------
 36 files changed, 172 insertions(+), 145 deletions(-)
Jia Liu - Sept. 4, 2013, 12:41 p.m.
On Wed, Sep 4, 2013 at 5:04 PM, Andreas Färber <afaerber@suse.de> wrote:
> Default to false.
>
> Tidy variable naming and inline cast uses while at it.
>
> Signed-off-by: Andreas Färber <afaerber@suse.de>
> ---
>  cpu-exec.c                  |  5 -----
>  cpus.c                      |  2 +-
>  include/qom/cpu.h           | 12 ++++++++++--
>  qom/cpu.c                   |  6 ++++++
>  target-alpha/cpu.c          | 16 ++++++++++++++++
>  target-alpha/cpu.h          | 15 ---------------
>  target-arm/cpu.c            |  7 +++++++
>  target-arm/cpu.h            |  6 ------
>  target-cris/cpu.c           |  6 ++++++
>  target-cris/cpu.h           |  5 -----
>  target-i386/cpu.c           | 15 +++++++++++++++
>  target-i386/cpu.h           | 14 --------------
>  target-lm32/cpu.c           |  6 ++++++
>  target-lm32/cpu.h           |  5 -----
>  target-m68k/cpu.c           |  6 ++++++
>  target-m68k/cpu.h           |  5 -----
>  target-microblaze/cpu.c     |  6 ++++++
>  target-microblaze/cpu.h     |  5 -----
>  target-mips/cpu.c           | 30 ++++++++++++++++++++++++++++++
>  target-mips/cpu.h           | 28 ----------------------------
>  target-moxie/cpu.c          |  6 ++++++
>  target-moxie/cpu.h          |  5 -----
>  target-openrisc/cpu.c       |  7 +++++++
>  target-openrisc/cpu.h       |  5 -----
>  target-ppc/cpu.h            |  8 --------
>  target-ppc/translate_init.c |  9 +++++++++
>  target-s390x/cpu.c          | 10 ++++++++++
>  target-s390x/cpu.h          |  9 ---------
>  target-sh4/cpu.c            |  6 ++++++
>  target-sh4/cpu.h            |  5 -----
>  target-sparc/cpu.c          | 10 ++++++++++
>  target-sparc/cpu.h          |  9 ---------
>  target-unicore32/cpu.c      |  7 +++++++
>  target-unicore32/cpu.h      |  6 ------
>  target-xtensa/cpu.c         |  8 ++++++++
>  target-xtensa/cpu.h         |  7 -------
>  36 files changed, 172 insertions(+), 145 deletions(-)
>
> diff --git a/cpu-exec.c b/cpu-exec.c
> index 5a43995..e9866b8 100644
> --- a/cpu-exec.c
> +++ b/cpu-exec.c
> @@ -23,11 +23,6 @@
>  #include "qemu/atomic.h"
>  #include "sysemu/qtest.h"
>
> -bool qemu_cpu_has_work(CPUState *cpu)
> -{
> -    return cpu_has_work(cpu);
> -}
> -
>  void cpu_loop_exit(CPUArchState *env)
>  {
>      CPUState *cpu = ENV_GET_CPU(env);
> diff --git a/cpus.c b/cpus.c
> index e566297..5acb98b 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -75,7 +75,7 @@ static bool cpu_thread_is_idle(CPUState *cpu)
>      if (cpu_is_stopped(cpu)) {
>          return true;
>      }
> -    if (!cpu->halted || qemu_cpu_has_work(cpu) ||
> +    if (!cpu->halted || cpu_has_work(cpu) ||
>          kvm_halt_in_kernel()) {
>          return false;
>      }
> diff --git a/include/qom/cpu.h b/include/qom/cpu.h
> index 7739e00..4d022c3 100644
> --- a/include/qom/cpu.h
> +++ b/include/qom/cpu.h
> @@ -69,6 +69,7 @@ struct TranslationBlock;
>   * instantiatable CPU type.
>   * @reset: Callback to reset the #CPUState to its initial state.
>   * @reset_dump_flags: #CPUDumpFlags to use for reset logging.
> + * @has_work: Callback for checking if there is work to do.
>   * @do_interrupt: Callback for interrupt handling.
>   * @do_unassigned_access: Callback for unassigned access handling.
>   * @memory_rw_debug: Callback for GDB memory access.
> @@ -98,6 +99,7 @@ typedef struct CPUClass {
>
>      void (*reset)(CPUState *cpu);
>      int reset_dump_flags;
> +    bool (*has_work)(CPUState *cpu);
>      void (*do_interrupt)(CPUState *cpu);
>      CPUUnassignedAccess do_unassigned_access;
>      int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
> @@ -344,14 +346,20 @@ void cpu_reset(CPUState *cpu);
>  ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model);
>
>  /**
> - * qemu_cpu_has_work:
> + * cpu_has_work:
>   * @cpu: The vCPU to check.
>   *
>   * Checks whether the CPU has work to do.
>   *
>   * Returns: %true if the CPU has work, %false otherwise.
>   */
> -bool qemu_cpu_has_work(CPUState *cpu);
> +static inline bool cpu_has_work(CPUState *cpu)
> +{
> +    CPUClass *cc = CPU_GET_CLASS(cpu);
> +
> +    g_assert(cc->has_work);
> +    return cc->has_work(cpu);
> +}
>
>  /**
>   * qemu_cpu_is_self:
> diff --git a/qom/cpu.c b/qom/cpu.c
> index fa7ec6b..c71fa35 100644
> --- a/qom/cpu.c
> +++ b/qom/cpu.c
> @@ -200,6 +200,11 @@ static void cpu_common_reset(CPUState *cpu)
>      cpu->halted = 0;
>  }
>
> +static bool cpu_common_has_work(CPUState *cs)
> +{
> +    return false;
> +}
> +
>  ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model)
>  {
>      CPUClass *cc = CPU_CLASS(object_class_by_name(typename));
> @@ -244,6 +249,7 @@ static void cpu_class_init(ObjectClass *klass, void *data)
>      k->class_by_name = cpu_common_class_by_name;
>      k->reset = cpu_common_reset;
>      k->get_arch_id = cpu_common_get_arch_id;
> +    k->has_work = cpu_common_has_work;
>      k->get_paging_enabled = cpu_common_get_paging_enabled;
>      k->get_memory_mapping = cpu_common_get_memory_mapping;
>      k->write_elf32_qemunote = cpu_common_write_elf32_qemunote;
> diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c
> index cfad2ea..053afa2 100644
> --- a/target-alpha/cpu.c
> +++ b/target-alpha/cpu.c
> @@ -31,6 +31,21 @@ static void alpha_cpu_set_pc(CPUState *cs, vaddr value)
>      cpu->env.pc = value;
>  }
>
> +static bool alpha_cpu_has_work(CPUState *cs)
> +{
> +    /* Here we are checking to see if the CPU should wake up from HALT.
> +       We will have gotten into this state only for WTINT from PALmode.  */
> +    /* ??? I'm not sure how the IPL state works with WTINT to keep a CPU
> +       asleep even if (some) interrupts have been asserted.  For now,
> +       assume that if a CPU really wants to stay asleep, it will mask
> +       interrupts at the chipset level, which will prevent these bits
> +       from being set in the first place.  */
> +    return cs->interrupt_request & (CPU_INTERRUPT_HARD
> +                                    | CPU_INTERRUPT_TIMER
> +                                    | CPU_INTERRUPT_SMP
> +                                    | CPU_INTERRUPT_MCHK);
> +}
> +
>  static void alpha_cpu_realizefn(DeviceState *dev, Error **errp)
>  {
>      CPUState *cs = CPU(dev);
> @@ -271,6 +286,7 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
>      dc->realize = alpha_cpu_realizefn;
>
>      cc->class_by_name = alpha_cpu_class_by_name;
> +    cc->has_work = alpha_cpu_has_work;
>      cc->do_interrupt = alpha_cpu_do_interrupt;
>      cc->dump_state = alpha_cpu_dump_state;
>      cc->set_pc = alpha_cpu_set_pc;
> diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
> index c85dc6e..a172124 100644
> --- a/target-alpha/cpu.h
> +++ b/target-alpha/cpu.h
> @@ -498,21 +498,6 @@ static inline void cpu_get_tb_cpu_state(CPUAlphaState *env, target_ulong *pc,
>      *pflags = flags;
>  }
>
> -static inline bool cpu_has_work(CPUState *cpu)
> -{
> -    /* Here we are checking to see if the CPU should wake up from HALT.
> -       We will have gotten into this state only for WTINT from PALmode.  */
> -    /* ??? I'm not sure how the IPL state works with WTINT to keep a CPU
> -       asleep even if (some) interrupts have been asserted.  For now,
> -       assume that if a CPU really wants to stay asleep, it will mask
> -       interrupts at the chipset level, which will prevent these bits
> -       from being set in the first place.  */
> -    return cpu->interrupt_request & (CPU_INTERRUPT_HARD
> -                                     | CPU_INTERRUPT_TIMER
> -                                     | CPU_INTERRUPT_SMP
> -                                     | CPU_INTERRUPT_MCHK);
> -}
> -
>  #include "exec/exec-all.h"
>
>  #endif /* !defined (__CPU_ALPHA_H__) */
> diff --git a/target-arm/cpu.c b/target-arm/cpu.c
> index b2556c6..f38c851 100644
> --- a/target-arm/cpu.c
> +++ b/target-arm/cpu.c
> @@ -34,6 +34,12 @@ static void arm_cpu_set_pc(CPUState *cs, vaddr value)
>      cpu->env.regs[15] = value;
>  }
>
> +static bool arm_cpu_has_work(CPUState *cs)
> +{
> +    return cs->interrupt_request &
> +        (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
> +}
> +
>  static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
>  {
>      /* Reset a single ARMCPRegInfo register */
> @@ -890,6 +896,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
>      cc->reset = arm_cpu_reset;
>
>      cc->class_by_name = arm_cpu_class_by_name;
> +    cc->has_work = arm_cpu_has_work;
>      cc->do_interrupt = arm_cpu_do_interrupt;
>      cc->dump_state = arm_cpu_dump_state;
>      cc->set_pc = arm_cpu_set_pc;
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index f2abdf3..a42822b 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -814,12 +814,6 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
>      }
>  }
>
> -static inline bool cpu_has_work(CPUState *cpu)
> -{
> -    return cpu->interrupt_request &
> -        (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
> -}
> -
>  #include "exec/exec-all.h"
>
>  /* Load an instruction and return it in the standard little-endian order */
> diff --git a/target-cris/cpu.c b/target-cris/cpu.c
> index 44301a4..998cded 100644
> --- a/target-cris/cpu.c
> +++ b/target-cris/cpu.c
> @@ -33,6 +33,11 @@ static void cris_cpu_set_pc(CPUState *cs, vaddr value)
>      cpu->env.pc = value;
>  }
>
> +static bool cris_cpu_has_work(CPUState *cs)
> +{
> +    return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
> +}
> +
>  /* CPUClass::reset() */
>  static void cris_cpu_reset(CPUState *s)
>  {
> @@ -257,6 +262,7 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
>      cc->reset = cris_cpu_reset;
>
>      cc->class_by_name = cris_cpu_class_by_name;
> +    cc->has_work = cris_cpu_has_work;
>      cc->do_interrupt = cris_cpu_do_interrupt;
>      cc->dump_state = cris_cpu_dump_state;
>      cc->set_pc = cris_cpu_set_pc;
> diff --git a/target-cris/cpu.h b/target-cris/cpu.h
> index 4b9fc4c..15a0497 100644
> --- a/target-cris/cpu.h
> +++ b/target-cris/cpu.h
> @@ -272,11 +272,6 @@ static inline void cpu_get_tb_cpu_state(CPUCRISState *env, target_ulong *pc,
>  #define cpu_list cris_cpu_list
>  void cris_cpu_list(FILE *f, fprintf_function cpu_fprintf);
>
> -static inline bool cpu_has_work(CPUState *cpu)
> -{
> -    return cpu->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
> -}
> -
>  #include "exec/exec-all.h"
>
>  #endif
> diff --git a/target-i386/cpu.c b/target-i386/cpu.c
> index c36345e..fa92950 100644
> --- a/target-i386/cpu.c
> +++ b/target-i386/cpu.c
> @@ -2676,6 +2676,20 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
>      cpu->env.eip = tb->pc - tb->cs_base;
>  }
>
> +static bool x86_cpu_has_work(CPUState *cs)
> +{
> +    X86CPU *cpu = X86_CPU(cs);
> +    CPUX86State *env = &cpu->env;
> +
> +    return ((cs->interrupt_request & (CPU_INTERRUPT_HARD |
> +                                      CPU_INTERRUPT_POLL)) &&
> +            (env->eflags & IF_MASK)) ||
> +           (cs->interrupt_request & (CPU_INTERRUPT_NMI |
> +                                     CPU_INTERRUPT_INIT |
> +                                     CPU_INTERRUPT_SIPI |
> +                                     CPU_INTERRUPT_MCE));
> +}
> +
>  static Property x86_cpu_properties[] = {
>      DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false),
>      DEFINE_PROP_END_OF_LIST()
> @@ -2696,6 +2710,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
>      cc->reset = x86_cpu_reset;
>      cc->reset_dump_flags = CPU_DUMP_FPU | CPU_DUMP_CCOP;
>
> +    cc->has_work = x86_cpu_has_work;
>      cc->do_interrupt = x86_cpu_do_interrupt;
>      cc->dump_state = x86_cpu_dump_state;
>      cc->set_pc = x86_cpu_set_pc;
> diff --git a/target-i386/cpu.h b/target-i386/cpu.h
> index 5723eff..6d46c75 100644
> --- a/target-i386/cpu.h
> +++ b/target-i386/cpu.h
> @@ -1161,20 +1161,6 @@ void optimize_flags_init(void);
>  #include "hw/i386/apic.h"
>  #endif
>
> -static inline bool cpu_has_work(CPUState *cs)
> -{
> -    X86CPU *cpu = X86_CPU(cs);
> -    CPUX86State *env = &cpu->env;
> -
> -    return ((cs->interrupt_request & (CPU_INTERRUPT_HARD |
> -                                      CPU_INTERRUPT_POLL)) &&
> -            (env->eflags & IF_MASK)) ||
> -           (cs->interrupt_request & (CPU_INTERRUPT_NMI |
> -                                     CPU_INTERRUPT_INIT |
> -                                     CPU_INTERRUPT_SIPI |
> -                                     CPU_INTERRUPT_MCE));
> -}
> -
>  #include "exec/exec-all.h"
>
>  static inline void cpu_get_tb_cpu_state(CPUX86State *env, target_ulong *pc,
> diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
> index 869878c..4fa8605 100644
> --- a/target-lm32/cpu.c
> +++ b/target-lm32/cpu.c
> @@ -29,6 +29,11 @@ static void lm32_cpu_set_pc(CPUState *cs, vaddr value)
>      cpu->env.pc = value;
>  }
>
> +static bool lm32_cpu_has_work(CPUState *cs)
> +{
> +    return cs->interrupt_request & CPU_INTERRUPT_HARD;
> +}
> +
>  /* CPUClass::reset() */
>  static void lm32_cpu_reset(CPUState *s)
>  {
> @@ -86,6 +91,7 @@ static void lm32_cpu_class_init(ObjectClass *oc, void *data)
>      lcc->parent_reset = cc->reset;
>      cc->reset = lm32_cpu_reset;
>
> +    cc->has_work = lm32_cpu_has_work;
>      cc->do_interrupt = lm32_cpu_do_interrupt;
>      cc->dump_state = lm32_cpu_dump_state;
>      cc->set_pc = lm32_cpu_set_pc;
> diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
> index dbfe043..a251a02 100644
> --- a/target-lm32/cpu.h
> +++ b/target-lm32/cpu.h
> @@ -225,11 +225,6 @@ static inline void cpu_get_tb_cpu_state(CPULM32State *env, target_ulong *pc,
>      *flags = 0;
>  }
>
> -static inline bool cpu_has_work(CPUState *cpu)
> -{
> -    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
> -}
> -
>  #include "exec/exec-all.h"
>
>  #endif
> diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
> index 008d8db..7d66ed0 100644
> --- a/target-m68k/cpu.c
> +++ b/target-m68k/cpu.c
> @@ -30,6 +30,11 @@ static void m68k_cpu_set_pc(CPUState *cs, vaddr value)
>      cpu->env.pc = value;
>  }
>
> +static bool m68k_cpu_has_work(CPUState *cs)
> +{
> +    return cs->interrupt_request & CPU_INTERRUPT_HARD;
> +}
> +
>  static void m68k_set_feature(CPUM68KState *env, int feature)
>  {
>      env->features |= (1u << feature);
> @@ -189,6 +194,7 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
>      cc->reset = m68k_cpu_reset;
>
>      cc->class_by_name = m68k_cpu_class_by_name;
> +    cc->has_work = m68k_cpu_has_work;
>      cc->do_interrupt = m68k_cpu_do_interrupt;
>      cc->dump_state = m68k_cpu_dump_state;
>      cc->set_pc = m68k_cpu_set_pc;
> diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
> index cfd6846..5f79d2a 100644
> --- a/target-m68k/cpu.h
> +++ b/target-m68k/cpu.h
> @@ -253,11 +253,6 @@ static inline void cpu_get_tb_cpu_state(CPUM68KState *env, target_ulong *pc,
>              | ((env->macsr >> 4) & 0xf);        /* Bits 0-3 */
>  }
>
> -static inline bool cpu_has_work(CPUState *cpu)
> -{
> -    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
> -}
> -
>  #include "exec/exec-all.h"
>
>  #endif
> diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
> index 0ef9aa4..6104939 100644
> --- a/target-microblaze/cpu.c
> +++ b/target-microblaze/cpu.c
> @@ -33,6 +33,11 @@ static void mb_cpu_set_pc(CPUState *cs, vaddr value)
>      cpu->env.sregs[SR_PC] = value;
>  }
>
> +static bool mb_cpu_has_work(CPUState *cs)
> +{
> +    return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
> +}
> +
>  /* CPUClass::reset() */
>  static void mb_cpu_reset(CPUState *s)
>  {
> @@ -139,6 +144,7 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
>      mcc->parent_reset = cc->reset;
>      cc->reset = mb_cpu_reset;
>
> +    cc->has_work = mb_cpu_has_work;
>      cc->do_interrupt = mb_cpu_do_interrupt;
>      cc->dump_state = mb_cpu_dump_state;
>      cc->set_pc = mb_cpu_set_pc;
> diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
> index 7508cf5..23f96f8 100644
> --- a/target-microblaze/cpu.h
> +++ b/target-microblaze/cpu.h
> @@ -358,11 +358,6 @@ void mb_cpu_unassigned_access(CPUState *cpu, hwaddr addr,
>                                unsigned size);
>  #endif
>
> -static inline bool cpu_has_work(CPUState *cpu)
> -{
> -    return cpu->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
> -}
> -
>  #include "exec/exec-all.h"
>
>  #endif
> diff --git a/target-mips/cpu.c b/target-mips/cpu.c
> index 9dd47e8..0a2dc46 100644
> --- a/target-mips/cpu.c
> +++ b/target-mips/cpu.c
> @@ -45,6 +45,35 @@ static void mips_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
>      env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
>  }
>
> +static bool mips_cpu_has_work(CPUState *cs)
> +{
> +    MIPSCPU *cpu = MIPS_CPU(cs);
> +    CPUMIPSState *env = &cpu->env;
> +    bool has_work = false;
> +
> +    /* It is implementation dependent if non-enabled interrupts
> +       wake-up the CPU, however most of the implementations only
> +       check for interrupts that can be taken. */
> +    if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
> +        cpu_mips_hw_interrupts_pending(env)) {
> +        has_work = true;
> +    }
> +
> +    /* MIPS-MT has the ability to halt the CPU.  */
> +    if (env->CP0_Config3 & (1 << CP0C3_MT)) {
> +        /* The QEMU model will issue an _WAKE request whenever the CPUs
> +           should be woken up.  */
> +        if (cs->interrupt_request & CPU_INTERRUPT_WAKE) {
> +            has_work = true;
> +        }
> +
> +        if (!mips_vpe_active(env)) {
> +            has_work = false;
> +        }
> +    }
> +    return has_work;
> +}
> +
>  /* CPUClass::reset() */
>  static void mips_cpu_reset(CPUState *s)
>  {
> @@ -97,6 +126,7 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
>      mcc->parent_reset = cc->reset;
>      cc->reset = mips_cpu_reset;
>
> +    cc->has_work = mips_cpu_has_work;
>      cc->do_interrupt = mips_cpu_do_interrupt;
>      cc->dump_state = mips_cpu_dump_state;
>      cc->set_pc = mips_cpu_set_pc;
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index a29c82f..dff2836 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -702,34 +702,6 @@ static inline int mips_vpe_active(CPUMIPSState *env)
>      return active;
>  }
>
> -static inline bool cpu_has_work(CPUState *cpu)
> -{
> -    CPUMIPSState *env = &MIPS_CPU(cpu)->env;
> -    bool has_work = false;
> -
> -    /* It is implementation dependent if non-enabled interrupts
> -       wake-up the CPU, however most of the implementations only
> -       check for interrupts that can be taken. */
> -    if ((cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
> -        cpu_mips_hw_interrupts_pending(env)) {
> -        has_work = true;
> -    }
> -
> -    /* MIPS-MT has the ability to halt the CPU.  */
> -    if (env->CP0_Config3 & (1 << CP0C3_MT)) {
> -        /* The QEMU model will issue an _WAKE request whenever the CPUs
> -           should be woken up.  */
> -        if (cpu->interrupt_request & CPU_INTERRUPT_WAKE) {
> -            has_work = true;
> -        }
> -
> -        if (!mips_vpe_active(env)) {
> -            has_work = false;
> -        }
> -    }
> -    return has_work;
> -}
> -
>  #include "exec/exec-all.h"
>
>  static inline void compute_hflags(CPUMIPSState *env)
> diff --git a/target-moxie/cpu.c b/target-moxie/cpu.c
> index d97a091..66f337e 100644
> --- a/target-moxie/cpu.c
> +++ b/target-moxie/cpu.c
> @@ -29,6 +29,11 @@ static void moxie_cpu_set_pc(CPUState *cs, vaddr value)
>      cpu->env.pc = value;
>  }
>
> +static bool moxie_cpu_has_work(CPUState *cs)
> +{
> +    return cs->interrupt_request & CPU_INTERRUPT_HARD;
> +}
> +
>  static void moxie_cpu_reset(CPUState *s)
>  {
>      MoxieCPU *cpu = MOXIE_CPU(s);
> @@ -99,6 +104,7 @@ static void moxie_cpu_class_init(ObjectClass *oc, void *data)
>
>      cc->class_by_name = moxie_cpu_class_by_name;
>
> +    cc->has_work = moxie_cpu_has_work;
>      cc->do_interrupt = moxie_cpu_do_interrupt;
>      cc->dump_state = moxie_cpu_dump_state;
>      cc->set_pc = moxie_cpu_set_pc;
> diff --git a/target-moxie/cpu.h b/target-moxie/cpu.h
> index 5ce14b5..778cfc0 100644
> --- a/target-moxie/cpu.h
> +++ b/target-moxie/cpu.h
> @@ -152,11 +152,6 @@ static inline void cpu_get_tb_cpu_state(CPUMoxieState *env, target_ulong *pc,
>      *flags = 0;
>  }
>
> -static inline int cpu_has_work(CPUState *cpu)
> -{
> -    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
> -}
> -
>  int cpu_moxie_handle_mmu_fault(CPUMoxieState *env, target_ulong address,
>                                 int rw, int mmu_idx);
>
> diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
> index 075f00a..ca8495f 100644
> --- a/target-openrisc/cpu.c
> +++ b/target-openrisc/cpu.c
> @@ -27,6 +27,12 @@ static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
>      cpu->env.pc = value;
>  }
>
> +static bool openrisc_cpu_has_work(CPUState *cs)
> +{
> +    return cs->interrupt_request & (CPU_INTERRUPT_HARD |
> +                                    CPU_INTERRUPT_TIMER);
> +}
> +
>  /* CPUClass::reset() */
>  static void openrisc_cpu_reset(CPUState *s)
>  {
> @@ -153,6 +159,7 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
>      cc->reset = openrisc_cpu_reset;
>
>      cc->class_by_name = openrisc_cpu_class_by_name;
> +    cc->has_work = openrisc_cpu_has_work;
>      cc->do_interrupt = openrisc_cpu_do_interrupt;
>      cc->dump_state = openrisc_cpu_dump_state;
>      cc->set_pc = openrisc_cpu_set_pc;
> diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
> index 8fd0bc0..4a27f22 100644
> --- a/target-openrisc/cpu.h
> +++ b/target-openrisc/cpu.h
> @@ -418,11 +418,6 @@ static inline int cpu_mmu_index(CPUOpenRISCState *env)
>  }
>
>  #define CPU_INTERRUPT_TIMER   CPU_INTERRUPT_TGT_INT_0
> -static inline bool cpu_has_work(CPUState *cpu)
> -{
> -    return cpu->interrupt_request & (CPU_INTERRUPT_HARD |
> -                                     CPU_INTERRUPT_TIMER);
> -}
>
>  #include "exec/exec-all.h"
>
> diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
> index 422a6bb..70c1ef5 100644
> --- a/target-ppc/cpu.h
> +++ b/target-ppc/cpu.h
> @@ -2134,14 +2134,6 @@ static inline bool msr_is_64bit(CPUPPCState *env, target_ulong msr)
>
>  extern void (*cpu_ppc_hypercall)(PowerPCCPU *);
>
> -static inline bool cpu_has_work(CPUState *cpu)
> -{
> -    PowerPCCPU *ppc_cpu = POWERPC_CPU(cpu);
> -    CPUPPCState *env = &ppc_cpu->env;
> -
> -    return msr_ee && (cpu->interrupt_request & CPU_INTERRUPT_HARD);
> -}
> -
>  #include "exec/exec-all.h"
>
>  void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env);
> diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
> index d2645ba..b552451 100644
> --- a/target-ppc/translate_init.c
> +++ b/target-ppc/translate_init.c
> @@ -8437,6 +8437,14 @@ static void ppc_cpu_set_pc(CPUState *cs, vaddr value)
>      cpu->env.nip = value;
>  }
>
> +static bool ppc_cpu_has_work(CPUState *cs)
> +{
> +    PowerPCCPU *cpu = POWERPC_CPU(cs);
> +    CPUPPCState *env = &cpu->env;
> +
> +    return msr_ee && (cs->interrupt_request & CPU_INTERRUPT_HARD);
> +}
> +
>  /* CPUClass::reset() */
>  static void ppc_cpu_reset(CPUState *s)
>  {
> @@ -8561,6 +8569,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
>      cc->reset = ppc_cpu_reset;
>
>      cc->class_by_name = ppc_cpu_class_by_name;
> +    cc->has_work = ppc_cpu_has_work;
>      cc->do_interrupt = ppc_cpu_do_interrupt;
>      cc->dump_state = ppc_cpu_dump_state;
>      cc->dump_statistics = ppc_cpu_dump_statistics;
> diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
> index 3c89f8a..a4c7a33 100644
> --- a/target-s390x/cpu.c
> +++ b/target-s390x/cpu.c
> @@ -65,6 +65,15 @@ static void s390_cpu_set_pc(CPUState *cs, vaddr value)
>      cpu->env.psw.addr = value;
>  }
>
> +static bool s390_cpu_has_work(CPUState *cs)
> +{
> +    S390CPU *cpu = S390_CPU(cs);
> +    CPUS390XState *env = &cpu->env;
> +
> +    return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
> +           (env->psw.mask & PSW_MASK_EXT);
> +}
> +
>  #if !defined(CONFIG_USER_ONLY)
>  /* S390CPUClass::load_normal() */
>  static void s390_cpu_load_normal(CPUState *s)
> @@ -217,6 +226,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
>      scc->cpu_reset = s390_cpu_reset;
>      scc->initial_cpu_reset = s390_cpu_initial_reset;
>      cc->reset = s390_cpu_full_reset;
> +    cc->has_work = s390_cpu_has_work;
>      cc->do_interrupt = s390_cpu_do_interrupt;
>      cc->dump_state = s390_cpu_dump_state;
>      cc->set_pc = s390_cpu_set_pc;
> diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
> index 8be5648..3b588af 100644
> --- a/target-s390x/cpu.h
> +++ b/target-s390x/cpu.h
> @@ -1036,15 +1036,6 @@ static inline void cpu_inject_crw_mchk(S390CPU *cpu)
>      cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
>  }
>
> -static inline bool cpu_has_work(CPUState *cpu)
> -{
> -    S390CPU *s390_cpu = S390_CPU(cpu);
> -    CPUS390XState *env = &s390_cpu->env;
> -
> -    return (cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
> -        (env->psw.mask & PSW_MASK_EXT);
> -}
> -
>  /* fpu_helper.c */
>  uint32_t set_cc_nz_f32(float32 v);
>  uint32_t set_cc_nz_f64(float64 v);
> diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c
> index 34b2b57..5bf6d9f 100644
> --- a/target-sh4/cpu.c
> +++ b/target-sh4/cpu.c
> @@ -39,6 +39,11 @@ static void superh_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
>      cpu->env.flags = tb->flags;
>  }
>
> +static bool superh_cpu_has_work(CPUState *cs)
> +{
> +    return cs->interrupt_request & CPU_INTERRUPT_HARD;
> +}
> +
>  /* CPUClass::reset() */
>  static void superh_cpu_reset(CPUState *s)
>  {
> @@ -283,6 +288,7 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
>      cc->reset = superh_cpu_reset;
>
>      cc->class_by_name = superh_cpu_class_by_name;
> +    cc->has_work = superh_cpu_has_work;
>      cc->do_interrupt = superh_cpu_do_interrupt;
>      cc->dump_state = superh_cpu_dump_state;
>      cc->set_pc = superh_cpu_set_pc;
> diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
> index 276d295..2eafc2d 100644
> --- a/target-sh4/cpu.h
> +++ b/target-sh4/cpu.h
> @@ -352,11 +352,6 @@ static inline void cpu_get_tb_cpu_state(CPUSH4State *env, target_ulong *pc,
>              | (env->movcal_backup ? TB_FLAG_PENDING_MOVCA : 0); /* Bit 4 */
>  }
>
> -static inline bool cpu_has_work(CPUState *cpu)
> -{
> -    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
> -}
> -
>  #include "exec/exec-all.h"
>
>  #endif                         /* _CPU_SH4_H */
> diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
> index 47ce60d..ede2c80 100644
> --- a/target-sparc/cpu.c
> +++ b/target-sparc/cpu.c
> @@ -739,6 +739,15 @@ static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
>      cpu->env.npc = tb->cs_base;
>  }
>
> +static bool sparc_cpu_has_work(CPUState *cs)
> +{
> +    SPARCCPU *cpu = SPARC_CPU(cs);
> +    CPUSPARCState *env = &cpu->env;
> +
> +    return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
> +           cpu_interrupts_enabled(env);
> +}
> +
>  static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
>  {
>      SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
> @@ -782,6 +791,7 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
>      scc->parent_reset = cc->reset;
>      cc->reset = sparc_cpu_reset;
>
> +    cc->has_work = sparc_cpu_has_work;
>      cc->do_interrupt = sparc_cpu_do_interrupt;
>      cc->dump_state = sparc_cpu_dump_state;
>  #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
> diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
> index 41194ec..adf6557 100644
> --- a/target-sparc/cpu.h
> +++ b/target-sparc/cpu.h
> @@ -747,15 +747,6 @@ static inline bool tb_am_enabled(int tb_flags)
>  #endif
>  }
>
> -static inline bool cpu_has_work(CPUState *cpu)
> -{
> -    SPARCCPU *sparc_cpu = SPARC_CPU(cpu);
> -    CPUSPARCState *env1 = &sparc_cpu->env;
> -
> -    return (cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
> -           cpu_interrupts_enabled(env1);
> -}
> -
>  #include "exec/exec-all.h"
>
>  #endif
> diff --git a/target-unicore32/cpu.c b/target-unicore32/cpu.c
> index 3f78208..1cfe50a 100644
> --- a/target-unicore32/cpu.c
> +++ b/target-unicore32/cpu.c
> @@ -23,6 +23,12 @@ static void uc32_cpu_set_pc(CPUState *cs, vaddr value)
>      cpu->env.regs[31] = value;
>  }
>
> +static bool uc32_cpu_has_work(CPUState *cs)
> +{
> +    return cs->interrupt_request &
> +        (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
> +}
> +
>  static inline void set_feature(CPUUniCore32State *env, int feature)
>  {
>      env->features |= feature;
> @@ -138,6 +144,7 @@ static void uc32_cpu_class_init(ObjectClass *oc, void *data)
>      dc->realize = uc32_cpu_realizefn;
>
>      cc->class_by_name = uc32_cpu_class_by_name;
> +    cc->has_work = uc32_cpu_has_work;
>      cc->do_interrupt = uc32_cpu_do_interrupt;
>      cc->dump_state = uc32_cpu_dump_state;
>      cc->set_pc = uc32_cpu_set_pc;
> diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
> index 967511e..1db7419 100644
> --- a/target-unicore32/cpu.h
> +++ b/target-unicore32/cpu.h
> @@ -160,10 +160,4 @@ static inline void cpu_get_tb_cpu_state(CPUUniCore32State *env, target_ulong *pc
>  void uc32_translate_init(void);
>  void switch_mode(CPUUniCore32State *, int);
>
> -static inline bool cpu_has_work(CPUState *cpu)
> -{
> -    return cpu->interrupt_request &
> -        (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
> -}
> -
>  #endif /* QEMU_UNICORE32_CPU_H */
> diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
> index c19d17a..46573c6 100644
> --- a/target-xtensa/cpu.c
> +++ b/target-xtensa/cpu.c
> @@ -40,6 +40,13 @@ static void xtensa_cpu_set_pc(CPUState *cs, vaddr value)
>      cpu->env.pc = value;
>  }
>
> +static bool xtensa_cpu_has_work(CPUState *cs)
> +{
> +    XtensaCPU *cpu = XTENSA_CPU(cs);
> +
> +    return cpu->env.pending_irq_level;
> +}
> +
>  /* CPUClass::reset() */
>  static void xtensa_cpu_reset(CPUState *s)
>  {
> @@ -132,6 +139,7 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
>      cc->reset = xtensa_cpu_reset;
>
>      cc->class_by_name = xtensa_cpu_class_by_name;
> +    cc->has_work = xtensa_cpu_has_work;
>      cc->do_interrupt = xtensa_cpu_do_interrupt;
>      cc->dump_state = xtensa_cpu_dump_state;
>      cc->set_pc = xtensa_cpu_set_pc;
> diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
> index 95103e9..de27c8c 100644
> --- a/target-xtensa/cpu.h
> +++ b/target-xtensa/cpu.h
> @@ -519,11 +519,4 @@ static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
>  #include "exec/cpu-all.h"
>  #include "exec/exec-all.h"
>
> -static inline int cpu_has_work(CPUState *cpu)
> -{
> -    CPUXtensaState *env = &XTENSA_CPU(cpu)->env;
> -
> -    return env->pending_irq_level;
> -}
> -
>  #endif

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

> --
> 1.8.1.4
>
Andreas Färber - Feb. 5, 2014, 6:51 p.m.
Am 04.09.2013 11:04, schrieb Andreas Färber:
> Default to false.
> 
> Tidy variable naming and inline cast uses while at it.
> 
> Signed-off-by: Andreas Färber <afaerber@suse.de>

If I've re-read the IRC transcript correctly, Paolo objected to patch
03/41 and had doubts about 02/41. I have therefore applied this 01/41 to
qom-cpu to crack down on functions new targets need to implement in cpu.h:

https://github.com/afaerber/qemu-cpu/commits/qom-cpu

Regards,
Andreas

> ---
>  cpu-exec.c                  |  5 -----
>  cpus.c                      |  2 +-
>  include/qom/cpu.h           | 12 ++++++++++--
>  qom/cpu.c                   |  6 ++++++
>  target-alpha/cpu.c          | 16 ++++++++++++++++
>  target-alpha/cpu.h          | 15 ---------------
>  target-arm/cpu.c            |  7 +++++++
>  target-arm/cpu.h            |  6 ------
>  target-cris/cpu.c           |  6 ++++++
>  target-cris/cpu.h           |  5 -----
>  target-i386/cpu.c           | 15 +++++++++++++++
>  target-i386/cpu.h           | 14 --------------
>  target-lm32/cpu.c           |  6 ++++++
>  target-lm32/cpu.h           |  5 -----
>  target-m68k/cpu.c           |  6 ++++++
>  target-m68k/cpu.h           |  5 -----
>  target-microblaze/cpu.c     |  6 ++++++
>  target-microblaze/cpu.h     |  5 -----
>  target-mips/cpu.c           | 30 ++++++++++++++++++++++++++++++
>  target-mips/cpu.h           | 28 ----------------------------
>  target-moxie/cpu.c          |  6 ++++++
>  target-moxie/cpu.h          |  5 -----
>  target-openrisc/cpu.c       |  7 +++++++
>  target-openrisc/cpu.h       |  5 -----
>  target-ppc/cpu.h            |  8 --------
>  target-ppc/translate_init.c |  9 +++++++++
>  target-s390x/cpu.c          | 10 ++++++++++
>  target-s390x/cpu.h          |  9 ---------
>  target-sh4/cpu.c            |  6 ++++++
>  target-sh4/cpu.h            |  5 -----
>  target-sparc/cpu.c          | 10 ++++++++++
>  target-sparc/cpu.h          |  9 ---------
>  target-unicore32/cpu.c      |  7 +++++++
>  target-unicore32/cpu.h      |  6 ------
>  target-xtensa/cpu.c         |  8 ++++++++
>  target-xtensa/cpu.h         |  7 -------
>  36 files changed, 172 insertions(+), 145 deletions(-)

Patch

diff --git a/cpu-exec.c b/cpu-exec.c
index 5a43995..e9866b8 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -23,11 +23,6 @@ 
 #include "qemu/atomic.h"
 #include "sysemu/qtest.h"
 
-bool qemu_cpu_has_work(CPUState *cpu)
-{
-    return cpu_has_work(cpu);
-}
-
 void cpu_loop_exit(CPUArchState *env)
 {
     CPUState *cpu = ENV_GET_CPU(env);
diff --git a/cpus.c b/cpus.c
index e566297..5acb98b 100644
--- a/cpus.c
+++ b/cpus.c
@@ -75,7 +75,7 @@  static bool cpu_thread_is_idle(CPUState *cpu)
     if (cpu_is_stopped(cpu)) {
         return true;
     }
-    if (!cpu->halted || qemu_cpu_has_work(cpu) ||
+    if (!cpu->halted || cpu_has_work(cpu) ||
         kvm_halt_in_kernel()) {
         return false;
     }
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 7739e00..4d022c3 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -69,6 +69,7 @@  struct TranslationBlock;
  * instantiatable CPU type.
  * @reset: Callback to reset the #CPUState to its initial state.
  * @reset_dump_flags: #CPUDumpFlags to use for reset logging.
+ * @has_work: Callback for checking if there is work to do.
  * @do_interrupt: Callback for interrupt handling.
  * @do_unassigned_access: Callback for unassigned access handling.
  * @memory_rw_debug: Callback for GDB memory access.
@@ -98,6 +99,7 @@  typedef struct CPUClass {
 
     void (*reset)(CPUState *cpu);
     int reset_dump_flags;
+    bool (*has_work)(CPUState *cpu);
     void (*do_interrupt)(CPUState *cpu);
     CPUUnassignedAccess do_unassigned_access;
     int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
@@ -344,14 +346,20 @@  void cpu_reset(CPUState *cpu);
 ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model);
 
 /**
- * qemu_cpu_has_work:
+ * cpu_has_work:
  * @cpu: The vCPU to check.
  *
  * Checks whether the CPU has work to do.
  *
  * Returns: %true if the CPU has work, %false otherwise.
  */
-bool qemu_cpu_has_work(CPUState *cpu);
+static inline bool cpu_has_work(CPUState *cpu)
+{
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+
+    g_assert(cc->has_work);
+    return cc->has_work(cpu);
+}
 
 /**
  * qemu_cpu_is_self:
diff --git a/qom/cpu.c b/qom/cpu.c
index fa7ec6b..c71fa35 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -200,6 +200,11 @@  static void cpu_common_reset(CPUState *cpu)
     cpu->halted = 0;
 }
 
+static bool cpu_common_has_work(CPUState *cs)
+{
+    return false;
+}
+
 ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model)
 {
     CPUClass *cc = CPU_CLASS(object_class_by_name(typename));
@@ -244,6 +249,7 @@  static void cpu_class_init(ObjectClass *klass, void *data)
     k->class_by_name = cpu_common_class_by_name;
     k->reset = cpu_common_reset;
     k->get_arch_id = cpu_common_get_arch_id;
+    k->has_work = cpu_common_has_work;
     k->get_paging_enabled = cpu_common_get_paging_enabled;
     k->get_memory_mapping = cpu_common_get_memory_mapping;
     k->write_elf32_qemunote = cpu_common_write_elf32_qemunote;
diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c
index cfad2ea..053afa2 100644
--- a/target-alpha/cpu.c
+++ b/target-alpha/cpu.c
@@ -31,6 +31,21 @@  static void alpha_cpu_set_pc(CPUState *cs, vaddr value)
     cpu->env.pc = value;
 }
 
+static bool alpha_cpu_has_work(CPUState *cs)
+{
+    /* Here we are checking to see if the CPU should wake up from HALT.
+       We will have gotten into this state only for WTINT from PALmode.  */
+    /* ??? I'm not sure how the IPL state works with WTINT to keep a CPU
+       asleep even if (some) interrupts have been asserted.  For now,
+       assume that if a CPU really wants to stay asleep, it will mask
+       interrupts at the chipset level, which will prevent these bits
+       from being set in the first place.  */
+    return cs->interrupt_request & (CPU_INTERRUPT_HARD
+                                    | CPU_INTERRUPT_TIMER
+                                    | CPU_INTERRUPT_SMP
+                                    | CPU_INTERRUPT_MCHK);
+}
+
 static void alpha_cpu_realizefn(DeviceState *dev, Error **errp)
 {
     CPUState *cs = CPU(dev);
@@ -271,6 +286,7 @@  static void alpha_cpu_class_init(ObjectClass *oc, void *data)
     dc->realize = alpha_cpu_realizefn;
 
     cc->class_by_name = alpha_cpu_class_by_name;
+    cc->has_work = alpha_cpu_has_work;
     cc->do_interrupt = alpha_cpu_do_interrupt;
     cc->dump_state = alpha_cpu_dump_state;
     cc->set_pc = alpha_cpu_set_pc;
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index c85dc6e..a172124 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -498,21 +498,6 @@  static inline void cpu_get_tb_cpu_state(CPUAlphaState *env, target_ulong *pc,
     *pflags = flags;
 }
 
-static inline bool cpu_has_work(CPUState *cpu)
-{
-    /* Here we are checking to see if the CPU should wake up from HALT.
-       We will have gotten into this state only for WTINT from PALmode.  */
-    /* ??? I'm not sure how the IPL state works with WTINT to keep a CPU
-       asleep even if (some) interrupts have been asserted.  For now,
-       assume that if a CPU really wants to stay asleep, it will mask
-       interrupts at the chipset level, which will prevent these bits
-       from being set in the first place.  */
-    return cpu->interrupt_request & (CPU_INTERRUPT_HARD
-                                     | CPU_INTERRUPT_TIMER
-                                     | CPU_INTERRUPT_SMP
-                                     | CPU_INTERRUPT_MCHK);
-}
-
 #include "exec/exec-all.h"
 
 #endif /* !defined (__CPU_ALPHA_H__) */
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index b2556c6..f38c851 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -34,6 +34,12 @@  static void arm_cpu_set_pc(CPUState *cs, vaddr value)
     cpu->env.regs[15] = value;
 }
 
+static bool arm_cpu_has_work(CPUState *cs)
+{
+    return cs->interrupt_request &
+        (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
+}
+
 static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
 {
     /* Reset a single ARMCPRegInfo register */
@@ -890,6 +896,7 @@  static void arm_cpu_class_init(ObjectClass *oc, void *data)
     cc->reset = arm_cpu_reset;
 
     cc->class_by_name = arm_cpu_class_by_name;
+    cc->has_work = arm_cpu_has_work;
     cc->do_interrupt = arm_cpu_do_interrupt;
     cc->dump_state = arm_cpu_dump_state;
     cc->set_pc = arm_cpu_set_pc;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index f2abdf3..a42822b 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -814,12 +814,6 @@  static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
     }
 }
 
-static inline bool cpu_has_work(CPUState *cpu)
-{
-    return cpu->interrupt_request &
-        (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
-}
-
 #include "exec/exec-all.h"
 
 /* Load an instruction and return it in the standard little-endian order */
diff --git a/target-cris/cpu.c b/target-cris/cpu.c
index 44301a4..998cded 100644
--- a/target-cris/cpu.c
+++ b/target-cris/cpu.c
@@ -33,6 +33,11 @@  static void cris_cpu_set_pc(CPUState *cs, vaddr value)
     cpu->env.pc = value;
 }
 
+static bool cris_cpu_has_work(CPUState *cs)
+{
+    return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
+}
+
 /* CPUClass::reset() */
 static void cris_cpu_reset(CPUState *s)
 {
@@ -257,6 +262,7 @@  static void cris_cpu_class_init(ObjectClass *oc, void *data)
     cc->reset = cris_cpu_reset;
 
     cc->class_by_name = cris_cpu_class_by_name;
+    cc->has_work = cris_cpu_has_work;
     cc->do_interrupt = cris_cpu_do_interrupt;
     cc->dump_state = cris_cpu_dump_state;
     cc->set_pc = cris_cpu_set_pc;
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index 4b9fc4c..15a0497 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -272,11 +272,6 @@  static inline void cpu_get_tb_cpu_state(CPUCRISState *env, target_ulong *pc,
 #define cpu_list cris_cpu_list
 void cris_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 
-static inline bool cpu_has_work(CPUState *cpu)
-{
-    return cpu->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
-}
-
 #include "exec/exec-all.h"
 
 #endif
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index c36345e..fa92950 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2676,6 +2676,20 @@  static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
     cpu->env.eip = tb->pc - tb->cs_base;
 }
 
+static bool x86_cpu_has_work(CPUState *cs)
+{
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
+
+    return ((cs->interrupt_request & (CPU_INTERRUPT_HARD |
+                                      CPU_INTERRUPT_POLL)) &&
+            (env->eflags & IF_MASK)) ||
+           (cs->interrupt_request & (CPU_INTERRUPT_NMI |
+                                     CPU_INTERRUPT_INIT |
+                                     CPU_INTERRUPT_SIPI |
+                                     CPU_INTERRUPT_MCE));
+}
+
 static Property x86_cpu_properties[] = {
     DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false),
     DEFINE_PROP_END_OF_LIST()
@@ -2696,6 +2710,7 @@  static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
     cc->reset = x86_cpu_reset;
     cc->reset_dump_flags = CPU_DUMP_FPU | CPU_DUMP_CCOP;
 
+    cc->has_work = x86_cpu_has_work;
     cc->do_interrupt = x86_cpu_do_interrupt;
     cc->dump_state = x86_cpu_dump_state;
     cc->set_pc = x86_cpu_set_pc;
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 5723eff..6d46c75 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -1161,20 +1161,6 @@  void optimize_flags_init(void);
 #include "hw/i386/apic.h"
 #endif
 
-static inline bool cpu_has_work(CPUState *cs)
-{
-    X86CPU *cpu = X86_CPU(cs);
-    CPUX86State *env = &cpu->env;
-
-    return ((cs->interrupt_request & (CPU_INTERRUPT_HARD |
-                                      CPU_INTERRUPT_POLL)) &&
-            (env->eflags & IF_MASK)) ||
-           (cs->interrupt_request & (CPU_INTERRUPT_NMI |
-                                     CPU_INTERRUPT_INIT |
-                                     CPU_INTERRUPT_SIPI |
-                                     CPU_INTERRUPT_MCE));
-}
-
 #include "exec/exec-all.h"
 
 static inline void cpu_get_tb_cpu_state(CPUX86State *env, target_ulong *pc,
diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
index 869878c..4fa8605 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -29,6 +29,11 @@  static void lm32_cpu_set_pc(CPUState *cs, vaddr value)
     cpu->env.pc = value;
 }
 
+static bool lm32_cpu_has_work(CPUState *cs)
+{
+    return cs->interrupt_request & CPU_INTERRUPT_HARD;
+}
+
 /* CPUClass::reset() */
 static void lm32_cpu_reset(CPUState *s)
 {
@@ -86,6 +91,7 @@  static void lm32_cpu_class_init(ObjectClass *oc, void *data)
     lcc->parent_reset = cc->reset;
     cc->reset = lm32_cpu_reset;
 
+    cc->has_work = lm32_cpu_has_work;
     cc->do_interrupt = lm32_cpu_do_interrupt;
     cc->dump_state = lm32_cpu_dump_state;
     cc->set_pc = lm32_cpu_set_pc;
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index dbfe043..a251a02 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -225,11 +225,6 @@  static inline void cpu_get_tb_cpu_state(CPULM32State *env, target_ulong *pc,
     *flags = 0;
 }
 
-static inline bool cpu_has_work(CPUState *cpu)
-{
-    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
-}
-
 #include "exec/exec-all.h"
 
 #endif
diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index 008d8db..7d66ed0 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -30,6 +30,11 @@  static void m68k_cpu_set_pc(CPUState *cs, vaddr value)
     cpu->env.pc = value;
 }
 
+static bool m68k_cpu_has_work(CPUState *cs)
+{
+    return cs->interrupt_request & CPU_INTERRUPT_HARD;
+}
+
 static void m68k_set_feature(CPUM68KState *env, int feature)
 {
     env->features |= (1u << feature);
@@ -189,6 +194,7 @@  static void m68k_cpu_class_init(ObjectClass *c, void *data)
     cc->reset = m68k_cpu_reset;
 
     cc->class_by_name = m68k_cpu_class_by_name;
+    cc->has_work = m68k_cpu_has_work;
     cc->do_interrupt = m68k_cpu_do_interrupt;
     cc->dump_state = m68k_cpu_dump_state;
     cc->set_pc = m68k_cpu_set_pc;
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index cfd6846..5f79d2a 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -253,11 +253,6 @@  static inline void cpu_get_tb_cpu_state(CPUM68KState *env, target_ulong *pc,
             | ((env->macsr >> 4) & 0xf);        /* Bits 0-3 */
 }
 
-static inline bool cpu_has_work(CPUState *cpu)
-{
-    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
-}
-
 #include "exec/exec-all.h"
 
 #endif
diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
index 0ef9aa4..6104939 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -33,6 +33,11 @@  static void mb_cpu_set_pc(CPUState *cs, vaddr value)
     cpu->env.sregs[SR_PC] = value;
 }
 
+static bool mb_cpu_has_work(CPUState *cs)
+{
+    return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
+}
+
 /* CPUClass::reset() */
 static void mb_cpu_reset(CPUState *s)
 {
@@ -139,6 +144,7 @@  static void mb_cpu_class_init(ObjectClass *oc, void *data)
     mcc->parent_reset = cc->reset;
     cc->reset = mb_cpu_reset;
 
+    cc->has_work = mb_cpu_has_work;
     cc->do_interrupt = mb_cpu_do_interrupt;
     cc->dump_state = mb_cpu_dump_state;
     cc->set_pc = mb_cpu_set_pc;
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 7508cf5..23f96f8 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -358,11 +358,6 @@  void mb_cpu_unassigned_access(CPUState *cpu, hwaddr addr,
                               unsigned size);
 #endif
 
-static inline bool cpu_has_work(CPUState *cpu)
-{
-    return cpu->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
-}
-
 #include "exec/exec-all.h"
 
 #endif
diff --git a/target-mips/cpu.c b/target-mips/cpu.c
index 9dd47e8..0a2dc46 100644
--- a/target-mips/cpu.c
+++ b/target-mips/cpu.c
@@ -45,6 +45,35 @@  static void mips_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
     env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
 }
 
+static bool mips_cpu_has_work(CPUState *cs)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+    bool has_work = false;
+
+    /* It is implementation dependent if non-enabled interrupts
+       wake-up the CPU, however most of the implementations only
+       check for interrupts that can be taken. */
+    if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
+        cpu_mips_hw_interrupts_pending(env)) {
+        has_work = true;
+    }
+
+    /* MIPS-MT has the ability to halt the CPU.  */
+    if (env->CP0_Config3 & (1 << CP0C3_MT)) {
+        /* The QEMU model will issue an _WAKE request whenever the CPUs
+           should be woken up.  */
+        if (cs->interrupt_request & CPU_INTERRUPT_WAKE) {
+            has_work = true;
+        }
+
+        if (!mips_vpe_active(env)) {
+            has_work = false;
+        }
+    }
+    return has_work;
+}
+
 /* CPUClass::reset() */
 static void mips_cpu_reset(CPUState *s)
 {
@@ -97,6 +126,7 @@  static void mips_cpu_class_init(ObjectClass *c, void *data)
     mcc->parent_reset = cc->reset;
     cc->reset = mips_cpu_reset;
 
+    cc->has_work = mips_cpu_has_work;
     cc->do_interrupt = mips_cpu_do_interrupt;
     cc->dump_state = mips_cpu_dump_state;
     cc->set_pc = mips_cpu_set_pc;
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index a29c82f..dff2836 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -702,34 +702,6 @@  static inline int mips_vpe_active(CPUMIPSState *env)
     return active;
 }
 
-static inline bool cpu_has_work(CPUState *cpu)
-{
-    CPUMIPSState *env = &MIPS_CPU(cpu)->env;
-    bool has_work = false;
-
-    /* It is implementation dependent if non-enabled interrupts
-       wake-up the CPU, however most of the implementations only
-       check for interrupts that can be taken. */
-    if ((cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
-        cpu_mips_hw_interrupts_pending(env)) {
-        has_work = true;
-    }
-
-    /* MIPS-MT has the ability to halt the CPU.  */
-    if (env->CP0_Config3 & (1 << CP0C3_MT)) {
-        /* The QEMU model will issue an _WAKE request whenever the CPUs
-           should be woken up.  */
-        if (cpu->interrupt_request & CPU_INTERRUPT_WAKE) {
-            has_work = true;
-        }
-
-        if (!mips_vpe_active(env)) {
-            has_work = false;
-        }
-    }
-    return has_work;
-}
-
 #include "exec/exec-all.h"
 
 static inline void compute_hflags(CPUMIPSState *env)
diff --git a/target-moxie/cpu.c b/target-moxie/cpu.c
index d97a091..66f337e 100644
--- a/target-moxie/cpu.c
+++ b/target-moxie/cpu.c
@@ -29,6 +29,11 @@  static void moxie_cpu_set_pc(CPUState *cs, vaddr value)
     cpu->env.pc = value;
 }
 
+static bool moxie_cpu_has_work(CPUState *cs)
+{
+    return cs->interrupt_request & CPU_INTERRUPT_HARD;
+}
+
 static void moxie_cpu_reset(CPUState *s)
 {
     MoxieCPU *cpu = MOXIE_CPU(s);
@@ -99,6 +104,7 @@  static void moxie_cpu_class_init(ObjectClass *oc, void *data)
 
     cc->class_by_name = moxie_cpu_class_by_name;
 
+    cc->has_work = moxie_cpu_has_work;
     cc->do_interrupt = moxie_cpu_do_interrupt;
     cc->dump_state = moxie_cpu_dump_state;
     cc->set_pc = moxie_cpu_set_pc;
diff --git a/target-moxie/cpu.h b/target-moxie/cpu.h
index 5ce14b5..778cfc0 100644
--- a/target-moxie/cpu.h
+++ b/target-moxie/cpu.h
@@ -152,11 +152,6 @@  static inline void cpu_get_tb_cpu_state(CPUMoxieState *env, target_ulong *pc,
     *flags = 0;
 }
 
-static inline int cpu_has_work(CPUState *cpu)
-{
-    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
-}
-
 int cpu_moxie_handle_mmu_fault(CPUMoxieState *env, target_ulong address,
                                int rw, int mmu_idx);
 
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
index 075f00a..ca8495f 100644
--- a/target-openrisc/cpu.c
+++ b/target-openrisc/cpu.c
@@ -27,6 +27,12 @@  static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
     cpu->env.pc = value;
 }
 
+static bool openrisc_cpu_has_work(CPUState *cs)
+{
+    return cs->interrupt_request & (CPU_INTERRUPT_HARD |
+                                    CPU_INTERRUPT_TIMER);
+}
+
 /* CPUClass::reset() */
 static void openrisc_cpu_reset(CPUState *s)
 {
@@ -153,6 +159,7 @@  static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
     cc->reset = openrisc_cpu_reset;
 
     cc->class_by_name = openrisc_cpu_class_by_name;
+    cc->has_work = openrisc_cpu_has_work;
     cc->do_interrupt = openrisc_cpu_do_interrupt;
     cc->dump_state = openrisc_cpu_dump_state;
     cc->set_pc = openrisc_cpu_set_pc;
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 8fd0bc0..4a27f22 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -418,11 +418,6 @@  static inline int cpu_mmu_index(CPUOpenRISCState *env)
 }
 
 #define CPU_INTERRUPT_TIMER   CPU_INTERRUPT_TGT_INT_0
-static inline bool cpu_has_work(CPUState *cpu)
-{
-    return cpu->interrupt_request & (CPU_INTERRUPT_HARD |
-                                     CPU_INTERRUPT_TIMER);
-}
 
 #include "exec/exec-all.h"
 
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 422a6bb..70c1ef5 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -2134,14 +2134,6 @@  static inline bool msr_is_64bit(CPUPPCState *env, target_ulong msr)
 
 extern void (*cpu_ppc_hypercall)(PowerPCCPU *);
 
-static inline bool cpu_has_work(CPUState *cpu)
-{
-    PowerPCCPU *ppc_cpu = POWERPC_CPU(cpu);
-    CPUPPCState *env = &ppc_cpu->env;
-
-    return msr_ee && (cpu->interrupt_request & CPU_INTERRUPT_HARD);
-}
-
 #include "exec/exec-all.h"
 
 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env);
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index d2645ba..b552451 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8437,6 +8437,14 @@  static void ppc_cpu_set_pc(CPUState *cs, vaddr value)
     cpu->env.nip = value;
 }
 
+static bool ppc_cpu_has_work(CPUState *cs)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
+
+    return msr_ee && (cs->interrupt_request & CPU_INTERRUPT_HARD);
+}
+
 /* CPUClass::reset() */
 static void ppc_cpu_reset(CPUState *s)
 {
@@ -8561,6 +8569,7 @@  static void ppc_cpu_class_init(ObjectClass *oc, void *data)
     cc->reset = ppc_cpu_reset;
 
     cc->class_by_name = ppc_cpu_class_by_name;
+    cc->has_work = ppc_cpu_has_work;
     cc->do_interrupt = ppc_cpu_do_interrupt;
     cc->dump_state = ppc_cpu_dump_state;
     cc->dump_statistics = ppc_cpu_dump_statistics;
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index 3c89f8a..a4c7a33 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -65,6 +65,15 @@  static void s390_cpu_set_pc(CPUState *cs, vaddr value)
     cpu->env.psw.addr = value;
 }
 
+static bool s390_cpu_has_work(CPUState *cs)
+{
+    S390CPU *cpu = S390_CPU(cs);
+    CPUS390XState *env = &cpu->env;
+
+    return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
+           (env->psw.mask & PSW_MASK_EXT);
+}
+
 #if !defined(CONFIG_USER_ONLY)
 /* S390CPUClass::load_normal() */
 static void s390_cpu_load_normal(CPUState *s)
@@ -217,6 +226,7 @@  static void s390_cpu_class_init(ObjectClass *oc, void *data)
     scc->cpu_reset = s390_cpu_reset;
     scc->initial_cpu_reset = s390_cpu_initial_reset;
     cc->reset = s390_cpu_full_reset;
+    cc->has_work = s390_cpu_has_work;
     cc->do_interrupt = s390_cpu_do_interrupt;
     cc->dump_state = s390_cpu_dump_state;
     cc->set_pc = s390_cpu_set_pc;
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 8be5648..3b588af 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -1036,15 +1036,6 @@  static inline void cpu_inject_crw_mchk(S390CPU *cpu)
     cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 
-static inline bool cpu_has_work(CPUState *cpu)
-{
-    S390CPU *s390_cpu = S390_CPU(cpu);
-    CPUS390XState *env = &s390_cpu->env;
-
-    return (cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
-        (env->psw.mask & PSW_MASK_EXT);
-}
-
 /* fpu_helper.c */
 uint32_t set_cc_nz_f32(float32 v);
 uint32_t set_cc_nz_f64(float64 v);
diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c
index 34b2b57..5bf6d9f 100644
--- a/target-sh4/cpu.c
+++ b/target-sh4/cpu.c
@@ -39,6 +39,11 @@  static void superh_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
     cpu->env.flags = tb->flags;
 }
 
+static bool superh_cpu_has_work(CPUState *cs)
+{
+    return cs->interrupt_request & CPU_INTERRUPT_HARD;
+}
+
 /* CPUClass::reset() */
 static void superh_cpu_reset(CPUState *s)
 {
@@ -283,6 +288,7 @@  static void superh_cpu_class_init(ObjectClass *oc, void *data)
     cc->reset = superh_cpu_reset;
 
     cc->class_by_name = superh_cpu_class_by_name;
+    cc->has_work = superh_cpu_has_work;
     cc->do_interrupt = superh_cpu_do_interrupt;
     cc->dump_state = superh_cpu_dump_state;
     cc->set_pc = superh_cpu_set_pc;
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 276d295..2eafc2d 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -352,11 +352,6 @@  static inline void cpu_get_tb_cpu_state(CPUSH4State *env, target_ulong *pc,
             | (env->movcal_backup ? TB_FLAG_PENDING_MOVCA : 0); /* Bit 4 */
 }
 
-static inline bool cpu_has_work(CPUState *cpu)
-{
-    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
-}
-
 #include "exec/exec-all.h"
 
 #endif				/* _CPU_SH4_H */
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 47ce60d..ede2c80 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -739,6 +739,15 @@  static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
     cpu->env.npc = tb->cs_base;
 }
 
+static bool sparc_cpu_has_work(CPUState *cs)
+{
+    SPARCCPU *cpu = SPARC_CPU(cs);
+    CPUSPARCState *env = &cpu->env;
+
+    return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
+           cpu_interrupts_enabled(env);
+}
+
 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
 {
     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
@@ -782,6 +791,7 @@  static void sparc_cpu_class_init(ObjectClass *oc, void *data)
     scc->parent_reset = cc->reset;
     cc->reset = sparc_cpu_reset;
 
+    cc->has_work = sparc_cpu_has_work;
     cc->do_interrupt = sparc_cpu_do_interrupt;
     cc->dump_state = sparc_cpu_dump_state;
 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 41194ec..adf6557 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -747,15 +747,6 @@  static inline bool tb_am_enabled(int tb_flags)
 #endif
 }
 
-static inline bool cpu_has_work(CPUState *cpu)
-{
-    SPARCCPU *sparc_cpu = SPARC_CPU(cpu);
-    CPUSPARCState *env1 = &sparc_cpu->env;
-
-    return (cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
-           cpu_interrupts_enabled(env1);
-}
-
 #include "exec/exec-all.h"
 
 #endif
diff --git a/target-unicore32/cpu.c b/target-unicore32/cpu.c
index 3f78208..1cfe50a 100644
--- a/target-unicore32/cpu.c
+++ b/target-unicore32/cpu.c
@@ -23,6 +23,12 @@  static void uc32_cpu_set_pc(CPUState *cs, vaddr value)
     cpu->env.regs[31] = value;
 }
 
+static bool uc32_cpu_has_work(CPUState *cs)
+{
+    return cs->interrupt_request &
+        (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
+}
+
 static inline void set_feature(CPUUniCore32State *env, int feature)
 {
     env->features |= feature;
@@ -138,6 +144,7 @@  static void uc32_cpu_class_init(ObjectClass *oc, void *data)
     dc->realize = uc32_cpu_realizefn;
 
     cc->class_by_name = uc32_cpu_class_by_name;
+    cc->has_work = uc32_cpu_has_work;
     cc->do_interrupt = uc32_cpu_do_interrupt;
     cc->dump_state = uc32_cpu_dump_state;
     cc->set_pc = uc32_cpu_set_pc;
diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
index 967511e..1db7419 100644
--- a/target-unicore32/cpu.h
+++ b/target-unicore32/cpu.h
@@ -160,10 +160,4 @@  static inline void cpu_get_tb_cpu_state(CPUUniCore32State *env, target_ulong *pc
 void uc32_translate_init(void);
 void switch_mode(CPUUniCore32State *, int);
 
-static inline bool cpu_has_work(CPUState *cpu)
-{
-    return cpu->interrupt_request &
-        (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
-}
-
 #endif /* QEMU_UNICORE32_CPU_H */
diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
index c19d17a..46573c6 100644
--- a/target-xtensa/cpu.c
+++ b/target-xtensa/cpu.c
@@ -40,6 +40,13 @@  static void xtensa_cpu_set_pc(CPUState *cs, vaddr value)
     cpu->env.pc = value;
 }
 
+static bool xtensa_cpu_has_work(CPUState *cs)
+{
+    XtensaCPU *cpu = XTENSA_CPU(cs);
+
+    return cpu->env.pending_irq_level;
+}
+
 /* CPUClass::reset() */
 static void xtensa_cpu_reset(CPUState *s)
 {
@@ -132,6 +139,7 @@  static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
     cc->reset = xtensa_cpu_reset;
 
     cc->class_by_name = xtensa_cpu_class_by_name;
+    cc->has_work = xtensa_cpu_has_work;
     cc->do_interrupt = xtensa_cpu_do_interrupt;
     cc->dump_state = xtensa_cpu_dump_state;
     cc->set_pc = xtensa_cpu_set_pc;
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 95103e9..de27c8c 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -519,11 +519,4 @@  static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
 #include "exec/cpu-all.h"
 #include "exec/exec-all.h"
 
-static inline int cpu_has_work(CPUState *cpu)
-{
-    CPUXtensaState *env = &XTENSA_CPU(cpu)->env;
-
-    return env->pending_irq_level;
-}
-
 #endif