kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PULL 05/43] kvm: Free current_cpu identifier
       [not found] <1373466860-32732-1-git-send-email-afaerber@suse.de>
@ 2013-07-10 14:33 ` Andreas Färber
  2013-07-10 14:33 ` [PULL 07/43] kvm: Change kvm_remove_all_breakpoints() argument to CPUState Andreas Färber
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Andreas Färber @ 2013-07-10 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: Andreas Färber, Gleb Natapov, Paolo Bonzini,
	open list:Overall

Since CPU loops are done as last step in kvm_{insert,remove}_breakpoint()
and kvm_remove_all_breakpoints(), we do not need to distinguish between
invoking CPU and iterated CPUs and can thereby free the identifier for
use as a global variable.

Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 include/sysemu/kvm.h | 10 +++++-----
 kvm-all.c            | 39 +++++++++++++++++----------------------
 kvm-stub.c           |  6 +++---
 3 files changed, 25 insertions(+), 30 deletions(-)

diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index a14cfe9..7596aca 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -169,11 +169,11 @@ void *kvm_arch_ram_alloc(ram_addr_t size);
 void kvm_setup_guest_memory(void *start, size_t size);
 void kvm_flush_coalesced_mmio_buffer(void);
 
-int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
+int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr,
                           target_ulong len, int type);
-int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr,
+int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
                           target_ulong len, int type);
-void kvm_remove_all_breakpoints(CPUArchState *current_env);
+void kvm_remove_all_breakpoints(CPUArchState *env);
 int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap);
 #ifndef _WIN32
 int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset);
@@ -252,9 +252,9 @@ struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu,
 
 int kvm_sw_breakpoints_active(CPUState *cpu);
 
-int kvm_arch_insert_sw_breakpoint(CPUState *current_cpu,
+int kvm_arch_insert_sw_breakpoint(CPUState *cpu,
                                   struct kvm_sw_breakpoint *bp);
-int kvm_arch_remove_sw_breakpoint(CPUState *current_cpu,
+int kvm_arch_remove_sw_breakpoint(CPUState *cpu,
                                   struct kvm_sw_breakpoint *bp);
 int kvm_arch_insert_hw_breakpoint(target_ulong addr,
                                   target_ulong len, int type);
diff --git a/kvm-all.c b/kvm-all.c
index de658de..ed13d57 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1903,16 +1903,15 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
     return data.err;
 }
 
-int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
+int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr,
                           target_ulong len, int type)
 {
-    CPUState *current_cpu = ENV_GET_CPU(current_env);
+    CPUState *cpu = ENV_GET_CPU(env);
     struct kvm_sw_breakpoint *bp;
-    CPUArchState *env;
     int err;
 
     if (type == GDB_BREAKPOINT_SW) {
-        bp = kvm_find_sw_breakpoint(current_cpu, addr);
+        bp = kvm_find_sw_breakpoint(cpu, addr);
         if (bp) {
             bp->use_count++;
             return 0;
@@ -1925,14 +1924,13 @@ int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
 
         bp->pc = addr;
         bp->use_count = 1;
-        err = kvm_arch_insert_sw_breakpoint(current_cpu, bp);
+        err = kvm_arch_insert_sw_breakpoint(cpu, bp);
         if (err) {
             g_free(bp);
             return err;
         }
 
-        QTAILQ_INSERT_HEAD(&current_cpu->kvm_state->kvm_sw_breakpoints,
-                          bp, entry);
+        QTAILQ_INSERT_HEAD(&cpu->kvm_state->kvm_sw_breakpoints, bp, entry);
     } else {
         err = kvm_arch_insert_hw_breakpoint(addr, len, type);
         if (err) {
@@ -1949,16 +1947,15 @@ int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
     return 0;
 }
 
-int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr,
+int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
                           target_ulong len, int type)
 {
-    CPUState *current_cpu = ENV_GET_CPU(current_env);
+    CPUState *cpu = ENV_GET_CPU(env);
     struct kvm_sw_breakpoint *bp;
-    CPUArchState *env;
     int err;
 
     if (type == GDB_BREAKPOINT_SW) {
-        bp = kvm_find_sw_breakpoint(current_cpu, addr);
+        bp = kvm_find_sw_breakpoint(cpu, addr);
         if (!bp) {
             return -ENOENT;
         }
@@ -1968,12 +1965,12 @@ int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr,
             return 0;
         }
 
-        err = kvm_arch_remove_sw_breakpoint(current_cpu, bp);
+        err = kvm_arch_remove_sw_breakpoint(cpu, bp);
         if (err) {
             return err;
         }
 
-        QTAILQ_REMOVE(&current_cpu->kvm_state->kvm_sw_breakpoints, bp, entry);
+        QTAILQ_REMOVE(&cpu->kvm_state->kvm_sw_breakpoints, bp, entry);
         g_free(bp);
     } else {
         err = kvm_arch_remove_hw_breakpoint(addr, len, type);
@@ -1991,16 +1988,14 @@ int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr,
     return 0;
 }
 
-void kvm_remove_all_breakpoints(CPUArchState *current_env)
+void kvm_remove_all_breakpoints(CPUArchState *env)
 {
-    CPUState *current_cpu = ENV_GET_CPU(current_env);
+    CPUState *cpu = ENV_GET_CPU(env);
     struct kvm_sw_breakpoint *bp, *next;
-    KVMState *s = current_cpu->kvm_state;
-    CPUArchState *env;
-    CPUState *cpu;
+    KVMState *s = cpu->kvm_state;
 
     QTAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) {
-        if (kvm_arch_remove_sw_breakpoint(current_cpu, bp) != 0) {
+        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);
@@ -2026,19 +2021,19 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
     return -EINVAL;
 }
 
-int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
+int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr,
                           target_ulong len, int type)
 {
     return -EINVAL;
 }
 
-int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr,
+int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
                           target_ulong len, int type)
 {
     return -EINVAL;
 }
 
