Patchwork [qom-cpu,v2,19/29] cpu: Replace cpu_single_env with CPUState cpu_single_cpu

login
register
mail settings
Submitter Andreas Färber
Date June 16, 2013, 3:57 p.m.
Message ID <1371398269-6213-20-git-send-email-afaerber@suse.de>
Download mbox | patch
Permalink /patch/251713/
State New
Headers show

Comments

Andreas Färber - June 16, 2013, 3:57 p.m.
Move it to qom/cpu.h.

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 cpu-exec.c              | 13 +++++++------
 cpus.c                  | 29 ++++++++++++++---------------
 exec.c                  | 12 +++++++-----
 hw/alpha/typhoon.c      | 16 ++++------------
 hw/arm/pxa2xx.c         |  3 +--
 hw/i386/kvmvapic.c      |  6 ++++--
 hw/i386/pc.c            | 11 ++++++-----
 hw/intc/arm_gic.c       |  3 +--
 hw/intc/armv7m_nvic.c   | 11 ++++++++---
 hw/intc/openpic.c       |  5 +----
 hw/mips/mips_fulong2e.c |  6 +++---
 hw/mips/mips_jazz.c     |  6 +++---
 hw/mips/mips_malta.c    |  6 +++---
 hw/misc/vmport.c        | 26 ++++++++++++++++----------
 hw/ppc/mpc8544_guts.c   |  3 ++-
 hw/ppc/prep.c           |  6 +++---
 hw/sparc/sun4m.c        |  5 ++---
 hw/timer/arm_mptimer.c  |  2 --
 include/exec/cpu-all.h  |  3 ---
 include/qom/cpu.h       |  4 ++++
 memory.c                | 10 ++++------
 translate-all.c         | 20 ++++++++++++--------
 user-exec.c             |  9 +++++----
 23 files changed, 110 insertions(+), 105 deletions(-)
Blue Swirl - June 16, 2013, 8:49 p.m.
On Sun, Jun 16, 2013 at 3:57 PM, Andreas Färber <afaerber@suse.de> wrote:
> Move it to qom/cpu.h.

While renaming, perhaps a more descriptive name could be used instead
of 'cpu_single_cpu', something like cpu_loop_current_cpu?

