All of lore.kernel.org
 help / color / mirror / Atom feed
From: TeLeMan <geleman@gmail.com>
To: "Andreas Färber" <afaerber@suse.de>
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
	"Gleb Natapov" <gleb@redhat.com>,
	qemu-devel <qemu-devel@nongnu.org>,
	"Luiz Capitulino" <lcapitulino@redhat.com>,
	"Peter Crosthwaite" <peter.crosthwaite@petalogix.com>,
	"Edgar E. Iglesias" <edgar.iglesias@gmail.com>,
	"Igor Mitsyanko" <i.mitsyanko@samsung.com>,
	"Evgeny Voevodin" <e.voevodin@samsung.com>,
	"Alexander Graf" <agraf@suse.de>,
	"Andreas Färber" <andreas.faerber@web.de>,
	"Maksim Kozlov" <m.kozlov@samsung.com>,
	"Riku Voipio" <riku.voipio@iki.fi>,
	"Paul Brook" <paul@codesourcery.com>,
	"open list:Overall" <kvm@vger.kernel.org>,
	"Scott Wood" <scottwood@freescale.com>,
	"Anthony Liguori" <aliguori@us.ibm.com>,
	"Mark Langsdorf" <mark.langsdorf@calxeda.com>,
	"Marcelo Tosatti" <mtosatti@redhat.com>,
	"open list:e500" <qemu-ppc@nongnu.org>,
	"Dmitry Solodkiy" <d.solodkiy@samsung.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>
Subject: Re: [PULL 09/43] cpu: Make first_cpu and next_cpu CPUState
Date: Thu, 11 Jul 2013 17:14:23 +0800	[thread overview]
Message-ID: <CAETRQWm+s+zrOFv9_RFYJnSuijVYUU6RiSsW1K26uGzT0pUhTA@mail.gmail.com> (raw)
In-Reply-To: <1373466860-32732-10-git-send-email-afaerber@suse.de>