-void kvm_remove_all_breakpoints(CPUArchState *current_env)
+void kvm_remove_all_breakpoints(CPUArchState *env)
 {
 }
 #endif /* !KVM_CAP_SET_GUEST_DEBUG */
diff --git a/kvm-stub.c b/kvm-stub.c
index dec7a83..583c636 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -83,19 +83,19 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
     return -ENOSYS;
 }
 
-int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
+int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr,
                           target_ulong len, int type)
 {
     return -EINVAL;
 }
 
-int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr,
+int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
                           target_ulong len, int type)
 {
     return -EINVAL;
 }
 
-void kvm_remove_all_breakpoints(CPUArchState *current_env)
+void kvm_remove_all_breakpoints(CPUArchState *env)
 {
 }
 
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PULL 07/43] kvm: Change kvm_remove_all_breakpoints() argument to CPUState
       [not found] <1373466860-32732-1-git-send-email-afaerber@suse.de>
  2013-07-10 14:33 ` [PULL 05/43] kvm: Free current_cpu identifier Andreas Färber
@ 2013-07-10 14:33 ` Andreas Färber
  2013-07-10 14:33 ` [PULL 09/43] cpu: Make first_cpu and next_cpu CPUState Andreas Färber
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Andreas Färber @ 2013-07-10 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: Andreas Färber, Gleb Natapov, Paolo Bonzini,
	open list:Overall

Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 gdbstub.c            | 2 +-
 include/sysemu/kvm.h | 2 +-
 kvm-all.c            | 6 +++---
 kvm-stub.c           | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 9ae6576..f7d9f13 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2019,7 +2019,7 @@ static void gdb_breakpoint_remove_all(void)
     CPUArchState *env;
 
     if (kvm_enabled()) {
-        kvm_remove_all_breakpoints(gdbserver_state->c_cpu);
+        kvm_remove_all_breakpoints(ENV_GET_CPU(gdbserver_state->c_cpu));
         return;
     }
 
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 7596aca..1e08a85 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -173,7 +173,7 @@ int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr,
                           target_ulong len, int type);
 int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
                           target_ulong len, int type);
-void kvm_remove_all_breakpoints(CPUArchState *env);
+void kvm_remove_all_breakpoints(CPUState *cpu);
 int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap);
 #ifndef _WIN32
 int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset);
diff --git a/kvm-all.c b/kvm-all.c
index ed13d57..2c14ef3 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1988,11 +1988,11 @@ int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
     return 0;
 }
 
-void kvm_remove_all_breakpoints(CPUArchState *env)
+void kvm_remove_all_breakpoints(CPUState *cpu)
 {
-    CPUState *cpu = ENV_GET_CPU(env);
     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) {
@@ -2033,7 +2033,7 @@ int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
     return -EINVAL;
 }
 
-void kvm_remove_all_breakpoints(CPUArchState *env)
+void kvm_remove_all_breakpoints(CPUState *cpu)
 {
 }
 #endif /* !KVM_CAP_SET_GUEST_DEBUG */
diff --git a/kvm-stub.c b/kvm-stub.c
index 583c636..370c837 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -95,7 +95,7 @@ int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
     return -EINVAL;
 }
 
-void kvm_remove_all_breakpoints(CPUArchState *env)
+void kvm_remove_all_breakpoints(CPUState *cpu)
 {
 }
 
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PULL 09/43] cpu: Make first_cpu and next_cpu CPUState
       [not found] <1373466860-32732-1-git-send-email-afaerber@suse.de>
  2013-07-10 14:33 ` [PULL 05/43] kvm: Free current_cpu identifier 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 ` Andreas Färber
  2013-07-11  9:14   ` TeLeMan
  2013-07-10 14:33 ` [PULL 16/43] target-s390x: Don't overuse ENV_GET_CPU() Andreas Färber
  2013-07-10 14:33 ` [PULL 17/43] target-s390x: Change handle_{hypercall,diag}() argument to S390CPU Andreas Färber
  4 siblings, 1 reply; 7+ messages in thread