>
> Signed-off-by: Andreas Färber <afaerber@suse.de>
> ---
>  cpu-exec.c              | 13 +++++++------
>  cpus.c                  | 29 ++++++++++++++---------------
>  exec.c                  | 12 +++++++-----
>  hw/alpha/typhoon.c      | 16 ++++------------
>  hw/arm/pxa2xx.c         |  3 +--
>  hw/i386/kvmvapic.c      |  6 ++++--
>  hw/i386/pc.c            | 11 ++++++-----
>  hw/intc/arm_gic.c       |  3 +--
>  hw/intc/armv7m_nvic.c   | 11 ++++++++---
>  hw/intc/openpic.c       |  5 +----
>  hw/mips/mips_fulong2e.c |  6 +++---
>  hw/mips/mips_jazz.c     |  6 +++---
>  hw/mips/mips_malta.c    |  6 +++---
>  hw/misc/vmport.c        | 26 ++++++++++++++++----------
>  hw/ppc/mpc8544_guts.c   |  3 ++-
>  hw/ppc/prep.c           |  6 +++---
>  hw/sparc/sun4m.c        |  5 ++---
>  hw/timer/arm_mptimer.c  |  2 --
>  include/exec/cpu-all.h  |  3 ---
>  include/qom/cpu.h       |  4 ++++
>  memory.c                | 10 ++++------
>  translate-all.c         | 20 ++++++++++++--------
>  user-exec.c             |  9 +++++----
>  23 files changed, 110 insertions(+), 105 deletions(-)
>
> diff --git a/cpu-exec.c b/cpu-exec.c
> index ec46380..1858c2e 100644
> --- a/cpu-exec.c
> +++ b/cpu-exec.c
> @@ -213,12 +213,12 @@ int cpu_exec(CPUArchState *env)
>          cpu->halted = 0;
>      }
>
> -    cpu_single_env = env;
> +    cpu_single_cpu = cpu;
>
> -    /* As long as cpu_single_env is null, up to the assignment just above,
> +    /* As long as cpu_single_cpu is null, up to the assignment just above,
>       * requests by other threads to exit the execution loop are expected to
>       * be issued using the exit_request global. We must make sure that our
> -     * evaluation of the global value is performed past the cpu_single_env
> +     * evaluation of the global value is performed past the cpu_single_cpu
>       * value transition point, which requires a memory barrier as well as
>       * an instruction scheduling constraint on modern architectures.  */
>      smp_mb();
> @@ -673,7 +673,8 @@ int cpu_exec(CPUArchState *env)
>          } else {
>              /* Reload env after longjmp - the compiler may have smashed all
>               * local variables as longjmp is marked 'noreturn'. */
> -            env = cpu_single_env;
> +            cpu = cpu_single_cpu;
> +            env = cpu->env_ptr;
>          }
>      } /* for(;;) */
>
> @@ -707,7 +708,7 @@ int cpu_exec(CPUArchState *env)
>  #error unsupported target CPU
>  #endif
>
> -    /* fail safe : never use cpu_single_env outside cpu_exec() */
> -    cpu_single_env = NULL;
> +    /* fail safe : never use cpu_single_cpu outside cpu_exec() */
> +    cpu_single_cpu = NULL;
>      return ret;
>  }
> diff --git a/cpus.c b/cpus.c
> index 775d998..808503b 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -118,10 +118,11 @@ TimersState timers_state;
>  int64_t cpu_get_icount(void)
>  {
>      int64_t icount;
> -    CPUArchState *env = cpu_single_env;
> +    CPUState *cpu = cpu_single_cpu;
>
>      icount = qemu_icount;
> -    if (env) {
> +    if (cpu) {
> +        CPUArchState *env = cpu->env_ptr;
>          if (!can_do_io(env)) {
>              fprintf(stderr, "Bad clock read\n");
>          }
> @@ -468,8 +469,8 @@ static void cpu_handle_guest_debug(CPUState *cpu)
>
>  static void cpu_signal(int sig)
>  {
> -    if (cpu_single_env) {
> -        cpu_exit(ENV_GET_CPU(cpu_single_env));
> +    if (cpu_single_cpu) {
> +        cpu_exit(cpu_single_cpu);
>      }
>      exit_request = 1;
>  }
> @@ -660,10 +661,10 @@ void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data)
>
>      qemu_cpu_kick(cpu);
>      while (!wi.done) {
> -        CPUArchState *self_env = cpu_single_env;
> +        CPUState *self_cpu = cpu_single_cpu;
>
>          qemu_cond_wait(&qemu_work_cond, &qemu_global_mutex);
> -        cpu_single_env = self_env;
> +        cpu_single_cpu = self_cpu;
>      }
>  }
>
> @@ -733,7 +734,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
>      qemu_mutex_lock(&qemu_global_mutex);
>      qemu_thread_get_self(cpu->thread);
>      cpu->thread_id = qemu_get_thread_id();
> -    cpu_single_env = cpu->env_ptr;
> +    cpu_single_cpu = cpu;
>
>      r = kvm_init_vcpu(cpu);
>      if (r < 0) {
> @@ -781,9 +782,9 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
>      cpu->created = true;
>      qemu_cond_signal(&qemu_cpu_cond);
>
> -    cpu_single_env = cpu->env_ptr;
> +    cpu_single_cpu = cpu;
>      while (1) {
> -        cpu_single_env = NULL;
> +        cpu_single_cpu = NULL;
>          qemu_mutex_unlock_iothread();
>          do {
>              int sig;
> @@ -794,7 +795,7 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
>              exit(1);
>          }
>          qemu_mutex_lock_iothread();
> -        cpu_single_env = cpu->env_ptr;
> +        cpu_single_cpu = cpu;
>          qemu_wait_io_event_common(cpu);
>      }
>
> @@ -894,8 +895,7 @@ void qemu_cpu_kick(CPUState *cpu)
>  void qemu_cpu_kick_self(void)
>  {
>  #ifndef _WIN32
> -    assert(cpu_single_env);
> -    CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
> +    assert(cpu_single_cpu);
>
>      if (!cpu_single_cpu->thread_kicked) {
>          qemu_cpu_kick_thread(cpu_single_cpu);
> @@ -913,7 +913,7 @@ bool qemu_cpu_is_self(CPUState *cpu)
>
>  static bool qemu_in_vcpu_thread(void)
>  {
> -    return cpu_single_env && qemu_cpu_is_self(ENV_GET_CPU(cpu_single_env));
> +    return cpu_single_cpu && qemu_cpu_is_self(cpu_single_cpu);
>  }
>
>  void qemu_mutex_lock_iothread(void)
> @@ -1069,8 +1069,7 @@ void qemu_init_vcpu(CPUState *cpu)
>
>  void cpu_stop_current(void)
>  {
> -    if (cpu_single_env) {
> -        CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
> +    if (cpu_single_cpu) {
>          cpu_single_cpu->stop = false;
>          cpu_single_cpu->stopped = true;
>          cpu_exit(cpu_single_cpu);
> diff --git a/exec.c b/exec.c
> index 2b99bb9..e14a815 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -73,7 +73,7 @@ static MemoryRegion io_mem_unassigned, io_mem_subpage_ram;
>  CPUArchState *first_cpu;
>  /* current CPU in the current thread. It is only valid inside
>     cpu_exec() */
> -DEFINE_TLS(CPUArchState *,cpu_single_env);
> +DEFINE_TLS(CPUState *,cpu_single_cpu);
>  /* 0 = Do not count executed instructions.
>     1 = Precise instruction counting.
>     2 = Adaptive rate instruction counting.  */
> @@ -1420,8 +1420,10 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
>      cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
>      /* we remove the notdirty callback only if the code has been
>         flushed */
> -    if (dirty_flags == 0xff)
> -        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
> +    if (dirty_flags == 0xff) {
> +        CPUArchState *env = cpu_single_cpu->env_ptr;
> +        tlb_set_dirty(env, env->mem_io_vaddr);
> +    }
>  }
>
>  static bool notdirty_mem_accepts(void *opaque, hwaddr addr,
> @@ -1439,7 +1441,7 @@ static const MemoryRegionOps notdirty_mem_ops = {
>  /* Generate a debug exception if a watchpoint has been hit.  */
>  static void check_watchpoint(int offset, int len_mask, int flags)
>  {
> -    CPUArchState *env = cpu_single_env;
> +    CPUArchState *env = cpu_single_cpu->env_ptr;
>      target_ulong pc, cs_base;
>      target_ulong vaddr;
>      CPUWatchpoint *wp;
> @@ -1912,7 +1914,7 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>          if (is_write) {
>              if (!memory_access_is_direct(section->mr, is_write)) {
>                  l = memory_access_size(l, addr1);
> -                /* XXX: could force cpu_single_env to NULL to avoid
> +                /* XXX: could force cpu_single_cpu to NULL to avoid
>                     potential bugs */
>                  if (l == 4) {
>                      /* 32 bit write access */
> diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
> index 207dcad..f0b1f6f 100644
> --- a/hw/alpha/typhoon.c
> +++ b/hw/alpha/typhoon.c
> @@ -72,9 +72,8 @@ static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
>
>  static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
>  {
> -    CPUAlphaState *env = cpu_single_env;
> +    CPUState *cpu = cpu_single_cpu;
>      TyphoonState *s = opaque;
> -    CPUState *cpu;
>      uint64_t ret = 0;
>
>      if (addr & 4) {
> @@ -95,7 +94,6 @@ static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
>
>      case 0x0080:
>          /* MISC: Miscellaneous Register.  */
> -        cpu = ENV_GET_CPU(env);
>          ret = s->cchip.misc | (cpu->cpu_index & 3);
>          break;
>
> @@ -197,8 +195,7 @@ static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
>          break;
>
>      default:
> -        cpu = CPU(alpha_env_get_cpu(cpu_single_env));
> -        cpu_unassigned_access(cpu, addr, false, false, 0, size);
> +        cpu_unassigned_access(cpu_single_cpu, addr, false, false, 0, size);
>          return -1;
>      }
>
> @@ -215,7 +212,6 @@ static uint64_t dchip_read(void *opaque, hwaddr addr, unsigned size)
>  static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size)
>  {
>      TyphoonState *s = opaque;
> -    CPUState *cs;
>      uint64_t ret = 0;
>
>      if (addr & 4) {
> @@ -302,8 +298,7 @@ static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size)
>          break;
>
>      default:
> -        cs = CPU(alpha_env_get_cpu(cpu_single_env));
> -        cpu_unassigned_access(cs, addr, false, false, 0, size);
> +        cpu_unassigned_access(cpu_single_cpu, addr, false, false, 0, size);
>          return -1;
>      }
>
> @@ -315,7 +310,6 @@ static void cchip_write(void *opaque, hwaddr addr,
>                          uint64_t v32, unsigned size)
>  {
>      TyphoonState *s = opaque;
> -    CPUState *cpu_single_cpu = CPU(alpha_env_get_cpu(cpu_single_env));
>      uint64_t val, oldval, newval;
>
>      if (addr & 4) {
> @@ -480,7 +474,6 @@ static void pchip_write(void *opaque, hwaddr addr,
>                          uint64_t v32, unsigned size)
>  {
>      TyphoonState *s = opaque;
> -    CPUState *cs;
>      uint64_t val, oldval;
>
>      if (addr & 4) {
> @@ -582,8 +575,7 @@ static void pchip_write(void *opaque, hwaddr addr,
>          break;
>
>      default:
> -        cs = CPU(alpha_env_get_cpu(cpu_single_env));
> -        cpu_unassigned_access(cs, addr, true, false, 0, size);
> +        cpu_unassigned_access(cpu_single_cpu, addr, true, false, 0, size);
>          return;
>      }
>  }
> diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
> index 24b03a0..d023167 100644
> --- a/hw/arm/pxa2xx.c
> +++ b/hw/arm/pxa2xx.c
> @@ -301,8 +301,7 @@ static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
>  #endif
>
>          /* Suspend */
> -        cpu_interrupt(CPU(arm_env_get_cpu(cpu_single_env)),
> -                      CPU_INTERRUPT_HALT);
> +        cpu_interrupt(cpu_single_cpu, CPU_INTERRUPT_HALT);
>
>          goto message;
>
> diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
> index f93629f..9aac9de 100644
> --- a/hw/i386/kvmvapic.c
> +++ b/hw/i386/kvmvapic.c
> @@ -623,11 +623,13 @@ static int vapic_prepare(VAPICROMState *s)
>  static void vapic_write(void *opaque, hwaddr addr, uint64_t data,
>                          unsigned int size)
>  {
> -    CPUX86State *env = cpu_single_env;
> +    CPUState *cs = cpu_single_cpu;
> +    X86CPU *cpu = X86_CPU(cs);
> +    CPUX86State *env = &cpu->env;
>      hwaddr rom_paddr;
>      VAPICROMState *s = opaque;
>
> -    cpu_synchronize_state(CPU(x86_env_get_cpu(env)));
> +    cpu_synchronize_state(cs);
>
>      /*
>       * The VAPIC supports two PIO-based hypercalls, both via port 0x7E.
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index d7e8507..c43be54 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -887,8 +887,9 @@ void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
>
>  DeviceState *cpu_get_current_apic(void)
>  {
> -    if (cpu_single_env) {
> -        return cpu_single_env->apic_state;
> +    if (cpu_single_cpu) {
> +        X86CPU *cpu = X86_CPU(cpu_single_cpu);
> +        return cpu->env.apic_state;
>      } else {
>          return NULL;
>      }
> @@ -1107,10 +1108,10 @@ DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
>
>  static void cpu_request_exit(void *opaque, int irq, int level)
>  {
> -    CPUX86State *env = cpu_single_env;
> +    CPUState *cpu = cpu_single_cpu;
>
> -    if (env && level) {
> -        cpu_exit(CPU(x86_env_get_cpu(env)));
> +    if (cpu && level) {
> +        cpu_exit(cpu);
>      }
>  }
>
> diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
> index bae6572..79fd4a9 100644
> --- a/hw/intc/arm_gic.c
> +++ b/hw/intc/arm_gic.c
> @@ -39,8 +39,7 @@ static const uint8_t gic_id[] = {
>  static inline int gic_get_current_cpu(GICState *s)
>  {
>      if (s->num_cpu > 1) {
> -        CPUState *cpu = ENV_GET_CPU(cpu_single_env);
> -        return cpu->cpu_index;
> +        return cpu_single_cpu->cpu_index;
>      }
>      return 0;
>  }
> diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
> index 25fa43c..53576c8 100644
> --- a/hw/intc/armv7m_nvic.c
> +++ b/hw/intc/armv7m_nvic.c
> @@ -140,6 +140,7 @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
>
>  static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
>  {
> +    ARMCPU *cpu;
>      uint32_t val;
>      int irq;
>
> @@ -171,7 +172,8 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
>      case 0x1c: /* SysTick Calibration Value.  */
>          return 10000;
>      case 0xd00: /* CPUID Base.  */
> -        return cpu_single_env->cp15.c0_cpuid;
> +        cpu = ARM_CPU(cpu_single_cpu);
> +        return cpu->env.cp15.c0_cpuid;
>      case 0xd04: /* Interrupt Control State.  */
>          /* VECTACTIVE */
>          val = s->gic.running_irq[0];
> @@ -206,7 +208,8 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
>              val |= (1 << 31);
>          return val;
>      case 0xd08: /* Vector Table Offset.  */
> -        return cpu_single_env->v7m.vecbase;
> +        cpu = ARM_CPU(cpu_single_cpu);
> +        return cpu->env.v7m.vecbase;
>      case 0xd0c: /* Application Interrupt/Reset Control.  */
>          return 0xfa05000;
>      case 0xd10: /* System Control.  */
> @@ -279,6 +282,7 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
>
>  static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
>  {
> +    ARMCPU *cpu;
>      uint32_t oldval;
>      switch (offset) {
>      case 0x10: /* SysTick Control and Status.  */
> @@ -331,7 +335,8 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
>          }
>          break;
>      case 0xd08: /* Vector Table Offset.  */
> -        cpu_single_env->v7m.vecbase = value & 0xffffff80;
> +        cpu = ARM_CPU(cpu_single_cpu);
> +        cpu->env.v7m.vecbase = value & 0xffffff80;
>          break;
>      case 0xd0c: /* Application Interrupt/Reset Control.  */
>          if ((value >> 16) == 0x05fa) {
> diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
> index c788714..6f152e0 100644
> --- a/hw/intc/openpic.c
> +++ b/hw/intc/openpic.c
> @@ -184,13 +184,10 @@ static int output_to_inttgt(int output)
>
>  static int get_current_cpu(void)
>  {
> -    CPUState *cpu_single_cpu;
> -
> -    if (!cpu_single_env) {
> +    if (!cpu_single_cpu) {
>          return -1;
>      }
>
> -    cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
>      return cpu_single_cpu->cpu_index;
>  }
>
> diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c
> index 00c9071..59ee1b4 100644
> --- a/hw/mips/mips_fulong2e.c
> +++ b/hw/mips/mips_fulong2e.c
> @@ -250,10 +250,10 @@ static void network_init (void)
>
>  static void cpu_request_exit(void *opaque, int irq, int level)
>  {
> -    CPUMIPSState *env = cpu_single_env;
> +    CPUState *cpu = cpu_single_cpu;
>
> -    if (env && level) {
> -        cpu_exit(CPU(mips_env_get_cpu(env)));
> +    if (cpu && level) {
> +        cpu_exit(cpu);
>      }
>  }
>
> diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
> index 2ad0c0b..2ffae59 100644
> --- a/hw/mips/mips_jazz.c
> +++ b/hw/mips/mips_jazz.c
> @@ -99,10 +99,10 @@ static const MemoryRegionOps dma_dummy_ops = {
>
>  static void cpu_request_exit(void *opaque, int irq, int level)
>  {
> -    CPUMIPSState *env = cpu_single_env;
> +    CPUState *cpu = cpu_single_cpu;
>
> -    if (env && level) {
> -        cpu_exit(CPU(mips_env_get_cpu(env)));
> +    if (cpu && level) {
> +        cpu_exit(cpu);
>      }
>  }
>
> diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
> index 8a4459d..4fc611c 100644
> --- a/hw/mips/mips_malta.c
> +++ b/hw/mips/mips_malta.c
> @@ -770,10 +770,10 @@ static void main_cpu_reset(void *opaque)
>
>  static void cpu_request_exit(void *opaque, int irq, int level)
>  {
> -    CPUMIPSState *env = cpu_single_env;
> +    CPUState *cpu = cpu_single_cpu;
>
> -    if (env && level) {
> -        cpu_exit(CPU(mips_env_get_cpu(env)));
> +    if (cpu && level) {
> +        cpu_exit(cpu);
>      }
>  }
>
> diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
> index 8363dfd..deb2232 100644
> --- a/hw/misc/vmport.c
> +++ b/hw/misc/vmport.c
> @@ -62,11 +62,13 @@ static uint64_t vmport_ioport_read(void *opaque, hwaddr addr,
>                                     unsigned size)
>  {
>      VMPortState *s = opaque;
> -    CPUX86State *env = cpu_single_env;
> +    CPUState *cs = cpu_single_cpu;
> +    X86CPU *cpu = X86_CPU(cs);
> +    CPUX86State *env = &cpu->env;
>      unsigned char command;
>      uint32_t eax;
>
> -    cpu_synchronize_state(CPU(x86_env_get_cpu(env)));
> +    cpu_synchronize_state(cs);
>
>      eax = env->regs[R_EAX];
>      if (eax != VMPORT_MAGIC)
> @@ -89,29 +91,32 @@ static uint64_t vmport_ioport_read(void *opaque, hwaddr addr,
>  static void vmport_ioport_write(void *opaque, hwaddr addr,
>                                  uint64_t val, unsigned size)
>  {
> -    CPUX86State *env = cpu_single_env;
> +    X86CPU *cpu = X86_CPU(cpu_single_cpu);
>
> -    env->regs[R_EAX] = vmport_ioport_read(opaque, addr, 4);
> +    cpu->env.regs[R_EAX] = vmport_ioport_read(opaque, addr, 4);
>  }
>
>  static uint32_t vmport_cmd_get_version(void *opaque, uint32_t addr)
>  {
> -    CPUX86State *env = cpu_single_env;
> -    env->regs[R_EBX] = VMPORT_MAGIC;
> +    X86CPU *cpu = X86_CPU(cpu_single_cpu);
> +
> +    cpu->env.regs[R_EBX] = VMPORT_MAGIC;
>      return 6;
>  }
>
>  static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr)
>  {
> -    CPUX86State *env = cpu_single_env;
> -    env->regs[R_EBX] = 0x1177;
> +    X86CPU *cpu = X86_CPU(cpu_single_cpu);
> +
> +    cpu->env.regs[R_EBX] = 0x1177;
>      return ram_size;
>  }
>
>  /* vmmouse helpers */
>  void vmmouse_get_data(uint32_t *data)
>  {
> -    CPUX86State *env = cpu_single_env;
> +    X86CPU *cpu = X86_CPU(cpu_single_cpu);
> +    CPUX86State *env = &cpu->env;
>
>      data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX];
>      data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX];
> @@ -120,7 +125,8 @@ void vmmouse_get_data(uint32_t *data)
>
>  void vmmouse_set_data(const uint32_t *data)
>  {
> -    CPUX86State *env = cpu_single_env;
> +    X86CPU *cpu = X86_CPU(cpu_single_cpu);
> +    CPUX86State *env = &cpu->env;
>
>      env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1];
>      env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3];
> diff --git a/hw/ppc/mpc8544_guts.c b/hw/ppc/mpc8544_guts.c
> index 193beab..89f950f 100644
> --- a/hw/ppc/mpc8544_guts.c
> +++ b/hw/ppc/mpc8544_guts.c
> @@ -62,7 +62,8 @@ static uint64_t mpc8544_guts_read(void *opaque, hwaddr addr,
>                                    unsigned size)
>  {
>      uint32_t value = 0;
> -    CPUPPCState *env = cpu_single_env;
> +    PowerPCCPU *cpu = POWERPC_CPU(cpu_single_cpu);
> +    CPUPPCState *env = &cpu->env;
>
>      addr &= MPC8544_GUTS_MMIO_SIZE - 1;
>      switch (addr) {
> diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
> index 90828f2..16e3132 100644
> --- a/hw/ppc/prep.c
> +++ b/hw/ppc/prep.c
> @@ -417,10 +417,10 @@ static const MemoryRegionOps PPC_prep_io_ops = {
>
>  static void cpu_request_exit(void *opaque, int irq, int level)
>  {
> -    CPUPPCState *env = cpu_single_env;
> +    CPUState *cpu = cpu_single_cpu;
>
> -    if (env && level) {
> -        cpu_exit(CPU(ppc_env_get_cpu(env)));
> +    if (cpu && level) {
> +        cpu_exit(cpu);
>      }
>  }
>
> diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
> index 0e86ca7..1273533 100644
> --- a/hw/sparc/sun4m.c
> +++ b/hw/sparc/sun4m.c
> @@ -264,9 +264,8 @@ static void secondary_cpu_reset(void *opaque)
>
>  static void cpu_halt_signal(void *opaque, int irq, int level)
>  {
> -    if (level && cpu_single_env) {
> -        cpu_interrupt(CPU(sparc_env_get_cpu(cpu_single_env)),
> -                      CPU_INTERRUPT_HALT);
> +    if (level && cpu_single_cpu) {
> +        cpu_interrupt(cpu_single_cpu, CPU_INTERRUPT_HALT);
>      }
>  }
>
> diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
> index 317f5e4..1aa300b 100644
> --- a/hw/timer/arm_mptimer.c
> +++ b/hw/timer/arm_mptimer.c
> @@ -49,8 +49,6 @@ typedef struct {
>
>  static inline int get_current_cpu(ARMMPTimerState *s)
>  {
> -    CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
> -
>      if (cpu_single_cpu->cpu_index >= s->num_cpu) {
>          hw_error("arm_mptimer: num-cpu %d but this cpu is %d!\n",
>                   s->num_cpu, cpu_single_cpu->cpu_index);
> diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
> index 35bdf85..6760851 100644
> --- a/include/exec/cpu-all.h
> +++ b/include/exec/cpu-all.h
> @@ -20,7 +20,6 @@
>  #define CPU_ALL_H
>
>  #include "qemu-common.h"
> -#include "qemu/tls.h"
>  #include "exec/cpu-common.h"
>  #include "qemu/thread.h"
>
> @@ -358,8 +357,6 @@ CPUArchState *cpu_copy(CPUArchState *env);
>  void QEMU_NORETURN cpu_abort(CPUArchState *env, const char *fmt, ...)
>      GCC_FMT_ATTR(2, 3);
>  extern CPUArchState *first_cpu;
> -DECLARE_TLS(CPUArchState *,cpu_single_env);
> -#define cpu_single_env tls_var(cpu_single_env)
>
>  /* Flags for use in ENV->INTERRUPT_PENDING.
>
> diff --git a/include/qom/cpu.h b/include/qom/cpu.h
> index 7afc442..0e2e76c 100644
> --- a/include/qom/cpu.h
> +++ b/include/qom/cpu.h
> @@ -24,6 +24,7 @@
>  #include "hw/qdev-core.h"
>  #include "exec/hwaddr.h"
>  #include "qemu/thread.h"
> +#include "qemu/tls.h"
>  #include "qemu/typedefs.h"
>
>  typedef int (*WriteCoreDumpFunction)(void *buf, size_t size, void *opaque);
> @@ -156,6 +157,9 @@ struct CPUState {
>      uint32_t halted; /* used by alpha, cris, ppc TCG */
>  };
>
> +DECLARE_TLS(CPUState *, cpu_single_cpu);
> +#define cpu_single_cpu tls_var(cpu_single_cpu)
> +
>  /**
>   * cpu_paging_enabled:
>   * @cpu: The CPU whose state is to be inspected.
> diff --git a/memory.c b/memory.c
> index 3bc98ad..f960bd0 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -857,9 +857,8 @@ static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
>  #ifdef DEBUG_UNASSIGNED
>      printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
>  #endif
> -    if (cpu_single_env != NULL) {
> -        cpu_unassigned_access(ENV_GET_CPU(cpu_single_env),
> -                              addr, false, false, 0, size);
> +    if (cpu_single_cpu != NULL) {
> +        cpu_unassigned_access(cpu_single_cpu, addr, false, false, 0, size);
>      }
>      return 0;
>  }
> @@ -870,9 +869,8 @@ static void unassigned_mem_write(void *opaque, hwaddr addr,
>  #ifdef DEBUG_UNASSIGNED
>      printf("Unassigned mem write " TARGET_FMT_plx " = 0x%"PRIx64"\n", addr, val);
>  #endif
> -    if (cpu_single_env != NULL) {
> -        cpu_unassigned_access(ENV_GET_CPU(cpu_single_env),
> -                              addr, true, false, 0, size);
> +    if (cpu_single_cpu != NULL) {
> +        cpu_unassigned_access(cpu_single_cpu, addr, true, false, 0, size);
>      }
>  }
>
> diff --git a/translate-all.c b/translate-all.c
> index df7c697..4177293 100644
> --- a/translate-all.c
> +++ b/translate-all.c
> @@ -999,8 +999,10 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
>                                     int is_cpu_write_access)
>  {
>      TranslationBlock *tb, *tb_next, *saved_tb;
> -    CPUArchState *env = cpu_single_env;
> -    CPUState *cpu = NULL;
> +    CPUState *cpu = cpu_single_cpu;
> +#if defined(TARGET_HAS_PRECISE_SMC) || !defined(CONFIG_USER_ONLY)
> +    CPUArchState *env = NULL;
> +#endif
>      tb_page_addr_t tb_start, tb_end;
>      PageDesc *p;
>      int n;
> @@ -1023,9 +1025,11 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
>          /* build code bitmap */
>          build_page_bitmap(p);
>      }
> -    if (env != NULL) {
> -        cpu = ENV_GET_CPU(env);
> +#if defined(TARGET_HAS_PRECISE_SMC) || !defined(CONFIG_USER_ONLY)
> +    if (cpu != NULL) {
> +        env = cpu->env_ptr;
>      }
> +#endif
>
>      /* we remove all the TBs in the range [start, end[ */
>      /* XXX: see if in some cases it could be faster to invalidate all
> @@ -1147,8 +1151,8 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr,
>      int n;
>  #ifdef TARGET_HAS_PRECISE_SMC
>      TranslationBlock *current_tb = NULL;
> -    CPUArchState *env = cpu_single_env;
> -    CPUState *cpu = NULL;
> +    CPUState *cpu = cpu_single_cpu;
> +    CPUArchState *env = NULL;
>      int current_tb_modified = 0;
>      target_ulong current_pc = 0;
>      target_ulong current_cs_base = 0;
> @@ -1165,8 +1169,8 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr,
>      if (tb && pc != 0) {
>          current_tb = tb_find_pc(pc);
>      }
> -    if (env != NULL) {
> -        cpu = ENV_GET_CPU(env);
> +    if (cpu != NULL) {
> +        env = cpu->env_ptr;
>      }
>  #endif
>      while (tb != NULL) {
> diff --git a/user-exec.c b/user-exec.c
> index fa7f1f1..aebdf1e 100644
> --- a/user-exec.c
> +++ b/user-exec.c
> @@ -81,6 +81,7 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
>                                      int is_write, sigset_t *old_set,
>                                      void *puc)
>  {
> +    CPUArchState *env;
>      int ret;
>
>  #if defined(DEBUG_SIGNAL)
> @@ -93,9 +94,9 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
>          return 1;
>      }
>
> +    env = cpu_single_cpu->env_ptr;
>      /* see if it is an MMU fault */
> -    ret = cpu_handle_mmu_fault(cpu_single_env, address, is_write,
> -                               MMU_USER_IDX);
> +    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX);
>      if (ret < 0) {
>          return 0; /* not an MMU fault */
>      }
> @@ -103,12 +104,12 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
>          return 1; /* the MMU fault was handled without causing real CPU fault */
>      }
>      /* now we have a real cpu fault */
> -    cpu_restore_state(cpu_single_env, pc);
> +    cpu_restore_state(env, pc);
>
>      /* we restore the process signal mask as the sigreturn should
>         do it (XXX: use sigsetjmp) */
>      sigprocmask(SIG_SETMASK, old_set, NULL);
> -    exception_action(cpu_single_env);
> +    exception_action(env);
>
>      /* never comes here */
>      return 1;
> --
> 1.8.1.4
>
Richard Henderson - June 17, 2013, 8:40 p.m.
On 06/16/2013 08:57 AM, Andreas Färber wrote:
> diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
> index 207dcad..f0b1f6f 100644
> --- a/hw/alpha/typhoon.c
> +++ b/hw/alpha/typhoon.c
> @@ -72,9 +72,8 @@ static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
>  
>  static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
>  {
> -    CPUAlphaState *env = cpu_single_env;
> +    CPUState *cpu = cpu_single_cpu;
>      TyphoonState *s = opaque;
> -    CPUState *cpu;
>      uint64_t ret = 0;
>  
>      if (addr & 4) {
> @@ -95,7 +94,6 @@ static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
>  
>      case 0x0080:
>          /* MISC: Miscellaneous Register.  */
> -        cpu = ENV_GET_CPU(env);
>          ret = s->cchip.misc | (cpu->cpu_index & 3);
>          break;
>  
> @@ -197,8 +195,7 @@ static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
>          break;
>  
>      default:
> -        cpu = CPU(alpha_env_get_cpu(cpu_single_env));
> -        cpu_unassigned_access(cpu, addr, false, false, 0, size);
> +        cpu_unassigned_access(cpu_single_cpu, addr, false, false, 0, size);

Keep using the local "cpu" variable?


r~
Andreas Färber - June 18, 2013, 4:52 p.m.
Am 16.06.2013 22:49, schrieb Blue Swirl:
> On Sun, Jun 16, 2013 at 3:57 PM, Andreas Färber <afaerber@suse.de> wrote:
>> Move it to qom/cpu.h.
> 
> While renaming, perhaps a more descriptive name could be used instead
> of 'cpu_single_cpu', something like cpu_loop_current_cpu?

There were some local variables named cpu_single_cpu (blame me :)) that
this way simply fall away, but I can certainly rename it, adding just a
few lines to the patch.

However, cpu_loop_current_cpu seems to codify that we have a sequential
loop of vCPUs, which Xen and IIUC KVM do not have and occasionally
people have looked into changing for TCG.

current_cpu is already used in a few places:

include/sysemu/kvm.h:int kvm_arch_insert_sw_breakpoint(CPUState
*current_cpu,
include/sysemu/kvm.h:int kvm_arch_remove_sw_breakpoint(CPUState
*current_cpu,
kvm-all.c:    CPUState *current_cpu = ENV_GET_CPU(current_env);
kvm-all.c:        bp = kvm_find_sw_breakpoint(current_cpu, addr);
kvm-all.c:        err = kvm_arch_insert_sw_breakpoint(current_cpu, bp);
kvm-all.c:
QTAILQ_INSERT_HEAD(&current_cpu->kvm_state->kvm_sw_breakpoints,
kvm-all.c:    CPUState *current_cpu = ENV_GET_CPU(current_env);
kvm-all.c:        bp = kvm_find_sw_breakpoint(current_cpu, addr);
kvm-all.c:        err = kvm_arch_remove_sw_breakpoint(current_cpu, bp);
kvm-all.c:
QTAILQ_REMOVE(&current_cpu->kvm_state->kvm_sw_breakpoints, bp, entry);
kvm-all.c:    CPUState *current_cpu = ENV_GET_CPU(current_env);
kvm-all.c:    KVMState *s = current_cpu->kvm_state;
kvm-all.c:        if (kvm_arch_remove_sw_breakpoint(current_cpu, bp) != 0) {

but we could probably ignore these variable shadowings.

Andreas
Paolo Bonzini - June 19, 2013, 12:59 p.m.
Il 18/06/2013 18:52, Andreas Färber ha scritto:
> Am 16.06.2013 22:49, schrieb Blue Swirl:
>> On Sun, Jun 16, 2013 at 3:57 PM, Andreas Färber <afaerber@suse.de> wrote:
>>> Move it to qom/cpu.h.
>>
>> While renaming, perhaps a more descriptive name could be used instead
>> of 'cpu_single_cpu', something like cpu_loop_current_cpu?
> 
> There were some local variables named cpu_single_cpu (blame me :)) that
> this way simply fall away, but I can certainly rename it, adding just a
> few lines to the patch.
> 
> However, cpu_loop_current_cpu seems to codify that we have a sequential
> loop of vCPUs, which Xen and IIUC KVM do not have and occasionally
> people have looked into changing for TCG.
> 
> current_cpu is already used in a few places:
> 
> include/sysemu/kvm.h:int kvm_arch_insert_sw_breakpoint(CPUState
> *current_cpu,
> include/sysemu/kvm.h:int kvm_arch_remove_sw_breakpoint(CPUState
> *current_cpu,
> kvm-all.c:    CPUState *current_cpu = ENV_GET_CPU(current_env);
> kvm-all.c:        bp = kvm_find_sw_breakpoint(current_cpu, addr);
> kvm-all.c:        err = kvm_arch_insert_sw_breakpoint(current_cpu, bp);
> kvm-all.c:
> QTAILQ_INSERT_HEAD(&current_cpu->kvm_state->kvm_sw_breakpoints,
> kvm-all.c:    CPUState *current_cpu = ENV_GET_CPU(current_env);
> kvm-all.c:        bp = kvm_find_sw_breakpoint(current_cpu, addr);
> kvm-all.c:        err = kvm_arch_remove_sw_breakpoint(current_cpu, bp);
> kvm-all.c:
> QTAILQ_REMOVE(&current_cpu->kvm_state->kvm_sw_breakpoints, bp, entry);
> kvm-all.c:    CPUState *current_cpu = ENV_GET_CPU(current_env);
> kvm-all.c:    KVMState *s = current_cpu->kvm_state;
> kvm-all.c:        if (kvm_arch_remove_sw_breakpoint(current_cpu, bp) != 0) {
> 
> but we could probably ignore these variable shadowings.

Renaming those to just "cpu" and "env" is pre-acked.

Paolo
Andreas Färber - June 21, 2013, 10:32 a.m.
Am 17.06.2013 22:40, schrieb Richard Henderson:
> On 06/16/2013 08:57 AM, Andreas Färber wrote:
>> diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
>> index 207dcad..f0b1f6f 100644
>> --- a/hw/alpha/typhoon.c
>> +++ b/hw/alpha/typhoon.c
>> @@ -72,9 +72,8 @@ static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
>>  
>>  static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
>>  {
>> -    CPUAlphaState *env = cpu_single_env;
>> +    CPUState *cpu = cpu_single_cpu;
>>      TyphoonState *s = opaque;
>> -    CPUState *cpu;
>>      uint64_t ret = 0;
>>  
>>      if (addr & 4) {
>> @@ -95,7 +94,6 @@ static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
>>  
>>      case 0x0080:
>>          /* MISC: Miscellaneous Register.  */
>> -        cpu = ENV_GET_CPU(env);
>>          ret = s->cchip.misc | (cpu->cpu_index & 3);
>>          break;
>>  
>> @@ -197,8 +195,7 @@ static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
>>          break;
>>  
>>      default:
>> -        cpu = CPU(alpha_env_get_cpu(cpu_single_env));
>> -        cpu_unassigned_access(cpu, addr, false, false, 0, size);
>> +        cpu_unassigned_access(cpu_single_cpu, addr, false, false, 0, size);
> 
> Keep using the local "cpu" variable?

Fixed, thanks.

Andreas
Paolo Bonzini - July 15, 2013, 2:56 p.m.
Il 16/06/2013 17:57, Andreas Färber ha scritto:
> Move it to qom/cpu.h.

Hmm, why move it to qom/cpu.h?  Isn't it an implementation detail that
there is a current CPU?

Paolo

> Signed-off-by: Andreas Färber <afaerber@suse.de>
> ---
>  cpu-exec.c              | 13 +++++++------
>  cpus.c                  | 29 ++++++++++++++---------------
>  exec.c                  | 12 +++++++-----
>  hw/alpha/typhoon.c      | 16 ++++------------
>  hw/arm/pxa2xx.c         |  3 +--
>  hw/i386/kvmvapic.c      |  6 ++++--
>  hw/i386/pc.c            | 11 ++++++-----
>  hw/intc/arm_gic.c       |  3 +--
>  hw/intc/armv7m_nvic.c   | 11 ++++++++---
>  hw/intc/openpic.c       |  5 +----
>  hw/mips/mips_fulong2e.c |  6 +++---
>  hw/mips/mips_jazz.c     |  6 +++---
>  hw/mips/mips_malta.c    |  6 +++---
>  hw/misc/vmport.c        | 26 ++++++++++++++++----------
>  hw/ppc/mpc8544_guts.c   |  3 ++-
>  hw/ppc/prep.c           |  6 +++---
>  hw/sparc/sun4m.c        |  5 ++---
>  hw/timer/arm_mptimer.c  |  2 --
>  include/exec/cpu-all.h  |  3 ---
>  include/qom/cpu.h       |  4 ++++
>  memory.c                | 10 ++++------
>  translate-all.c         | 20 ++++++++++++--------
>  user-exec.c             |  9 +++++----
>  23 files changed, 110 insertions(+), 105 deletions(-)
> 
> diff --git a/cpu-exec.c b/cpu-exec.c
> index ec46380..1858c2e 100644
> --- a/cpu-exec.c
> +++ b/cpu-exec.c
> @@ -213,12 +213,12 @@ int cpu_exec(CPUArchState *env)
>          cpu->halted = 0;
>      }
>  
> -    cpu_single_env = env;
> +    cpu_single_cpu = cpu;
>  
> -    /* As long as cpu_single_env is null, up to the assignment just above,
> +    /* As long as cpu_single_cpu is null, up to the assignment just above,
>       * requests by other threads to exit the execution loop are expected to
>       * be issued using the exit_request global. We must make sure that our
> -     * evaluation of the global value is performed past the cpu_single_env
> +     * evaluation of the global value is performed past the cpu_single_cpu
>       * value transition point, which requires a memory barrier as well as
>       * an instruction scheduling constraint on modern architectures.  */
>      smp_mb();
> @@ -673,7 +673,8 @@ int cpu_exec(CPUArchState *env)
>          } else {
>              /* Reload env after longjmp - the compiler may have smashed all
>               * local variables as longjmp is marked 'noreturn'. */
> -            env = cpu_single_env;
> +            cpu = cpu_single_cpu;
> +            env = cpu->env_ptr;
>          }
>      } /* for(;;) */
>  
> @@ -707,7 +708,7 @@ int cpu_exec(CPUArchState *env)
>  #error unsupported target CPU
>  #endif
>  
> -    /* fail safe : never use cpu_single_env outside cpu_exec() */
> -    cpu_single_env = NULL;
> +    /* fail safe : never use cpu_single_cpu outside cpu_exec() */
> +    cpu_single_cpu = NULL;
>      return ret;
>  }
> diff --git a/cpus.c b/cpus.c
> index 775d998..808503b 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -118,10 +118,11 @@ TimersState timers_state;
>  int64_t cpu_get_icount(void)
>  {
>      int64_t icount;
> -    CPUArchState *env = cpu_single_env;
> +    CPUState *cpu = cpu_single_cpu;
>  
>      icount = qemu_icount;
> -    if (env) {
> +    if (cpu) {
> +        CPUArchState *env = cpu->env_ptr;
>          if (!can_do_io(env)) {
>              fprintf(stderr, "Bad clock read\n");
>          }
> @@ -468,8 +469,8 @@ static void cpu_handle_guest_debug(CPUState *cpu)
>  
>  static void cpu_signal(int sig)
>  {
> -    if (cpu_single_env) {
> -        cpu_exit(ENV_GET_CPU(cpu_single_env));
> +    if (cpu_single_cpu) {
> +        cpu_exit(cpu_single_cpu);
>      }
>      exit_request = 1;
>  }
> @@ -660,10 +661,10 @@ void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data)
>  
>      qemu_cpu_kick(cpu);
>      while (!wi.done) {
> -        CPUArchState *self_env = cpu_single_env;
> +        CPUState *self_cpu = cpu_single_cpu;
>  
>          qemu_cond_wait(&qemu_work_cond, &qemu_global_mutex);
> -        cpu_single_env = self_env;
> +        cpu_single_cpu = self_cpu;
>      }
>  }
>  
> @@ -733,7 +734,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
>      qemu_mutex_lock(&qemu_global_mutex);
>      qemu_thread_get_self(cpu->thread);
>      cpu->thread_id = qemu_get_thread_id();
> -    cpu_single_env = cpu->env_ptr;
> +    cpu_single_cpu = cpu;
>  
>      r = kvm_init_vcpu(cpu);
>      if (r < 0) {
> @@ -781,9 +782,9 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
>      cpu->created = true;
>      qemu_cond_signal(&qemu_cpu_cond);
>  
> -    cpu_single_env = cpu->env_ptr;
> +    cpu_single_cpu = cpu;
>      while (1) {
> -        cpu_single_env = NULL;
> +        cpu_single_cpu = NULL;
>          qemu_mutex_unlock_iothread();
>          do {
>              int sig;
> @@ -794,7 +795,7 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
>              exit(1);
>          }
>          qemu_mutex_lock_iothread();
> -        cpu_single_env = cpu->env_ptr;
> +        cpu_single_cpu = cpu;
>          qemu_wait_io_event_common(cpu);
>      }
>  
> @@ -894,8 +895,7 @@ void qemu_cpu_kick(CPUState *cpu)
>  void qemu_cpu_kick_self(void)
>  {
>  #ifndef _WIN32
> -    assert(cpu_single_env);
> -    CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
> +    assert(cpu_single_cpu);
>  
>      if (!cpu_single_cpu->thread_kicked) {
>          qemu_cpu_kick_thread(cpu_single_cpu);
> @@ -913,7 +913,7 @@ bool qemu_cpu_is_self(CPUState *cpu)
>  
>  static bool qemu_in_vcpu_thread(void)
>  {
> -    return cpu_single_env && qemu_cpu_is_self(ENV_GET_CPU(cpu_single_env));
> +    return cpu_single_cpu && qemu_cpu_is_self(cpu_single_cpu);
>  }
>  
>  void qemu_mutex_lock_iothread(void)
> @@ -1069,8 +1069,7 @@ void qemu_init_vcpu(CPUState *cpu)
>  
>  void cpu_stop_current(void)
>  {
> -    if (cpu_single_env) {
> -        CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
> +    if (cpu_single_cpu) {
>          cpu_single_cpu->stop = false;
>          cpu_single_cpu->stopped = true;
>          cpu_exit(cpu_single_cpu);
> diff --git a/exec.c b/exec.c
> index 2b99bb9..e14a815 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -73,7 +73,7 @@ static MemoryRegion io_mem_unassigned, io_mem_subpage_ram;
>  CPUArchState *first_cpu;
>  /* current CPU in the current thread. It is only valid inside
>     cpu_exec() */
> -DEFINE_TLS(CPUArchState *,cpu_single_env);
> +DEFINE_TLS(CPUState *,cpu_single_cpu);
>  /* 0 = Do not count executed instructions.
>     1 = Precise instruction counting.
>     2 = Adaptive rate instruction counting.  */
> @@ -1420,8 +1420,10 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
>      cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
>      /* we remove the notdirty callback only if the code has been
>         flushed */
> -    if (dirty_flags == 0xff)
> -        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
> +    if (dirty_flags == 0xff) {
> +        CPUArchState *env = cpu_single_cpu->env_ptr;
> +        tlb_set_dirty(env, env->mem_io_vaddr);
> +    }
>  }
>  
>  static bool notdirty_mem_accepts(void *opaque, hwaddr addr,
> @@ -1439,7 +1441,7 @@ static const MemoryRegionOps notdirty_mem_ops = {
>  /* Generate a debug exception if a watchpoint has been hit.  */
>  static void check_watchpoint(int offset, int len_mask, int flags)
>  {
> -    CPUArchState *env = cpu_single_env;
> +    CPUArchState *env = cpu_single_cpu->env_ptr;
>      target_ulong pc, cs_base;
>      target_ulong vaddr;
>      CPUWatchpoint *wp;
> @@ -1912,7 +1914,7 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>          if (is_write) {
>              if (!memory_access_is_direct(section->mr, is_write)) {
>                  l = memory_access_size(l, addr1);
> -                /* XXX: could force cpu_single_env to NULL to avoid
> +                /* XXX: could force cpu_single_cpu to NULL to avoid
>                     potential bugs */
>                  if (l == 4) {
>                      /* 32 bit write access */
> diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
> index 207dcad..f0b1f6f 100644
> --- a/hw/alpha/typhoon.c
> +++ b/hw/alpha/typhoon.c
> @@ -72,9 +72,8 @@ static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
>  
>  static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
>  {
> -    CPUAlphaState *env = cpu_single_env;
> +    CPUState *cpu = cpu_single_cpu;
>      TyphoonState *s = opaque;
> -    CPUState *cpu;
>      uint64_t ret = 0;
>  
>      if (addr & 4) {
> @@ -95,7 +94,6 @@ static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
>  
>      case 0x0080:
>          /* MISC: Miscellaneous Register.  */
> -        cpu = ENV_GET_CPU(env);
>          ret = s->cchip.misc | (cpu->cpu_index & 3);
>          break;
>  
> @@ -197,8 +195,7 @@ static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
>          break;
>  
>      default:
> -        cpu = CPU(alpha_env_get_cpu(cpu_single_env));
> -        cpu_unassigned_access(cpu, addr, false, false, 0, size);
> +        cpu_unassigned_access(cpu_single_cpu, addr, false, false, 0, size);
>          return -1;
>      }
>  
> @@ -215,7 +212,6 @@ static uint64_t dchip_read(void *opaque, hwaddr addr, unsigned size)
>  static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size)
>  {
>      TyphoonState *s = opaque;
> -    CPUState *cs;
>      uint64_t ret = 0;
>  
>      if (addr & 4) {
> @@ -302,8 +298,7 @@ static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size)
>          break;
>  
>      default:
> -        cs = CPU(alpha_env_get_cpu(cpu_single_env));
> -        cpu_unassigned_access(cs, addr, false, false, 0, size);
> +        cpu_unassigned_access(cpu_single_cpu, addr, false, false, 0, size);
>          return -1;
>      }
>  
> @@ -315,7 +310,6 @@ static void cchip_write(void *opaque, hwaddr addr,
>                          uint64_t v32, unsigned size)
>  {
>      TyphoonState *s = opaque;
> -    CPUState *cpu_single_cpu = CPU(alpha_env_get_cpu(cpu_single_env));
>      uint64_t val, oldval, newval;
>  
>      if (addr & 4) {
> @@ -480,7 +474,6 @@ static void pchip_write(void *opaque, hwaddr addr,
>                          uint64_t v32, unsigned size)
>  {
>      TyphoonState *s = opaque;
> -    CPUState *cs;
>      uint64_t val, oldval;
>  
>      if (addr & 4) {
> @@ -582,8 +575,7 @@ static void pchip_write(void *opaque, hwaddr addr,
>          break;
>  
>      default:
> -        cs = CPU(alpha_env_get_cpu(cpu_single_env));
> -        cpu_unassigned_access(cs, addr, true, false, 0, size);
> +        cpu_unassigned_access(cpu_single_cpu, addr, true, false, 0, size);
>          return;
>      }
>  }
> diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
> index 24b03a0..d023167 100644
> --- a/hw/arm/pxa2xx.c
> +++ b/hw/arm/pxa2xx.c
> @@ -301,8 +301,7 @@ static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
>  #endif
>  
>          /* Suspend */
> -        cpu_interrupt(CPU(arm_env_get_cpu(cpu_single_env)),
> -                      CPU_INTERRUPT_HALT);
> +        cpu_interrupt(cpu_single_cpu, CPU_INTERRUPT_HALT);
>  
>          goto message;
>  
> diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
> index f93629f..9aac9de 100644
> --- a/hw/i386/kvmvapic.c
> +++ b/hw/i386/kvmvapic.c
> @@ -623,11 +623,13 @@ static int vapic_prepare(VAPICROMState *s)
>  static void vapic_write(void *opaque, hwaddr addr, uint64_t data,
>                          unsigned int size)
>  {
> -    CPUX86State *env = cpu_single_env;
> +    CPUState *cs = cpu_single_cpu;
> +    X86CPU *cpu = X86_CPU(cs);
> +    CPUX86State *env = &cpu->env;
>      hwaddr rom_paddr;
>      VAPICROMState *s = opaque;
>  
> -    cpu_synchronize_state(CPU(x86_env_get_cpu(env)));
> +    cpu_synchronize_state(cs);
>  
>      /*
>       * The VAPIC supports two PIO-based hypercalls, both via port 0x7E.
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index d7e8507..c43be54 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -887,8 +887,9 @@ void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
>  
>  DeviceState *cpu_get_current_apic(void)
>  {
> -    if (cpu_single_env) {
> -        return cpu_single_env->apic_state;
> +    if (cpu_single_cpu) {
> +        X86CPU *cpu = X86_CPU(cpu_single_cpu);
> +        return cpu->env.apic_state;
>      } else {
>          return NULL;
>      }
> @@ -1107,10 +1108,10 @@ DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
>  
>  static void cpu_request_exit(void *opaque, int irq, int level)
>  {
> -    CPUX86State *env = cpu_single_env;
> +    CPUState *cpu = cpu_single_cpu;
>  
> -    if (env && level) {
> -        cpu_exit(CPU(x86_env_get_cpu(env)));
> +    if (cpu && level) {
> +        cpu_exit(cpu);
>      }
>  }
>  
> diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
> index bae6572..79fd4a9 100644
> --- a/hw/intc/arm_gic.c
> +++ b/hw/intc/arm_gic.c
> @@ -39,8 +39,7 @@ static const uint8_t gic_id[] = {
>  static inline int gic_get_current_cpu(GICState *s)
>  {
>      if (s->num_cpu > 1) {
> -        CPUState *cpu = ENV_GET_CPU(cpu_single_env);
> -        return cpu->cpu_index;
> +        return cpu_single_cpu->cpu_index;
>      }
>      return 0;
>  }
> diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
> index 25fa43c..53576c8 100644
> --- a/hw/intc/armv7m_nvic.c
> +++ b/hw/intc/armv7m_nvic.c
> @@ -140,6 +140,7 @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
>  
>  static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
>  {
> +    ARMCPU *cpu;
>      uint32_t val;
>      int irq;
>  
> @@ -171,7 +172,8 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
>      case 0x1c: /* SysTick Calibration Value.  */
>          return 10000;
>      case 0xd00: /* CPUID Base.  */
> -        return cpu_single_env->cp15.c0_cpuid;
> +        cpu = ARM_CPU(cpu_single_cpu);
> +        return cpu->env.cp15.c0_cpuid;
>      case 0xd04: /* Interrupt Control State.  */
>          /* VECTACTIVE */
>          val = s->gic.running_irq[0];
> @@ -206,7 +208,8 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
>              val |= (1 << 31);
>          return val;
>      case 0xd08: /* Vector Table Offset.  */
> -        return cpu_single_env->v7m.vecbase;
> +        cpu = ARM_CPU(cpu_single_cpu);
> +        return cpu->env.v7m.vecbase;
>      case 0xd0c: /* Application Interrupt/Reset Control.  */
>          return 0xfa05000;
>      case 0xd10: /* System Control.  */
> @@ -279,6 +282,7 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
>  
>  static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
>  {
> +    ARMCPU *cpu;
>      uint32_t oldval;
>      switch (offset) {
>      case 0x10: /* SysTick Control and Status.  */
> @@ -331,7 +335,8 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
>          }
>          break;
>      case 0xd08: /* Vector Table Offset.  */
> -        cpu_single_env->v7m.vecbase = value & 0xffffff80;
> +        cpu = ARM_CPU(cpu_single_cpu);
> +        cpu->env.v7m.vecbase = value & 0xffffff80;
>          break;
>      case 0xd0c: /* Application Interrupt/Reset Control.  */
>          if ((value >> 16) == 0x05fa) {
> diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
> index c788714..6f152e0 100644
> --- a/hw/intc/openpic.c
> +++ b/hw/intc/openpic.c
> @@ -184,13 +184,10 @@ static int output_to_inttgt(int output)
>  
>  static int get_current_cpu(void)
>  {
> -    CPUState *cpu_single_cpu;
> -
> -    if (!cpu_single_env) {
> +    if (!cpu_single_cpu) {
>          return -1;
>      }
>  
> -    cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
>      return cpu_single_cpu->cpu_index;
>  }
>  
> diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c
> index 00c9071..59ee1b4 100644
> --- a/hw/mips/mips_fulong2e.c
> +++ b/hw/mips/mips_fulong2e.c
> @@ -250,10 +250,10 @@ static void network_init (void)
>  
>  static void cpu_request_exit(void *opaque, int irq, int level)
>  {
> -    CPUMIPSState *env = cpu_single_env;
> +    CPUState *cpu = cpu_single_cpu;
>  
> -    if (env && level) {
> -        cpu_exit(CPU(mips_env_get_cpu(env)));
> +    if (cpu && level) {
> +        cpu_exit(cpu);
>      }
>  }
>  
> diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
> index 2ad0c0b..2ffae59 100644
> --- a/hw/mips/mips_jazz.c
> +++ b/hw/mips/mips_jazz.c
> @@ -99,10 +99,10 @@ static const MemoryRegionOps dma_dummy_ops = {
>  
>  static void cpu_request_exit(void *opaque, int irq, int level)
>  {
> -    CPUMIPSState *env = cpu_single_env;
> +    CPUState *cpu = cpu_single_cpu;
>  
> -    if (env && level) {
> -        cpu_exit(CPU(mips_env_get_cpu(env)));
> +    if (cpu && level) {
> +        cpu_exit(cpu);
>      }
>  }
>  
> diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
> index 8a4459d..4fc611c 100644
> --- a/hw/mips/mips_malta.c
> +++ b/hw/mips/mips_malta.c
> @@ -770,10 +770,10 @@ static void main_cpu_reset(void *opaque)
>  
>  static void cpu_request_exit(void *opaque, int irq, int level)
>  {
> -    CPUMIPSState *env = cpu_single_env;
> +    CPUState *cpu = cpu_single_cpu;
>  
> -    if (env && level) {
> -        cpu_exit(CPU(mips_env_get_cpu(env)));
> +    if (cpu && level) {
> +        cpu_exit(cpu);
>      }
>  }
>  
> diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
> index 8363dfd..deb2232 100644
> --- a/hw/misc/vmport.c
> +++ b/hw/misc/vmport.c
> @@ -62,11 +62,13 @@ static uint64_t vmport_ioport_read(void *opaque, hwaddr addr,
>                                     unsigned size)
>  {
>      VMPortState *s = opaque;
> -    CPUX86State *env = cpu_single_env;
> +    CPUState *cs = cpu_single_cpu;
> +    X86CPU *cpu = X86_CPU(cs);
> +    CPUX86State *env = &cpu->env;
>      unsigned char command;
>      uint32_t eax;
>  
> -    cpu_synchronize_state(CPU(x86_env_get_cpu(env)));
> +    cpu_synchronize_state(cs);
>  
>      eax = env->regs[R_EAX];
>      if (eax != VMPORT_MAGIC)
> @@ -89,29 +91,32 @@ static uint64_t vmport_ioport_read(void *opaque, hwaddr addr,
>  static void vmport_ioport_write(void *opaque, hwaddr addr,
>                                  uint64_t val, unsigned size)
>  {
> -    CPUX86State *env = cpu_single_env;
> +    X86CPU *cpu = X86_CPU(cpu_single_cpu);
>  
> -    env->regs[R_EAX] = vmport_ioport_read(opaque, addr, 4);
> +    cpu->env.regs[R_EAX] = vmport_ioport_read(opaque, addr, 4);
>  }
>  
>  static uint32_t vmport_cmd_get_version(void *opaque, uint32_t addr)
>  {
> -    CPUX86State *env = cpu_single_env;
> -    env->regs[R_EBX] = VMPORT_MAGIC;
> +    X86CPU *cpu = X86_CPU(cpu_single_cpu);
> +
> +    cpu->env.regs[R_EBX] = VMPORT_MAGIC;
>      return 6;
>  }
>  
>  static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr)
>  {
> -    CPUX86State *env = cpu_single_env;
> -    env->regs[R_EBX] = 0x1177;
> +    X86CPU *cpu = X86_CPU(cpu_single_cpu);
> +
> +    cpu->env.regs[R_EBX] = 0x1177;
>      return ram_size;
>  }
>  
>  /* vmmouse helpers */
>  void vmmouse_get_data(uint32_t *data)
>  {
> -    CPUX86State *env = cpu_single_env;
> +    X86CPU *cpu = X86_CPU(cpu_single_cpu);
> +    CPUX86State *env = &cpu->env;
>  
>      data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX];
>      data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX];
> @@ -120,7 +125,8 @@ void vmmouse_get_data(uint32_t *data)
>  
>  void vmmouse_set_data(const uint32_t *data)
>  {
> -    CPUX86State *env = cpu_single_env;
> +    X86CPU *cpu = X86_CPU(cpu_single_cpu);
> +    CPUX86State *env = &cpu->env;
>  
>      env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1];
>      env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3];
> diff --git a/hw/ppc/mpc8544_guts.c b/hw/ppc/mpc8544_guts.c
> index 193beab..89f950f 100644
> --- a/hw/ppc/mpc8544_guts.c
> +++ b/hw/ppc/mpc8544_guts.c
> @@ -62,7 +62,8 @@ static uint64_t mpc8544_guts_read(void *opaque, hwaddr addr,
>                                    unsigned size)
>  {
>      uint32_t value = 0;
> -    CPUPPCState *env = cpu_single_env;
> +    PowerPCCPU *cpu = POWERPC_CPU(cpu_single_cpu);
> +    CPUPPCState *env = &cpu->env;
>  
>      addr &= MPC8544_GUTS_MMIO_SIZE - 1;
>      switch (addr) {
> diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
> index 90828f2..16e3132 100644
> --- a/hw/ppc/prep.c
> +++ b/hw/ppc/prep.c
> @@ -417,10 +417,10 @@ static const MemoryRegionOps PPC_prep_io_ops = {
>  
>  static void cpu_request_exit(void *opaque, int irq, int level)
>  {
> -    CPUPPCState *env = cpu_single_env;
> +    CPUState *cpu = cpu_single_cpu;
>  
> -    if (env && level) {
> -        cpu_exit(CPU(ppc_env_get_cpu(env)));
> +    if (cpu && level) {
> +        cpu_exit(cpu);
>      }
>  }
>  
> diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
> index 0e86ca7..1273533 100644
> --- a/hw/sparc/sun4m.c
> +++ b/hw/sparc/sun4m.c
> @@ -264,9 +264,8 @@ static void secondary_cpu_reset(void *opaque)
>  
>  static void cpu_halt_signal(void *opaque, int irq, int level)
>  {
> -    if (level && cpu_single_env) {
> -        cpu_interrupt(CPU(sparc_env_get_cpu(cpu_single_env)),
> -                      CPU_INTERRUPT_HALT);
> +    if (level && cpu_single_cpu) {
> +        cpu_interrupt(cpu_single_cpu, CPU_INTERRUPT_HALT);
>      }
>  }
>  
> diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
> index 317f5e4..1aa300b 100644
> --- a/hw/timer/arm_mptimer.c
> +++ b/hw/timer/arm_mptimer.c
> @@ -49,8 +49,6 @@ typedef struct {
>  
>  static inline int get_current_cpu(ARMMPTimerState *s)
>  {
> -    CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
> -
>      if (cpu_single_cpu->cpu_index >= s->num_cpu) {
>          hw_error("arm_mptimer: num-cpu %d but this cpu is %d!\n",
>                   s->num_cpu, cpu_single_cpu->cpu_index);
> diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
> index 35bdf85..6760851 100644
> --- a/include/exec/cpu-all.h
> +++ b/include/exec/cpu-all.h
> @@ -20,7 +20,6 @@
>  #define CPU_ALL_H
>  
>  #include "qemu-common.h"
> -#include "qemu/tls.h"
>  #include "exec/cpu-common.h"
>  #include "qemu/thread.h"
>  
> @@ -358,8 +357,6 @@ CPUArchState *cpu_copy(CPUArchState *env);
>  void QEMU_NORETURN cpu_abort(CPUArchState *env, const char *fmt, ...)
>      GCC_FMT_ATTR(2, 3);
>  extern CPUArchState *first_cpu;
> -DECLARE_TLS(CPUArchState *,cpu_single_env);
> -#define cpu_single_env tls_var(cpu_single_env)
>  
>  /* Flags for use in ENV->INTERRUPT_PENDING.
>  
> diff --git a/include/qom/cpu.h b/include/qom/cpu.h
> index 7afc442..0e2e76c 100644
> --- a/include/qom/cpu.h
> +++ b/include/qom/cpu.h
> @@ -24,6 +24,7 @@
>  #include "hw/qdev-core.h"
>  #include "exec/hwaddr.h"
>  #include "qemu/thread.h"
> +#include "qemu/tls.h"
>  #include "qemu/typedefs.h"
>  
>  typedef int (*WriteCoreDumpFunction)(void *buf, size_t size, void *opaque);
> @@ -156,6 +157,9 @@ struct CPUState {
>      uint32_t halted; /* used by alpha, cris, ppc TCG */
>  };
>  
> +DECLARE_TLS(CPUState *, cpu_single_cpu);
> +#define cpu_single_cpu tls_var(cpu_single_cpu)
> +
>  /**
>   * cpu_paging_enabled:
>   * @cpu: The CPU whose state is to be inspected.
> diff --git a/memory.c b/memory.c
> index 3bc98ad..f960bd0 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -857,9 +857,8 @@ static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
>  #ifdef DEBUG_UNASSIGNED
>      printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
>  #endif
> -    if (cpu_single_env != NULL) {
> -        cpu_unassigned_access(ENV_GET_CPU(cpu_single_env),
> -                              addr, false, false, 0, size);
> +    if (cpu_single_cpu != NULL) {
> +        cpu_unassigned_access(cpu_single_cpu, addr, false, false, 0, size);
>      }
>      return 0;
>  }
> @@ -870,9 +869,8 @@ static void unassigned_mem_write(void *opaque, hwaddr addr,
>  #ifdef DEBUG_UNASSIGNED
>      printf("Unassigned mem write " TARGET_FMT_plx " = 0x%"PRIx64"\n", addr, val);
>  #endif
> -    if (cpu_single_env != NULL) {
> -        cpu_unassigned_access(ENV_GET_CPU(cpu_single_env),
> -                              addr, true, false, 0, size);
> +    if (cpu_single_cpu != NULL) {
> +        cpu_unassigned_access(cpu_single_cpu, addr, true, false, 0, size);
>      }
>  }
>  
> diff --git a/translate-all.c b/translate-all.c
> index df7c697..4177293 100644
> --- a/translate-all.c
> +++ b/translate-all.c
> @@ -999,8 +999,10 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
>                                     int is_cpu_write_access)
>  {
>      TranslationBlock *tb, *tb_next, *saved_tb;
> -    CPUArchState *env = cpu_single_env;
> -    CPUState *cpu = NULL;
> +    CPUState *cpu = cpu_single_cpu;
> +#if defined(TARGET_HAS_PRECISE_SMC) || !defined(CONFIG_USER_ONLY)
> +    CPUArchState *env = NULL;
> +#endif
>      tb_page_addr_t tb_start, tb_end;
>      PageDesc *p;
>      int n;
> @@ -1023,9 +1025,11 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
>          /* build code bitmap */
>          build_page_bitmap(p);
>      }
> -    if (env != NULL) {
> -        cpu = ENV_GET_CPU(env);
> +#if defined(TARGET_HAS_PRECISE_SMC) || !defined(CONFIG_USER_ONLY)
> +    if (cpu != NULL) {
> +        env = cpu->env_ptr;
>      }
> +#endif
>  
>      /* we remove all the TBs in the range [start, end[ */
>      /* XXX: see if in some cases it could be faster to invalidate all
> @@ -1147,8 +1151,8 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr,
>      int n;
>  #ifdef TARGET_HAS_PRECISE_SMC
>      TranslationBlock *current_tb = NULL;
> -    CPUArchState *env = cpu_single_env;
> -    CPUState *cpu = NULL;
> +    CPUState *cpu = cpu_single_cpu;
> +    CPUArchState *env = NULL;
>      int current_tb_modified = 0;
>      target_ulong current_pc = 0;
>      target_ulong current_cs_base = 0;
> @@ -1165,8 +1169,8 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr,
>      if (tb && pc != 0) {
>          current_tb = tb_find_pc(pc);
>      }
> -    if (env != NULL) {
> -        cpu = ENV_GET_CPU(env);
> +    if (cpu != NULL) {
> +        env = cpu->env_ptr;
>      }
>  #endif
>      while (tb != NULL) {
> diff --git a/user-exec.c b/user-exec.c
> index fa7f1f1..aebdf1e 100644
> --- a/user-exec.c
> +++ b/user-exec.c
> @@ -81,6 +81,7 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
>                                      int is_write, sigset_t *old_set,
>                                      void *puc)
>  {
> +    CPUArchState *env;
>      int ret;
>  
>  #if defined(DEBUG_SIGNAL)
> @@ -93,9 +94,9 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
>          return 1;
>      }
>  
> +    env = cpu_single_cpu->env_ptr;
>      /* see if it is an MMU fault */
> -    ret = cpu_handle_mmu_fault(cpu_single_env, address, is_write,
> -                               MMU_USER_IDX);
> +    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX);
>      if (ret < 0) {
>          return 0; /* not an MMU fault */
>      }
> @@ -103,12 +104,12 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
>          return 1; /* the MMU fault was handled without causing real CPU fault */
>      }
>      /* now we have a real cpu fault */
> -    cpu_restore_state(cpu_single_env, pc);
> +    cpu_restore_state(env, pc);
>  
>      /* we restore the process signal mask as the sigreturn should
>         do it (XXX: use sigsetjmp) */
>      sigprocmask(SIG_SETMASK, old_set, NULL);
> -    exception_action(cpu_single_env);
> +    exception_action(env);
>  
>      /* never comes here */
>      return 1;
>
Andreas Färber - July 15, 2013, 3:20 p.m.
Am 15.07.2013 16:56, schrieb Paolo Bonzini:
> Il 16/06/2013 17:57, Andreas Färber ha scritto:
>> Move it to qom/cpu.h.
> 
> Hmm, why move it to qom/cpu.h?  Isn't it an implementation detail that
> there is a current CPU?

We have some ugly include chains - yes, it shouldn't be here forever.
Just like the qemu/log.h situation is pretty unsatisfactory (I wouldve
liked to place log_cpu_state() into qom/cpu.h but it depends in
qemu-common.h and even ignoring that didn't build for all targets
depending on include order inside cpu.h and of cpu.h).
What we need is (a) header(s) that allows use of CPUState type and that
doesn't use CPUArchState or other target-specifics. I believe the
benefits of getting rid of CPUArchState outweigh the choice of qom/cpu.h
here, which has been serving as a dumpbin for some now
CPUState-dependent functions living in exec.c or cpus.c, too, simply
because CPUState is guaranteed to be available there and to separate it
from anything that still needs to be seen through similar to cpu-qom.h
vs. cpu.h. If you have a spontaneous suggestion I'd be all ears.

Andreas
Paolo Bonzini - July 15, 2013, 3:29 p.m.
Il 15/07/2013 17:20, Andreas Färber ha scritto:
> We have some ugly include chains - yes, it shouldn't be here forever.
> Just like the qemu/log.h situation is pretty unsatisfactory (I wouldve
> liked to place log_cpu_state() into qom/cpu.h but it depends in
> qemu-common.h and even ignoring that didn't build for all targets
> depending on include order inside cpu.h and of cpu.h).
> What we need is (a) header(s) that allows use of CPUState type and that
> doesn't use CPUArchState or other target-specifics. I believe the
> benefits of getting rid of CPUArchState outweigh the choice of qom/cpu.h
> here, which has been serving as a dumpbin for some now
> CPUState-dependent functions living in exec.c or cpus.c, too, simply
> because CPUState is guaranteed to be available there and to separate it
> from anything that still needs to be seen through similar to cpu-qom.h
> vs. cpu.h. If you have a spontaneous suggestion I'd be all ears.

I'm not sure why it couldn't have stayed in cpu-all.h, but I must be
missing something. :)

Paolo
Andreas Färber - July 18, 2013, 10:25 a.m.
Am 15.07.2013 17:29, schrieb Paolo Bonzini:
> Il 15/07/2013 17:20, Andreas Färber ha scritto:
>> We have some ugly include chains - yes, it shouldn't be here forever.
>> Just like the qemu/log.h situation is pretty unsatisfactory (I wouldve
>> liked to place log_cpu_state() into qom/cpu.h but it depends in
>> qemu-common.h and even ignoring that didn't build for all targets
>> depending on include order inside cpu.h and of cpu.h).
>> What we need is (a) header(s) that allows use of CPUState type and that
>> doesn't use CPUArchState or other target-specifics. I believe the
>> benefits of getting rid of CPUArchState outweigh the choice of qom/cpu.h
>> here, which has been serving as a dumpbin for some now
>> CPUState-dependent functions living in exec.c or cpus.c, too, simply
>> because CPUState is guaranteed to be available there and to separate it
>> from anything that still needs to be seen through similar to cpu-qom.h
>> vs. cpu.h. If you have a spontaneous suggestion I'd be all ears.
> 
> I'm not sure why it couldn't have stayed in cpu-all.h, but I must be
> missing something. :)

You're missing TARGET_WORDS_BIGENDIAN on line 39, target_ulong further
down, CPUArchState in cpu_copy() and cpu_abort(), etc.

By placing it in a header that does not have this baggage, some timer
and intc devices in this series were able to drop their dependency on
cpu.h in favor of qom/cpu.h and be built in common-obj-y rather than obj-y.

Andreas

Patch

diff --git a/cpu-exec.c b/cpu-exec.c
index ec46380..1858c2e 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -213,12 +213,12 @@  int cpu_exec(CPUArchState *env)
         cpu->halted = 0;
     }
 
-    cpu_single_env = env;
+    cpu_single_cpu = cpu;
 
-    /* As long as cpu_single_env is null, up to the assignment just above,
+    /* As long as cpu_single_cpu is null, up to the assignment just above,
      * requests by other threads to exit the execution loop are expected to
      * be issued using the exit_request global. We must make sure that our
-     * evaluation of the global value is performed past the cpu_single_env
+     * evaluation of the global value is performed past the cpu_single_cpu
      * value transition point, which requires a memory barrier as well as
      * an instruction scheduling constraint on modern architectures.  */
     smp_mb();
@@ -673,7 +673,8 @@  int cpu_exec(CPUArchState *env)
         } else {
             /* Reload env after longjmp - the compiler may have smashed all
              * local variables as longjmp is marked 'noreturn'. */
-            env = cpu_single_env;
+            cpu = cpu_single_cpu;
+            env = cpu->env_ptr;
         }
     } /* for(;;) */
 
@@ -707,7 +708,7 @@  int cpu_exec(CPUArchState *env)
 #error unsupported target CPU
 #endif
 
-    /* fail safe : never use cpu_single_env outside cpu_exec() */
-    cpu_single_env = NULL;
+    /* fail safe : never use cpu_single_cpu outside cpu_exec() */
+    cpu_single_cpu = NULL;
     return ret;
 }
diff --git a/cpus.c b/cpus.c
index 775d998..808503b 100644
--- a/cpus.c
+++ b/cpus.c
@@ -118,10 +118,11 @@  TimersState timers_state;
 int64_t cpu_get_icount(void)
 {
     int64_t icount;
-    CPUArchState *env = cpu_single_env;
+    CPUState *cpu = cpu_single_cpu;
 
     icount = qemu_icount;
-    if (env) {
+    if (cpu) {
+        CPUArchState *env = cpu->env_ptr;
         if (!can_do_io(env)) {
             fprintf(stderr, "Bad clock read\n");
         }
@@ -468,8 +469,8 @@  static void cpu_handle_guest_debug(CPUState *cpu)
 
 static void cpu_signal(int sig)
 {
-    if (cpu_single_env) {
-        cpu_exit(ENV_GET_CPU(cpu_single_env));
+    if (cpu_single_cpu) {
+        cpu_exit(cpu_single_cpu);
     }
     exit_request = 1;
 }
@@ -660,10 +661,10 @@  void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data)
 
     qemu_cpu_kick(cpu);
     while (!wi.done) {
-        CPUArchState *self_env = cpu_single_env;
+        CPUState *self_cpu = cpu_single_cpu;
 
         qemu_cond_wait(&qemu_work_cond, &qemu_global_mutex);
-        cpu_single_env = self_env;
+        cpu_single_cpu = self_cpu;
     }
 }
 
@@ -733,7 +734,7 @@  static void *qemu_kvm_cpu_thread_fn(void *arg)
     qemu_mutex_lock(&qemu_global_mutex);
     qemu_thread_get_self(cpu->thread);
     cpu->thread_id = qemu_get_thread_id();
-    cpu_single_env = cpu->env_ptr;
+    cpu_single_cpu = cpu;
 
     r = kvm_init_vcpu(cpu);
     if (r < 0) {
@@ -781,9 +782,9 @@  static void *qemu_dummy_cpu_thread_fn(void *arg)
     cpu->created = true;
     qemu_cond_signal(&qemu_cpu_cond);
 
-    cpu_single_env = cpu->env_ptr;
+    cpu_single_cpu = cpu;
     while (1) {
-        cpu_single_env = NULL;
+        cpu_single_cpu = NULL;
         qemu_mutex_unlock_iothread();
         do {
             int sig;
@@ -794,7 +795,7 @@  static void *qemu_dummy_cpu_thread_fn(void *arg)
             exit(1);
         }
         qemu_mutex_lock_iothread();
-        cpu_single_env = cpu->env_ptr;
+        cpu_single_cpu = cpu;
         qemu_wait_io_event_common(cpu);
     }
 
@@ -894,8 +895,7 @@  void qemu_cpu_kick(CPUState *cpu)
 void qemu_cpu_kick_self(void)
 {
 #ifndef _WIN32
-    assert(cpu_single_env);
-    CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
+    assert(cpu_single_cpu);
 
     if (!cpu_single_cpu->thread_kicked) {
         qemu_cpu_kick_thread(cpu_single_cpu);
@@ -913,7 +913,7 @@  bool qemu_cpu_is_self(CPUState *cpu)
 
 static bool qemu_in_vcpu_thread(void)
 {
-    return cpu_single_env && qemu_cpu_is_self(ENV_GET_CPU(cpu_single_env));
+    return cpu_single_cpu && qemu_cpu_is_self(cpu_single_cpu);
 }
 
 void qemu_mutex_lock_iothread(void)
@@ -1069,8 +1069,7 @@  void qemu_init_vcpu(CPUState *cpu)
 
 void cpu_stop_current(void)
 {
-    if (cpu_single_env) {
-        CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
+    if (cpu_single_cpu) {
         cpu_single_cpu->stop = false;
         cpu_single_cpu->stopped = true;
         cpu_exit(cpu_single_cpu);
diff --git a/exec.c b/exec.c
index 2b99bb9..e14a815 100644
--- a/exec.c
+++ b/exec.c
@@ -73,7 +73,7 @@  static MemoryRegion io_mem_unassigned, io_mem_subpage_ram;
 CPUArchState *first_cpu;
 /* current CPU in the current thread. It is only valid inside
    cpu_exec() */
-DEFINE_TLS(CPUArchState *,cpu_single_env);
+DEFINE_TLS(CPUState *,cpu_single_cpu);
 /* 0 = Do not count executed instructions.
    1 = Precise instruction counting.
    2 = Adaptive rate instruction counting.  */
@@ -1420,8 +1420,10 @@  static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
     cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
     /* we remove the notdirty callback only if the code has been
        flushed */
-    if (dirty_flags == 0xff)
-        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
+    if (dirty_flags == 0xff) {
+        CPUArchState *env = cpu_single_cpu->env_ptr;
+        tlb_set_dirty(env, env->mem_io_vaddr);
+    }
 }
 
 static bool notdirty_mem_accepts(void *opaque, hwaddr addr,
@@ -1439,7 +1441,7 @@  static const MemoryRegionOps notdirty_mem_ops = {
 /* Generate a debug exception if a watchpoint has been hit.  */
 static void check_watchpoint(int offset, int len_mask, int flags)
 {
-    CPUArchState *env = cpu_single_env;
+    CPUArchState *env = cpu_single_cpu->env_ptr;
     target_ulong pc, cs_base;
     target_ulong vaddr;
     CPUWatchpoint *wp;
@@ -1912,7 +1914,7 @@  bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
         if (is_write) {
             if (!memory_access_is_direct(section->mr, is_write)) {
                 l = memory_access_size(l, addr1);
-                /* XXX: could force cpu_single_env to NULL to avoid
+                /* XXX: could force cpu_single_cpu to NULL to avoid
                    potential bugs */
                 if (l == 4) {
                     /* 32 bit write access */
diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
index 207dcad..f0b1f6f 100644
--- a/hw/alpha/typhoon.c
+++ b/hw/alpha/typhoon.c
@@ -72,9 +72,8 @@  static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
 
 static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
 {
-    CPUAlphaState *env = cpu_single_env;
+    CPUState *cpu = cpu_single_cpu;
     TyphoonState *s = opaque;
-    CPUState *cpu;
     uint64_t ret = 0;
 
     if (addr & 4) {
@@ -95,7 +94,6 @@  static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
 
     case 0x0080:
         /* MISC: Miscellaneous Register.  */
-        cpu = ENV_GET_CPU(env);
         ret = s->cchip.misc | (cpu->cpu_index & 3);
         break;
 
@@ -197,8 +195,7 @@  static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
         break;
 
     default:
-        cpu = CPU(alpha_env_get_cpu(cpu_single_env));
-        cpu_unassigned_access(cpu, addr, false, false, 0, size);
+        cpu_unassigned_access(cpu_single_cpu, addr, false, false, 0, size);
         return -1;
     }
 
@@ -215,7 +212,6 @@  static uint64_t dchip_read(void *opaque, hwaddr addr, unsigned size)
 static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size)
 {
     TyphoonState *s = opaque;
-    CPUState *cs;
     uint64_t ret = 0;
 
     if (addr & 4) {
@@ -302,8 +298,7 @@  static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size)
         break;
 
     default:
-        cs = CPU(alpha_env_get_cpu(cpu_single_env));
-        cpu_unassigned_access(cs, addr, false, false, 0, size);
+        cpu_unassigned_access(cpu_single_cpu, addr, false, false, 0, size);
         return -1;
     }
 
@@ -315,7 +310,6 @@  static void cchip_write(void *opaque, hwaddr addr,
                         uint64_t v32, unsigned size)
 {
     TyphoonState *s = opaque;
-    CPUState *cpu_single_cpu = CPU(alpha_env_get_cpu(cpu_single_env));
     uint64_t val, oldval, newval;
 
     if (addr & 4) {
@@ -480,7 +474,6 @@  static void pchip_write(void *opaque, hwaddr addr,
                         uint64_t v32, unsigned size)
 {
     TyphoonState *s = opaque;
-    CPUState *cs;
     uint64_t val, oldval;
 
     if (addr & 4) {
@@ -582,8 +575,7 @@  static void pchip_write(void *opaque, hwaddr addr,
         break;
 
     default:
-        cs = CPU(alpha_env_get_cpu(cpu_single_env));
-        cpu_unassigned_access(cs, addr, true, false, 0, size);
+        cpu_unassigned_access(cpu_single_cpu, addr, true, false, 0, size);
         return;
     }
 }
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 24b03a0..d023167 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -301,8 +301,7 @@  static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
 #endif
 
         /* Suspend */
-        cpu_interrupt(CPU(arm_env_get_cpu(cpu_single_env)),
-                      CPU_INTERRUPT_HALT);
+        cpu_interrupt(cpu_single_cpu, CPU_INTERRUPT_HALT);
 
         goto message;
 
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
index f93629f..9aac9de 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -623,11 +623,13 @@  static int vapic_prepare(VAPICROMState *s)
 static void vapic_write(void *opaque, hwaddr addr, uint64_t data,
                         unsigned int size)
 {
-    CPUX86State *env = cpu_single_env;
+    CPUState *cs = cpu_single_cpu;
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
     hwaddr rom_paddr;
     VAPICROMState *s = opaque;
 
-    cpu_synchronize_state(CPU(x86_env_get_cpu(env)));
+    cpu_synchronize_state(cs);
 
     /*
      * The VAPIC supports two PIO-based hypercalls, both via port 0x7E.
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index d7e8507..c43be54 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -887,8 +887,9 @@  void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
 
 DeviceState *cpu_get_current_apic(void)
 {
-    if (cpu_single_env) {
-        return cpu_single_env->apic_state;
+    if (cpu_single_cpu) {
+        X86CPU *cpu = X86_CPU(cpu_single_cpu);
+        return cpu->env.apic_state;
     } else {
         return NULL;
     }
@@ -1107,10 +1108,10 @@  DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
 
 static void cpu_request_exit(void *opaque, int irq, int level)
 {
-    CPUX86State *env = cpu_single_env;
+    CPUState *cpu = cpu_single_cpu;
 
-    if (env && level) {
-        cpu_exit(CPU(x86_env_get_cpu(env)));
+    if (cpu && level) {
+        cpu_exit(cpu);
     }
 }
 
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index bae6572..79fd4a9 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -39,8 +39,7 @@  static const uint8_t gic_id[] = {
 static inline int gic_get_current_cpu(GICState *s)
 {
     if (s->num_cpu > 1) {
-        CPUState *cpu = ENV_GET_CPU(cpu_single_env);
-        return cpu->cpu_index;
+        return cpu_single_cpu->cpu_index;
     }
     return 0;
 }
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 25fa43c..53576c8 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -140,6 +140,7 @@  void armv7m_nvic_complete_irq(void *opaque, int irq)
 
 static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
 {
+    ARMCPU *cpu;
     uint32_t val;
     int irq;
 
@@ -171,7 +172,8 @@  static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
     case 0x1c: /* SysTick Calibration Value.  */
         return 10000;
     case 0xd00: /* CPUID Base.  */
-        return cpu_single_env->cp15.c0_cpuid;
+        cpu = ARM_CPU(cpu_single_cpu);
+        return cpu->env.cp15.c0_cpuid;
     case 0xd04: /* Interrupt Control State.  */
         /* VECTACTIVE */
         val = s->gic.running_irq[0];
@@ -206,7 +208,8 @@  static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
             val |= (1 << 31);
         return val;
     case 0xd08: /* Vector Table Offset.  */
-        return cpu_single_env->v7m.vecbase;
+        cpu = ARM_CPU(cpu_single_cpu);
+        return cpu->env.v7m.vecbase;
     case 0xd0c: /* Application Interrupt/Reset Control.  */
         return 0xfa05000;
     case 0xd10: /* System Control.  */
@@ -279,6 +282,7 @@  static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
 
 static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
 {
+    ARMCPU *cpu;
     uint32_t oldval;
     switch (offset) {
     case 0x10: /* SysTick Control and Status.  */
@@ -331,7 +335,8 @@  static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
         }
         break;
     case 0xd08: /* Vector Table Offset.  */
-        cpu_single_env->v7m.vecbase = value & 0xffffff80;
+        cpu = ARM_CPU(cpu_single_cpu);
+        cpu->env.v7m.vecbase = value & 0xffffff80;
         break;
     case 0xd0c: /* Application Interrupt/Reset Control.  */
         if ((value >> 16) == 0x05fa) {
diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
index c788714..6f152e0 100644
--- a/hw/intc/openpic.c
+++ b/hw/intc/openpic.c
@@ -184,13 +184,10 @@  static int output_to_inttgt(int output)
 
 static int get_current_cpu(void)
 {
-    CPUState *cpu_single_cpu;
-
-    if (!cpu_single_env) {
+    if (!cpu_single_cpu) {
         return -1;
     }
 
-    cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
     return cpu_single_cpu->cpu_index;
 }
 
diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c
index 00c9071..59ee1b4 100644
--- a/hw/mips/mips_fulong2e.c
+++ b/hw/mips/mips_fulong2e.c
@@ -250,10 +250,10 @@  static void network_init (void)
 
 static void cpu_request_exit(void *opaque, int irq, int level)
 {
-    CPUMIPSState *env = cpu_single_env;
+    CPUState *cpu = cpu_single_cpu;
 
-    if (env && level) {
-        cpu_exit(CPU(mips_env_get_cpu(env)));
+    if (cpu && level) {
+        cpu_exit(cpu);
     }
 }
 
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index 2ad0c0b..2ffae59 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -99,10 +99,10 @@  static const MemoryRegionOps dma_dummy_ops = {
 
 static void cpu_request_exit(void *opaque, int irq, int level)
 {
-    CPUMIPSState *env = cpu_single_env;
+    CPUState *cpu = cpu_single_cpu;
 
-    if (env && level) {
-        cpu_exit(CPU(mips_env_get_cpu(env)));
+    if (cpu && level) {
+        cpu_exit(cpu);
     }
 }
 
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 8a4459d..4fc611c 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -770,10 +770,10 @@  static void main_cpu_reset(void *opaque)
 
 static void cpu_request_exit(void *opaque, int irq, int level)
 {
-    CPUMIPSState *env = cpu_single_env;
+    CPUState *cpu = cpu_single_cpu;
 
-    if (env && level) {
-        cpu_exit(CPU(mips_env_get_cpu(env)));
+    if (cpu && level) {
+        cpu_exit(cpu);
     }
 }
 
diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
index 8363dfd..deb2232 100644
--- a/hw/misc/vmport.c
+++ b/hw/misc/vmport.c
@@ -62,11 +62,13 @@  static uint64_t vmport_ioport_read(void *opaque, hwaddr addr,
                                    unsigned size)
 {
     VMPortState *s = opaque;
-    CPUX86State *env = cpu_single_env;
+    CPUState *cs = cpu_single_cpu;
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
     unsigned char command;
     uint32_t eax;
 
-    cpu_synchronize_state(CPU(x86_env_get_cpu(env)));
+    cpu_synchronize_state(cs);
 
     eax = env->regs[R_EAX];
     if (eax != VMPORT_MAGIC)
@@ -89,29 +91,32 @@  static uint64_t vmport_ioport_read(void *opaque, hwaddr addr,
 static void vmport_ioport_write(void *opaque, hwaddr addr,
                                 uint64_t val, unsigned size)
 {
-    CPUX86State *env = cpu_single_env;
+    X86CPU *cpu = X86_CPU(cpu_single_cpu);
 
-    env->regs[R_EAX] = vmport_ioport_read(opaque, addr, 4);
+    cpu->env.regs[R_EAX] = vmport_ioport_read(opaque, addr, 4);
 }
 
 static uint32_t vmport_cmd_get_version(void *opaque, uint32_t addr)
 {
-    CPUX86State *env = cpu_single_env;
-    env->regs[R_EBX] = VMPORT_MAGIC;
+    X86CPU *cpu = X86_CPU(cpu_single_cpu);
+
+    cpu->env.regs[R_EBX] = VMPORT_MAGIC;
     return 6;
 }
 
 static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr)
 {
-    CPUX86State *env = cpu_single_env;
-    env->regs[R_EBX] = 0x1177;
+    X86CPU *cpu = X86_CPU(cpu_single_cpu);
+
+    cpu->env.regs[R_EBX] = 0x1177;
     return ram_size;
 }
 
 /* vmmouse helpers */
 void vmmouse_get_data(uint32_t *data)
 {
-    CPUX86State *env = cpu_single_env;
+    X86CPU *cpu = X86_CPU(cpu_single_cpu);
+    CPUX86State *env = &cpu->env;
 
     data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX];
     data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX];
@@ -120,7 +125,8 @@  void vmmouse_get_data(uint32_t *data)
 
 void vmmouse_set_data(const uint32_t *data)
 {
-    CPUX86State *env = cpu_single_env;
+    X86CPU *cpu = X86_CPU(cpu_single_cpu);
+    CPUX86State *env = &cpu->env;
 
     env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1];
     env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3];
diff --git a/hw/ppc/mpc8544_guts.c b/hw/ppc/mpc8544_guts.c
index 193beab..89f950f 100644
--- a/hw/ppc/mpc8544_guts.c
+++ b/hw/ppc/mpc8544_guts.c
@@ -62,7 +62,8 @@  static uint64_t mpc8544_guts_read(void *opaque, hwaddr addr,
                                   unsigned size)
 {
     uint32_t value = 0;
-    CPUPPCState *env = cpu_single_env;
+    PowerPCCPU *cpu = POWERPC_CPU(cpu_single_cpu);
+    CPUPPCState *env = &cpu->env;
 
     addr &= MPC8544_GUTS_MMIO_SIZE - 1;
     switch (addr) {
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 90828f2..16e3132 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -417,10 +417,10 @@  static const MemoryRegionOps PPC_prep_io_ops = {
 
 static void cpu_request_exit(void *opaque, int irq, int level)
 {
-    CPUPPCState *env = cpu_single_env;
+    CPUState *cpu = cpu_single_cpu;
 
-    if (env && level) {
-        cpu_exit(CPU(ppc_env_get_cpu(env)));
+    if (cpu && level) {
+        cpu_exit(cpu);
     }
 }
 
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 0e86ca7..1273533 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -264,9 +264,8 @@  static void secondary_cpu_reset(void *opaque)
 
 static void cpu_halt_signal(void *opaque, int irq, int level)
 {
-    if (level && cpu_single_env) {
-        cpu_interrupt(CPU(sparc_env_get_cpu(cpu_single_env)),
-                      CPU_INTERRUPT_HALT);
+    if (level && cpu_single_cpu) {
+        cpu_interrupt(cpu_single_cpu, CPU_INTERRUPT_HALT);
     }
 }
 
diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
index 317f5e4..1aa300b 100644
--- a/hw/timer/arm_mptimer.c
+++ b/hw/timer/arm_mptimer.c
@@ -49,8 +49,6 @@  typedef struct {
 
 static inline int get_current_cpu(ARMMPTimerState *s)
 {
-    CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
-
     if (cpu_single_cpu->cpu_index >= s->num_cpu) {
         hw_error("arm_mptimer: num-cpu %d but this cpu is %d!\n",
                  s->num_cpu, cpu_single_cpu->cpu_index);
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 35bdf85..6760851 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -20,7 +20,6 @@ 
 #define CPU_ALL_H
 
 #include "qemu-common.h"
-#include "qemu/tls.h"
 #include "exec/cpu-common.h"
 #include "qemu/thread.h"
 
@@ -358,8 +357,6 @@  CPUArchState *cpu_copy(CPUArchState *env);
 void QEMU_NORETURN cpu_abort(CPUArchState *env, const char *fmt, ...)
     GCC_FMT_ATTR(2, 3);
 extern CPUArchState *first_cpu;
-DECLARE_TLS(CPUArchState *,cpu_single_env);
-#define cpu_single_env tls_var(cpu_single_env)
 
 /* Flags for use in ENV->INTERRUPT_PENDING.
 
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 7afc442..0e2e76c 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -24,6 +24,7 @@ 
 #include "hw/qdev-core.h"
 #include "exec/hwaddr.h"
 #include "qemu/thread.h"
+#include "qemu/tls.h"
 #include "qemu/typedefs.h"
 
 typedef int (*WriteCoreDumpFunction)(void *buf, size_t size, void *opaque);
@@ -156,6 +157,9 @@  struct CPUState {
     uint32_t halted; /* used by alpha, cris, ppc TCG */
 };
 
+DECLARE_TLS(CPUState *, cpu_single_cpu);
+#define cpu_single_cpu tls_var(cpu_single_cpu)
+
 /**
  * cpu_paging_enabled:
  * @cpu: The CPU whose state is to be inspected.
diff --git a/memory.c b/memory.c
index 3bc98ad..f960bd0 100644
--- a/memory.c
+++ b/memory.c
@@ -857,9 +857,8 @@  static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
 #endif
-    if (cpu_single_env != NULL) {
-        cpu_unassigned_access(ENV_GET_CPU(cpu_single_env),
-                              addr, false, false, 0, size);
+    if (cpu_single_cpu != NULL) {
+        cpu_unassigned_access(cpu_single_cpu, addr, false, false, 0, size);
     }
     return 0;
 }
@@ -870,9 +869,8 @@  static void unassigned_mem_write(void *opaque, hwaddr addr,
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem write " TARGET_FMT_plx " = 0x%"PRIx64"\n", addr, val);
 #endif
-    if (cpu_single_env != NULL) {
-        cpu_unassigned_access(ENV_GET_CPU(cpu_single_env),
-                              addr, true, false, 0, size);
+    if (cpu_single_cpu != NULL) {
+        cpu_unassigned_access(cpu_single_cpu, addr, true, false, 0, size);
     }
 }
 
diff --git a/translate-all.c b/translate-all.c
index df7c697..4177293 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -999,8 +999,10 @@  void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
                                    int is_cpu_write_access)
 {
     TranslationBlock *tb, *tb_next, *saved_tb;
-    CPUArchState *env = cpu_single_env;
-    CPUState *cpu = NULL;
+    CPUState *cpu = cpu_single_cpu;
+#if defined(TARGET_HAS_PRECISE_SMC) || !defined(CONFIG_USER_ONLY)
+    CPUArchState *env = NULL;
+#endif
     tb_page_addr_t tb_start, tb_end;
     PageDesc *p;
     int n;
@@ -1023,9 +1025,11 @@  void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
         /* build code bitmap */
         build_page_bitmap(p);
     }
-    if (env != NULL) {
-        cpu = ENV_GET_CPU(env);
+#if defined(TARGET_HAS_PRECISE_SMC) || !defined(CONFIG_USER_ONLY)
+    if (cpu != NULL) {
+        env = cpu->env_ptr;
     }
+#endif
 
     /* we remove all the TBs in the range [start, end[ */
     /* XXX: see if in some cases it could be faster to invalidate all
@@ -1147,8 +1151,8 @@  static void tb_invalidate_phys_page(tb_page_addr_t addr,
     int n;
 #ifdef TARGET_HAS_PRECISE_SMC
     TranslationBlock *current_tb = NULL;
-    CPUArchState *env = cpu_single_env;
-    CPUState *cpu = NULL;
+    CPUState *cpu = cpu_single_cpu;
+    CPUArchState *env = NULL;
     int current_tb_modified = 0;
     target_ulong current_pc = 0;
     target_ulong current_cs_base = 0;
@@ -1165,8 +1169,8 @@  static void tb_invalidate_phys_page(tb_page_addr_t addr,
     if (tb && pc != 0) {
         current_tb = tb_find_pc(pc);
     }
-    if (env != NULL) {
-        cpu = ENV_GET_CPU(env);
+    if (cpu != NULL) {
+        env = cpu->env_ptr;
     }
 #endif
     while (tb != NULL) {
diff --git a/user-exec.c b/user-exec.c
index fa7f1f1..aebdf1e 100644
--- a/user-exec.c
+++ b/user-exec.c
@@ -81,6 +81,7 @@  static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
                                     int is_write, sigset_t *old_set,
                                     void *puc)
 {
+    CPUArchState *env;
     int ret;
 
 #if defined(DEBUG_SIGNAL)
@@ -93,9 +94,9 @@  static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
         return 1;
     }
 
+    env = cpu_single_cpu->env_ptr;
     /* see if it is an MMU fault */
-    ret = cpu_handle_mmu_fault(cpu_single_env, address, is_write,
-                               MMU_USER_IDX);
+    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX);
     if (ret < 0) {
         return 0; /* not an MMU fault */
     }
@@ -103,12 +104,12 @@  static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
         return 1; /* the MMU fault was handled without causing real CPU fault */
     }
     /* now we have a real cpu fault */
-    cpu_restore_state(cpu_single_env, pc);
+    cpu_restore_state(env, pc);
 
     /* we restore the process signal mask as the sigreturn should
        do it (XXX: use sigsetjmp) */
     sigprocmask(SIG_SETMASK, old_set, NULL);
-    exception_action(cpu_single_env);
+    exception_action(env);
 
     /* never comes here */
     return 1;