On Wed, Jul 10, 2013 at 10:33 PM, Andreas Färber <afaerber@suse.de> wrote:
> Move next_cpu from CPU_COMMON to CPUState.
> Move first_cpu variable to qom/cpu.h.
>
> gdbstub needs to use CPUState::env_ptr for now.
> cpu_copy() no longer needs to save and restore cpu_next.
>
> Acked-by: Paolo Bonzini <pbonzini@redhat.com>
> [AF: Rebased, simplified cpu_copy()]
> Signed-off-by: Andreas Färber <afaerber@suse.de>
> ---
>  cpus.c                    | 126 ++++++++++++++++++++++++----------------------
>  cputlb.c                  |   4 +-
>  dump.c                    |  16 +++---
>  exec.c                    |  43 ++++++++--------
>  gdbstub.c                 |  39 ++++++++------
>  hw/arm/boot.c             |  10 ++--
>  hw/arm/exynos4_boards.c   |   4 +-
>  hw/arm/highbank.c         |   2 +-
>  hw/arm/realview.c         |   2 +-
>  hw/arm/vexpress.c         |   2 +-
>  hw/arm/xilinx_zynq.c      |   2 +-
>  hw/i386/kvm/clock.c       |  12 +++--
>  hw/i386/kvmvapic.c        |  13 +++--
>  hw/i386/pc.c              |  17 ++++---
>  hw/i386/pc_piix.c         |   3 +-
>  hw/intc/sh_intc.c         |   5 +-
>  hw/isa/lpc_ich9.c         |   2 +-
>  hw/mips/mips_malta.c      |   3 +-
>  hw/ppc/e500.c             |   5 +-
>  hw/ppc/ppc.c              |  11 ++--
>  hw/ppc/prep.c             |   6 ++-
>  hw/ppc/spapr.c            |  27 +++++-----
>  include/exec/cpu-all.h    |   1 -
>  include/exec/cpu-defs.h   |   1 -
>  include/qom/cpu.h         |   4 ++
>  kvm-all.c                 |  16 +++---
>  linux-user/elfload.c      |   7 +--
>  linux-user/main.c         |   8 ++-
>  linux-user/syscall.c      |   9 ++--
>  memory_mapping.c          |  16 +++---
>  monitor.c                 |   4 +-
>  target-i386/arch_dump.c   |   7 ++-
>  target-i386/helper.c      |  15 +++---
>  target-i386/kvm.c         |   8 +--
>  target-i386/misc_helper.c |   2 +-
>  target-mips/op_helper.c   |  25 +++++----
>  target-ppc/excp_helper.c  |   9 ++--
>  target-ppc/kvm.c          |   2 +-
>  translate-all.c           |  12 +++--
>  39 files changed, 266 insertions(+), 234 deletions(-)
>
> diff --git a/cpus.c b/cpus.c
> index e9bfa71..f141428 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -60,7 +60,7 @@
>
>  #endif /* CONFIG_LINUX */
>
> -static CPUArchState *next_cpu;
> +static CPUState *next_cpu;
>
>  static bool cpu_thread_is_idle(CPUState *cpu)
>  {
> @@ -79,10 +79,10 @@ static bool cpu_thread_is_idle(CPUState *cpu)
>
>  static bool all_cpu_threads_idle(void)
>  {
> -    CPUArchState *env;
> +    CPUState *cpu;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        if (!cpu_thread_is_idle(ENV_GET_CPU(env))) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        if (!cpu_thread_is_idle(cpu)) {
>              return false;
>          }
>      }
> @@ -388,15 +388,13 @@ void configure_icount(const char *option)
>  void hw_error(const char *fmt, ...)
>  {
>      va_list ap;
> -    CPUArchState *env;
>      CPUState *cpu;
>
>      va_start(ap, fmt);
>      fprintf(stderr, "qemu: hardware error: ");
>      vfprintf(stderr, fmt, ap);
>      fprintf(stderr, "\n");
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        cpu = ENV_GET_CPU(env);
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          fprintf(stderr, "CPU #%d:\n", cpu->cpu_index);
>          cpu_dump_state(cpu, stderr, fprintf, CPU_DUMP_FPU);
>      }
> @@ -406,28 +404,28 @@ void hw_error(const char *fmt, ...)
>
>  void cpu_synchronize_all_states(void)
>  {
> -    CPUArchState *env;
> +    CPUState *cpu;
>
> -    for (env = first_cpu; env; env = env->next_cpu) {
> -        cpu_synchronize_state(ENV_GET_CPU(env));
> +    for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
> +        cpu_synchronize_state(cpu);
>      }
>  }
>
>  void cpu_synchronize_all_post_reset(void)
>  {
> -    CPUArchState *cpu;
> +    CPUState *cpu;
>
>      for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
> -        cpu_synchronize_post_reset(ENV_GET_CPU(cpu));
> +        cpu_synchronize_post_reset(cpu);
>      }
>  }
>
>  void cpu_synchronize_all_post_init(void)
>  {
> -    CPUArchState *cpu;
> +    CPUState *cpu;
>
>      for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
> -        cpu_synchronize_post_init(ENV_GET_CPU(cpu));
> +        cpu_synchronize_post_init(cpu);
>      }
>  }
>
> @@ -698,7 +696,7 @@ static void qemu_wait_io_event_common(CPUState *cpu)
>
>  static void qemu_tcg_wait_io_event(void)
>  {
> -    CPUArchState *env;
> +    CPUState *cpu;
>
>      while (all_cpu_threads_idle()) {
>         /* Start accounting real time to the virtual clock if the CPUs
> @@ -711,8 +709,8 @@ static void qemu_tcg_wait_io_event(void)
>          qemu_cond_wait(&qemu_io_proceeded_cond, &qemu_global_mutex);
>      }
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        qemu_wait_io_event_common(ENV_GET_CPU(env));
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        qemu_wait_io_event_common(cpu);
>      }
>  }
>
> @@ -814,7 +812,6 @@ static void tcg_signal_cpu_creation(CPUState *cpu, void *data)
>  static void *qemu_tcg_cpu_thread_fn(void *arg)
>  {
>      CPUState *cpu = arg;
> -    CPUArchState *env;
>
>      qemu_tcg_init_cpu_signals();
>      qemu_thread_get_self(cpu->thread);
> @@ -824,12 +821,12 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
>      qemu_cond_signal(&qemu_cpu_cond);
>
>      /* wait for initial kick-off after machine start */
> -    while (ENV_GET_CPU(first_cpu)->stopped) {
> +    while (first_cpu->stopped) {
>          qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
>
>          /* process any pending work */
> -        for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -            qemu_wait_io_event_common(ENV_GET_CPU(env));
> +        for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +            qemu_wait_io_event_common(cpu);
>          }
>      }
>
> @@ -923,7 +920,7 @@ void qemu_mutex_lock_iothread(void)
>      } else {
>          iothread_requesting_mutex = true;
>          if (qemu_mutex_trylock(&qemu_global_mutex)) {
> -            qemu_cpu_kick_thread(ENV_GET_CPU(first_cpu));
> +            qemu_cpu_kick_thread(first_cpu);
>              qemu_mutex_lock(&qemu_global_mutex);
>          }
>          iothread_requesting_mutex = false;
> @@ -938,14 +935,13 @@ void qemu_mutex_unlock_iothread(void)
>
>  static int all_vcpus_paused(void)
>  {
> -    CPUArchState *penv = first_cpu;
> +    CPUState *cpu = first_cpu;
>
> -    while (penv) {
> -        CPUState *pcpu = ENV_GET_CPU(penv);
> -        if (!pcpu->stopped) {
> +    while (cpu) {
> +        if (!cpu->stopped) {
>              return 0;
>          }
> -        penv = penv->next_cpu;
> +        cpu = cpu->next_cpu;
>      }
>
>      return 1;
> @@ -953,25 +949,23 @@ static int all_vcpus_paused(void)
>
>  void pause_all_vcpus(void)
>  {
> -    CPUArchState *penv = first_cpu;
> +    CPUState *cpu = first_cpu;
>
>      qemu_clock_enable(vm_clock, false);
> -    while (penv) {
> -        CPUState *pcpu = ENV_GET_CPU(penv);
> -        pcpu->stop = true;
> -        qemu_cpu_kick(pcpu);
> -        penv = penv->next_cpu;
> +    while (cpu) {
> +        cpu->stop = true;
> +        qemu_cpu_kick(cpu);
> +        cpu = cpu->next_cpu;
>      }
>
>      if (qemu_in_vcpu_thread()) {
>          cpu_stop_current();
>          if (!kvm_enabled()) {
> -            penv = first_cpu;
> -            while (penv) {
> -                CPUState *pcpu = ENV_GET_CPU(penv);
> -                pcpu->stop = false;
> -                pcpu->stopped = true;
> -                penv = penv->next_cpu;
> +            cpu = first_cpu;
> +            while (cpu) {
> +                cpu->stop = false;
> +                cpu->stopped = true;
> +                cpu = cpu->next_cpu;
>              }
>              return;
>          }
> @@ -979,10 +973,10 @@ void pause_all_vcpus(void)
>
>      while (!all_vcpus_paused()) {
>          qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex);
> -        penv = first_cpu;
> -        while (penv) {
> -            qemu_cpu_kick(ENV_GET_CPU(penv));
> -            penv = penv->next_cpu;
> +        cpu = first_cpu;
> +        while (cpu) {
> +            qemu_cpu_kick(cpu);
> +            cpu = cpu->next_cpu;
>          }
>      }
>  }
> @@ -996,13 +990,12 @@ void cpu_resume(CPUState *cpu)
>
>  void resume_all_vcpus(void)
>  {
> -    CPUArchState *penv = first_cpu;
> +    CPUState *cpu = first_cpu;
>
>      qemu_clock_enable(vm_clock, true);
> -    while (penv) {
> -        CPUState *pcpu = ENV_GET_CPU(penv);
> -        cpu_resume(pcpu);
> -        penv = penv->next_cpu;
> +    while (cpu) {
> +        cpu_resume(cpu);
> +        cpu = cpu->next_cpu;
>      }
>  }
>
> @@ -1151,8 +1144,8 @@ static void tcg_exec_all(void)
>          next_cpu = first_cpu;
>      }
>      for (; next_cpu != NULL && !exit_request; next_cpu = next_cpu->next_cpu) {
> -        CPUArchState *env = next_cpu;
> -        CPUState *cpu = ENV_GET_CPU(env);
> +        CPUState *cpu = next_cpu;
> +        CPUArchState *env = cpu->env_ptr;
>
>          qemu_clock_enable(vm_clock,
>                            (env->singlestep_enabled & SSTEP_NOTIMER) == 0);
> @@ -1172,12 +1165,10 @@ static void tcg_exec_all(void)
>
>  void set_numa_modes(void)
>  {
> -    CPUArchState *env;
>      CPUState *cpu;
>      int i;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        cpu = ENV_GET_CPU(env);
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          for (i = 0; i < nb_numa_nodes; i++) {
>              if (test_bit(cpu->cpu_index, node_cpumask[i])) {
>                  cpu->numa_node = i;
> @@ -1197,18 +1188,30 @@ void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
>  CpuInfoList *qmp_query_cpus(Error **errp)
>  {
>      CpuInfoList *head = NULL, *cur_item = NULL;
> -    CPUArchState *env;
> +    CPUState *cpu;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        CPUState *cpu = ENV_GET_CPU(env);
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          CpuInfoList *info;
> +#if defined(TARGET_I386)
> +        X86CPU *x86_cpu = X86_CPU(cpu);
> +        CPUX86State *env = &x86_cpu->env;
> +#elif defined(TARGET_PPC)
> +        PowerPCCPU *ppc_cpu = POWERPC_CPU(cpu);
> +        CPUPPCState *env = &ppc_cpu->env;
> +#elif defined(TARGET_SPARC)
> +        SPARCCPU *sparc_cpu = SPARC_CPU(cpu);
> +        CPUSPARCState *env = &sparc_cpu->env;
> +#elif defined(TARGET_MIPS)
> +        MIPSCPU *mips_cpu = MIPS_CPU(cpu);
> +        CPUMIPSState *env = &mips_cpu->env;
> +#endif
>
>          cpu_synchronize_state(cpu);
>
>          info = g_malloc0(sizeof(*info));
>          info->value = g_malloc0(sizeof(*info->value));
>          info->value->CPU = cpu->cpu_index;
> -        info->value->current = (env == first_cpu);
> +        info->value->current = (cpu == first_cpu);
>          info->value->halted = cpu->halted;
>          info->value->thread_id = cpu->thread_id;
>  #if defined(TARGET_I386)
> @@ -1316,11 +1319,14 @@ exit:
>  void qmp_inject_nmi(Error **errp)
>  {
>  #if defined(TARGET_I386)
> -    CPUArchState *env;
> +    CPUState *cs;
> +
> +    for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
> +        X86CPU *cpu = X86_CPU(cs);
> +        CPUX86State *env = &cpu->env;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
>          if (!env->apic_state) {
> -            cpu_interrupt(CPU(x86_env_get_cpu(env)), CPU_INTERRUPT_NMI);
> +            cpu_interrupt(cs, CPU_INTERRUPT_NMI);
>          } else {
>              apic_deliver_nmi(env->apic_state);
>          }
> diff --git a/cputlb.c b/cputlb.c
> index 828007c..977c0ca 100644
> --- a/cputlb.c
> +++ b/cputlb.c
> @@ -186,11 +186,13 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
>
>  void cpu_tlb_reset_dirty_all(ram_addr_t start1, ram_addr_t length)
>  {
> +    CPUState *cpu;
>      CPUArchState *env;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          int mmu_idx;
>
> +        env = cpu->env_ptr;
>          for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
>              unsigned int i;
>
> diff --git a/dump.c b/dump.c
> index c812cfa..6a3a72a 100644
> --- a/dump.c
> +++ b/dump.c
> @@ -275,13 +275,11 @@ static inline int cpu_index(CPUState *cpu)
>
>  static int write_elf64_notes(DumpState *s)
>  {
> -    CPUArchState *env;
>      CPUState *cpu;
>      int ret;
>      int id;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        cpu = ENV_GET_CPU(env);
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          id = cpu_index(cpu);
>          ret = cpu_write_elf64_note(fd_write_vmcore, cpu, id, s);
>          if (ret < 0) {
> @@ -290,7 +288,7 @@ static int write_elf64_notes(DumpState *s)
>          }
>      }
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          ret = cpu_write_elf64_qemunote(fd_write_vmcore, cpu, s);
>          if (ret < 0) {
>              dump_error(s, "dump: failed to write CPU status.\n");
> @@ -327,13 +325,11 @@ static int write_elf32_note(DumpState *s)
>
>  static int write_elf32_notes(DumpState *s)
>  {
> -    CPUArchState *env;
>      CPUState *cpu;
>      int ret;
>      int id;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        cpu = ENV_GET_CPU(env);
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          id = cpu_index(cpu);
>          ret = cpu_write_elf32_note(fd_write_vmcore, cpu, id, s);
>          if (ret < 0) {
> @@ -342,7 +338,7 @@ static int write_elf32_notes(DumpState *s)
>          }
>      }
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          ret = cpu_write_elf32_qemunote(fd_write_vmcore, cpu, s);
>          if (ret < 0) {
>              dump_error(s, "dump: failed to write CPU status.\n");
> @@ -705,7 +701,7 @@ static ram_addr_t get_start_block(DumpState *s)
>  static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
>                       int64_t begin, int64_t length, Error **errp)
>  {
> -    CPUArchState *env;
> +    CPUState *cpu;
>      int nr_cpus;
>      Error *err = NULL;
>      int ret;
> @@ -738,7 +734,7 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
>       */
>      cpu_synchronize_all_states();
>      nr_cpus = 0;
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          nr_cpus++;
>      }
>
> diff --git a/exec.c b/exec.c
> index 9ca80cc..61b094a 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -69,7 +69,7 @@ static MemoryRegion io_mem_unassigned;
>
>  #endif
>
> -CPUArchState *first_cpu;
> +CPUState *first_cpu;
>  /* current CPU in the current thread. It is only valid inside
>     cpu_exec() */
>  DEFINE_TLS(CPUState *, current_cpu);
> @@ -351,27 +351,26 @@ const VMStateDescription vmstate_cpu_common = {
>
>  CPUState *qemu_get_cpu(int index)
>  {
> -    CPUArchState *env = first_cpu;
> -    CPUState *cpu = NULL;
> +    CPUState *cpu = first_cpu;
>
> -    while (env) {
> -        cpu = ENV_GET_CPU(env);
> +    while (cpu) {
>          if (cpu->cpu_index == index) {
>              break;
>          }
> -        env = env->next_cpu;
> +        cpu = cpu->next_cpu;
>      }
>
> -    return env ? cpu : NULL;
> +    return cpu;
>  }
>
>  void qemu_for_each_cpu(void (*func)(CPUState *cpu, void *data), void *data)
>  {
> -    CPUArchState *env = first_cpu;
> +    CPUState *cpu;
>
> -    while (env) {
> -        func(ENV_GET_CPU(env), data);
> -        env = env->next_cpu;
> +    cpu = first_cpu;
> +    while (cpu) {
> +        func(cpu, data);
> +        cpu = cpu->next_cpu;
>      }
>  }
>
> @@ -379,17 +378,17 @@ void cpu_exec_init(CPUArchState *env)
>  {
>      CPUState *cpu = ENV_GET_CPU(env);
>      CPUClass *cc = CPU_GET_CLASS(cpu);
> -    CPUArchState **penv;
> +    CPUState **pcpu;
>      int cpu_index;
>
>  #if defined(CONFIG_USER_ONLY)
>      cpu_list_lock();
>  #endif
> -    env->next_cpu = NULL;
> -    penv = &first_cpu;
> +    cpu->next_cpu = NULL;
> +    pcpu = &first_cpu;
>      cpu_index = 0;
> -    while (*penv != NULL) {
> -        penv = &(*penv)->next_cpu;
> +    while (*pcpu != NULL) {
> +        pcpu = &(*pcpu)->next_cpu;
>          cpu_index++;
>      }
>      cpu->cpu_index = cpu_index;
> @@ -399,7 +398,7 @@ void cpu_exec_init(CPUArchState *env)
>  #ifndef CONFIG_USER_ONLY
>      cpu->thread_id = qemu_get_thread_id();
>  #endif
> -    *penv = env;
> +    *pcpu = cpu;
>  #if defined(CONFIG_USER_ONLY)
>      cpu_list_unlock();
>  #endif
> @@ -638,7 +637,6 @@ void cpu_abort(CPUArchState *env, const char *fmt, ...)
>  CPUArchState *cpu_copy(CPUArchState *env)
>  {
>      CPUArchState *new_env = cpu_init(env->cpu_model_str);
> -    CPUArchState *next_cpu = new_env->next_cpu;
>  #if defined(TARGET_HAS_ICE)
>      CPUBreakpoint *bp;
>      CPUWatchpoint *wp;
> @@ -646,9 +644,6 @@ CPUArchState *cpu_copy(CPUArchState *env)
>
>      memcpy(new_env, env, sizeof(CPUArchState));
>
> -    /* Preserve chaining. */
> -    new_env->next_cpu = next_cpu;
> -
>      /* Clone all break/watchpoints.
>         Note: Once we support ptrace with hw-debug register access, make sure
>         BP_CPU break/watchpoints are handled correctly on clone. */
> @@ -1757,12 +1752,14 @@ static void core_commit(MemoryListener *listener)
>
>  static void tcg_commit(MemoryListener *listener)
>  {
> -    CPUArchState *env;
> +    CPUState *cpu;
>
>      /* since each CPU stores ram addresses in its TLB cache, we must
>         reset the modified entries */
>      /* XXX: slow ! */
> -    for(env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        CPUArchState *env = cpu->env_ptr;
> +
>          tlb_flush(env, 1);
>      }
>  }
> diff --git a/gdbstub.c b/gdbstub.c
> index f7d9f13..0ee82a9 100644
> --- a/gdbstub.c
> +++ b/gdbstub.c
> @@ -1839,6 +1839,7 @@ static const char *get_feature_xml(const char *p, const char **newp)
>          /* Generate the XML description for this CPU.  */
>          if (!target_xml[0]) {
>              GDBRegisterState *r;
> +            CPUArchState *env = first_cpu->env_ptr;
>
>              snprintf(target_xml, sizeof(target_xml),
>                       "<?xml version=\"1.0\"?>"
> @@ -1847,7 +1848,7 @@ static const char *get_feature_xml(const char *p, const char **newp)
>                       "<xi:include href=\"%s\"/>",
>                       GDB_CORE_XML);
>
> -            for (r = first_cpu->gdb_regs; r; r = r->next) {
> +            for (r = env->gdb_regs; r; r = r->next) {
>                  pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\"");
>                  pstrcat(target_xml, sizeof(target_xml), r->xml);
>                  pstrcat(target_xml, sizeof(target_xml), "\"/>");
> @@ -1949,6 +1950,7 @@ static const int xlat_gdb_type[] = {
>
>  static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
>  {
> +    CPUState *cpu;
>      CPUArchState *env;
>      int err = 0;
>
> @@ -1958,7 +1960,8 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
>      switch (type) {
>      case GDB_BREAKPOINT_SW:
>      case GDB_BREAKPOINT_HW:
> -        for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +        for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +            env = cpu->env_ptr;
>              err = cpu_breakpoint_insert(env, addr, BP_GDB, NULL);
>              if (err)
>                  break;
> @@ -1968,7 +1971,8 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
>      case GDB_WATCHPOINT_WRITE:
>      case GDB_WATCHPOINT_READ:
>      case GDB_WATCHPOINT_ACCESS:
> -        for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +        for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +            env = cpu->env_ptr;
>              err = cpu_watchpoint_insert(env, addr, len, xlat_gdb_type[type],
>                                          NULL);
>              if (err)
> @@ -1983,6 +1987,7 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
>
>  static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
>  {
> +    CPUState *cpu;
>      CPUArchState *env;
>      int err = 0;
>
> @@ -1992,7 +1997,8 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
>      switch (type) {
>      case GDB_BREAKPOINT_SW:
>      case GDB_BREAKPOINT_HW:
> -        for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +        for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +            env = cpu->env_ptr;
>              err = cpu_breakpoint_remove(env, addr, BP_GDB);
>              if (err)
>                  break;
> @@ -2002,7 +2008,8 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
>      case GDB_WATCHPOINT_WRITE:
>      case GDB_WATCHPOINT_READ:
>      case GDB_WATCHPOINT_ACCESS:
> -        for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +        for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +            env = cpu->env_ptr;
>              err = cpu_watchpoint_remove(env, addr, len, xlat_gdb_type[type]);
>              if (err)
>                  break;
> @@ -2016,6 +2023,7 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
>
>  static void gdb_breakpoint_remove_all(void)
>  {
> +    CPUState *cpu;
>      CPUArchState *env;
>
>      if (kvm_enabled()) {
> @@ -2023,7 +2031,8 @@ static void gdb_breakpoint_remove_all(void)
>          return;
>      }
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        env = cpu->env_ptr;
>          cpu_breakpoint_remove_all(env, BP_GDB);
>  #ifndef CONFIG_USER_ONLY
>          cpu_watchpoint_remove_all(env, BP_GDB);
> @@ -2071,13 +2080,11 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
>
>  static CPUArchState *find_cpu(uint32_t thread_id)
>  {
> -    CPUArchState *env;
>      CPUState *cpu;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        cpu = ENV_GET_CPU(env);
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          if (cpu_index(cpu) == thread_id) {
> -            return env;
> +            return cpu->env_ptr;
>          }
>      }
>
> @@ -2394,7 +2401,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
>              put_packet(s, "QC1");
>              break;
>          } else if (strcmp(p,"fThreadInfo") == 0) {
> -            s->query_cpu = first_cpu;
> +            s->query_cpu = first_cpu->env_ptr;
>              goto report_cpuinfo;
>          } else if (strcmp(p,"sThreadInfo") == 0) {
>          report_cpuinfo:
> @@ -2402,7 +2409,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
>                  snprintf(buf, sizeof(buf), "m%x",
>                           cpu_index(ENV_GET_CPU(s->query_cpu)));
>                  put_packet(s, buf);
> -                s->query_cpu = s->query_cpu->next_cpu;
> +                s->query_cpu = ENV_GET_CPU(s->query_cpu)->next_cpu->env_ptr;
next_cpu may be NULL.

>              } else
>                  put_packet(s, "l");
>              break;
> @@ -2869,8 +2876,8 @@ static void gdb_accept(void)
>      socket_set_nodelay(fd);
>
>      s = g_malloc0(sizeof(GDBState));
> -    s->c_cpu = first_cpu;
> -    s->g_cpu = first_cpu;
> +    s->c_cpu = first_cpu->env_ptr;
> +    s->g_cpu = first_cpu->env_ptr;
>      s->fd = fd;
>      gdb_has_xml = 0;
>
> @@ -3054,8 +3061,8 @@ int gdbserver_start(const char *device)
>          mon_chr = s->mon_chr;
>          memset(s, 0, sizeof(GDBState));
>      }
> -    s->c_cpu = first_cpu;
> -    s->g_cpu = first_cpu;
> +    s->c_cpu = first_cpu->env_ptr;
> +    s->g_cpu = first_cpu->env_ptr;
>      s->chr = chr;
>      s->state = chr ? RS_IDLE : RS_INACTIVE;
>      s->mon_chr = mon_chr;
> diff --git a/hw/arm/boot.c b/hw/arm/boot.c
> index 7c0090f..2b33444 100644
> --- a/hw/arm/boot.c
> +++ b/hw/arm/boot.c
> @@ -333,7 +333,7 @@ static void do_cpu_reset(void *opaque)
>              env->regs[15] = info->entry & 0xfffffffe;
>              env->thumb = info->entry & 1;
>          } else {
> -            if (env == first_cpu) {
> +            if (CPU(cpu) == first_cpu) {
>                  env->regs[15] = info->loader_start;
>                  if (!info->dtb_filename) {
>                      if (old_param) {
> @@ -351,7 +351,7 @@ static void do_cpu_reset(void *opaque)
>
>  void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
>  {
> -    CPUARMState *env = &cpu->env;
> +    CPUState *cs = CPU(cpu);
>      int kernel_size;
>      int initrd_size;
>      int n;
> @@ -476,9 +476,9 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
>      }
>      info->is_linux = is_linux;
>
> -    for (; env; env = env->next_cpu) {
> -        cpu = arm_env_get_cpu(env);
> -        env->boot_info = info;
> +    for (; cs; cs = cs->next_cpu) {
> +        cpu = ARM_CPU(cs);
> +        cpu->env.boot_info = info;
>          qemu_register_reset(do_cpu_reset, cpu);
>      }
>  }
> diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
> index 74f110b..7c90b2d 100644
> --- a/hw/arm/exynos4_boards.c
> +++ b/hw/arm/exynos4_boards.c
> @@ -131,7 +131,7 @@ static void nuri_init(QEMUMachineInitArgs *args)
>  {
>      exynos4_boards_init_common(args, EXYNOS4_BOARD_NURI);
>
> -    arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
> +    arm_load_kernel(ARM_CPU(first_cpu), &exynos4_board_binfo);
>  }
>
>  static void smdkc210_init(QEMUMachineInitArgs *args)
> @@ -141,7 +141,7 @@ static void smdkc210_init(QEMUMachineInitArgs *args)
>
>      lan9215_init(SMDK_LAN9118_BASE_ADDR,
>              qemu_irq_invert(s->irq_table[exynos4210_get_irq(37, 1)]));
> -    arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
> +    arm_load_kernel(ARM_CPU(first_cpu), &exynos4_board_binfo);
>  }
>
>  static QEMUMachine exynos4_machines[EXYNOS4_NUM_OF_BOARDS] = {
> diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
> index de6c98a..3a2fb4c 100644
> --- a/hw/arm/highbank.c
> +++ b/hw/arm/highbank.c
> @@ -321,7 +321,7 @@ static void highbank_init(QEMUMachineInitArgs *args)
>      highbank_binfo.loader_start = 0;
>      highbank_binfo.write_secondary_boot = hb_write_secondary;
>      highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
> -    arm_load_kernel(arm_env_get_cpu(first_cpu), &highbank_binfo);
> +    arm_load_kernel(ARM_CPU(first_cpu), &highbank_binfo);
>  }
>
>  static QEMUMachine highbank_machine = {
> diff --git a/hw/arm/realview.c b/hw/arm/realview.c
> index b596256..3060f48 100644
> --- a/hw/arm/realview.c
> +++ b/hw/arm/realview.c
> @@ -331,7 +331,7 @@ static void realview_init(QEMUMachineInitArgs *args,
>      realview_binfo.nb_cpus = smp_cpus;
>      realview_binfo.board_id = realview_board_id[board_type];
>      realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0);
> -    arm_load_kernel(arm_env_get_cpu(first_cpu), &realview_binfo);
> +    arm_load_kernel(ARM_CPU(first_cpu), &realview_binfo);
>  }
>
>  static void realview_eb_init(QEMUMachineInitArgs *args)
> diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
> index 710413e..fd18b60 100644
> --- a/hw/arm/vexpress.c
> +++ b/hw/arm/vexpress.c
> @@ -519,7 +519,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
>      vexpress_binfo.smp_loader_start = map[VE_SRAM];
>      vexpress_binfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30;
>      vexpress_binfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr;
> -    arm_load_kernel(arm_env_get_cpu(first_cpu), &vexpress_binfo);
> +    arm_load_kernel(ARM_CPU(first_cpu), &vexpress_binfo);
>  }
>
>  static void vexpress_a9_init(QEMUMachineInitArgs *args)
> diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
> index 0dc0871..3444823 100644
> --- a/hw/arm/xilinx_zynq.c
> +++ b/hw/arm/xilinx_zynq.c
> @@ -226,7 +226,7 @@ static void zynq_init(QEMUMachineInitArgs *args)
>      zynq_binfo.nb_cpus = 1;
>      zynq_binfo.board_id = 0xd32;
>      zynq_binfo.loader_start = 0;
> -    arm_load_kernel(arm_env_get_cpu(first_cpu), &zynq_binfo);
> +    arm_load_kernel(ARM_CPU(first_cpu), &zynq_binfo);
>  }
>
>  static QEMUMachine zynq_machine = {
> diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c
> index 98e5ca5..1022d67 100644
> --- a/hw/i386/kvm/clock.c
> +++ b/hw/i386/kvm/clock.c
> @@ -33,7 +33,7 @@ static void kvmclock_vm_state_change(void *opaque, int running,
>                                       RunState state)
>  {
>      KVMClockState *s = opaque;
> -    CPUArchState *penv = first_cpu;
> +    CPUState *cpu = first_cpu;
>      int cap_clock_ctrl = kvm_check_extension(kvm_state, KVM_CAP_KVMCLOCK_CTRL);
>      int ret;
>
> @@ -53,8 +53,8 @@ static void kvmclock_vm_state_change(void *opaque, int running,
>          if (!cap_clock_ctrl) {
>              return;
>          }
> -        for (penv = first_cpu; penv != NULL; penv = penv->next_cpu) {
> -            ret = kvm_vcpu_ioctl(ENV_GET_CPU(penv), KVM_KVMCLOCK_CTRL, 0);
> +        for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +            ret = kvm_vcpu_ioctl(cpu, KVM_KVMCLOCK_CTRL, 0);
>              if (ret) {
>                  if (ret != -EINVAL) {
>                      fprintf(stderr, "%s: %s\n", __func__, strerror(-ret));
> @@ -124,9 +124,11 @@ static const TypeInfo kvmclock_info = {
>  /* Note: Must be called after VCPU initialization. */
>  void kvmclock_create(void)
>  {
> +    X86CPU *cpu = X86_CPU(first_cpu);
> +
>      if (kvm_enabled() &&
> -        first_cpu->features[FEAT_KVM] & ((1ULL << KVM_FEATURE_CLOCKSOURCE) |
> -                                         (1ULL << KVM_FEATURE_CLOCKSOURCE2))) {
> +        cpu->env.features[FEAT_KVM] & ((1ULL << KVM_FEATURE_CLOCKSOURCE) |
> +                                       (1ULL << KVM_FEATURE_CLOCKSOURCE2))) {
>          sysbus_create_simple("kvmclock", -1, NULL);
>      }
>  }
> diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
> index e13678f..ccd089a 100644
> --- a/hw/i386/kvmvapic.c
> +++ b/hw/i386/kvmvapic.c
> @@ -490,13 +490,15 @@ static void vapic_enable_tpr_reporting(bool enable)
>      VAPICEnableTPRReporting info = {
>          .enable = enable,
>      };
> +    CPUState *cs;
>      X86CPU *cpu;
>      CPUX86State *env;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        cpu = x86_env_get_cpu(env);
> +    for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
> +        cpu = X86_CPU(cs);
> +        env = &cpu->env;
>          info.apic = env->apic_state;
> -        run_on_cpu(CPU(cpu), vapic_do_enable_tpr_reporting, &info);
> +        run_on_cpu(cs, vapic_do_enable_tpr_reporting, &info);
>      }
>  }
>
> @@ -719,8 +721,9 @@ static int vapic_init(SysBusDevice *dev)
>  static void do_vapic_enable(void *data)
>  {
>      VAPICROMState *s = data;
> +    X86CPU *cpu = X86_CPU(first_cpu);
>
> -    vapic_enable(s, first_cpu);
> +    vapic_enable(s, &cpu->env);
>  }
>
>  static int vapic_post_load(void *opaque, int version_id)
> @@ -743,7 +746,7 @@ static int vapic_post_load(void *opaque, int version_id)
>      }
>      if (s->state == VAPIC_ACTIVE) {
>          if (smp_cpus == 1) {
> -            run_on_cpu(ENV_GET_CPU(first_cpu), do_vapic_enable, s);
> +            run_on_cpu(first_cpu, do_vapic_enable, s);
>          } else {
>              zero = g_malloc0(s->rom_state.vapic_size);
>              cpu_physical_memory_rw(s->vapic_paddr, zero,
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index 5224256..c5d8570 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -160,8 +160,9 @@ void cpu_smm_register(cpu_set_smm_t callback, void *arg)
>
>  void cpu_smm_update(CPUX86State *env)
>  {
> -    if (smm_set && smm_arg && env == first_cpu)
> +    if (smm_set && smm_arg && CPU(x86_env_get_cpu(env)) == first_cpu) {
>          smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg);
> +    }
>  }
>
>
> @@ -185,18 +186,21 @@ int cpu_get_pic_interrupt(CPUX86State *env)
>
>  static void pic_irq_request(void *opaque, int irq, int level)
>  {
> -    CPUX86State *env = first_cpu;
> +    CPUState *cs = first_cpu;
> +    X86CPU *cpu = X86_CPU(cs);
> +    CPUX86State *env = &cpu->env;
>
>      DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
>      if (env->apic_state) {
> -        while (env) {
> +        while (cs) {
> +            cpu = X86_CPU(cs);
> +            env = &cpu->env;
>              if (apic_accept_pic_intr(env->apic_state)) {
>                  apic_deliver_pic_intr(env->apic_state, level);
>              }
> -            env = env->next_cpu;
> +            cs = cs->next_cpu;
>          }
>      } else {
> -        CPUState *cs = CPU(x86_env_get_cpu(env));
>          if (level) {
>              cpu_interrupt(cs, CPU_INTERRUPT_HARD);
>          } else {
> @@ -1274,8 +1278,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
>          }
>      }
>
> -    a20_line = qemu_allocate_irqs(handle_a20_line_change,
> -                                  x86_env_get_cpu(first_cpu), 2);
> +    a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);
>      i8042 = isa_create_simple(isa_bus, "i8042");
>      i8042_setup_a20_line(i8042, &a20_line[0]);
>      if (!no_vmport) {
> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> index 01323a9..b58c255 100644
> --- a/hw/i386/pc_piix.c
> +++ b/hw/i386/pc_piix.c
> @@ -229,8 +229,7 @@ static void pc_init1(MemoryRegion *system_memory,
>      if (pci_enabled && acpi_enabled) {
>          i2c_bus *smbus;
>
> -        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt,
> -                                     x86_env_get_cpu(first_cpu), 1);
> +        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
>          /* TODO: Populate SPD eeprom data.  */
>          smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
>                                gsi[9], *smi_irq,
> diff --git a/hw/intc/sh_intc.c b/hw/intc/sh_intc.c
> index f397950..55c76e4 100644
> --- a/hw/intc/sh_intc.c
> +++ b/hw/intc/sh_intc.c
> @@ -42,16 +42,15 @@ void sh_intc_toggle_source(struct intc_source *source,
>          pending_changed = 1;
>
>      if (pending_changed) {
> -        CPUState *cpu = CPU(sh_env_get_cpu(first_cpu));
>          if (source->pending) {
>              source->parent->pending++;
>              if (source->parent->pending == 1) {
> -                cpu_interrupt(cpu, CPU_INTERRUPT_HARD);
> +                cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD);
>              }
>          } else {
>              source->parent->pending--;
>              if (source->parent->pending == 0) {
> -                cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
> +                cpu_reset_interrupt(first_cpu, CPU_INTERRUPT_HARD);
>              }
>         }
>      }
> diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
> index b49be4d..d1921aa 100644
> --- a/hw/isa/lpc_ich9.c
> +++ b/hw/isa/lpc_ich9.c
> @@ -380,7 +380,7 @@ static void ich9_apm_ctrl_changed(uint32_t val, void *arg)
>
>      /* SMI_EN = PMBASE + 30. SMI control and enable register */
>      if (lpc->pm.smi_en & ICH9_PMIO_SMI_EN_APMC_EN) {
> -        cpu_interrupt(CPU(x86_env_get_cpu(first_cpu)), CPU_INTERRUPT_SMI);
> +        cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
>      }
>  }
>
> diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
> index 7e56121..de87241 100644
> --- a/hw/mips/mips_malta.c
> +++ b/hw/mips/mips_malta.c
> @@ -844,7 +844,8 @@ void mips_malta_init(QEMUMachineInitArgs *args)
>          cpu_mips_clock_init(env);
>          qemu_register_reset(main_cpu_reset, cpu);
>      }
> -    env = first_cpu;
> +    cpu = MIPS_CPU(first_cpu);
> +    env = &cpu->env;
>
>      /* allocate RAM */
>      if (ram_size > (256 << 20)) {
> diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
> index 69837a5..9600599 100644
> --- a/hw/ppc/e500.c
> +++ b/hw/ppc/e500.c
> @@ -500,7 +500,6 @@ static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params,
>                                            qemu_irq **irqs)
>  {
>      DeviceState *dev;
> -    CPUPPCState *env;
>      CPUState *cs;
>      int r;
>
> @@ -512,9 +511,7 @@ static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params,
>          return NULL;
>      }
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        cs = ENV_GET_CPU(env);
> -
> +    for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
>          if (kvm_openpic_connect_vcpu(dev, cs)) {
>              fprintf(stderr, "%s: failed to connect vcpu to irqchip\n",
>                      __func__);
> diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
> index fb57b42..554f244 100644
> --- a/hw/ppc/ppc.c
> +++ b/hw/ppc/ppc.c
> @@ -440,15 +440,14 @@ void ppce500_irq_init(CPUPPCState *env)
>  /* Enable or Disable the E500 EPR capability */
>  void ppce500_set_mpic_proxy(bool enabled)
>  {
> -    CPUPPCState *env;
> +    CPUState *cs;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        PowerPCCPU *cpu = ppc_env_get_cpu(env);
> -        CPUState *cs = CPU(cpu);
> +    for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
> +        PowerPCCPU *cpu = POWERPC_CPU(cs);
>
> -        env->mpic_proxy = enabled;
> +        cpu->env.mpic_proxy = enabled;
>          if (kvm_enabled()) {
> -            kvmppc_set_mpic_proxy(POWERPC_CPU(cs), enabled);
> +            kvmppc_set_mpic_proxy(cpu, enabled);
>          }
>      }
>  }
> diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
> index d07dd01..19f2442 100644
> --- a/hw/ppc/prep.c
> +++ b/hw/ppc/prep.c
> @@ -605,8 +605,9 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
>      /* PCI -> ISA bridge */
>      pci = pci_create_simple(pci_bus, PCI_DEVFN(1, 0), "i82378");
>      cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
> +    cpu = POWERPC_CPU(first_cpu);
>      qdev_connect_gpio_out(&pci->qdev, 0,
> -                          first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
> +                          cpu->env.irq_inputs[PPC6xx_INPUT_INT]);
>      qdev_connect_gpio_out(&pci->qdev, 1, *cpu_exit_irq);
>      sysbus_connect_irq(&pcihost->busdev, 0, qdev_get_gpio_in(&pci->qdev, 9));
>      sysbus_connect_irq(&pcihost->busdev, 1, qdev_get_gpio_in(&pci->qdev, 11));
> @@ -651,7 +652,8 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
>      }
>      isa_create_simple(isa_bus, "i8042");
>
> -    sysctrl->reset_irq = first_cpu->irq_inputs[PPC6xx_INPUT_HRESET];
> +    cpu = POWERPC_CPU(first_cpu);
> +    sysctrl->reset_irq = cpu->env.irq_inputs[PPC6xx_INPUT_HRESET];
>
>      portio_list_init(port_list, NULL, prep_portio_list, sysctrl, "prep");
>      portio_list_add(port_list, get_system_io(), 0x0);
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index c040794..e46aad3 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -131,7 +131,6 @@ int spapr_allocate_irq_block(int num, bool lsi)
>  static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
>  {
>      int ret = 0, offset;
> -    CPUPPCState *env;
>      CPUState *cpu;
>      char cpu_model[32];
>      int smt = kvmppc_smt_threads();
> @@ -139,8 +138,7 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
>
>      assert(spapr->cpu_model);
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        cpu = CPU(ppc_env_get_cpu(env));
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          uint32_t associativity[] = {cpu_to_be32(0x5),
>                                      cpu_to_be32(0x0),
>                                      cpu_to_be32(0x0),
> @@ -231,7 +229,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
>                                     uint32_t epow_irq)
>  {
>      void *fdt;
> -    CPUPPCState *env;
> +    CPUState *cs;
>      uint32_t start_prop = cpu_to_be32(initrd_base);
>      uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
>      char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
> @@ -304,10 +302,11 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
>      /* This is needed during FDT finalization */
>      spapr->cpu_model = g_strdup(modelname);
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        CPUState *cpu = CPU(ppc_env_get_cpu(env));
> -        PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
> -        int index = cpu->cpu_index;
> +    for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
> +        PowerPCCPU *cpu = POWERPC_CPU(cs);
> +        CPUPPCState *env = &cpu->env;
> +        PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
> +        int index = cs->cpu_index;
>          uint32_t servers_prop[smp_threads];
>          uint32_t gservers_prop[smp_threads * 2];
>          char *nodename;
> @@ -632,7 +631,7 @@ static void spapr_reset_htab(sPAPREnvironment *spapr)
>
>  static void ppc_spapr_reset(void)
>  {
> -    CPUState *first_cpu_cpu;
> +    PowerPCCPU *first_ppc_cpu;
>
>      /* Reset the hash table & recalc the RMA */
>      spapr_reset_htab(spapr);
> @@ -644,11 +643,11 @@ static void ppc_spapr_reset(void)
>                         spapr->rtas_size);
>
>      /* Set up the entry state */
> -    first_cpu_cpu = ENV_GET_CPU(first_cpu);
> -    first_cpu->gpr[3] = spapr->fdt_addr;
> -    first_cpu->gpr[5] = 0;
> -    first_cpu_cpu->halted = 0;
> -    first_cpu->nip = spapr->entry_point;
> +    first_ppc_cpu = POWERPC_CPU(first_cpu);
> +    first_ppc_cpu->env.gpr[3] = spapr->fdt_addr;
> +    first_ppc_cpu->env.gpr[5] = 0;
> +    first_cpu->halted = 0;
> +    first_ppc_cpu->env.nip = spapr->entry_point;
>
>  }
>
> diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
> index 6760851..6499cd0 100644
> --- a/include/exec/cpu-all.h
> +++ b/include/exec/cpu-all.h
> @@ -356,7 +356,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;
>
>  /* Flags for use in ENV->INTERRUPT_PENDING.
>
> diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
> index c4ac929..39094b3 100644
> --- a/include/exec/cpu-defs.h
> +++ b/include/exec/cpu-defs.h
> @@ -181,7 +181,6 @@ typedef struct CPUWatchpoint {
>      sigjmp_buf jmp_env;                                                 \
>      int exception_index;                                                \
>                                                                          \
> -    CPUArchState *next_cpu; /* next CPU sharing TB cache */                 \
>      /* user data */                                                     \
>      void *opaque;                                                       \
>                                                                          \
> diff --git a/include/qom/cpu.h b/include/qom/cpu.h
> index d7fc186..a08a8ab 100644
> --- a/include/qom/cpu.h
> +++ b/include/qom/cpu.h
> @@ -114,6 +114,7 @@ struct kvm_run;
>   *           CPU and return to its top level loop.
>   * @env_ptr: Pointer to subclass-specific CPUArchState field.
>   * @current_tb: Currently executing TB.
> + * @next_cpu: Next CPU sharing TB cache.
>   * @kvm_fd: vCPU file descriptor for KVM.
>   *
>   * State of one CPU core or thread.
> @@ -146,6 +147,7 @@ struct CPUState {
>
>      void *env_ptr; /* CPUArchState */
>      struct TranslationBlock *current_tb;
> +    CPUState *next_cpu;
>
>      int kvm_fd;
>      bool kvm_vcpu_dirty;
> @@ -157,6 +159,8 @@ struct CPUState {
>      uint32_t halted; /* used by alpha, cris, ppc TCG */
>  };
>
> +extern CPUState *first_cpu;
> +
>  DECLARE_TLS(CPUState *, current_cpu);
>  #define current_cpu tls_var(current_cpu)
>
> diff --git a/kvm-all.c b/kvm-all.c
> index 2c14ef3..c130705 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -1938,7 +1938,9 @@ int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr,
>          }
>      }
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        CPUArchState *env = cpu->env_ptr;
> +
>          err = kvm_update_guest_debug(env, 0);
>          if (err) {
>              return err;
> @@ -1979,7 +1981,9 @@ int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
>          }
>      }
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        CPUArchState *env = cpu->env_ptr;
> +
>          err = kvm_update_guest_debug(env, 0);
>          if (err) {
>              return err;
> @@ -1992,13 +1996,11 @@ void kvm_remove_all_breakpoints(CPUState *cpu)
>  {
>      struct kvm_sw_breakpoint *bp, *next;
>      KVMState *s = cpu->kvm_state;
> -    CPUArchState *env;
>
>      QTAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) {
>          if (kvm_arch_remove_sw_breakpoint(cpu, bp) != 0) {
>              /* Try harder to find a CPU that currently sees the breakpoint. */
> -            for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -                cpu = ENV_GET_CPU(env);
> +            for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>                  if (kvm_arch_remove_sw_breakpoint(cpu, bp) == 0) {
>                      break;
>                  }
> @@ -2009,7 +2011,9 @@ void kvm_remove_all_breakpoints(CPUState *cpu)
>      }
>      kvm_arch_remove_all_hw_breakpoints();
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        CPUArchState *env = cpu->env_ptr;
> +
>          kvm_update_guest_debug(env, 0);
>      }
>  }
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index ddef23e..d517450 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -2628,7 +2628,7 @@ static int fill_note_info(struct elf_note_info *info,
>                            long signr, const CPUArchState *env)
>  {
>  #define NUMNOTES 3
> -    CPUArchState *cpu = NULL;
> +    CPUState *cpu = NULL;
>      TaskState *ts = (TaskState *)env->opaque;
>      int i;
>
> @@ -2667,9 +2667,10 @@ static int fill_note_info(struct elf_note_info *info,
>      /* read and fill status of all threads */
>      cpu_list_lock();
>      for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> -        if (cpu == thread_env)
> +        if (cpu == ENV_GET_CPU(thread_env)) {
>              continue;
> -        fill_thread_info(info, cpu);
> +        }
> +        fill_thread_info(info, (CPUArchState *)cpu->env_ptr);
>      }
>      cpu_list_unlock();
>
> diff --git a/linux-user/main.c b/linux-user/main.c
> index af82db8..564bed6 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -120,8 +120,8 @@ void fork_end(int child)
>      if (child) {
>          /* Child processes created by fork() only have a single thread.
>             Discard information about the parent threads.  */
> -        first_cpu = thread_env;
> -        thread_env->next_cpu = NULL;
> +        first_cpu = ENV_GET_CPU(thread_env);
> +        first_cpu->next_cpu = NULL;
>          pending_cpus = 0;
>          pthread_mutex_init(&exclusive_lock, NULL);
>          pthread_mutex_init(&cpu_list_mutex, NULL);
> @@ -148,7 +148,6 @@ static inline void exclusive_idle(void)
>     Must only be called from outside cpu_arm_exec.   */
>  static inline void start_exclusive(void)
>  {
> -    CPUArchState *other;
>      CPUState *other_cpu;
>
>      pthread_mutex_lock(&exclusive_lock);
> @@ -156,8 +155,7 @@ static inline void start_exclusive(void)
>
>      pending_cpus = 1;
>      /* Make all other cpus stop executing.  */
> -    for (other = first_cpu; other; other = other->next_cpu) {
> -        other_cpu = ENV_GET_CPU(other);
> +    for (other_cpu = first_cpu; other_cpu; other_cpu = other_cpu->next_cpu) {
>          if (other_cpu->running) {
>              pending_cpus++;
>              cpu_exit(other_cpu);
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index a2125fa..4c96f4f 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -5030,6 +5030,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>                      abi_long arg5, abi_long arg6, abi_long arg7,
>                      abi_long arg8)
>  {
> +#ifdef CONFIG_USE_NPTL
> +    CPUState *cpu = ENV_GET_CPU(cpu_env);
> +#endif
>      abi_long ret;
>      struct stat st;
>      struct statfs stfs;
> @@ -5052,13 +5055,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>             be disabling signals.  */
>          if (first_cpu->next_cpu) {
>              TaskState *ts;
> -            CPUArchState **lastp;
> -            CPUArchState *p;
> +            CPUState **lastp;
> +            CPUState *p;
>
>              cpu_list_lock();
>              lastp = &first_cpu;
>              p = first_cpu;
> -            while (p && p != (CPUArchState *)cpu_env) {
> +            while (p && p != cpu) {
>                  lastp = &p->next_cpu;
>                  p = p->next_cpu;
>              }
> diff --git a/memory_mapping.c b/memory_mapping.c
> index 5634f81..515a984 100644
> --- a/memory_mapping.c
> +++ b/memory_mapping.c
> @@ -165,13 +165,13 @@ void memory_mapping_list_init(MemoryMappingList *list)
>      QTAILQ_INIT(&list->head);
>  }
>
> -static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu)
> +static CPUState *find_paging_enabled_cpu(CPUState *start_cpu)
>  {
> -    CPUArchState *env;
> +    CPUState *cpu;
>
> -    for (env = start_cpu; env != NULL; env = env->next_cpu) {
> -        if (cpu_paging_enabled(ENV_GET_CPU(env))) {
> -            return env;
> +    for (cpu = start_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        if (cpu_paging_enabled(cpu)) {
> +            return cpu;
>          }
>      }
>
> @@ -180,15 +180,15 @@ static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu)
>
>  void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp)
>  {
> -    CPUArchState *env, *first_paging_enabled_cpu;
> +    CPUState *cpu, *first_paging_enabled_cpu;
>      RAMBlock *block;
>      ram_addr_t offset, length;
>
>      first_paging_enabled_cpu = find_paging_enabled_cpu(first_cpu);
>      if (first_paging_enabled_cpu) {
> -        for (env = first_paging_enabled_cpu; env != NULL; env = env->next_cpu) {
> +        for (cpu = first_paging_enabled_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>              Error *err = NULL;
> -            cpu_get_memory_mapping(ENV_GET_CPU(env), list, &err);
> +            cpu_get_memory_mapping(cpu, list, &err);
>              if (err) {
>                  error_propagate(errp, err);
>                  return;
> diff --git a/monitor.c b/monitor.c
> index 9be515c..2ba7876 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -1806,14 +1806,12 @@ static void do_info_mtree(Monitor *mon, const QDict *qdict)
>  static void do_info_numa(Monitor *mon, const QDict *qdict)
>  {
>      int i;
> -    CPUArchState *env;
>      CPUState *cpu;
>
>      monitor_printf(mon, "%d nodes\n", nb_numa_nodes);
>      for (i = 0; i < nb_numa_nodes; i++) {
>          monitor_printf(mon, "node %d cpus:", i);
> -        for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -            cpu = ENV_GET_CPU(env);
> +        for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>              if (cpu->numa_node == i) {
>                  monitor_printf(mon, " %d", cpu->cpu_index);
>              }
> diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
> index 83898cd..d133228 100644
> --- a/target-i386/arch_dump.c
> +++ b/target-i386/arch_dump.c
> @@ -185,7 +185,8 @@ int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
>      X86CPU *cpu = X86_CPU(cs);
>      int ret;
>  #ifdef TARGET_X86_64
> -    bool lma = !!(first_cpu->hflags & HF_LMA_MASK);
> +    X86CPU *first_x86_cpu = X86_CPU(first_cpu);
> +    bool lma = !!(first_x86_cpu->env.hflags & HF_LMA_MASK);
>
>      if (lma) {
>          ret = x86_64_write_elf64_note(f, &cpu->env, cpuid, opaque);
> @@ -394,7 +395,9 @@ int cpu_get_dump_info(ArchDumpInfo *info)
>      RAMBlock *block;
>
>  #ifdef TARGET_X86_64
> -    lma = !!(first_cpu->hflags & HF_LMA_MASK);
> +    X86CPU *first_x86_cpu = X86_CPU(first_cpu);
> +
> +    lma = !!(first_x86_cpu->env.hflags & HF_LMA_MASK);
>  #endif
>
>      if (lma) {
> diff --git a/target-i386/helper.c b/target-i386/helper.c
> index 5e5abe3..d6f43d7 100644
> --- a/target-i386/helper.c
> +++ b/target-i386/helper.c
> @@ -1188,6 +1188,7 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
>                          uint64_t status, uint64_t mcg_status, uint64_t addr,
>                          uint64_t misc, int flags)
>  {
> +    CPUState *cs = CPU(cpu);
>      CPUX86State *cenv = &cpu->env;
>      MCEInjectionParams params = {
>          .mon = mon,
> @@ -1200,7 +1201,6 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
>          .flags = flags,
>      };
>      unsigned bank_num = cenv->mcg_cap & 0xff;
> -    CPUX86State *env;
>
>      if (!cenv->mcg_cap) {
>          monitor_printf(mon, "MCE injection not supported\n");
> @@ -1220,19 +1220,22 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
>          return;
>      }
>
> -    run_on_cpu(CPU(cpu), do_inject_x86_mce, &params);
> +    run_on_cpu(cs, do_inject_x86_mce, &params);
>      if (flags & MCE_INJECT_BROADCAST) {
> +        CPUState *other_cs;
> +
>          params.bank = 1;
>          params.status = MCI_STATUS_VAL | MCI_STATUS_UC;
>          params.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV;
>          params.addr = 0;
>          params.misc = 0;
> -        for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -            if (cenv == env) {
> +        for (other_cs = first_cpu; other_cs != NULL;
> +             other_cs = other_cs->next_cpu) {
> +            if (other_cs == cs) {
>                  continue;
>              }
> -            params.cpu = x86_env_get_cpu(env);
> -            run_on_cpu(CPU(cpu), do_inject_x86_mce, &params);
> +            params.cpu = X86_CPU(other_cs);
> +            run_on_cpu(other_cs, do_inject_x86_mce, &params);
>          }
>      }
>  }
> diff --git a/target-i386/kvm.c b/target-i386/kvm.c
> index 4b557b3..935ef63 100644
> --- a/target-i386/kvm.c
> +++ b/target-i386/kvm.c
> @@ -345,20 +345,22 @@ int kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
>
>  int kvm_arch_on_sigbus(int code, void *addr)
>  {
> -    if ((first_cpu->mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) {
> +    X86CPU *cpu = X86_CPU(first_cpu);
> +
> +    if ((cpu->env.mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) {
>          ram_addr_t ram_addr;
>          hwaddr paddr;
>
>          /* Hope we are lucky for AO MCE */
>          if (qemu_ram_addr_from_host(addr, &ram_addr) == NULL ||
> -            !kvm_physical_memory_addr_from_host(CPU(first_cpu)->kvm_state,
> +            !kvm_physical_memory_addr_from_host(first_cpu->kvm_state,
>                                                  addr, &paddr)) {
>              fprintf(stderr, "Hardware memory error for memory used by "
>                      "QEMU itself instead of guest system!: %p\n", addr);
>              return 0;
>          }
>          kvm_hwpoison_page_add(ram_addr);
> -        kvm_mce_inject(x86_env_get_cpu(first_cpu), paddr, code);
> +        kvm_mce_inject(X86_CPU(first_cpu), paddr, code);
>      } else {
>          if (code == BUS_MCEERR_AO) {
>              return 0;
> diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
> index e345f9a..957926c 100644
> --- a/target-i386/misc_helper.c
> +++ b/target-i386/misc_helper.c
> @@ -610,7 +610,7 @@ void helper_mwait(CPUX86State *env, int next_eip_addend)
>      cpu = x86_env_get_cpu(env);
>      cs = CPU(cpu);
>      /* XXX: not complete but not completely erroneous */
> -    if (cs->cpu_index != 0 || env->next_cpu != NULL) {
> +    if (cs->cpu_index != 0 || cs->next_cpu != NULL) {
>          /* more than one CPU: do not sleep because another CPU may
>             wake this one */
>      } else {
> diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
> index f6838ec..5cf1c3f 100644
> --- a/target-mips/op_helper.c
> +++ b/target-mips/op_helper.c
> @@ -1696,39 +1696,38 @@ target_ulong helper_emt(void)
>
>  target_ulong helper_dvpe(CPUMIPSState *env)
>  {
> -    CPUMIPSState *other_cpu_env = first_cpu;
> +    CPUState *other_cs = first_cpu;
>      target_ulong prev = env->mvp->CP0_MVPControl;
>
>      do {
> +        MIPSCPU *other_cpu = MIPS_CPU(other_cs);
>          /* Turn off all VPEs except the one executing the dvpe.  */
> -        if (other_cpu_env != env) {
> -            MIPSCPU *other_cpu = mips_env_get_cpu(other_cpu_env);
> -
> -            other_cpu_env->mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP);
> +        if (&other_cpu->env != env) {
> +            other_cpu->env.mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP);
>              mips_vpe_sleep(other_cpu);
>          }
> -        other_cpu_env = other_cpu_env->next_cpu;
> -    } while (other_cpu_env);
> +        other_cs = other_cs->next_cpu;
> +    } while (other_cs);
>      return prev;
>  }
>
>  target_ulong helper_evpe(CPUMIPSState *env)
>  {
> -    CPUMIPSState *other_cpu_env = first_cpu;
> +    CPUState *other_cs = first_cpu;
>      target_ulong prev = env->mvp->CP0_MVPControl;
>
>      do {
> -        MIPSCPU *other_cpu = mips_env_get_cpu(other_cpu_env);
> +        MIPSCPU *other_cpu = MIPS_CPU(other_cs);
>
> -        if (other_cpu_env != env
> +        if (&other_cpu->env != env
>              /* If the VPE is WFI, don't disturb its sleep.  */
>              && !mips_vpe_is_wfi(other_cpu)) {
>              /* Enable the VPE.  */
> -            other_cpu_env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
> +            other_cpu->env.mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
>              mips_vpe_wake(other_cpu); /* And wake it up.  */
>          }
> -        other_cpu_env = other_cpu_env->next_cpu;
> -    } while (other_cpu_env);
> +        other_cs = other_cs->next_cpu;
> +    } while (other_cs);
>      return prev;
>  }
>  #endif /* !CONFIG_USER_ONLY */
> diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
> index 4a0fc6d..e9fcad8 100644
> --- a/target-ppc/excp_helper.c
> +++ b/target-ppc/excp_helper.c
> @@ -986,16 +986,19 @@ void helper_msgsnd(target_ulong rb)
>  {
>      int irq = dbell2irq(rb);
>      int pir = rb & DBELL_PIRTAG_MASK;
> -    CPUPPCState *cenv;
> +    CPUState *cs;
>
>      if (irq < 0) {
>          return;
>      }
>
> -    for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
> +    for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
> +        PowerPCCPU *cpu = POWERPC_CPU(cs);
> +        CPUPPCState *cenv = &cpu->env;
> +
>          if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
>              cenv->pending_interrupts |= 1 << irq;
> -            cpu_interrupt(CPU(ppc_env_get_cpu(cenv)), CPU_INTERRUPT_HARD);
> +            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
>          }
>      }
>  }
> diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
> index e95ad4a..b0099e1 100644
> --- a/target-ppc/kvm.c
> +++ b/target-ppc/kvm.c
> @@ -1579,7 +1579,7 @@ uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
>
>      /* Find the largest hardware supported page size that's less than
>       * or equal to the (logical) backing page size of guest RAM */
> -    kvm_get_smmu_info(ppc_env_get_cpu(first_cpu), &info);
> +    kvm_get_smmu_info(POWERPC_CPU(first_cpu), &info);
>      rampagesize = getrampagesize();
>      best_page_shift = 0;
>
> diff --git a/translate-all.c b/translate-all.c
> index 02f8e5e..e8683d2 100644
> --- a/translate-all.c
> +++ b/translate-all.c
> @@ -681,7 +681,7 @@ static void page_flush_tb(void)
>  /* XXX: tb_flush is currently not thread safe */
>  void tb_flush(CPUArchState *env1)
>  {
> -    CPUArchState *env;
> +    CPUState *cpu;
>
>  #if defined(DEBUG_FLUSH)
>      printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
> @@ -696,7 +696,9 @@ void tb_flush(CPUArchState *env1)
>      }
>      tcg_ctx.tb_ctx.nb_tbs = 0;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        CPUArchState *env = cpu->env_ptr;
> +
>          memset(env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof(void *));
>      }
>
> @@ -821,7 +823,7 @@ static inline void tb_reset_jump(TranslationBlock *tb, int n)
>  /* invalidate one TB */
>  void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
>  {
> -    CPUArchState *env;
> +    CPUState *cpu;
>      PageDesc *p;
>      unsigned int h, n1;
>      tb_page_addr_t phys_pc;
> @@ -848,7 +850,9 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
>
>      /* remove the TB from the hash list */
>      h = tb_jmp_cache_hash_func(tb->pc);
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        CPUArchState *env = cpu->env_ptr;
> +
>          if (env->tb_jmp_cache[h] == tb) {
>              env->tb_jmp_cache[h] = NULL;
>          }
> --
> 1.8.1.4
>
>

WARNING: multiple messages have this Message-ID (diff)
From: TeLeMan <geleman@gmail.com>
To: "Andreas Färber" <afaerber@suse.de>
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
	"Gleb Natapov" <gleb@redhat.com>,
	qemu-devel <qemu-devel@nongnu.org>,
	"Luiz Capitulino" <lcapitulino@redhat.com>,
	"Peter Crosthwaite" <peter.crosthwaite@petalogix.com>,
	"Edgar E. Iglesias" <edgar.iglesias@gmail.com>,
	"Igor Mitsyanko" <i.mitsyanko@samsung.com>,
	"Evgeny Voevodin" <e.voevodin@samsung.com>,
	"Alexander Graf" <agraf@suse.de>,
	"Andreas Färber" <andreas.faerber@web.de>,
	"Maksim Kozlov" <m.kozlov@samsung.com>,
	"Riku Voipio" <riku.voipio@iki.fi>,
	"Paul Brook" <paul@codesourcery.com>,
	"open list:Overall" <kvm@vger.kernel.org>,
	"Scott Wood" <scottwood@freescale.com>,
	"Anthony Liguori" <aliguori@us.ibm.com>,
	"Mark Langsdorf" <mark.langsdorf@calxeda.com>,
	"Marcelo Tosatti" <mtosatti@redhat.com>,
	"open list:e500" <qemu-ppc@nongnu.org>,
	"Dmitry Solodkiy" <d.solodkiy@samsung.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Aurelien Jarno" <aurelien@aurel32.net>
Subject: Re: [Qemu-devel] [PULL 09/43] cpu: Make first_cpu and next_cpu CPUState
Date: Thu, 11 Jul 2013 17:14:23 +0800	[thread overview]
Message-ID: <CAETRQWm+s+zrOFv9_RFYJnSuijVYUU6RiSsW1K26uGzT0pUhTA@mail.gmail.com> (raw)
In-Reply-To: <1373466860-32732-10-git-send-email-afaerber@suse.de>

On Wed, Jul 10, 2013 at 10:33 PM, Andreas Färber <afaerber@suse.de> wrote:
> Move next_cpu from CPU_COMMON to CPUState.
> Move first_cpu variable to qom/cpu.h.
>
> gdbstub needs to use CPUState::env_ptr for now.
> cpu_copy() no longer needs to save and restore cpu_next.
>
> Acked-by: Paolo Bonzini <pbonzini@redhat.com>
> [AF: Rebased, simplified cpu_copy()]
> Signed-off-by: Andreas Färber <afaerber@suse.de>
> ---
>  cpus.c                    | 126 ++++++++++++++++++++++++----------------------
>  cputlb.c                  |   4 +-
>  dump.c                    |  16 +++---
>  exec.c                    |  43 ++++++++--------
>  gdbstub.c                 |  39 ++++++++------
>  hw/arm/boot.c             |  10 ++--
>  hw/arm/exynos4_boards.c   |   4 +-
>  hw/arm/highbank.c         |   2 +-
>  hw/arm/realview.c         |   2 +-
>  hw/arm/vexpress.c         |   2 +-
>  hw/arm/xilinx_zynq.c      |   2 +-
>  hw/i386/kvm/clock.c       |  12 +++--
>  hw/i386/kvmvapic.c        |  13 +++--
>  hw/i386/pc.c              |  17 ++++---
>  hw/i386/pc_piix.c         |   3 +-
>  hw/intc/sh_intc.c         |   5 +-
>  hw/isa/lpc_ich9.c         |   2 +-
>  hw/mips/mips_malta.c      |   3 +-
>  hw/ppc/e500.c             |   5 +-
>  hw/ppc/ppc.c              |  11 ++--
>  hw/ppc/prep.c             |   6 ++-
>  hw/ppc/spapr.c            |  27 +++++-----
>  include/exec/cpu-all.h    |   1 -
>  include/exec/cpu-defs.h   |   1 -
>  include/qom/cpu.h         |   4 ++
>  kvm-all.c                 |  16 +++---
>  linux-user/elfload.c      |   7 +--
>  linux-user/main.c         |   8 ++-
>  linux-user/syscall.c      |   9 ++--
>  memory_mapping.c          |  16 +++---
>  monitor.c                 |   4 +-
>  target-i386/arch_dump.c   |   7 ++-
>  target-i386/helper.c      |  15 +++---
>  target-i386/kvm.c         |   8 +--
>  target-i386/misc_helper.c |   2 +-
>  target-mips/op_helper.c   |  25 +++++----
>  target-ppc/excp_helper.c  |   9 ++--
>  target-ppc/kvm.c          |   2 +-
>  translate-all.c           |  12 +++--
>  39 files changed, 266 insertions(+), 234 deletions(-)
>
> diff --git a/cpus.c b/cpus.c
> index e9bfa71..f141428 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -60,7 +60,7 @@
>
>  #endif /* CONFIG_LINUX */
>
> -static CPUArchState *next_cpu;
> +static CPUState *next_cpu;
>
>  static bool cpu_thread_is_idle(CPUState *cpu)
>  {
> @@ -79,10 +79,10 @@ static bool cpu_thread_is_idle(CPUState *cpu)
>
>  static bool all_cpu_threads_idle(void)
>  {
> -    CPUArchState *env;
> +    CPUState *cpu;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        if (!cpu_thread_is_idle(ENV_GET_CPU(env))) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        if (!cpu_thread_is_idle(cpu)) {
>              return false;
>          }
>      }
> @@ -388,15 +388,13 @@ void configure_icount(const char *option)
>  void hw_error(const char *fmt, ...)
>  {
>      va_list ap;
> -    CPUArchState *env;
>      CPUState *cpu;
>
>      va_start(ap, fmt);
>      fprintf(stderr, "qemu: hardware error: ");
>      vfprintf(stderr, fmt, ap);
>      fprintf(stderr, "\n");
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        cpu = ENV_GET_CPU(env);
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          fprintf(stderr, "CPU #%d:\n", cpu->cpu_index);
>          cpu_dump_state(cpu, stderr, fprintf, CPU_DUMP_FPU);
>      }
> @@ -406,28 +404,28 @@ void hw_error(const char *fmt, ...)
>
>  void cpu_synchronize_all_states(void)
>  {
> -    CPUArchState *env;
> +    CPUState *cpu;
>
> -    for (env = first_cpu; env; env = env->next_cpu) {
> -        cpu_synchronize_state(ENV_GET_CPU(env));
> +    for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
> +        cpu_synchronize_state(cpu);
>      }
>  }
>
>  void cpu_synchronize_all_post_reset(void)
>  {
> -    CPUArchState *cpu;
> +    CPUState *cpu;
>
>      for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
> -        cpu_synchronize_post_reset(ENV_GET_CPU(cpu));
> +        cpu_synchronize_post_reset(cpu);
>      }
>  }
>
>  void cpu_synchronize_all_post_init(void)
>  {
> -    CPUArchState *cpu;
> +    CPUState *cpu;
>
>      for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
> -        cpu_synchronize_post_init(ENV_GET_CPU(cpu));
> +        cpu_synchronize_post_init(cpu);
>      }
>  }
>
> @@ -698,7 +696,7 @@ static void qemu_wait_io_event_common(CPUState *cpu)
>
>  static void qemu_tcg_wait_io_event(void)
>  {
> -    CPUArchState *env;
> +    CPUState *cpu;
>
>      while (all_cpu_threads_idle()) {
>         /* Start accounting real time to the virtual clock if the CPUs
> @@ -711,8 +709,8 @@ static void qemu_tcg_wait_io_event(void)
>          qemu_cond_wait(&qemu_io_proceeded_cond, &qemu_global_mutex);
>      }
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        qemu_wait_io_event_common(ENV_GET_CPU(env));
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        qemu_wait_io_event_common(cpu);
>      }
>  }
>
> @@ -814,7 +812,6 @@ static void tcg_signal_cpu_creation(CPUState *cpu, void *data)
>  static void *qemu_tcg_cpu_thread_fn(void *arg)
>  {
>      CPUState *cpu = arg;
> -    CPUArchState *env;
>
>      qemu_tcg_init_cpu_signals();
>      qemu_thread_get_self(cpu->thread);
> @@ -824,12 +821,12 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
>      qemu_cond_signal(&qemu_cpu_cond);
>
>      /* wait for initial kick-off after machine start */
> -    while (ENV_GET_CPU(first_cpu)->stopped) {
> +    while (first_cpu->stopped) {
>          qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
>
>          /* process any pending work */
> -        for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -            qemu_wait_io_event_common(ENV_GET_CPU(env));
> +        for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +            qemu_wait_io_event_common(cpu);
>          }
>      }
>
> @@ -923,7 +920,7 @@ void qemu_mutex_lock_iothread(void)
>      } else {
>          iothread_requesting_mutex = true;
>          if (qemu_mutex_trylock(&qemu_global_mutex)) {
> -            qemu_cpu_kick_thread(ENV_GET_CPU(first_cpu));
> +            qemu_cpu_kick_thread(first_cpu);
>              qemu_mutex_lock(&qemu_global_mutex);
>          }
>          iothread_requesting_mutex = false;
> @@ -938,14 +935,13 @@ void qemu_mutex_unlock_iothread(void)
>
>  static int all_vcpus_paused(void)
>  {
> -    CPUArchState *penv = first_cpu;
> +    CPUState *cpu = first_cpu;
>
> -    while (penv) {
> -        CPUState *pcpu = ENV_GET_CPU(penv);
> -        if (!pcpu->stopped) {
> +    while (cpu) {
> +        if (!cpu->stopped) {
>              return 0;
>          }
> -        penv = penv->next_cpu;
> +        cpu = cpu->next_cpu;
>      }
>
>      return 1;
> @@ -953,25 +949,23 @@ static int all_vcpus_paused(void)
>
>  void pause_all_vcpus(void)
>  {
> -    CPUArchState *penv = first_cpu;
> +    CPUState *cpu = first_cpu;
>
>      qemu_clock_enable(vm_clock, false);
> -    while (penv) {
> -        CPUState *pcpu = ENV_GET_CPU(penv);
> -        pcpu->stop = true;
> -        qemu_cpu_kick(pcpu);
> -        penv = penv->next_cpu;
> +    while (cpu) {
> +        cpu->stop = true;
> +        qemu_cpu_kick(cpu);
> +        cpu = cpu->next_cpu;
>      }
>
>      if (qemu_in_vcpu_thread()) {
>          cpu_stop_current();
>          if (!kvm_enabled()) {
> -            penv = first_cpu;
> -            while (penv) {
> -                CPUState *pcpu = ENV_GET_CPU(penv);
> -                pcpu->stop = false;
> -                pcpu->stopped = true;
> -                penv = penv->next_cpu;
> +            cpu = first_cpu;
> +            while (cpu) {
> +                cpu->stop = false;
> +                cpu->stopped = true;
> +                cpu = cpu->next_cpu;
>              }
>              return;
>          }
> @@ -979,10 +973,10 @@ void pause_all_vcpus(void)
>
>      while (!all_vcpus_paused()) {
>          qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex);
> -        penv = first_cpu;
> -        while (penv) {
> -            qemu_cpu_kick(ENV_GET_CPU(penv));
> -            penv = penv->next_cpu;
> +        cpu = first_cpu;
> +        while (cpu) {
> +            qemu_cpu_kick(cpu);
> +            cpu = cpu->next_cpu;
>          }
>      }
>  }
> @@ -996,13 +990,12 @@ void cpu_resume(CPUState *cpu)
>
>  void resume_all_vcpus(void)
>  {
> -    CPUArchState *penv = first_cpu;
> +    CPUState *cpu = first_cpu;
>
>      qemu_clock_enable(vm_clock, true);
> -    while (penv) {
> -        CPUState *pcpu = ENV_GET_CPU(penv);
> -        cpu_resume(pcpu);
> -        penv = penv->next_cpu;
> +    while (cpu) {
> +        cpu_resume(cpu);
> +        cpu = cpu->next_cpu;
>      }
>  }
>
> @@ -1151,8 +1144,8 @@ static void tcg_exec_all(void)
>          next_cpu = first_cpu;
>      }
>      for (; next_cpu != NULL && !exit_request; next_cpu = next_cpu->next_cpu) {
> -        CPUArchState *env = next_cpu;
> -        CPUState *cpu = ENV_GET_CPU(env);
> +        CPUState *cpu = next_cpu;
> +        CPUArchState *env = cpu->env_ptr;
>
>          qemu_clock_enable(vm_clock,
>                            (env->singlestep_enabled & SSTEP_NOTIMER) == 0);
> @@ -1172,12 +1165,10 @@ static void tcg_exec_all(void)
>
>  void set_numa_modes(void)
>  {
> -    CPUArchState *env;
>      CPUState *cpu;
>      int i;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        cpu = ENV_GET_CPU(env);
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          for (i = 0; i < nb_numa_nodes; i++) {
>              if (test_bit(cpu->cpu_index, node_cpumask[i])) {
>                  cpu->numa_node = i;
> @@ -1197,18 +1188,30 @@ void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
>  CpuInfoList *qmp_query_cpus(Error **errp)
>  {
>      CpuInfoList *head = NULL, *cur_item = NULL;
> -    CPUArchState *env;
> +    CPUState *cpu;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        CPUState *cpu = ENV_GET_CPU(env);
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          CpuInfoList *info;
> +#if defined(TARGET_I386)
> +        X86CPU *x86_cpu = X86_CPU(cpu);
> +        CPUX86State *env = &x86_cpu->env;
> +#elif defined(TARGET_PPC)
> +        PowerPCCPU *ppc_cpu = POWERPC_CPU(cpu);
> +        CPUPPCState *env = &ppc_cpu->env;
> +#elif defined(TARGET_SPARC)
> +        SPARCCPU *sparc_cpu = SPARC_CPU(cpu);
> +        CPUSPARCState *env = &sparc_cpu->env;
> +#elif defined(TARGET_MIPS)
> +        MIPSCPU *mips_cpu = MIPS_CPU(cpu);
> +        CPUMIPSState *env = &mips_cpu->env;
> +#endif
>
>          cpu_synchronize_state(cpu);
>
>          info = g_malloc0(sizeof(*info));
>          info->value = g_malloc0(sizeof(*info->value));
>          info->value->CPU = cpu->cpu_index;
> -        info->value->current = (env == first_cpu);
> +        info->value->current = (cpu == first_cpu);
>          info->value->halted = cpu->halted;
>          info->value->thread_id = cpu->thread_id;
>  #if defined(TARGET_I386)
> @@ -1316,11 +1319,14 @@ exit:
>  void qmp_inject_nmi(Error **errp)
>  {
>  #if defined(TARGET_I386)
> -    CPUArchState *env;
> +    CPUState *cs;
> +
> +    for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
> +        X86CPU *cpu = X86_CPU(cs);
> +        CPUX86State *env = &cpu->env;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
>          if (!env->apic_state) {
> -            cpu_interrupt(CPU(x86_env_get_cpu(env)), CPU_INTERRUPT_NMI);
> +            cpu_interrupt(cs, CPU_INTERRUPT_NMI);
>          } else {
>              apic_deliver_nmi(env->apic_state);
>          }
> diff --git a/cputlb.c b/cputlb.c
> index 828007c..977c0ca 100644
> --- a/cputlb.c
> +++ b/cputlb.c
> @@ -186,11 +186,13 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
>
>  void cpu_tlb_reset_dirty_all(ram_addr_t start1, ram_addr_t length)
>  {
> +    CPUState *cpu;
>      CPUArchState *env;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          int mmu_idx;
>
> +        env = cpu->env_ptr;
>          for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
>              unsigned int i;
>
> diff --git a/dump.c b/dump.c
> index c812cfa..6a3a72a 100644
> --- a/dump.c
> +++ b/dump.c
> @@ -275,13 +275,11 @@ static inline int cpu_index(CPUState *cpu)
>
>  static int write_elf64_notes(DumpState *s)
>  {
> -    CPUArchState *env;
>      CPUState *cpu;
>      int ret;
>      int id;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        cpu = ENV_GET_CPU(env);
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          id = cpu_index(cpu);
>          ret = cpu_write_elf64_note(fd_write_vmcore, cpu, id, s);
>          if (ret < 0) {
> @@ -290,7 +288,7 @@ static int write_elf64_notes(DumpState *s)
>          }
>      }
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          ret = cpu_write_elf64_qemunote(fd_write_vmcore, cpu, s);
>          if (ret < 0) {
>              dump_error(s, "dump: failed to write CPU status.\n");
> @@ -327,13 +325,11 @@ static int write_elf32_note(DumpState *s)
>
>  static int write_elf32_notes(DumpState *s)
>  {
> -    CPUArchState *env;
>      CPUState *cpu;
>      int ret;
>      int id;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        cpu = ENV_GET_CPU(env);
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          id = cpu_index(cpu);
>          ret = cpu_write_elf32_note(fd_write_vmcore, cpu, id, s);
>          if (ret < 0) {
> @@ -342,7 +338,7 @@ static int write_elf32_notes(DumpState *s)
>          }
>      }
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          ret = cpu_write_elf32_qemunote(fd_write_vmcore, cpu, s);
>          if (ret < 0) {
>              dump_error(s, "dump: failed to write CPU status.\n");
> @@ -705,7 +701,7 @@ static ram_addr_t get_start_block(DumpState *s)
>  static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
>                       int64_t begin, int64_t length, Error **errp)
>  {
> -    CPUArchState *env;
> +    CPUState *cpu;
>      int nr_cpus;
>      Error *err = NULL;
>      int ret;
> @@ -738,7 +734,7 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
>       */
>      cpu_synchronize_all_states();
>      nr_cpus = 0;
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          nr_cpus++;
>      }
>
> diff --git a/exec.c b/exec.c
> index 9ca80cc..61b094a 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -69,7 +69,7 @@ static MemoryRegion io_mem_unassigned;
>
>  #endif
>
> -CPUArchState *first_cpu;
> +CPUState *first_cpu;
>  /* current CPU in the current thread. It is only valid inside
>     cpu_exec() */
>  DEFINE_TLS(CPUState *, current_cpu);
> @@ -351,27 +351,26 @@ const VMStateDescription vmstate_cpu_common = {
>
>  CPUState *qemu_get_cpu(int index)
>  {
> -    CPUArchState *env = first_cpu;
> -    CPUState *cpu = NULL;
> +    CPUState *cpu = first_cpu;
>
> -    while (env) {
> -        cpu = ENV_GET_CPU(env);
> +    while (cpu) {
>          if (cpu->cpu_index == index) {
>              break;
>          }
> -        env = env->next_cpu;
> +        cpu = cpu->next_cpu;
>      }
>
> -    return env ? cpu : NULL;
> +    return cpu;
>  }
>
>  void qemu_for_each_cpu(void (*func)(CPUState *cpu, void *data), void *data)
>  {
> -    CPUArchState *env = first_cpu;
> +    CPUState *cpu;
>
> -    while (env) {
> -        func(ENV_GET_CPU(env), data);
> -        env = env->next_cpu;
> +    cpu = first_cpu;
> +    while (cpu) {
> +        func(cpu, data);
> +        cpu = cpu->next_cpu;
>      }
>  }
>
> @@ -379,17 +378,17 @@ void cpu_exec_init(CPUArchState *env)
>  {
>      CPUState *cpu = ENV_GET_CPU(env);
>      CPUClass *cc = CPU_GET_CLASS(cpu);
> -    CPUArchState **penv;
> +    CPUState **pcpu;
>      int cpu_index;
>
>  #if defined(CONFIG_USER_ONLY)
>      cpu_list_lock();
>  #endif
> -    env->next_cpu = NULL;
> -    penv = &first_cpu;
> +    cpu->next_cpu = NULL;
> +    pcpu = &first_cpu;
>      cpu_index = 0;
> -    while (*penv != NULL) {
> -        penv = &(*penv)->next_cpu;
> +    while (*pcpu != NULL) {
> +        pcpu = &(*pcpu)->next_cpu;
>          cpu_index++;
>      }
>      cpu->cpu_index = cpu_index;
> @@ -399,7 +398,7 @@ void cpu_exec_init(CPUArchState *env)
>  #ifndef CONFIG_USER_ONLY
>      cpu->thread_id = qemu_get_thread_id();
>  #endif
> -    *penv = env;
> +    *pcpu = cpu;
>  #if defined(CONFIG_USER_ONLY)
>      cpu_list_unlock();
>  #endif
> @@ -638,7 +637,6 @@ void cpu_abort(CPUArchState *env, const char *fmt, ...)
>  CPUArchState *cpu_copy(CPUArchState *env)
>  {
>      CPUArchState *new_env = cpu_init(env->cpu_model_str);
> -    CPUArchState *next_cpu = new_env->next_cpu;
>  #if defined(TARGET_HAS_ICE)
>      CPUBreakpoint *bp;
>      CPUWatchpoint *wp;
> @@ -646,9 +644,6 @@ CPUArchState *cpu_copy(CPUArchState *env)
>
>      memcpy(new_env, env, sizeof(CPUArchState));
>
> -    /* Preserve chaining. */
> -    new_env->next_cpu = next_cpu;
> -
>      /* Clone all break/watchpoints.
>         Note: Once we support ptrace with hw-debug register access, make sure
>         BP_CPU break/watchpoints are handled correctly on clone. */
> @@ -1757,12 +1752,14 @@ static void core_commit(MemoryListener *listener)
>
>  static void tcg_commit(MemoryListener *listener)
>  {
> -    CPUArchState *env;
> +    CPUState *cpu;
>
>      /* since each CPU stores ram addresses in its TLB cache, we must
>         reset the modified entries */
>      /* XXX: slow ! */
> -    for(env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        CPUArchState *env = cpu->env_ptr;
> +
>          tlb_flush(env, 1);
>      }
>  }
> diff --git a/gdbstub.c b/gdbstub.c
> index f7d9f13..0ee82a9 100644
> --- a/gdbstub.c
> +++ b/gdbstub.c
> @@ -1839,6 +1839,7 @@ static const char *get_feature_xml(const char *p, const char **newp)
>          /* Generate the XML description for this CPU.  */
>          if (!target_xml[0]) {
>              GDBRegisterState *r;
> +            CPUArchState *env = first_cpu->env_ptr;
>
>              snprintf(target_xml, sizeof(target_xml),
>                       "<?xml version=\"1.0\"?>"
> @@ -1847,7 +1848,7 @@ static const char *get_feature_xml(const char *p, const char **newp)
>                       "<xi:include href=\"%s\"/>",
>                       GDB_CORE_XML);
>
> -            for (r = first_cpu->gdb_regs; r; r = r->next) {
> +            for (r = env->gdb_regs; r; r = r->next) {
>                  pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\"");
>                  pstrcat(target_xml, sizeof(target_xml), r->xml);
>                  pstrcat(target_xml, sizeof(target_xml), "\"/>");
> @@ -1949,6 +1950,7 @@ static const int xlat_gdb_type[] = {
>
>  static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
>  {
> +    CPUState *cpu;
>      CPUArchState *env;
>      int err = 0;
>
> @@ -1958,7 +1960,8 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
>      switch (type) {
>      case GDB_BREAKPOINT_SW:
>      case GDB_BREAKPOINT_HW:
> -        for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +        for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +            env = cpu->env_ptr;
>              err = cpu_breakpoint_insert(env, addr, BP_GDB, NULL);
>              if (err)
>                  break;
> @@ -1968,7 +1971,8 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
>      case GDB_WATCHPOINT_WRITE:
>      case GDB_WATCHPOINT_READ:
>      case GDB_WATCHPOINT_ACCESS:
> -        for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +        for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +            env = cpu->env_ptr;
>              err = cpu_watchpoint_insert(env, addr, len, xlat_gdb_type[type],
>                                          NULL);
>              if (err)
> @@ -1983,6 +1987,7 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
>
>  static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
>  {
> +    CPUState *cpu;
>      CPUArchState *env;
>      int err = 0;
>
> @@ -1992,7 +1997,8 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
>      switch (type) {
>      case GDB_BREAKPOINT_SW:
>      case GDB_BREAKPOINT_HW:
> -        for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +        for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +            env = cpu->env_ptr;
>              err = cpu_breakpoint_remove(env, addr, BP_GDB);
>              if (err)
>                  break;
> @@ -2002,7 +2008,8 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
>      case GDB_WATCHPOINT_WRITE:
>      case GDB_WATCHPOINT_READ:
>      case GDB_WATCHPOINT_ACCESS:
> -        for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +        for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +            env = cpu->env_ptr;
>              err = cpu_watchpoint_remove(env, addr, len, xlat_gdb_type[type]);
>              if (err)
>                  break;
> @@ -2016,6 +2023,7 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
>
>  static void gdb_breakpoint_remove_all(void)
>  {
> +    CPUState *cpu;
>      CPUArchState *env;
>
>      if (kvm_enabled()) {
> @@ -2023,7 +2031,8 @@ static void gdb_breakpoint_remove_all(void)
>          return;
>      }
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        env = cpu->env_ptr;
>          cpu_breakpoint_remove_all(env, BP_GDB);
>  #ifndef CONFIG_USER_ONLY
>          cpu_watchpoint_remove_all(env, BP_GDB);
> @@ -2071,13 +2080,11 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
>
>  static CPUArchState *find_cpu(uint32_t thread_id)
>  {
> -    CPUArchState *env;
>      CPUState *cpu;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        cpu = ENV_GET_CPU(env);
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          if (cpu_index(cpu) == thread_id) {
> -            return env;
> +            return cpu->env_ptr;
>          }
>      }
>
> @@ -2394,7 +2401,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
>              put_packet(s, "QC1");
>              break;
>          } else if (strcmp(p,"fThreadInfo") == 0) {
> -            s->query_cpu = first_cpu;
> +            s->query_cpu = first_cpu->env_ptr;
>              goto report_cpuinfo;
>          } else if (strcmp(p,"sThreadInfo") == 0) {
>          report_cpuinfo:
> @@ -2402,7 +2409,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
>                  snprintf(buf, sizeof(buf), "m%x",
>                           cpu_index(ENV_GET_CPU(s->query_cpu)));
>                  put_packet(s, buf);
> -                s->query_cpu = s->query_cpu->next_cpu;
> +                s->query_cpu = ENV_GET_CPU(s->query_cpu)->next_cpu->env_ptr;
next_cpu may be NULL.

>              } else
>                  put_packet(s, "l");
>              break;
> @@ -2869,8 +2876,8 @@ static void gdb_accept(void)
>      socket_set_nodelay(fd);
>
>      s = g_malloc0(sizeof(GDBState));
> -    s->c_cpu = first_cpu;
> -    s->g_cpu = first_cpu;
> +    s->c_cpu = first_cpu->env_ptr;
> +    s->g_cpu = first_cpu->env_ptr;
>      s->fd = fd;
>      gdb_has_xml = 0;
>
> @@ -3054,8 +3061,8 @@ int gdbserver_start(const char *device)
>          mon_chr = s->mon_chr;
>          memset(s, 0, sizeof(GDBState));
>      }
> -    s->c_cpu = first_cpu;
> -    s->g_cpu = first_cpu;
> +    s->c_cpu = first_cpu->env_ptr;
> +    s->g_cpu = first_cpu->env_ptr;
>      s->chr = chr;
>      s->state = chr ? RS_IDLE : RS_INACTIVE;
>      s->mon_chr = mon_chr;
> diff --git a/hw/arm/boot.c b/hw/arm/boot.c
> index 7c0090f..2b33444 100644
> --- a/hw/arm/boot.c
> +++ b/hw/arm/boot.c
> @@ -333,7 +333,7 @@ static void do_cpu_reset(void *opaque)
>              env->regs[15] = info->entry & 0xfffffffe;
>              env->thumb = info->entry & 1;
>          } else {
> -            if (env == first_cpu) {
> +            if (CPU(cpu) == first_cpu) {
>                  env->regs[15] = info->loader_start;
>                  if (!info->dtb_filename) {
>                      if (old_param) {
> @@ -351,7 +351,7 @@ static void do_cpu_reset(void *opaque)
>
>  void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
>  {
> -    CPUARMState *env = &cpu->env;
> +    CPUState *cs = CPU(cpu);
>      int kernel_size;
>      int initrd_size;
>      int n;
> @@ -476,9 +476,9 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
>      }
>      info->is_linux = is_linux;
>
> -    for (; env; env = env->next_cpu) {
> -        cpu = arm_env_get_cpu(env);
> -        env->boot_info = info;
> +    for (; cs; cs = cs->next_cpu) {
> +        cpu = ARM_CPU(cs);
> +        cpu->env.boot_info = info;
>          qemu_register_reset(do_cpu_reset, cpu);
>      }
>  }
> diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
> index 74f110b..7c90b2d 100644
> --- a/hw/arm/exynos4_boards.c
> +++ b/hw/arm/exynos4_boards.c
> @@ -131,7 +131,7 @@ static void nuri_init(QEMUMachineInitArgs *args)
>  {
>      exynos4_boards_init_common(args, EXYNOS4_BOARD_NURI);
>
> -    arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
> +    arm_load_kernel(ARM_CPU(first_cpu), &exynos4_board_binfo);
>  }
>
>  static void smdkc210_init(QEMUMachineInitArgs *args)
> @@ -141,7 +141,7 @@ static void smdkc210_init(QEMUMachineInitArgs *args)
>
>      lan9215_init(SMDK_LAN9118_BASE_ADDR,
>              qemu_irq_invert(s->irq_table[exynos4210_get_irq(37, 1)]));
> -    arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
> +    arm_load_kernel(ARM_CPU(first_cpu), &exynos4_board_binfo);
>  }
>
>  static QEMUMachine exynos4_machines[EXYNOS4_NUM_OF_BOARDS] = {
> diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
> index de6c98a..3a2fb4c 100644
> --- a/hw/arm/highbank.c
> +++ b/hw/arm/highbank.c
> @@ -321,7 +321,7 @@ static void highbank_init(QEMUMachineInitArgs *args)
>      highbank_binfo.loader_start = 0;
>      highbank_binfo.write_secondary_boot = hb_write_secondary;
>      highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
> -    arm_load_kernel(arm_env_get_cpu(first_cpu), &highbank_binfo);
> +    arm_load_kernel(ARM_CPU(first_cpu), &highbank_binfo);
>  }
>
>  static QEMUMachine highbank_machine = {
> diff --git a/hw/arm/realview.c b/hw/arm/realview.c
> index b596256..3060f48 100644
> --- a/hw/arm/realview.c
> +++ b/hw/arm/realview.c
> @@ -331,7 +331,7 @@ static void realview_init(QEMUMachineInitArgs *args,
>      realview_binfo.nb_cpus = smp_cpus;
>      realview_binfo.board_id = realview_board_id[board_type];
>      realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0);
> -    arm_load_kernel(arm_env_get_cpu(first_cpu), &realview_binfo);
> +    arm_load_kernel(ARM_CPU(first_cpu), &realview_binfo);
>  }
>
>  static void realview_eb_init(QEMUMachineInitArgs *args)
> diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
> index 710413e..fd18b60 100644
> --- a/hw/arm/vexpress.c
> +++ b/hw/arm/vexpress.c
> @@ -519,7 +519,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
>      vexpress_binfo.smp_loader_start = map[VE_SRAM];
>      vexpress_binfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30;
>      vexpress_binfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr;
> -    arm_load_kernel(arm_env_get_cpu(first_cpu), &vexpress_binfo);
> +    arm_load_kernel(ARM_CPU(first_cpu), &vexpress_binfo);
>  }
>
>  static void vexpress_a9_init(QEMUMachineInitArgs *args)
> diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
> index 0dc0871..3444823 100644
> --- a/hw/arm/xilinx_zynq.c
> +++ b/hw/arm/xilinx_zynq.c
> @@ -226,7 +226,7 @@ static void zynq_init(QEMUMachineInitArgs *args)
>      zynq_binfo.nb_cpus = 1;
>      zynq_binfo.board_id = 0xd32;
>      zynq_binfo.loader_start = 0;
> -    arm_load_kernel(arm_env_get_cpu(first_cpu), &zynq_binfo);
> +    arm_load_kernel(ARM_CPU(first_cpu), &zynq_binfo);
>  }
>
>  static QEMUMachine zynq_machine = {
> diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c
> index 98e5ca5..1022d67 100644
> --- a/hw/i386/kvm/clock.c
> +++ b/hw/i386/kvm/clock.c
> @@ -33,7 +33,7 @@ static void kvmclock_vm_state_change(void *opaque, int running,
>                                       RunState state)
>  {
>      KVMClockState *s = opaque;
> -    CPUArchState *penv = first_cpu;
> +    CPUState *cpu = first_cpu;
>      int cap_clock_ctrl = kvm_check_extension(kvm_state, KVM_CAP_KVMCLOCK_CTRL);
>      int ret;
>
> @@ -53,8 +53,8 @@ static void kvmclock_vm_state_change(void *opaque, int running,
>          if (!cap_clock_ctrl) {
>              return;
>          }
> -        for (penv = first_cpu; penv != NULL; penv = penv->next_cpu) {
> -            ret = kvm_vcpu_ioctl(ENV_GET_CPU(penv), KVM_KVMCLOCK_CTRL, 0);
> +        for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +            ret = kvm_vcpu_ioctl(cpu, KVM_KVMCLOCK_CTRL, 0);
>              if (ret) {
>                  if (ret != -EINVAL) {
>                      fprintf(stderr, "%s: %s\n", __func__, strerror(-ret));
> @@ -124,9 +124,11 @@ static const TypeInfo kvmclock_info = {
>  /* Note: Must be called after VCPU initialization. */
>  void kvmclock_create(void)
>  {
> +    X86CPU *cpu = X86_CPU(first_cpu);
> +
>      if (kvm_enabled() &&
> -        first_cpu->features[FEAT_KVM] & ((1ULL << KVM_FEATURE_CLOCKSOURCE) |
> -                                         (1ULL << KVM_FEATURE_CLOCKSOURCE2))) {
> +        cpu->env.features[FEAT_KVM] & ((1ULL << KVM_FEATURE_CLOCKSOURCE) |
> +                                       (1ULL << KVM_FEATURE_CLOCKSOURCE2))) {
>          sysbus_create_simple("kvmclock", -1, NULL);
>      }
>  }
> diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
> index e13678f..ccd089a 100644
> --- a/hw/i386/kvmvapic.c
> +++ b/hw/i386/kvmvapic.c
> @@ -490,13 +490,15 @@ static void vapic_enable_tpr_reporting(bool enable)
>      VAPICEnableTPRReporting info = {
>          .enable = enable,
>      };
> +    CPUState *cs;
>      X86CPU *cpu;
>      CPUX86State *env;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        cpu = x86_env_get_cpu(env);
> +    for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
> +        cpu = X86_CPU(cs);
> +        env = &cpu->env;
>          info.apic = env->apic_state;
> -        run_on_cpu(CPU(cpu), vapic_do_enable_tpr_reporting, &info);
> +        run_on_cpu(cs, vapic_do_enable_tpr_reporting, &info);
>      }
>  }
>
> @@ -719,8 +721,9 @@ static int vapic_init(SysBusDevice *dev)
>  static void do_vapic_enable(void *data)
>  {
>      VAPICROMState *s = data;
> +    X86CPU *cpu = X86_CPU(first_cpu);
>
> -    vapic_enable(s, first_cpu);
> +    vapic_enable(s, &cpu->env);
>  }
>
>  static int vapic_post_load(void *opaque, int version_id)
> @@ -743,7 +746,7 @@ static int vapic_post_load(void *opaque, int version_id)
>      }
>      if (s->state == VAPIC_ACTIVE) {
>          if (smp_cpus == 1) {
> -            run_on_cpu(ENV_GET_CPU(first_cpu), do_vapic_enable, s);
> +            run_on_cpu(first_cpu, do_vapic_enable, s);
>          } else {
>              zero = g_malloc0(s->rom_state.vapic_size);
>              cpu_physical_memory_rw(s->vapic_paddr, zero,
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index 5224256..c5d8570 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -160,8 +160,9 @@ void cpu_smm_register(cpu_set_smm_t callback, void *arg)
>
>  void cpu_smm_update(CPUX86State *env)
>  {
> -    if (smm_set && smm_arg && env == first_cpu)
> +    if (smm_set && smm_arg && CPU(x86_env_get_cpu(env)) == first_cpu) {
>          smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg);
> +    }
>  }
>
>
> @@ -185,18 +186,21 @@ int cpu_get_pic_interrupt(CPUX86State *env)
>
>  static void pic_irq_request(void *opaque, int irq, int level)
>  {
> -    CPUX86State *env = first_cpu;
> +    CPUState *cs = first_cpu;
> +    X86CPU *cpu = X86_CPU(cs);
> +    CPUX86State *env = &cpu->env;
>
>      DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
>      if (env->apic_state) {
> -        while (env) {
> +        while (cs) {
> +            cpu = X86_CPU(cs);
> +            env = &cpu->env;
>              if (apic_accept_pic_intr(env->apic_state)) {
>                  apic_deliver_pic_intr(env->apic_state, level);
>              }
> -            env = env->next_cpu;
> +            cs = cs->next_cpu;
>          }
>      } else {
> -        CPUState *cs = CPU(x86_env_get_cpu(env));
>          if (level) {
>              cpu_interrupt(cs, CPU_INTERRUPT_HARD);
>          } else {
> @@ -1274,8 +1278,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
>          }
>      }
>
> -    a20_line = qemu_allocate_irqs(handle_a20_line_change,
> -                                  x86_env_get_cpu(first_cpu), 2);
> +    a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);
>      i8042 = isa_create_simple(isa_bus, "i8042");
>      i8042_setup_a20_line(i8042, &a20_line[0]);
>      if (!no_vmport) {
> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> index 01323a9..b58c255 100644
> --- a/hw/i386/pc_piix.c
> +++ b/hw/i386/pc_piix.c
> @@ -229,8 +229,7 @@ static void pc_init1(MemoryRegion *system_memory,
>      if (pci_enabled && acpi_enabled) {
>          i2c_bus *smbus;
>
> -        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt,
> -                                     x86_env_get_cpu(first_cpu), 1);
> +        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
>          /* TODO: Populate SPD eeprom data.  */
>          smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
>                                gsi[9], *smi_irq,
> diff --git a/hw/intc/sh_intc.c b/hw/intc/sh_intc.c
> index f397950..55c76e4 100644
> --- a/hw/intc/sh_intc.c
> +++ b/hw/intc/sh_intc.c
> @@ -42,16 +42,15 @@ void sh_intc_toggle_source(struct intc_source *source,
>          pending_changed = 1;
>
>      if (pending_changed) {
> -        CPUState *cpu = CPU(sh_env_get_cpu(first_cpu));
>          if (source->pending) {
>              source->parent->pending++;
>              if (source->parent->pending == 1) {
> -                cpu_interrupt(cpu, CPU_INTERRUPT_HARD);
> +                cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD);
>              }
>          } else {
>              source->parent->pending--;
>              if (source->parent->pending == 0) {
> -                cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
> +                cpu_reset_interrupt(first_cpu, CPU_INTERRUPT_HARD);
>              }
>         }
>      }
> diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
> index b49be4d..d1921aa 100644
> --- a/hw/isa/lpc_ich9.c
> +++ b/hw/isa/lpc_ich9.c
> @@ -380,7 +380,7 @@ static void ich9_apm_ctrl_changed(uint32_t val, void *arg)
>
>      /* SMI_EN = PMBASE + 30. SMI control and enable register */
>      if (lpc->pm.smi_en & ICH9_PMIO_SMI_EN_APMC_EN) {
> -        cpu_interrupt(CPU(x86_env_get_cpu(first_cpu)), CPU_INTERRUPT_SMI);
> +        cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
>      }
>  }
>
> diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
> index 7e56121..de87241 100644
> --- a/hw/mips/mips_malta.c
> +++ b/hw/mips/mips_malta.c
> @@ -844,7 +844,8 @@ void mips_malta_init(QEMUMachineInitArgs *args)
>          cpu_mips_clock_init(env);
>          qemu_register_reset(main_cpu_reset, cpu);
>      }
> -    env = first_cpu;
> +    cpu = MIPS_CPU(first_cpu);
> +    env = &cpu->env;
>
>      /* allocate RAM */
>      if (ram_size > (256 << 20)) {
> diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
> index 69837a5..9600599 100644
> --- a/hw/ppc/e500.c
> +++ b/hw/ppc/e500.c
> @@ -500,7 +500,6 @@ static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params,
>                                            qemu_irq **irqs)
>  {
>      DeviceState *dev;
> -    CPUPPCState *env;
>      CPUState *cs;
>      int r;
>
> @@ -512,9 +511,7 @@ static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params,
>          return NULL;
>      }
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        cs = ENV_GET_CPU(env);
> -
> +    for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
>          if (kvm_openpic_connect_vcpu(dev, cs)) {
>              fprintf(stderr, "%s: failed to connect vcpu to irqchip\n",
>                      __func__);
> diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
> index fb57b42..554f244 100644
> --- a/hw/ppc/ppc.c
> +++ b/hw/ppc/ppc.c
> @@ -440,15 +440,14 @@ void ppce500_irq_init(CPUPPCState *env)
>  /* Enable or Disable the E500 EPR capability */
>  void ppce500_set_mpic_proxy(bool enabled)
>  {
> -    CPUPPCState *env;
> +    CPUState *cs;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        PowerPCCPU *cpu = ppc_env_get_cpu(env);
> -        CPUState *cs = CPU(cpu);
> +    for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
> +        PowerPCCPU *cpu = POWERPC_CPU(cs);
>
> -        env->mpic_proxy = enabled;
> +        cpu->env.mpic_proxy = enabled;
>          if (kvm_enabled()) {
> -            kvmppc_set_mpic_proxy(POWERPC_CPU(cs), enabled);
> +            kvmppc_set_mpic_proxy(cpu, enabled);
>          }
>      }
>  }
> diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
> index d07dd01..19f2442 100644
> --- a/hw/ppc/prep.c
> +++ b/hw/ppc/prep.c
> @@ -605,8 +605,9 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
>      /* PCI -> ISA bridge */
>      pci = pci_create_simple(pci_bus, PCI_DEVFN(1, 0), "i82378");
>      cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
> +    cpu = POWERPC_CPU(first_cpu);
>      qdev_connect_gpio_out(&pci->qdev, 0,
> -                          first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
> +                          cpu->env.irq_inputs[PPC6xx_INPUT_INT]);
>      qdev_connect_gpio_out(&pci->qdev, 1, *cpu_exit_irq);
>      sysbus_connect_irq(&pcihost->busdev, 0, qdev_get_gpio_in(&pci->qdev, 9));
>      sysbus_connect_irq(&pcihost->busdev, 1, qdev_get_gpio_in(&pci->qdev, 11));
> @@ -651,7 +652,8 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
>      }
>      isa_create_simple(isa_bus, "i8042");
>
> -    sysctrl->reset_irq = first_cpu->irq_inputs[PPC6xx_INPUT_HRESET];
> +    cpu = POWERPC_CPU(first_cpu);
> +    sysctrl->reset_irq = cpu->env.irq_inputs[PPC6xx_INPUT_HRESET];
>
>      portio_list_init(port_list, NULL, prep_portio_list, sysctrl, "prep");
>      portio_list_add(port_list, get_system_io(), 0x0);
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index c040794..e46aad3 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -131,7 +131,6 @@ int spapr_allocate_irq_block(int num, bool lsi)
>  static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
>  {
>      int ret = 0, offset;
> -    CPUPPCState *env;
>      CPUState *cpu;
>      char cpu_model[32];
>      int smt = kvmppc_smt_threads();
> @@ -139,8 +138,7 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
>
>      assert(spapr->cpu_model);
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        cpu = CPU(ppc_env_get_cpu(env));
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>          uint32_t associativity[] = {cpu_to_be32(0x5),
>                                      cpu_to_be32(0x0),
>                                      cpu_to_be32(0x0),
> @@ -231,7 +229,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
>                                     uint32_t epow_irq)
>  {
>      void *fdt;
> -    CPUPPCState *env;
> +    CPUState *cs;
>      uint32_t start_prop = cpu_to_be32(initrd_base);
>      uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
>      char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
> @@ -304,10 +302,11 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
>      /* This is needed during FDT finalization */
>      spapr->cpu_model = g_strdup(modelname);
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -        CPUState *cpu = CPU(ppc_env_get_cpu(env));
> -        PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
> -        int index = cpu->cpu_index;
> +    for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
> +        PowerPCCPU *cpu = POWERPC_CPU(cs);
> +        CPUPPCState *env = &cpu->env;
> +        PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
> +        int index = cs->cpu_index;
>          uint32_t servers_prop[smp_threads];
>          uint32_t gservers_prop[smp_threads * 2];
>          char *nodename;
> @@ -632,7 +631,7 @@ static void spapr_reset_htab(sPAPREnvironment *spapr)
>
>  static void ppc_spapr_reset(void)
>  {
> -    CPUState *first_cpu_cpu;
> +    PowerPCCPU *first_ppc_cpu;
>
>      /* Reset the hash table & recalc the RMA */
>      spapr_reset_htab(spapr);
> @@ -644,11 +643,11 @@ static void ppc_spapr_reset(void)
>                         spapr->rtas_size);
>
>      /* Set up the entry state */
> -    first_cpu_cpu = ENV_GET_CPU(first_cpu);
> -    first_cpu->gpr[3] = spapr->fdt_addr;
> -    first_cpu->gpr[5] = 0;
> -    first_cpu_cpu->halted = 0;
> -    first_cpu->nip = spapr->entry_point;
> +    first_ppc_cpu = POWERPC_CPU(first_cpu);
> +    first_ppc_cpu->env.gpr[3] = spapr->fdt_addr;
> +    first_ppc_cpu->env.gpr[5] = 0;
> +    first_cpu->halted = 0;
> +    first_ppc_cpu->env.nip = spapr->entry_point;
>
>  }
>
> diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
> index 6760851..6499cd0 100644
> --- a/include/exec/cpu-all.h
> +++ b/include/exec/cpu-all.h
> @@ -356,7 +356,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;
>
>  /* Flags for use in ENV->INTERRUPT_PENDING.
>
> diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
> index c4ac929..39094b3 100644
> --- a/include/exec/cpu-defs.h
> +++ b/include/exec/cpu-defs.h
> @@ -181,7 +181,6 @@ typedef struct CPUWatchpoint {
>      sigjmp_buf jmp_env;                                                 \
>      int exception_index;                                                \
>                                                                          \
> -    CPUArchState *next_cpu; /* next CPU sharing TB cache */                 \
>      /* user data */                                                     \
>      void *opaque;                                                       \
>                                                                          \
> diff --git a/include/qom/cpu.h b/include/qom/cpu.h
> index d7fc186..a08a8ab 100644
> --- a/include/qom/cpu.h
> +++ b/include/qom/cpu.h
> @@ -114,6 +114,7 @@ struct kvm_run;
>   *           CPU and return to its top level loop.
>   * @env_ptr: Pointer to subclass-specific CPUArchState field.
>   * @current_tb: Currently executing TB.
> + * @next_cpu: Next CPU sharing TB cache.
>   * @kvm_fd: vCPU file descriptor for KVM.
>   *
>   * State of one CPU core or thread.
> @@ -146,6 +147,7 @@ struct CPUState {
>
>      void *env_ptr; /* CPUArchState */
>      struct TranslationBlock *current_tb;
> +    CPUState *next_cpu;
>
>      int kvm_fd;
>      bool kvm_vcpu_dirty;
> @@ -157,6 +159,8 @@ struct CPUState {
>      uint32_t halted; /* used by alpha, cris, ppc TCG */
>  };
>
> +extern CPUState *first_cpu;
> +
>  DECLARE_TLS(CPUState *, current_cpu);
>  #define current_cpu tls_var(current_cpu)
>
> diff --git a/kvm-all.c b/kvm-all.c
> index 2c14ef3..c130705 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -1938,7 +1938,9 @@ int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr,
>          }
>      }
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        CPUArchState *env = cpu->env_ptr;
> +
>          err = kvm_update_guest_debug(env, 0);
>          if (err) {
>              return err;
> @@ -1979,7 +1981,9 @@ int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
>          }
>      }
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        CPUArchState *env = cpu->env_ptr;
> +
>          err = kvm_update_guest_debug(env, 0);
>          if (err) {
>              return err;
> @@ -1992,13 +1996,11 @@ void kvm_remove_all_breakpoints(CPUState *cpu)
>  {
>      struct kvm_sw_breakpoint *bp, *next;
>      KVMState *s = cpu->kvm_state;
> -    CPUArchState *env;
>
>      QTAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) {
>          if (kvm_arch_remove_sw_breakpoint(cpu, bp) != 0) {
>              /* Try harder to find a CPU that currently sees the breakpoint. */
> -            for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -                cpu = ENV_GET_CPU(env);
> +            for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>                  if (kvm_arch_remove_sw_breakpoint(cpu, bp) == 0) {
>                      break;
>                  }
> @@ -2009,7 +2011,9 @@ void kvm_remove_all_breakpoints(CPUState *cpu)
>      }
>      kvm_arch_remove_all_hw_breakpoints();
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        CPUArchState *env = cpu->env_ptr;
> +
>          kvm_update_guest_debug(env, 0);
>      }
>  }
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index ddef23e..d517450 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -2628,7 +2628,7 @@ static int fill_note_info(struct elf_note_info *info,
>                            long signr, const CPUArchState *env)
>  {
>  #define NUMNOTES 3
> -    CPUArchState *cpu = NULL;
> +    CPUState *cpu = NULL;
>      TaskState *ts = (TaskState *)env->opaque;
>      int i;
>
> @@ -2667,9 +2667,10 @@ static int fill_note_info(struct elf_note_info *info,
>      /* read and fill status of all threads */
>      cpu_list_lock();
>      for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> -        if (cpu == thread_env)
> +        if (cpu == ENV_GET_CPU(thread_env)) {
>              continue;
> -        fill_thread_info(info, cpu);
> +        }
> +        fill_thread_info(info, (CPUArchState *)cpu->env_ptr);
>      }
>      cpu_list_unlock();
>
> diff --git a/linux-user/main.c b/linux-user/main.c
> index af82db8..564bed6 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -120,8 +120,8 @@ void fork_end(int child)
>      if (child) {
>          /* Child processes created by fork() only have a single thread.
>             Discard information about the parent threads.  */
> -        first_cpu = thread_env;
> -        thread_env->next_cpu = NULL;
> +        first_cpu = ENV_GET_CPU(thread_env);
> +        first_cpu->next_cpu = NULL;
>          pending_cpus = 0;
>          pthread_mutex_init(&exclusive_lock, NULL);
>          pthread_mutex_init(&cpu_list_mutex, NULL);
> @@ -148,7 +148,6 @@ static inline void exclusive_idle(void)
>     Must only be called from outside cpu_arm_exec.   */
>  static inline void start_exclusive(void)
>  {
> -    CPUArchState *other;
>      CPUState *other_cpu;
>
>      pthread_mutex_lock(&exclusive_lock);
> @@ -156,8 +155,7 @@ static inline void start_exclusive(void)
>
>      pending_cpus = 1;
>      /* Make all other cpus stop executing.  */
> -    for (other = first_cpu; other; other = other->next_cpu) {
> -        other_cpu = ENV_GET_CPU(other);
> +    for (other_cpu = first_cpu; other_cpu; other_cpu = other_cpu->next_cpu) {
>          if (other_cpu->running) {
>              pending_cpus++;
>              cpu_exit(other_cpu);
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index a2125fa..4c96f4f 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -5030,6 +5030,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>                      abi_long arg5, abi_long arg6, abi_long arg7,
>                      abi_long arg8)
>  {
> +#ifdef CONFIG_USE_NPTL
> +    CPUState *cpu = ENV_GET_CPU(cpu_env);
> +#endif
>      abi_long ret;
>      struct stat st;
>      struct statfs stfs;
> @@ -5052,13 +5055,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>             be disabling signals.  */
>          if (first_cpu->next_cpu) {
>              TaskState *ts;
> -            CPUArchState **lastp;
> -            CPUArchState *p;
> +            CPUState **lastp;
> +            CPUState *p;
>
>              cpu_list_lock();
>              lastp = &first_cpu;
>              p = first_cpu;
> -            while (p && p != (CPUArchState *)cpu_env) {
> +            while (p && p != cpu) {
>                  lastp = &p->next_cpu;
>                  p = p->next_cpu;
>              }
> diff --git a/memory_mapping.c b/memory_mapping.c
> index 5634f81..515a984 100644
> --- a/memory_mapping.c
> +++ b/memory_mapping.c
> @@ -165,13 +165,13 @@ void memory_mapping_list_init(MemoryMappingList *list)
>      QTAILQ_INIT(&list->head);
>  }
>
> -static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu)
> +static CPUState *find_paging_enabled_cpu(CPUState *start_cpu)
>  {
> -    CPUArchState *env;
> +    CPUState *cpu;
>
> -    for (env = start_cpu; env != NULL; env = env->next_cpu) {
> -        if (cpu_paging_enabled(ENV_GET_CPU(env))) {
> -            return env;
> +    for (cpu = start_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        if (cpu_paging_enabled(cpu)) {
> +            return cpu;
>          }
>      }
>
> @@ -180,15 +180,15 @@ static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu)
>
>  void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp)
>  {
> -    CPUArchState *env, *first_paging_enabled_cpu;
> +    CPUState *cpu, *first_paging_enabled_cpu;
>      RAMBlock *block;
>      ram_addr_t offset, length;
>
>      first_paging_enabled_cpu = find_paging_enabled_cpu(first_cpu);
>      if (first_paging_enabled_cpu) {
> -        for (env = first_paging_enabled_cpu; env != NULL; env = env->next_cpu) {
> +        for (cpu = first_paging_enabled_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>              Error *err = NULL;
> -            cpu_get_memory_mapping(ENV_GET_CPU(env), list, &err);
> +            cpu_get_memory_mapping(cpu, list, &err);
>              if (err) {
>                  error_propagate(errp, err);
>                  return;
> diff --git a/monitor.c b/monitor.c
> index 9be515c..2ba7876 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -1806,14 +1806,12 @@ static void do_info_mtree(Monitor *mon, const QDict *qdict)
>  static void do_info_numa(Monitor *mon, const QDict *qdict)
>  {
>      int i;
> -    CPUArchState *env;
>      CPUState *cpu;
>
>      monitor_printf(mon, "%d nodes\n", nb_numa_nodes);
>      for (i = 0; i < nb_numa_nodes; i++) {
>          monitor_printf(mon, "node %d cpus:", i);
> -        for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -            cpu = ENV_GET_CPU(env);
> +        for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
>              if (cpu->numa_node == i) {
>                  monitor_printf(mon, " %d", cpu->cpu_index);
>              }
> diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
> index 83898cd..d133228 100644
> --- a/target-i386/arch_dump.c
> +++ b/target-i386/arch_dump.c
> @@ -185,7 +185,8 @@ int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
>      X86CPU *cpu = X86_CPU(cs);
>      int ret;
>  #ifdef TARGET_X86_64
> -    bool lma = !!(first_cpu->hflags & HF_LMA_MASK);
> +    X86CPU *first_x86_cpu = X86_CPU(first_cpu);
> +    bool lma = !!(first_x86_cpu->env.hflags & HF_LMA_MASK);
>
>      if (lma) {
>          ret = x86_64_write_elf64_note(f, &cpu->env, cpuid, opaque);
> @@ -394,7 +395,9 @@ int cpu_get_dump_info(ArchDumpInfo *info)
>      RAMBlock *block;
>
>  #ifdef TARGET_X86_64
> -    lma = !!(first_cpu->hflags & HF_LMA_MASK);
> +    X86CPU *first_x86_cpu = X86_CPU(first_cpu);
> +
> +    lma = !!(first_x86_cpu->env.hflags & HF_LMA_MASK);
>  #endif
>
>      if (lma) {
> diff --git a/target-i386/helper.c b/target-i386/helper.c
> index 5e5abe3..d6f43d7 100644
> --- a/target-i386/helper.c
> +++ b/target-i386/helper.c
> @@ -1188,6 +1188,7 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
>                          uint64_t status, uint64_t mcg_status, uint64_t addr,
>                          uint64_t misc, int flags)
>  {
> +    CPUState *cs = CPU(cpu);
>      CPUX86State *cenv = &cpu->env;
>      MCEInjectionParams params = {
>          .mon = mon,
> @@ -1200,7 +1201,6 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
>          .flags = flags,
>      };
>      unsigned bank_num = cenv->mcg_cap & 0xff;
> -    CPUX86State *env;
>
>      if (!cenv->mcg_cap) {
>          monitor_printf(mon, "MCE injection not supported\n");
> @@ -1220,19 +1220,22 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
>          return;
>      }
>
> -    run_on_cpu(CPU(cpu), do_inject_x86_mce, &params);
> +    run_on_cpu(cs, do_inject_x86_mce, &params);
>      if (flags & MCE_INJECT_BROADCAST) {
> +        CPUState *other_cs;
> +
>          params.bank = 1;
>          params.status = MCI_STATUS_VAL | MCI_STATUS_UC;
>          params.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV;
>          params.addr = 0;
>          params.misc = 0;
> -        for (env = first_cpu; env != NULL; env = env->next_cpu) {
> -            if (cenv == env) {
> +        for (other_cs = first_cpu; other_cs != NULL;
> +             other_cs = other_cs->next_cpu) {
> +            if (other_cs == cs) {
>                  continue;
>              }
> -            params.cpu = x86_env_get_cpu(env);
> -            run_on_cpu(CPU(cpu), do_inject_x86_mce, &params);
> +            params.cpu = X86_CPU(other_cs);
> +            run_on_cpu(other_cs, do_inject_x86_mce, &params);
>          }
>      }
>  }
> diff --git a/target-i386/kvm.c b/target-i386/kvm.c
> index 4b557b3..935ef63 100644
> --- a/target-i386/kvm.c
> +++ b/target-i386/kvm.c
> @@ -345,20 +345,22 @@ int kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
>
>  int kvm_arch_on_sigbus(int code, void *addr)
>  {
> -    if ((first_cpu->mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) {
> +    X86CPU *cpu = X86_CPU(first_cpu);
> +
> +    if ((cpu->env.mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) {
>          ram_addr_t ram_addr;
>          hwaddr paddr;
>
>          /* Hope we are lucky for AO MCE */
>          if (qemu_ram_addr_from_host(addr, &ram_addr) == NULL ||
> -            !kvm_physical_memory_addr_from_host(CPU(first_cpu)->kvm_state,
> +            !kvm_physical_memory_addr_from_host(first_cpu->kvm_state,
>                                                  addr, &paddr)) {
>              fprintf(stderr, "Hardware memory error for memory used by "
>                      "QEMU itself instead of guest system!: %p\n", addr);
>              return 0;
>          }
>          kvm_hwpoison_page_add(ram_addr);
> -        kvm_mce_inject(x86_env_get_cpu(first_cpu), paddr, code);
> +        kvm_mce_inject(X86_CPU(first_cpu), paddr, code);
>      } else {
>          if (code == BUS_MCEERR_AO) {
>              return 0;
> diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
> index e345f9a..957926c 100644
> --- a/target-i386/misc_helper.c
> +++ b/target-i386/misc_helper.c
> @@ -610,7 +610,7 @@ void helper_mwait(CPUX86State *env, int next_eip_addend)
>      cpu = x86_env_get_cpu(env);
>      cs = CPU(cpu);
>      /* XXX: not complete but not completely erroneous */
> -    if (cs->cpu_index != 0 || env->next_cpu != NULL) {
> +    if (cs->cpu_index != 0 || cs->next_cpu != NULL) {
>          /* more than one CPU: do not sleep because another CPU may
>             wake this one */
>      } else {
> diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
> index f6838ec..5cf1c3f 100644
> --- a/target-mips/op_helper.c
> +++ b/target-mips/op_helper.c
> @@ -1696,39 +1696,38 @@ target_ulong helper_emt(void)
>
>  target_ulong helper_dvpe(CPUMIPSState *env)
>  {
> -    CPUMIPSState *other_cpu_env = first_cpu;
> +    CPUState *other_cs = first_cpu;
>      target_ulong prev = env->mvp->CP0_MVPControl;
>
>      do {
> +        MIPSCPU *other_cpu = MIPS_CPU(other_cs);
>          /* Turn off all VPEs except the one executing the dvpe.  */
> -        if (other_cpu_env != env) {
> -            MIPSCPU *other_cpu = mips_env_get_cpu(other_cpu_env);
> -
> -            other_cpu_env->mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP);
> +        if (&other_cpu->env != env) {
> +            other_cpu->env.mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP);
>              mips_vpe_sleep(other_cpu);
>          }
> -        other_cpu_env = other_cpu_env->next_cpu;
> -    } while (other_cpu_env);
> +        other_cs = other_cs->next_cpu;
> +    } while (other_cs);
>      return prev;
>  }
>
>  target_ulong helper_evpe(CPUMIPSState *env)
>  {
> -    CPUMIPSState *other_cpu_env = first_cpu;
> +    CPUState *other_cs = first_cpu;
>      target_ulong prev = env->mvp->CP0_MVPControl;
>
>      do {
> -        MIPSCPU *other_cpu = mips_env_get_cpu(other_cpu_env);
> +        MIPSCPU *other_cpu = MIPS_CPU(other_cs);
>
> -        if (other_cpu_env != env
> +        if (&other_cpu->env != env
>              /* If the VPE is WFI, don't disturb its sleep.  */
>              && !mips_vpe_is_wfi(other_cpu)) {
>              /* Enable the VPE.  */
> -            other_cpu_env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
> +            other_cpu->env.mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
>              mips_vpe_wake(other_cpu); /* And wake it up.  */
>          }
> -        other_cpu_env = other_cpu_env->next_cpu;
> -    } while (other_cpu_env);
> +        other_cs = other_cs->next_cpu;
> +    } while (other_cs);
>      return prev;
>  }
>  #endif /* !CONFIG_USER_ONLY */
> diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
> index 4a0fc6d..e9fcad8 100644
> --- a/target-ppc/excp_helper.c
> +++ b/target-ppc/excp_helper.c
> @@ -986,16 +986,19 @@ void helper_msgsnd(target_ulong rb)
>  {
>      int irq = dbell2irq(rb);
>      int pir = rb & DBELL_PIRTAG_MASK;
> -    CPUPPCState *cenv;
> +    CPUState *cs;
>
>      if (irq < 0) {
>          return;
>      }
>
> -    for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
> +    for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
> +        PowerPCCPU *cpu = POWERPC_CPU(cs);
> +        CPUPPCState *cenv = &cpu->env;
> +
>          if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
>              cenv->pending_interrupts |= 1 << irq;
> -            cpu_interrupt(CPU(ppc_env_get_cpu(cenv)), CPU_INTERRUPT_HARD);
> +            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
>          }
>      }
>  }
> diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
> index e95ad4a..b0099e1 100644
> --- a/target-ppc/kvm.c
> +++ b/target-ppc/kvm.c
> @@ -1579,7 +1579,7 @@ uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
>
>      /* Find the largest hardware supported page size that's less than
>       * or equal to the (logical) backing page size of guest RAM */
> -    kvm_get_smmu_info(ppc_env_get_cpu(first_cpu), &info);
> +    kvm_get_smmu_info(POWERPC_CPU(first_cpu), &info);
>      rampagesize = getrampagesize();
>      best_page_shift = 0;
>
> diff --git a/translate-all.c b/translate-all.c
> index 02f8e5e..e8683d2 100644
> --- a/translate-all.c
> +++ b/translate-all.c
> @@ -681,7 +681,7 @@ static void page_flush_tb(void)
>  /* XXX: tb_flush is currently not thread safe */
>  void tb_flush(CPUArchState *env1)
>  {
> -    CPUArchState *env;
> +    CPUState *cpu;
>
>  #if defined(DEBUG_FLUSH)
>      printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
> @@ -696,7 +696,9 @@ void tb_flush(CPUArchState *env1)
>      }
>      tcg_ctx.tb_ctx.nb_tbs = 0;
>
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        CPUArchState *env = cpu->env_ptr;
> +
>          memset(env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof(void *));
>      }
>
> @@ -821,7 +823,7 @@ static inline void tb_reset_jump(TranslationBlock *tb, int n)
>  /* invalidate one TB */
>  void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
>  {
> -    CPUArchState *env;
> +    CPUState *cpu;
>      PageDesc *p;
>      unsigned int h, n1;
>      tb_page_addr_t phys_pc;
> @@ -848,7 +850,9 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
>
>      /* remove the TB from the hash list */
>      h = tb_jmp_cache_hash_func(tb->pc);
> -    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
> +        CPUArchState *env = cpu->env_ptr;
> +
>          if (env->tb_jmp_cache[h] == tb) {
>              env->tb_jmp_cache[h] = NULL;
>          }
> --
> 1.8.1.4
>
>

  reply	other threads:[~2013-07-11  9:14 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-10 14:33 [Qemu-devel] [PULL 00/43] QOM CPUState patch queue 2013-07-10 Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 01/43] target-openrisc: Fix typename in openrisc_cpu_class_by_name() Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 02/43] Revert "gdbstub: Simplify find_cpu()" Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 03/43] linux-user: Move cpu_clone_regs() and cpu_set_tls() into linux-user Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 04/43] cpu: Drop unnecessary dynamic casts in *_env_get_cpu() Andreas Färber
2013-07-10 14:33 ` [PULL 05/43] kvm: Free current_cpu identifier Andreas Färber
2013-07-10 14:33   ` [Qemu-devel] " Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 06/43] cpu: Replace cpu_single_env with CPUState current_cpu Andreas Färber
2013-07-10 14:33 ` [PULL 07/43] kvm: Change kvm_remove_all_breakpoints() argument to CPUState Andreas Färber
2013-07-10 14:33   ` [Qemu-devel] " Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 08/43] linux-user: Clean up do_syscall() Coding Style for TARGET_NR_exit Andreas Färber
2013-07-10 14:33 ` [PULL 09/43] cpu: Make first_cpu and next_cpu CPUState Andreas Färber
2013-07-10 14:33   ` [Qemu-devel] " Andreas Färber
2013-07-11  9:14   ` TeLeMan [this message]
2013-07-11  9:14     ` TeLeMan
2013-07-11  9:55     ` Andreas Färber
2013-07-11  9:55       ` Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 10/43] linux-user: Change thread_env to CPUState Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 11/43] bsd-user: " Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 12/43] intc/arm_gic: Build arm_gic only once Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 13/43] intc/openpic: Build openpic " Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 14/43] timer/arm_mptimer: Build arm_mptimer " Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 15/43] target-ppc: Don't overuse ENV_GET_CPU() Andreas Färber
2013-07-10 14:33 ` [PULL 16/43] target-s390x: " Andreas Färber
2013-07-10 14:33   ` [Qemu-devel] " Andreas Färber
2013-07-10 14:33 ` [PULL 17/43] target-s390x: Change handle_{hypercall,diag}() argument to S390CPU Andreas Färber
2013-07-10 14:33   ` [Qemu-devel] [PULL 17/43] target-s390x: Change handle_{hypercall, diag}() " Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 18/43] target-i386: Don't overuse CPUArchState Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 19/43] target-cris: gen_intermediate_code_internal() should be inlined Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 20/43] target-lm32: " Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 21/43] target-microblaze: " Andreas Färber
2013-07-10 14:33 ` [Qemu-devel] [PULL 22/43] target-moxie: " Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 23/43] target-xtensa: " Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 24/43] target-alpha: Change gen_intermediate_code_internal() argument to AlphaCPU Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 25/43] target-arm: Change gen_intermediate_code_internal() argument to ARMCPU Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 26/43] target-cris: Change gen_intermediate_code_internal() argument to CRISCPU Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 27/43] target-i386: Change gen_intermediate_code_internal() argument to X86CPU Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 28/43] target-lm32: Change gen_intermediate_code_internal() argument to LM32CPU Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 29/43] target-m68k: Change gen_intermediate_code_internal() argument to M68kCPU Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 30/43] target-microblaze: Change gen_intermediate_code_internal() argument types Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 31/43] target-mips: Change gen_intermediate_code_internal() argument to MIPSCPU Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 32/43] target-ppc: Change gen_intermediate_code_internal() argument to PowerPCCPU Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 33/43] target-s390x: Change gen_intermediate_code_internal() argument to S390CPU Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 34/43] target-sh4: Change gen_intermediate_code_internal() argument to SuperHCPU Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 35/43] target-sparc: Change gen_intermediate_code_internal() argument to SPARCCPU Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 36/43] target-unicore32: Change gen_intermediate_code_internal() signature Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 37/43] target-xtensa: Change gen_intermediate_code_internal() arg to XtensaCPU Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 38/43] target-i386: Change do_interrupt_all() argument to X86CPU Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 39/43] target-i386: Change do_smm_enter() " Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 40/43] log: Change log_cpu_state[_mask]() argument to CPUState Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 41/43] target-i386: Change LOG_PCALL_STATE() " Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 42/43] target-ppc: Change LOG_MMU_STATE() " Andreas Färber
2013-07-10 14:34 ` [Qemu-devel] [PULL 43/43] cpu: Move reset logging " Andreas Färber

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAETRQWm+s+zrOFv9_RFYJnSuijVYUU6RiSsW1K26uGzT0pUhTA@mail.gmail.com \
    --to=geleman@gmail.com \
    --cc=afaerber@suse.de \
    --cc=agraf@suse.de \
    --cc=aliguori@us.ibm.com \
    --cc=andreas.faerber@web.de \
    --cc=d.solodkiy@samsung.com \
    --cc=e.voevodin@samsung.com \
    --cc=edgar.iglesias@gmail.com \
    --cc=gleb@redhat.com \
    --cc=i.mitsyanko@samsung.com \
    --cc=kvm@vger.kernel.org \
    --cc=lcapitulino@redhat.com \
    --cc=m.kozlov@samsung.com \
    --cc=mark.langsdorf@calxeda.com \
    --cc=mtosatti@redhat.com \
    --cc=paul@codesourcery.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.crosthwaite@petalogix.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    --cc=riku.voipio@iki.fi \
    --cc=scottwood@freescale.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.