From: Andreas Färber @ 2013-07-10 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: Andreas Färber, Paul Brook, Peter Maydell, Evgeny Voevodin,
	Maksim Kozlov, Igor Mitsyanko, Dmitry Solodkiy, Mark Langsdorf,
	Peter Crosthwaite, Edgar E. Iglesias, Anthony Liguori,
	Aurelien Jarno, Alexander Graf, Scott Wood, Andreas Färber,
	Gleb Natapov, Paolo Bonzini, Riku Voipio, Luiz Capitulino,
	Marcelo Tosatti, open list:e500

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;
             } 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


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PULL 16/43] target-s390x: Don't overuse ENV_GET_CPU()
       [not found] <1373466860-32732-1-git-send-email-afaerber@suse.de>
                   ` (2 preceding siblings ...)
  2013-07-10 14:33 ` [PULL 09/43] cpu: Make first_cpu and next_cpu CPUState Andreas Färber
@ 2013-07-10 14:33 ` Andreas Färber
  2013-07-10 14:33 ` [PULL 17/43] target-s390x: Change handle_{hypercall,diag}() argument to S390CPU Andreas Färber
  4 siblings, 0 replies; 7+ messages in thread
From: Andreas Färber @ 2013-07-10 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: Andreas Färber, Jason J. Herne, Alexander Graf,
	Richard Henderson, Gleb Natapov, Paolo Bonzini, open list:Overall

Commit 3474b679486caa8f6448bae974e131370f360c13 (Utilize selective
runtime reg sync for hot code paths) introduced two uses of
ENV_GET_CPU() inside target-s390x/ KVM code. In one case we can use a
direct CPU() cast instead.

Cc: Jason J. Herne <jjherne@us.ibm.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 target-s390x/kvm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 42f758f..af499cf 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -469,7 +469,7 @@ static int kvm_handle_css_inst(S390CPU *cpu, struct kvm_run *run,
     int r = 0;
     int no_cc = 0;
     CPUS390XState *env = &cpu->env;
-    CPUState *cs = ENV_GET_CPU(env);
+    CPUState *cs = CPU(cpu);
 
     if (ipa0 != 0xb2) {
         /* Not handled for now. */
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PULL 17/43] target-s390x: Change handle_{hypercall,diag}() argument to S390CPU
       [not found] <1373466860-32732-1-git-send-email-afaerber@suse.de>
                   ` (3 preceding siblings ...)
  2013-07-10 14:33 ` [PULL 16/43] target-s390x: Don't overuse ENV_GET_CPU() Andreas Färber
@ 2013-07-10 14:33 ` Andreas Färber
  4 siblings, 0 replies; 7+ messages in thread
From: Andreas Färber @ 2013-07-10 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: Andreas Färber, Jason J. Herne, Alexander Graf,
	Richard Henderson, Gleb Natapov, Paolo Bonzini, open list:Overall

This allows to get rid of the last remaining ENV_GET_CPU() in
target-s390x/ by using CPU() cast directly on the argument.

Cc: Jason J. Herne <jjherne@us.ibm.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 target-s390x/kvm.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index af499cf..60e94f8 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -607,9 +607,10 @@ static int handle_priv(S390CPU *cpu, struct kvm_run *run,
     return r;
 }
 
-static int handle_hypercall(CPUS390XState *env, struct kvm_run *run)
+static int handle_hypercall(S390CPU *cpu, struct kvm_run *run)
 {
-    CPUState *cs = ENV_GET_CPU(env);
+    CPUState *cs = CPU(cpu);
+    CPUS390XState *env = &cpu->env;
 
     kvm_s390_get_registers_partial(cs);
     cs->kvm_vcpu_dirty = true;
@@ -618,13 +619,13 @@ static int handle_hypercall(CPUS390XState *env, struct kvm_run *run)
     return 0;
 }
 
-static int handle_diag(CPUS390XState *env, struct kvm_run *run, int ipb_code)
+static int handle_diag(S390CPU *cpu, struct kvm_run *run, int ipb_code)
 {
     int r = 0;
 
     switch (ipb_code) {
         case DIAG_KVM_HYPERCALL:
-            r = handle_hypercall(env, run);
+            r = handle_hypercall(cpu, run);
             break;
         case DIAG_KVM_BREAKPOINT:
             sleep(10);
@@ -735,7 +736,6 @@ out:
 
 static int handle_instruction(S390CPU *cpu, struct kvm_run *run)
 {
-    CPUS390XState *env = &cpu->env;
     unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00);
     uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff;
     int ipb_code = (run->s390_sieic.ipb & 0x0fff0000) >> 16;
@@ -749,7 +749,7 @@ static int handle_instruction(S390CPU *cpu, struct kvm_run *run)
         r = handle_priv(cpu, run, ipa0 >> 8, ipa1);
         break;
     case IPA0_DIAG:
-        r = handle_diag(env, run, ipb_code);
+        r = handle_diag(cpu, run, ipb_code);
         break;
     case IPA0_SIGP:
         r = handle_sigp(cpu, run, ipa1);
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PULL 09/43] cpu: Make first_cpu and next_cpu CPUState
  2013-07-10 14:33 ` [PULL 09/43] cpu: Make first_cpu and next_cpu CPUState Andreas Färber
@ 2013-07-11  9:14   ` TeLeMan
  2013-07-11  9:55     ` [Qemu-devel] " Andreas Färber
  0 siblings, 1 reply; 7+ messages in thread
From: TeLeMan @ 2013-07-11  9:14 UTC (permalink / raw)
  To: Andreas Färber
  Cc: Peter Maydell, Gleb Natapov, qemu-devel, Luiz Capitulino,
	Peter Crosthwaite, Edgar E. Iglesias, Igor Mitsyanko,
	Evgeny Voevodin, Alexander Graf, Andreas Färber,
	Maksim Kozlov, Riku Voipio, Paul Brook, open list:Overall,
	Scott Wood, Anthony Liguori, Mark Langsdorf, Marcelo Tosatti,
	open list:e500, Dmitry Solodkiy, Paolo Bonzini

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
>
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PULL 09/43] cpu: Make first_cpu and next_cpu CPUState
  2013-07-11  9:14   ` TeLeMan
@ 2013-07-11  9:55     ` Andreas Färber
  0 siblings, 0 replies; 7+ messages in thread
From: Andreas Färber @ 2013-07-11  9:55 UTC (permalink / raw)
  To: TeLeMan
  Cc: qemu-devel, Peter Maydell, Evgeny Voevodin, Luiz Capitulino,
	Peter Crosthwaite, Edgar E. Iglesias, Igor Mitsyanko,
	Gleb Natapov, Alexander Graf, Maksim Kozlov, Riku Voipio,
	Paul Brook, kvm, Scott Wood, Anthony Liguori, Mark Langsdorf,
	Marcelo Tosatti, qemu-ppc, Dmitry Solodkiy, Paolo Bonzini,
	Aurelien Jarno

Am 11.07.2013 11:14, schrieb TeLeMan:
> On Wed, Jul 10, 2013 at 10:33 PM, Andreas Färber <afaerber@suse.de> wrote:
>> diff --git a/gdbstub.c b/gdbstub.c
>> index f7d9f13..0ee82a9 100644
>> --- a/gdbstub.c
>> +++ b/gdbstub.c
[...]
>> @@ -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.

True. If this is the only place where you've found that mistake then the
implicit fix is already queued next on qom-cpu:
http://patchwork.ozlabs.org/patch/255756/

Review and/or testing of the remaining gdbstub patches would be appreciated:
http://lists.nongnu.org/archive/html/qemu-devel/2013-07/msg01510.html
Mainly I'm waiting on an ack or feedback for the vaddr typedef to proceed.

Thanks,
Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2013-07-11  9:55 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1373466860-32732-1-git-send-email-afaerber@suse.de>
2013-07-10 14:33 ` [PULL 05/43] kvm: Free current_cpu identifier 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 ` [PULL 09/43] cpu: Make first_cpu and next_cpu CPUState Andreas Färber
2013-07-11  9:14   ` TeLeMan
2013-07-11  9:55     ` [Qemu-devel] " Andreas Färber
2013-07-10 14:33 ` [PULL 16/43] target-s390x: Don't overuse ENV_GET_CPU() Andreas Färber
2013-07-10 14:33 ` [PULL 17/43] target-s390x: Change handle_{hypercall,diag}() argument to S390CPU Andreas Färber

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).