Merge remote-tracking branch 'afaerber/tags/qom-cpu-for-anthony' into staging

QOM CPUState refactorings

* Fix for OpenRISCCPU subclasses
* Fix for gdbstub CPU selection
* Move linux-user CPU functions into new header
* CPUState part 10 refactoring: first_cpu, next_cpu, cpu_single_env et al.
* Fix some targets to consistently inline TCG code generation
* Centrally log CPU reset

# gpg: Signature made Wed 10 Jul 2013 07:52:39 AM CDT using RSA key ID 3E7E013F
# gpg: Can't check signature: public key not found

# By Andreas Färber (41) and others
# Via Andreas Färber
* afaerber/tags/qom-cpu-for-anthony: (43 commits)
  cpu: Move reset logging to CPUState
  target-ppc: Change LOG_MMU_STATE() argument to CPUState
  target-i386: Change LOG_PCALL_STATE() argument to CPUState
  log: Change log_cpu_state[_mask]() argument to CPUState
  target-i386: Change do_smm_enter() argument to X86CPU
  target-i386: Change do_interrupt_all() argument to X86CPU
  target-xtensa: Change gen_intermediate_code_internal() arg to XtensaCPU
  target-unicore32: Change gen_intermediate_code_internal() signature
  target-sparc: Change gen_intermediate_code_internal() argument to SPARCCPU
  target-sh4: Change gen_intermediate_code_internal() argument to SuperHCPU
  target-s390x: Change gen_intermediate_code_internal() argument to S390CPU
  target-ppc: Change gen_intermediate_code_internal() argument to PowerPCCPU
  target-mips: Change gen_intermediate_code_internal() argument to MIPSCPU
  target-microblaze: Change gen_intermediate_code_internal() argument types
  target-m68k: Change gen_intermediate_code_internal() argument to M68kCPU
  target-lm32: Change gen_intermediate_code_internal() argument to LM32CPU
  target-i386: Change gen_intermediate_code_internal() argument to X86CPU
  target-cris: Change gen_intermediate_code_internal() argument to CRISCPU
  target-arm: Change gen_intermediate_code_internal() argument to ARMCPU
  target-alpha: Change gen_intermediate_code_internal() argument to AlphaCPU
  ...
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 5e20510..93fd9e4 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -98,7 +98,7 @@
 static const char *get_elf_platform(void)
 {
     static char elf_platform[] = "i386";
-    int family = (thread_env->cpuid_version >> 8) & 0xff;
+    int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL);
     if (family > 6)
         family = 6;
     if (family >= 3)
@@ -110,7 +110,9 @@
 
 static uint32_t get_elf_hwcap(void)
 {
-    return thread_env->features[FEAT_1_EDX];
+    X86CPU *cpu = X86_CPU(thread_cpu);
+
+    return cpu->env.features[FEAT_1_EDX];
 }
 
 #ifdef TARGET_X86_64
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 75dbd7f..1e92552 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -92,7 +92,7 @@
 void fork_end(int child)
 {
     if (child) {
-        gdbserver_fork(thread_env);
+        gdbserver_fork((CPUArchState *)thread_cpu->env_ptr);
     }
 }
 
@@ -713,7 +713,7 @@
     exit(1);
 }
 
-THREAD CPUArchState *thread_env;
+THREAD CPUState *thread_cpu;
 
 /* Assumes contents are already zeroed.  */
 void init_task_state(TaskState *ts)
@@ -915,7 +915,7 @@
 #if defined(TARGET_SPARC) || defined(TARGET_PPC)
     cpu_reset(ENV_GET_CPU(env));
 #endif
-    thread_env = env;
+    thread_cpu = ENV_GET_CPU(env);
 
     if (getenv("QEMU_STRACE")) {
         do_strace = 1;
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index a826086..325f564 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -139,7 +139,7 @@
                             abi_long arg2, abi_long arg3, abi_long arg4,
                             abi_long arg5, abi_long arg6);
 void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
-extern THREAD CPUArchState *thread_env;
+extern THREAD CPUState *thread_cpu;
 void cpu_loop(CPUArchState *env);
 char *target_strerror(int err);
 int get_osversion(void);
diff --git a/cpu-exec.c b/cpu-exec.c
index ec46380..6c784a7 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -213,12 +213,12 @@
         cpu->halted = 0;
     }
 
-    cpu_single_env = env;
+    current_cpu = cpu;
 
-    /* As long as cpu_single_env is null, up to the assignment just above,
+    /* As long as current_cpu is null, up to the assignment just above,
      * requests by other threads to exit the execution loop are expected to
      * be issued using the exit_request global. We must make sure that our
-     * evaluation of the global value is performed past the cpu_single_env
+     * evaluation of the global value is performed past the current_cpu
      * value transition point, which requires a memory barrier as well as
      * an instruction scheduling constraint on modern architectures.  */
     smp_mb();
@@ -331,7 +331,7 @@
                             cpu_svm_check_intercept_param(env, SVM_EXIT_SMI,
                                                           0);
                             cpu->interrupt_request &= ~CPU_INTERRUPT_SMI;
-                            do_smm_enter(env);
+                            do_smm_enter(x86_env_get_cpu(env));
                             next_tb = 0;
                         } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
                                    !(env->hflags2 & HF2_NMI_MASK)) {
@@ -577,15 +577,15 @@
                 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
                     /* restore flags in standard format */
 #if defined(TARGET_I386)
-                    log_cpu_state(env, CPU_DUMP_CCOP);
+                    log_cpu_state(cpu, CPU_DUMP_CCOP);
 #elif defined(TARGET_M68K)
                     cpu_m68k_flush_flags(env, env->cc_op);
                     env->cc_op = CC_OP_FLAGS;
                     env->sr = (env->sr & 0xffe0)
                               | env->cc_dest | (env->cc_x << 4);
-                    log_cpu_state(env, 0);
+                    log_cpu_state(cpu, 0);
 #else
-                    log_cpu_state(env, 0);
+                    log_cpu_state(cpu, 0);
 #endif
                 }
 #endif /* DEBUG_DISAS */
@@ -673,7 +673,8 @@
         } else {
             /* Reload env after longjmp - the compiler may have smashed all
              * local variables as longjmp is marked 'noreturn'. */
-            env = cpu_single_env;
+            cpu = current_cpu;
+            env = cpu->env_ptr;
         }
     } /* for(;;) */
 
@@ -707,7 +708,7 @@
 #error unsupported target CPU
 #endif
 
-    /* fail safe : never use cpu_single_env outside cpu_exec() */
-    cpu_single_env = NULL;
+    /* fail safe : never use current_cpu outside cpu_exec() */
+    current_cpu = NULL;
     return ret;
 }
diff --git a/cpus.c b/cpus.c
index 20958e5..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 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;
         }
     }
@@ -118,10 +118,11 @@
 int64_t cpu_get_icount(void)
 {
     int64_t icount;
-    CPUArchState *env = cpu_single_env;
+    CPUState *cpu = current_cpu;
 
     icount = qemu_icount;
-    if (env) {
+    if (cpu) {
+        CPUArchState *env = cpu->env_ptr;
         if (!can_do_io(env)) {
             fprintf(stderr, "Bad clock read\n");
         }
@@ -387,15 +388,13 @@
 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);
     }
@@ -405,28 +404,28 @@
 
 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);
     }
 }
 
@@ -468,8 +467,8 @@
 
 static void cpu_signal(int sig)
 {
-    if (cpu_single_env) {
-        cpu_exit(ENV_GET_CPU(cpu_single_env));
+    if (current_cpu) {
+        cpu_exit(current_cpu);
     }
     exit_request = 1;
 }
@@ -660,10 +659,10 @@
 
     qemu_cpu_kick(cpu);
     while (!wi.done) {
-        CPUArchState *self_env = cpu_single_env;
+        CPUState *self_cpu = current_cpu;
 
         qemu_cond_wait(&qemu_work_cond, &qemu_global_mutex);
-        cpu_single_env = self_env;
+        current_cpu = self_cpu;
     }
 }
 
@@ -697,7 +696,7 @@
 
 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
@@ -710,8 +709,8 @@
         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);
     }
 }
 
@@ -733,7 +732,7 @@
     qemu_mutex_lock(&qemu_global_mutex);
     qemu_thread_get_self(cpu->thread);
     cpu->thread_id = qemu_get_thread_id();
-    cpu_single_env = cpu->env_ptr;
+    current_cpu = cpu;
 
     r = kvm_init_vcpu(cpu);
     if (r < 0) {
@@ -781,9 +780,9 @@
     cpu->created = true;
     qemu_cond_signal(&qemu_cpu_cond);
 
-    cpu_single_env = cpu->env_ptr;
+    current_cpu = cpu;
     while (1) {
-        cpu_single_env = NULL;
+        current_cpu = NULL;
         qemu_mutex_unlock_iothread();
         do {
             int sig;
@@ -794,7 +793,7 @@
             exit(1);
         }
         qemu_mutex_lock_iothread();
-        cpu_single_env = cpu->env_ptr;
+        current_cpu = cpu;
         qemu_wait_io_event_common(cpu);
     }
 
@@ -813,7 +812,6 @@
 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);
@@ -823,12 +821,12 @@
     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);
         }
     }
 
@@ -894,12 +892,11 @@
 void qemu_cpu_kick_self(void)
 {
 #ifndef _WIN32
-    assert(cpu_single_env);
-    CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
+    assert(current_cpu);
 
-    if (!cpu_single_cpu->thread_kicked) {
-        qemu_cpu_kick_thread(cpu_single_cpu);
-        cpu_single_cpu->thread_kicked = true;
+    if (!current_cpu->thread_kicked) {
+        qemu_cpu_kick_thread(current_cpu);
+        current_cpu->thread_kicked = true;
     }
 #else
     abort();
@@ -913,7 +910,7 @@
 
 static bool qemu_in_vcpu_thread(void)
 {
-    return cpu_single_env && qemu_cpu_is_self(ENV_GET_CPU(cpu_single_env));
+    return current_cpu && qemu_cpu_is_self(current_cpu);
 }
 
 void qemu_mutex_lock_iothread(void)
@@ -923,7 +920,7 @@
     } 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 @@
 
 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 @@
 
 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 @@
 
     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 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;
     }
 }
 
@@ -1069,11 +1062,10 @@
 
 void cpu_stop_current(void)
 {
-    if (cpu_single_env) {
-        CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
-        cpu_single_cpu->stop = false;
-        cpu_single_cpu->stopped = true;
-        cpu_exit(cpu_single_cpu);
+    if (current_cpu) {
+        current_cpu->stop = false;
+        current_cpu->stopped = true;
+        cpu_exit(current_cpu);
         qemu_cond_signal(&qemu_pause_cond);
     }
 }
@@ -1152,8 +1144,8 @@
         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);
@@ -1173,12 +1165,10 @@
 
 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;
@@ -1198,18 +1188,30 @@
 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)
@@ -1317,11 +1319,14 @@
 void qmp_inject_nmi(Error **errp)
 {
 #if defined(TARGET_I386)
-    CPUArchState *env;
+    CPUState *cs;
 
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+    for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
+        X86CPU *cpu = X86_CPU(cs);
+        CPUX86State *env = &cpu->env;
+
         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 @@
 
 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 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 @@
         }
     }
 
-    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_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 @@
         }
     }
 
-    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 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 @@
      */
     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 e150935..80ee2ab 100644
--- a/exec.c
+++ b/exec.c
@@ -69,10 +69,10 @@
 
 #endif
 
-CPUArchState *first_cpu;
+CPUState *first_cpu;
 /* current CPU in the current thread. It is only valid inside
    cpu_exec() */
-DEFINE_TLS(CPUArchState *,cpu_single_env);
+DEFINE_TLS(CPUState *, current_cpu);
 /* 0 = Do not count executed instructions.
    1 = Precise instruction counting.
    2 = Adaptive rate instruction counting.  */
@@ -351,27 +351,26 @@
 
 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 @@
 {
     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 @@
 #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
@@ -618,7 +617,7 @@
         qemu_log("qemu: fatal: ");
         qemu_log_vprintf(fmt, ap2);
         qemu_log("\n");
-        log_cpu_state(env, CPU_DUMP_FPU | CPU_DUMP_CCOP);
+        log_cpu_state(cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP);
         qemu_log_flush();
         qemu_log_close();
     }
@@ -638,7 +637,6 @@
 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 @@
 
     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. */
@@ -1467,8 +1462,10 @@
     cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
     /* we remove the notdirty callback only if the code has been
        flushed */
-    if (dirty_flags == 0xff)
-        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
+    if (dirty_flags == 0xff) {
+        CPUArchState *env = current_cpu->env_ptr;
+        tlb_set_dirty(env, env->mem_io_vaddr);
+    }
 }
 
 static bool notdirty_mem_accepts(void *opaque, hwaddr addr,
@@ -1486,7 +1483,7 @@
 /* Generate a debug exception if a watchpoint has been hit.  */
 static void check_watchpoint(int offset, int len_mask, int flags)
 {
-    CPUArchState *env = cpu_single_env;
+    CPUArchState *env = current_cpu->env_ptr;
     target_ulong pc, cs_base;
     target_ulong vaddr;
     CPUWatchpoint *wp;
@@ -1750,12 +1747,14 @@
 
 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);
     }
 }
@@ -1925,7 +1924,7 @@
         if (is_write) {
             if (!memory_access_is_direct(mr, is_write)) {
                 l = memory_access_size(mr, l, addr1);
-                /* XXX: could force cpu_single_env to NULL to avoid
+                /* XXX: could force current_cpu to NULL to avoid
                    potential bugs */
                 if (l == 4) {
                     /* 32 bit write access */
diff --git a/gdbstub.c b/gdbstub.c
index 3101a43..0ee82a9 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1839,6 +1839,7 @@
         /* 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 @@
                      "<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 int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
 {
+    CPUState *cpu;
     CPUArchState *env;
     int err = 0;
 
@@ -1958,7 +1960,8 @@
     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 @@
     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_remove(target_ulong addr, target_ulong len, int type)
 {
+    CPUState *cpu;
     CPUArchState *env;
     int err = 0;
 
@@ -1992,7 +1997,8 @@
     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 @@
     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,14 +2023,16 @@
 
 static void gdb_breakpoint_remove_all(void)
 {
+    CPUState *cpu;
     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;
     }
 
-    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);
@@ -2073,11 +2082,13 @@
 {
     CPUState *cpu;
 
-    cpu = qemu_get_cpu(thread_id);
-    if (cpu == NULL) {
-        return NULL;
+    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
+        if (cpu_index(cpu) == thread_id) {
+            return cpu->env_ptr;
+        }
     }
-    return cpu->env_ptr;
+
+    return NULL;
 }
 
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
@@ -2390,7 +2401,7 @@
             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:
@@ -2398,7 +2409,7 @@
                 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;
@@ -2865,8 +2876,8 @@
     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;
 
@@ -3050,8 +3061,8 @@
         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/alpha/typhoon.c b/hw/alpha/typhoon.c
index 63cc2cb..1c3ac8e 100644
--- a/hw/alpha/typhoon.c
+++ b/hw/alpha/typhoon.c
@@ -72,9 +72,8 @@
 
 static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
 {
-    CPUAlphaState *env = cpu_single_env;
+    CPUState *cpu = current_cpu;
     TyphoonState *s = opaque;
-    CPUState *cpu;
     uint64_t ret = 0;
 
     if (addr & 4) {
@@ -95,7 +94,6 @@
 
     case 0x0080:
         /* MISC: Miscellaneous Register.  */
-        cpu = ENV_GET_CPU(env);
         ret = s->cchip.misc | (cpu->cpu_index & 3);
         break;
 
@@ -197,7 +195,6 @@
         break;
 
     default:
-        cpu = CPU(alpha_env_get_cpu(cpu_single_env));
         cpu_unassigned_access(cpu, addr, false, false, 0, size);
         return -1;
     }
@@ -215,7 +212,6 @@
 static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size)
 {
     TyphoonState *s = opaque;
-    CPUState *cs;
     uint64_t ret = 0;
 
     if (addr & 4) {
@@ -302,8 +298,7 @@
         break;
 
     default:
-        cs = CPU(alpha_env_get_cpu(cpu_single_env));
-        cpu_unassigned_access(cs, addr, false, false, 0, size);
+        cpu_unassigned_access(current_cpu, addr, false, false, 0, size);
         return -1;
     }
 
@@ -315,7 +310,6 @@
                         uint64_t v32, unsigned size)
 {
     TyphoonState *s = opaque;
-    CPUState *cpu_single_cpu = CPU(alpha_env_get_cpu(cpu_single_env));
     uint64_t val, oldval, newval;
 
     if (addr & 4) {
@@ -465,7 +459,7 @@
         break;
 
     default:
-        cpu_unassigned_access(cpu_single_cpu, addr, true, false, 0, size);
+        cpu_unassigned_access(current_cpu, addr, true, false, 0, size);
         return;
     }
 }
@@ -480,7 +474,6 @@
                         uint64_t v32, unsigned size)
 {
     TyphoonState *s = opaque;
-    CPUState *cs;
     uint64_t val, oldval;
 
     if (addr & 4) {
@@ -582,8 +575,7 @@
         break;
 
     default:
-        cs = CPU(alpha_env_get_cpu(cpu_single_env));
-        cpu_unassigned_access(cs, addr, true, false, 0, size);
+        cpu_unassigned_access(current_cpu, addr, true, false, 0, size);
         return;
     }
 }
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 3e8741e..a2e4032 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -333,7 +333,7 @@
             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 @@
 
 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;
@@ -470,9 +470,9 @@
     }
     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 @@
 {
     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 @@
 
     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 @@
     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/pxa2xx.c b/hw/arm/pxa2xx.c
index 5a22654..3c520d7 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -301,8 +301,7 @@
 #endif
 
         /* Suspend */
-        cpu_interrupt(CPU(arm_env_get_cpu(cpu_single_env)),
-                      CPU_INTERRUPT_HALT);
+        cpu_interrupt(current_cpu, CPU_INTERRUPT_HALT);
 
         goto message;
 
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 @@
     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 @@
     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 @@
     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 @@
                                      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 @@
         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 @@
 /* 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 9850a85..ccd089a 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -490,13 +490,15 @@
     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);
     }
 }
 
@@ -624,11 +626,13 @@
 static void vapic_write(void *opaque, hwaddr addr, uint64_t data,
                         unsigned int size)
 {
-    CPUX86State *env = cpu_single_env;
+    CPUState *cs = current_cpu;
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
     hwaddr rom_paddr;
     VAPICROMState *s = opaque;
 
-    cpu_synchronize_state(CPU(x86_env_get_cpu(env)));
+    cpu_synchronize_state(cs);
 
     /*
      * The VAPIC supports two PIO-based hypercalls, both via port 0x7E.
@@ -717,8 +721,9 @@
 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)
@@ -741,7 +746,7 @@
     }
     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 e00f9dc..c5d8570 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -160,8 +160,9 @@
 
 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 @@
 
 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 {
@@ -886,8 +890,9 @@
 
 DeviceState *cpu_get_current_apic(void)
 {
-    if (cpu_single_env) {
-        return cpu_single_env->apic_state;
+    if (current_cpu) {
+        X86CPU *cpu = X86_CPU(current_cpu);
+        return cpu->env.apic_state;
     } else {
         return NULL;
     }
@@ -1176,10 +1181,10 @@
 
 static void cpu_request_exit(void *opaque, int irq, int level)
 {
-    CPUX86State *env = cpu_single_env;
+    CPUState *cpu = current_cpu;
 
-    if (env && level) {
-        cpu_exit(CPU(x86_env_get_cpu(env)));
+    if (cpu && level) {
+        cpu_exit(cpu);
     }
 }
 
@@ -1273,8 +1278,7 @@
         }
     }
 
-    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 @@
     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/Makefile.objs b/hw/intc/Makefile.objs
index 2ba49d0..86f9d5b 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -10,15 +10,15 @@
 common-obj-$(CONFIG_SLAVIO) += slavio_intctl.o
 common-obj-$(CONFIG_IOAPIC) += ioapic_common.o
 common-obj-$(CONFIG_ARM_GIC) += arm_gic_common.o
+common-obj-$(CONFIG_ARM_GIC) += arm_gic.o
+common-obj-$(CONFIG_OPENPIC) += openpic.o
 
 obj-$(CONFIG_APIC) += apic.o apic_common.o
-obj-$(CONFIG_ARM_GIC) += arm_gic.o
 obj-$(CONFIG_ARM_GIC_KVM) += arm_gic_kvm.o
 obj-$(CONFIG_STELLARIS) += armv7m_nvic.o
 obj-$(CONFIG_EXYNOS4) += exynos4210_gic.o exynos4210_combiner.o
 obj-$(CONFIG_GRLIB) += grlib_irqmp.o
 obj-$(CONFIG_IOAPIC) += ioapic.o
 obj-$(CONFIG_OMAP) += omap_intc.o
-obj-$(CONFIG_OPENPIC) += openpic.o
 obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o
 obj-$(CONFIG_SH4) += sh_intc.o
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index b59df06..8e34004 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -20,6 +20,7 @@
 
 #include "hw/sysbus.h"
 #include "gic_internal.h"
+#include "qom/cpu.h"
 
 //#define DEBUG_GIC
 
@@ -39,8 +40,7 @@
 static inline int gic_get_current_cpu(GICState *s)
 {
     if (s->num_cpu > 1) {
-        CPUState *cpu = ENV_GET_CPU(cpu_single_env);
-        return cpu->cpu_index;
+        return current_cpu->cpu_index;
     }
     return 0;
 }
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 2a57f77..178344b 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -140,6 +140,7 @@
 
 static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
 {
+    ARMCPU *cpu;
     uint32_t val;
     int irq;
 
@@ -171,7 +172,8 @@
     case 0x1c: /* SysTick Calibration Value.  */
         return 10000;
     case 0xd00: /* CPUID Base.  */
-        return cpu_single_env->cp15.c0_cpuid;
+        cpu = ARM_CPU(current_cpu);
+        return cpu->env.cp15.c0_cpuid;
     case 0xd04: /* Interrupt Control State.  */
         /* VECTACTIVE */
         val = s->gic.running_irq[0];
@@ -206,7 +208,8 @@
             val |= (1 << 31);
         return val;
     case 0xd08: /* Vector Table Offset.  */
-        return cpu_single_env->v7m.vecbase;
+        cpu = ARM_CPU(current_cpu);
+        return cpu->env.v7m.vecbase;
     case 0xd0c: /* Application Interrupt/Reset Control.  */
         return 0xfa05000;
     case 0xd10: /* System Control.  */
@@ -279,6 +282,7 @@
 
 static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
 {
+    ARMCPU *cpu;
     uint32_t oldval;
     switch (offset) {
     case 0x10: /* SysTick Control and Status.  */
@@ -331,7 +335,8 @@
         }
         break;
     case 0xd08: /* Vector Table Offset.  */
-        cpu_single_env->v7m.vecbase = value & 0xffffff80;
+        cpu = ARM_CPU(current_cpu);
+        cpu->env.v7m.vecbase = value & 0xffffff80;
         break;
     case 0xd0c: /* Application Interrupt/Reset Control.  */
         if ((value >> 16) == 0x05fa) {
diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
index 937e292..7df72f4 100644
--- a/hw/intc/openpic.c
+++ b/hw/intc/openpic.c
@@ -37,10 +37,10 @@
 #include "hw/ppc/mac.h"
 #include "hw/pci/pci.h"
 #include "hw/ppc/openpic.h"
+#include "hw/ppc/ppc_e500.h"
 #include "hw/sysbus.h"
 #include "hw/pci/msi.h"
 #include "qemu/bitops.h"
-#include "hw/ppc/ppc.h"
 
 //#define DEBUG_OPENPIC
 
@@ -180,14 +180,11 @@
 
 static int get_current_cpu(void)
 {
-    CPUState *cpu_single_cpu;
-
-    if (!cpu_single_env) {
+    if (!current_cpu) {
         return -1;
     }
 
-    cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
-    return cpu_single_cpu->cpu_index;
+    return current_cpu->cpu_index;
 }
 
 static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
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 @@
         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 @@
 
     /* 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_fulong2e.c b/hw/mips/mips_fulong2e.c
index 03e44d5..9e305d2 100644
--- a/hw/mips/mips_fulong2e.c
+++ b/hw/mips/mips_fulong2e.c
@@ -250,10 +250,10 @@
 
 static void cpu_request_exit(void *opaque, int irq, int level)
 {
-    CPUMIPSState *env = cpu_single_env;
+    CPUState *cpu = current_cpu;
 
-    if (env && level) {
-        cpu_exit(CPU(mips_env_get_cpu(env)));
+    if (cpu && level) {
+        cpu_exit(cpu);
     }
 }
 
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index 3eac63b..31e138b 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -99,10 +99,10 @@
 
 static void cpu_request_exit(void *opaque, int irq, int level)
 {
-    CPUMIPSState *env = cpu_single_env;
+    CPUState *cpu = current_cpu;
 
-    if (env && level) {
-        cpu_exit(CPU(mips_env_get_cpu(env)));
+    if (cpu && level) {
+        cpu_exit(cpu);
     }
 }
 
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index ceadc72..de87241 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -770,10 +770,10 @@
 
 static void cpu_request_exit(void *opaque, int irq, int level)
 {
-    CPUMIPSState *env = cpu_single_env;
+    CPUState *cpu = current_cpu;
 
-    if (env && level) {
-        cpu_exit(CPU(mips_env_get_cpu(env)));
+    if (cpu && level) {
+        cpu_exit(cpu);
     }
 }
 
@@ -844,7 +844,8 @@
         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/misc/vmport.c b/hw/misc/vmport.c
index 7463776..0b5a564 100644
--- a/hw/misc/vmport.c
+++ b/hw/misc/vmport.c
@@ -62,11 +62,13 @@
                                    unsigned size)
 {
     VMPortState *s = opaque;
-    CPUX86State *env = cpu_single_env;
+    CPUState *cs = current_cpu;
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
     unsigned char command;
     uint32_t eax;
 
-    cpu_synchronize_state(CPU(x86_env_get_cpu(env)));
+    cpu_synchronize_state(cs);
 
     eax = env->regs[R_EAX];
     if (eax != VMPORT_MAGIC)
@@ -89,29 +91,32 @@
 static void vmport_ioport_write(void *opaque, hwaddr addr,
                                 uint64_t val, unsigned size)
 {
-    CPUX86State *env = cpu_single_env;
+    X86CPU *cpu = X86_CPU(current_cpu);
 
-    env->regs[R_EAX] = vmport_ioport_read(opaque, addr, 4);
+    cpu->env.regs[R_EAX] = vmport_ioport_read(opaque, addr, 4);
 }
 
 static uint32_t vmport_cmd_get_version(void *opaque, uint32_t addr)
 {
-    CPUX86State *env = cpu_single_env;
-    env->regs[R_EBX] = VMPORT_MAGIC;
+    X86CPU *cpu = X86_CPU(current_cpu);
+
+    cpu->env.regs[R_EBX] = VMPORT_MAGIC;
     return 6;
 }
 
 static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr)
 {
-    CPUX86State *env = cpu_single_env;
-    env->regs[R_EBX] = 0x1177;
+    X86CPU *cpu = X86_CPU(current_cpu);
+
+    cpu->env.regs[R_EBX] = 0x1177;
     return ram_size;
 }
 
 /* vmmouse helpers */
 void vmmouse_get_data(uint32_t *data)
 {
-    CPUX86State *env = cpu_single_env;
+    X86CPU *cpu = X86_CPU(current_cpu);
+    CPUX86State *env = &cpu->env;
 
     data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX];
     data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX];
@@ -120,7 +125,8 @@
 
 void vmmouse_set_data(const uint32_t *data)
 {
-    CPUX86State *env = cpu_single_env;
+    X86CPU *cpu = X86_CPU(current_cpu);
+    CPUX86State *env = &cpu->env;
 
     env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1];
     env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3];
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index ee7e49a..f00a62a 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -494,7 +494,6 @@
                                           qemu_irq **irqs)
 {
     DeviceState *dev;
-    CPUPPCState *env;
     CPUState *cs;
     int r;
 
@@ -506,9 +505,7 @@
         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/mpc8544_guts.c b/hw/ppc/mpc8544_guts.c
index 2e2f2eb..a10abe9 100644
--- a/hw/ppc/mpc8544_guts.c
+++ b/hw/ppc/mpc8544_guts.c
@@ -68,7 +68,8 @@
                                   unsigned size)
 {
     uint32_t value = 0;
-    CPUPPCState *env = cpu_single_env;
+    PowerPCCPU *cpu = POWERPC_CPU(current_cpu);
+    CPUPPCState *env = &cpu->env;
 
     addr &= MPC8544_GUTS_MMIO_SIZE - 1;
     switch (addr) {
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index fb57b42..e1c095c 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -23,6 +23,7 @@
  */
 #include "hw/hw.h"
 #include "hw/ppc/ppc.h"
+#include "hw/ppc/ppc_e500.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
 #include "hw/timer/m48t59.h"
@@ -440,15 +441,14 @@
 /* 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 7b2559d..19f2442 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -417,10 +417,10 @@
 
 static void cpu_request_exit(void *opaque, int irq, int level)
 {
-    CPUPPCState *env = cpu_single_env;
+    CPUState *cpu = current_cpu;
 
-    if (env && level) {
-        cpu_exit(CPU(ppc_env_get_cpu(env)));
+    if (cpu && level) {
+        cpu_exit(cpu);
     }
 }
 
@@ -605,8 +605,9 @@
     /* 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 @@
     }
     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 226ae70..5c31ad3 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -131,7 +131,6 @@
 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 @@
 
     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 @@
                                    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 @@
     /* 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 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 @@
                        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/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 90b7b60..7a0c1ab 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -264,9 +264,8 @@
 
 static void cpu_halt_signal(void *opaque, int irq, int level)
 {
-    if (level && cpu_single_env) {
-        cpu_interrupt(CPU(sparc_env_get_cpu(cpu_single_env)),
-                      CPU_INTERRUPT_HALT);
+    if (level && current_cpu) {
+        cpu_interrupt(current_cpu, CPU_INTERRUPT_HALT);
     }
 }
 
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
index 32b5c1a..eca5905 100644
--- a/hw/timer/Makefile.objs
+++ b/hw/timer/Makefile.objs
@@ -1,4 +1,5 @@
 common-obj-$(CONFIG_ARM_TIMER) += arm_timer.o
+common-obj-$(CONFIG_ARM_MPTIMER) += arm_mptimer.o
 common-obj-$(CONFIG_CADENCE) += cadence_ttc.o
 common-obj-$(CONFIG_DS1338) += ds1338.o
 common-obj-$(CONFIG_HPET) += hpet.o
@@ -25,5 +26,4 @@
 obj-$(CONFIG_SH4) += sh_timer.o
 obj-$(CONFIG_TUSB6010) += tusb6010.o
 
-obj-$(CONFIG_ARM_MPTIMER) += arm_mptimer.o
 obj-$(CONFIG_MC146818RTC) += mc146818rtc.o
diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
index d23462d..0ceb240 100644
--- a/hw/timer/arm_mptimer.c
+++ b/hw/timer/arm_mptimer.c
@@ -21,6 +21,7 @@
 
 #include "hw/sysbus.h"
 #include "qemu/timer.h"
+#include "qom/cpu.h"
 
 /* This device implements the per-cpu private timer and watchdog block
  * which is used in both the ARM11MPCore and Cortex-A9MP.
@@ -49,13 +50,11 @@
 
 static inline int get_current_cpu(ARMMPTimerState *s)
 {
-    CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
-
-    if (cpu_single_cpu->cpu_index >= s->num_cpu) {
+    if (current_cpu->cpu_index >= s->num_cpu) {
         hw_error("arm_mptimer: num-cpu %d but this cpu is %d!\n",
-                 s->num_cpu, cpu_single_cpu->cpu_index);
+                 s->num_cpu, current_cpu->cpu_index);
     }
-    return cpu_single_cpu->cpu_index;
+    return current_cpu->cpu_index;
 }
 
 static inline void timerblock_update_irq(TimerBlock *tb)
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index e791c05..5084202 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -20,7 +20,6 @@
 #define CPU_ALL_H
 
 #include "qemu-common.h"
-#include "qemu/tls.h"
 #include "exec/cpu-common.h"
 #include "qemu/thread.h"
 
@@ -357,9 +356,6 @@
 
 void QEMU_NORETURN cpu_abort(CPUArchState *env, const char *fmt, ...)
     GCC_FMT_ATTR(2, 3);
-extern CPUArchState *first_cpu;
-DECLARE_TLS(CPUArchState *,cpu_single_env);
-#define cpu_single_env tls_var(cpu_single_env)
 
 /* Flags for use in ENV->INTERRUPT_PENDING.
 
diff --git a/include/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 @@
     sigjmp_buf jmp_env;                                                 \
     int exception_index;                                                \
                                                                         \
-    CPUArchState *next_cpu; /* next CPU sharing TB cache */                 \
     /* user data */                                                     \
     void *opaque;                                                       \
                                                                         \
diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h
index dfcad25..132ab97 100644
--- a/include/hw/ppc/ppc.h
+++ b/include/hw/ppc/ppc.h
@@ -73,8 +73,6 @@
 void ppc970_irq_init (CPUPPCState *env);
 void ppcPOWER7_irq_init (CPUPPCState *env);
 
-void ppce500_set_mpic_proxy(bool enabled);
-
 /* PPC machines for OpenBIOS */
 enum {
     ARCH_PREP = 0,
diff --git a/include/hw/ppc/ppc_e500.h b/include/hw/ppc/ppc_e500.h
new file mode 100644
index 0000000..b66c0e3
--- /dev/null
+++ b/include/hw/ppc/ppc_e500.h
@@ -0,0 +1,6 @@
+#ifndef HW_PPC_E500_H
+#define HW_PPC_E500_H
+
+void ppce500_set_mpic_proxy(bool enabled);
+
+#endif
diff --git a/include/qemu/log.h b/include/qemu/log.h
index a9cf214..d515424 100644
--- a/include/qemu/log.h
+++ b/include/qemu/log.h
@@ -5,6 +5,7 @@
 #include <stdbool.h>
 #include <stdio.h>
 #include "qemu/compiler.h"
+#include "qom/cpu.h"
 #ifdef NEED_CPU_H
 #include "disas/disas.h"
 #endif
@@ -70,22 +71,37 @@
 
 /* Special cases: */
 
-#ifdef NEED_CPU_H
 /* cpu_dump_state() logging functions: */
-static inline void log_cpu_state(CPUArchState *env1, int flags)
+/**
+ * log_cpu_state:
+ * @cpu: The CPU whose state is to be logged.
+ * @flags: Flags what to log.
+ *
+ * Logs the output of cpu_dump_state().
+ */
+static inline void log_cpu_state(CPUState *cpu, int flags)
 {
     if (qemu_log_enabled()) {
-        cpu_dump_state(ENV_GET_CPU(env1), qemu_logfile, fprintf, flags);
+        cpu_dump_state(cpu, qemu_logfile, fprintf, flags);
     }
 }
 
-static inline void log_cpu_state_mask(int mask, CPUArchState *env1, int flags)
+/**
+ * log_cpu_state_mask:
+ * @mask: Mask when to log.
+ * @cpu: The CPU whose state is to be logged.
+ * @flags: Flags what to log.
+ *
+ * Logs the output of cpu_dump_state() if loglevel includes @mask.
+ */
+static inline void log_cpu_state_mask(int mask, CPUState *cpu, int flags)
 {
     if (qemu_loglevel & mask) {
-        log_cpu_state(env1, flags);
+        log_cpu_state(cpu, flags);
     }
 }
 
+#ifdef NEED_CPU_H
 /* disas() and target_disas() to qemu_logfile: */
 static inline void log_target_disas(CPUArchState *env, target_ulong start,
                                     target_ulong len, int flags)
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 7cb5e54..147c256 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -24,6 +24,7 @@
 #include "hw/qdev-core.h"
 #include "exec/hwaddr.h"
 #include "qemu/thread.h"
+#include "qemu/tls.h"
 #include "qemu/typedefs.h"
 
 typedef int (*WriteCoreDumpFunction)(void *buf, size_t size, void *opaque);
@@ -52,6 +53,7 @@
  * @class_by_name: Callback to map -cpu command line model name to an
  * instantiatable CPU type.
  * @reset: Callback to reset the #CPUState to its initial state.
+ * @reset_dump_flags: #CPUDumpFlags to use for reset logging.
  * @do_interrupt: Callback for interrupt handling.
  * @do_unassigned_access: Callback for unassigned access handling.
  * @dump_state: Callback for dumping state.
@@ -71,6 +73,7 @@
     ObjectClass *(*class_by_name)(const char *cpu_model);
 
     void (*reset)(CPUState *cpu);
+    int reset_dump_flags;
     void (*do_interrupt)(CPUState *cpu);
     CPUUnassignedAccess do_unassigned_access;
     void (*dump_state)(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
@@ -113,6 +116,7 @@
  *           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.
@@ -145,6 +149,7 @@
 
     void *env_ptr; /* CPUArchState */
     struct TranslationBlock *current_tb;
+    CPUState *next_cpu;
 
     int kvm_fd;
     bool kvm_vcpu_dirty;
@@ -156,6 +161,11 @@
     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)
+
 /**
  * cpu_paging_enabled:
  * @cpu: The CPU whose state is to be inspected.
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index a14cfe9..1e08a85 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -169,11 +169,11 @@
 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(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);
@@ -252,9 +252,9 @@
 
 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 a5cd3d3..232c39a 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1900,16 +1900,15 @@
     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;
@@ -1922,14 +1921,13 @@
 
         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) {
@@ -1937,7 +1935,9 @@
         }
     }
 
-    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;
@@ -1946,16 +1946,15 @@
     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;
         }
@@ -1965,12 +1964,12 @@
             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);
@@ -1979,7 +1978,9 @@
         }
     }
 
-    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;
@@ -1988,19 +1989,15 @@
     return 0;
 }
 
-void kvm_remove_all_breakpoints(CPUArchState *current_env)
+void kvm_remove_all_breakpoints(CPUState *cpu)
 {
-    CPUState *current_cpu = ENV_GET_CPU(current_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);
+            for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
                 if (kvm_arch_remove_sw_breakpoint(cpu, bp) == 0) {
                     break;
                 }
@@ -2011,7 +2008,9 @@
     }
     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);
     }
 }
@@ -2023,19 +2022,19 @@
     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(CPUState *cpu)
 {
 }
 #endif /* !KVM_CAP_SET_GUEST_DEBUG */
diff --git a/kvm-stub.c b/kvm-stub.c
index dec7a83..370c837 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -83,19 +83,19 @@
     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(CPUState *cpu)
 {
 }
 
diff --git a/linux-user/alpha/target_cpu.h b/linux-user/alpha/target_cpu.h
new file mode 100644
index 0000000..4256245
--- /dev/null
+++ b/linux-user/alpha/target_cpu.h
@@ -0,0 +1,36 @@
+/*
+ * Alpha specific CPU ABI and functions for linux-user
+ *
+ *  Copyright (c) 2007 Jocelyn Mayer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUAlphaState *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->ir[IR_SP] = newsp;
+    }
+    env->ir[IR_V0] = 0;
+    env->ir[IR_A3] = 0;
+}
+
+static inline void cpu_set_tls(CPUAlphaState *env, target_ulong newtls)
+{
+    env->unique = newtls;
+}
+
+#endif
diff --git a/linux-user/arm/target_cpu.h b/linux-user/arm/target_cpu.h
new file mode 100644
index 0000000..ed323c0
--- /dev/null
+++ b/linux-user/arm/target_cpu.h
@@ -0,0 +1,35 @@
+/*
+ * ARM specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->regs[13] = newsp;
+    }
+    env->regs[0] = 0;
+}
+
+static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
+{
+    env->cp15.c13_tls2 = newtls;
+}
+
+#endif
diff --git a/linux-user/cris/target_cpu.h b/linux-user/cris/target_cpu.h
new file mode 100644
index 0000000..4d787e5
--- /dev/null
+++ b/linux-user/cris/target_cpu.h
@@ -0,0 +1,36 @@
+/*
+ * CRIS specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2007 AXIS Communications AB
+ * Written by Edgar E. Iglesias
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUCRISState *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->regs[14] = newsp;
+    }
+    env->regs[10] = 0;
+}
+
+static inline void cpu_set_tls(CPUCRISState *env, target_ulong newtls)
+{
+    env->pregs[PR_PID] = (env->pregs[PR_PID] & 0xff) | newtls;
+}
+
+#endif
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index ddef23e..7ce2eab 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -125,7 +125,7 @@
 static const char *get_elf_platform(void)
 {
     static char elf_platform[] = "i386";
-    int family = (thread_env->cpuid_version >> 8) & 0xff;
+    int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL);
     if (family > 6)
         family = 6;
     if (family >= 3)
@@ -137,7 +137,9 @@
 
 static uint32_t get_elf_hwcap(void)
 {
-    return thread_env->features[FEAT_1_EDX];
+    X86CPU *cpu = X86_CPU(thread_cpu);
+
+    return cpu->env.features[FEAT_1_EDX];
 }
 
 #ifdef TARGET_X86_64
@@ -404,7 +406,7 @@
 
 static uint32_t get_elf_hwcap(void)
 {
-    CPUARMState *e = thread_env;
+    ARMCPU *cpu = ARM_CPU(thread_cpu);
     uint32_t hwcaps = 0;
 
     hwcaps |= ARM_HWCAP_ARM_SWP;
@@ -415,7 +417,7 @@
 
     /* probe for the extra features */
 #define GET_FEATURE(feat, hwcap) \
-    do {if (arm_feature(e, feat)) { hwcaps |= hwcap; } } while (0)
+    do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0)
     GET_FEATURE(ARM_FEATURE_VFP, ARM_HWCAP_ARM_VFP);
     GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT);
     GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE);
@@ -619,13 +621,13 @@
 
 static uint32_t get_elf_hwcap(void)
 {
-    CPUPPCState *e = thread_env;
+    PowerPCCPU *cpu = POWERPC_CPU(thread_cpu);
     uint32_t features = 0;
 
     /* We don't have to be terribly complete here; the high points are
        Altivec/FP/SPE support.  Anything else is just a bonus.  */
 #define GET_FEATURE(flag, feature)                                      \
-    do {if (e->insns_flags & flag) features |= feature; } while(0)
+    do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0)
     GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
     GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
     GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC);
@@ -2628,7 +2630,7 @@
                           long signr, const CPUArchState *env)
 {
 #define NUMNOTES 3
-    CPUArchState *cpu = NULL;
+    CPUState *cpu = NULL;
     TaskState *ts = (TaskState *)env->opaque;
     int i;
 
@@ -2667,9 +2669,10 @@
     /* 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 == thread_cpu) {
             continue;
-        fill_thread_info(info, cpu);
+        }
+        fill_thread_info(info, (CPUArchState *)cpu->env_ptr);
     }
     cpu_list_unlock();
 
diff --git a/linux-user/i386/target_cpu.h b/linux-user/i386/target_cpu.h
new file mode 100644
index 0000000..abcac79
--- /dev/null
+++ b/linux-user/i386/target_cpu.h
@@ -0,0 +1,33 @@
+/*
+ * i386 specific CPU ABI and functions for linux-user
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->regs[R_ESP] = newsp;
+    }
+    env->regs[R_EAX] = 0;
+}
+
+/* TODO: need to implement cpu_set_tls() */
+
+#endif
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 381ab89..5cd6d91 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -89,7 +89,8 @@
 abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
                               abi_ulong stringp, int push_ptr)
 {
-    TaskState *ts = (TaskState *)thread_env->opaque;
+    CPUArchState *env = thread_cpu->env_ptr;
+    TaskState *ts = (TaskState *)env->opaque;
     int n = sizeof(abi_ulong);
     abi_ulong envp;
     abi_ulong argv;
diff --git a/linux-user/m68k/target_cpu.h b/linux-user/m68k/target_cpu.h
new file mode 100644
index 0000000..8a2a305
--- /dev/null
+++ b/linux-user/m68k/target_cpu.h
@@ -0,0 +1,34 @@
+/*
+ * m68k specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2005-2007 CodeSourcery
+ * Written by Paul Brook
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUM68KState *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->aregs[7] = newsp;
+    }
+    env->dregs[0] = 0;
+}
+
+/* TODO: need to implement cpu_set_tls() */
+
+#endif
diff --git a/linux-user/main.c b/linux-user/main.c
index af82db8..7f15d3d 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -120,15 +120,15 @@
     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 = thread_cpu;
+        first_cpu->next_cpu = NULL;
         pending_cpus = 0;
         pthread_mutex_init(&exclusive_lock, NULL);
         pthread_mutex_init(&cpu_list_mutex, NULL);
         pthread_cond_init(&exclusive_cond, NULL);
         pthread_cond_init(&exclusive_resume, NULL);
         pthread_mutex_init(&tcg_ctx.tb_ctx.tb_lock, NULL);
-        gdbserver_fork(thread_env);
+        gdbserver_fork((CPUArchState *)thread_cpu->env_ptr);
     } else {
         pthread_mutex_unlock(&exclusive_lock);
         pthread_mutex_unlock(&tcg_ctx.tb_ctx.tb_lock);
@@ -148,7 +148,6 @@
    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 @@
 
     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);
@@ -234,7 +232,7 @@
 void fork_end(int child)
 {
     if (child) {
-        gdbserver_fork(thread_env);
+        gdbserver_fork((CPUArchState *)thread_cpu->env_ptr);
     }
 }
 
@@ -1304,11 +1302,12 @@
 
 #define EXCP_DUMP(env, fmt, ...)                                        \
 do {                                                                    \
+    CPUState *cs = ENV_GET_CPU(env);                                    \
     fprintf(stderr, fmt , ## __VA_ARGS__);                              \
-    cpu_dump_state(ENV_GET_CPU(env), stderr, fprintf, 0);               \
+    cpu_dump_state(cs, stderr, fprintf, 0);                             \
     qemu_log(fmt, ## __VA_ARGS__);                                      \
     if (qemu_log_enabled()) {                                           \
-        log_cpu_state(env, 0);                                          \
+        log_cpu_state(cs, 0);                                           \
     }                                                                   \
 } while (0)
 
@@ -3152,7 +3151,7 @@
 
 #endif /* TARGET_S390X */
 
-THREAD CPUArchState *thread_env;
+THREAD CPUState *thread_cpu;
 
 void task_settid(TaskState *ts)
 {
@@ -3642,7 +3641,7 @@
     cpu_reset(ENV_GET_CPU(env));
 #endif
 
-    thread_env = env;
+    thread_cpu = ENV_GET_CPU(env);
 
     if (getenv("QEMU_STRACE")) {
         do_strace = 1;
diff --git a/linux-user/microblaze/target_cpu.h b/linux-user/microblaze/target_cpu.h
new file mode 100644
index 0000000..c6386ea
--- /dev/null
+++ b/linux-user/microblaze/target_cpu.h
@@ -0,0 +1,35 @@
+/*
+ * MicroBlaze specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2009 Edgar E. Iglesias
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUMBState *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->regs[R_SP] = newsp;
+    }
+    env->regs[3] = 0;
+}
+
+static inline void cpu_set_tls(CPUMBState *env, target_ulong newtls)
+{
+    env->regs[21] = newtls;
+}
+
+#endif
diff --git a/linux-user/mips/target_cpu.h b/linux-user/mips/target_cpu.h
new file mode 100644
index 0000000..ba8e9eb
--- /dev/null
+++ b/linux-user/mips/target_cpu.h
@@ -0,0 +1,36 @@
+/*
+ * MIPS specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2004-2005 Jocelyn Mayer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUMIPSState *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->active_tc.gpr[29] = newsp;
+    }
+    env->active_tc.gpr[7] = 0;
+    env->active_tc.gpr[2] = 0;
+}
+
+static inline void cpu_set_tls(CPUMIPSState *env, target_ulong newtls)
+{
+    env->tls_value = newtls;
+}
+
+#endif
diff --git a/linux-user/mips64/target_cpu.h b/linux-user/mips64/target_cpu.h
new file mode 100644
index 0000000..fa36407
--- /dev/null
+++ b/linux-user/mips64/target_cpu.h
@@ -0,0 +1 @@
+#include "../mips/target_cpu.h"
diff --git a/linux-user/openrisc/target_cpu.h b/linux-user/openrisc/target_cpu.h
new file mode 100644
index 0000000..501fb81
--- /dev/null
+++ b/linux-user/openrisc/target_cpu.h
@@ -0,0 +1,33 @@
+/*
+ * OpenRISC specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->gpr[1] = newsp;
+    }
+    env->gpr[2] = 0;
+}
+
+/* TODO: need to implement cpu_set_tls() */
+
+#endif
diff --git a/linux-user/ppc/target_cpu.h b/linux-user/ppc/target_cpu.h
new file mode 100644
index 0000000..9cc0c3b
--- /dev/null
+++ b/linux-user/ppc/target_cpu.h
@@ -0,0 +1,41 @@
+/*
+ * PowerPC specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2003-2007 Jocelyn Mayer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->gpr[1] = newsp;
+    }
+    env->gpr[3] = 0;
+}
+
+static inline void cpu_set_tls(CPUPPCState *env, target_ulong newtls)
+{
+#if defined(TARGET_PPC64)
+    /* The kernel checks TIF_32BIT here; we don't support loading 32-bit
+       binaries on PPC64 yet. */
+    env->gpr[13] = newtls;
+#else
+    env->gpr[2] = newtls;
+#endif
+}
+
+#endif
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index b10e957..6569608 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -16,6 +16,7 @@
 #include "exec/user/thunk.h"
 #include "syscall_defs.h"
 #include "syscall.h"
+#include "target_cpu.h"
 #include "target_signal.h"
 #include "exec/gdbstub.h"
 #include "qemu/queue.h"
@@ -197,7 +198,7 @@
                     abi_long arg5, abi_long arg6, abi_long arg7,
                     abi_long arg8);
 void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
-extern THREAD CPUArchState *thread_env;
+extern THREAD CPUState *thread_cpu;
 void cpu_loop(CPUArchState *env);
 char *target_strerror(int err);
 int get_osversion(void);
diff --git a/linux-user/s390x/target_cpu.h b/linux-user/s390x/target_cpu.h
new file mode 100644
index 0000000..f10abe8
--- /dev/null
+++ b/linux-user/s390x/target_cpu.h
@@ -0,0 +1,39 @@
+/*
+ * S/390 specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2009 Ulrich Hecht
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * Contributions after 2012-10-29 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ *
+ * You should have received a copy of the GNU (Lesser) General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUS390XState *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->regs[15] = newsp;
+    }
+    env->regs[2] = 0;
+}
+
+static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls)
+{
+    env->aregs[0] = newtls >> 32;
+    env->aregs[1] = newtls & 0xffffffffULL;
+}
+
+#endif
diff --git a/linux-user/sh4/target_cpu.h b/linux-user/sh4/target_cpu.h
new file mode 100644
index 0000000..141856f
--- /dev/null
+++ b/linux-user/sh4/target_cpu.h
@@ -0,0 +1,35 @@
+/*
+ * SH4 specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2005 Samuel Tardieu
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUSH4State *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->gregs[15] = newsp;
+    }
+    env->gregs[0] = 0;
+}
+
+static inline void cpu_set_tls(CPUSH4State *env, target_ulong newtls)
+{
+  env->gbr = newtls;
+}
+
+#endif
diff --git a/linux-user/signal.c b/linux-user/signal.c
index d84e189..d0727be 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -388,17 +388,18 @@
 /* abort execution with signal */
 static void QEMU_NORETURN force_sig(int target_sig)
 {
-    TaskState *ts = (TaskState *)thread_env->opaque;
+    CPUArchState *env = thread_cpu->env_ptr;
+    TaskState *ts = (TaskState *)env->opaque;
     int host_sig, core_dumped = 0;
     struct sigaction act;
     host_sig = target_to_host_signal(target_sig);
-    gdb_signalled(thread_env, target_sig);
+    gdb_signalled(env, target_sig);
 
     /* dump core if supported by target binary format */
     if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
         stop_all_tasks();
         core_dumped =
-            ((*ts->bprm->core_dump)(target_sig, thread_env) == 0);
+            ((*ts->bprm->core_dump)(target_sig, env) == 0);
     }
     if (core_dumped) {
         /* we already dumped the core of target process, we don't want
@@ -503,6 +504,7 @@
 static void host_signal_handler(int host_signum, siginfo_t *info,
                                 void *puc)
 {
+    CPUArchState *env = thread_cpu->env_ptr;
     int sig;
     target_siginfo_t tinfo;
 
@@ -522,9 +524,9 @@
     fprintf(stderr, "qemu: got signal %d\n", sig);
 #endif
     host_to_target_siginfo_noswap(&tinfo, info);
-    if (queue_signal(thread_env, sig, &tinfo) == 1) {
+    if (queue_signal(env, sig, &tinfo) == 1) {
         /* interrupt the virtual CPU as soon as possible */
-        cpu_exit(ENV_GET_CPU(thread_env));
+        cpu_exit(thread_cpu);
     }
 }
 
diff --git a/linux-user/sparc/target_cpu.h b/linux-user/sparc/target_cpu.h
new file mode 100644
index 0000000..5a620a2
--- /dev/null
+++ b/linux-user/sparc/target_cpu.h
@@ -0,0 +1,36 @@
+/*
+ * SPARC specific CPU ABI and functions for linux-user
+ *
+ * Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
+ * Copyright (C) 2003-2005 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->regwptr[22] = newsp;
+    }
+    env->regwptr[0] = 0;
+    /* FIXME: Do we also need to clear CF?  */
+    /* XXXXX */
+    printf("HELPME: %s:%d\n", __FILE__, __LINE__);
+}
+
+/* TODO: need to implement cpu_set_tls() */
+
+#endif
diff --git a/linux-user/sparc64/target_cpu.h b/linux-user/sparc64/target_cpu.h
new file mode 100644
index 0000000..b22263d
--- /dev/null
+++ b/linux-user/sparc64/target_cpu.h
@@ -0,0 +1 @@
+#include "../sparc/target_cpu.h"
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index a6a7828..00a0390 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4250,8 +4250,8 @@
 
     env = info->env;
     cpu = ENV_GET_CPU(env);
-    thread_env = env;
-    ts = (TaskState *)thread_env->opaque;
+    thread_cpu = cpu;
+    ts = (TaskState *)env->opaque;
     info->tid = gettid();
     cpu->host_tid = info->tid;
     task_settid(ts);
@@ -5132,6 +5132,9 @@
                     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;
@@ -5146,42 +5149,43 @@
     switch(num) {
     case TARGET_NR_exit:
 #ifdef CONFIG_USE_NPTL
-      /* In old applications this may be used to implement _exit(2).
-         However in threaded applictions it is used for thread termination,
-         and _exit_group is used for application termination.
-         Do thread termination if we have more then one thread.  */
-      /* FIXME: This probably breaks if a signal arrives.  We should probably
-         be disabling signals.  */
-      if (first_cpu->next_cpu) {
-          TaskState *ts;
-          CPUArchState **lastp;
-          CPUArchState *p;
+        /* In old applications this may be used to implement _exit(2).
+           However in threaded applictions it is used for thread termination,
+           and _exit_group is used for application termination.
+           Do thread termination if we have more then one thread.  */
+        /* FIXME: This probably breaks if a signal arrives.  We should probably
+           be disabling signals.  */
+        if (first_cpu->next_cpu) {
+            TaskState *ts;
+            CPUState **lastp;
+            CPUState *p;
 
-          cpu_list_lock();
-          lastp = &first_cpu;
-          p = first_cpu;
-          while (p && p != (CPUArchState *)cpu_env) {
-              lastp = &p->next_cpu;
-              p = p->next_cpu;
-          }
-          /* If we didn't find the CPU for this thread then something is
-             horribly wrong.  */
-          if (!p)
-              abort();
-          /* Remove the CPU from the list.  */
-          *lastp = p->next_cpu;
-          cpu_list_unlock();
-          ts = ((CPUArchState *)cpu_env)->opaque;
-          if (ts->child_tidptr) {
-              put_user_u32(0, ts->child_tidptr);
-              sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
-                        NULL, NULL, 0);
-          }
-          thread_env = NULL;
-          object_unref(OBJECT(ENV_GET_CPU(cpu_env)));
-          g_free(ts);
-          pthread_exit(NULL);
-      }
+            cpu_list_lock();
+            lastp = &first_cpu;
+            p = first_cpu;
+            while (p && p != cpu) {
+                lastp = &p->next_cpu;
+                p = p->next_cpu;
+            }
+            /* If we didn't find the CPU for this thread then something is
+               horribly wrong.  */
+            if (!p) {
+                abort();
+            }
+            /* Remove the CPU from the list.  */
+            *lastp = p->next_cpu;
+            cpu_list_unlock();
+            ts = ((CPUArchState *)cpu_env)->opaque;
+            if (ts->child_tidptr) {
+                put_user_u32(0, ts->child_tidptr);
+                sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
+                          NULL, NULL, 0);
+            }
+            thread_cpu = NULL;
+            object_unref(OBJECT(ENV_GET_CPU(cpu_env)));
+            g_free(ts);
+            pthread_exit(NULL);
+        }
 #endif
 #ifdef TARGET_GPROF
         _mcleanup();
diff --git a/linux-user/unicore32/target_cpu.h b/linux-user/unicore32/target_cpu.h
new file mode 100644
index 0000000..fb79087
--- /dev/null
+++ b/linux-user/unicore32/target_cpu.h
@@ -0,0 +1,27 @@
+/*
+ * UniCore32 specific CPU ABI and functions for linux-user
+ *
+ * Copyright (C) 2010-2012 Guan Xuetao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or (at your option) any
+ * later version. See the COPYING file in the top-level directory.
+ */
+#ifndef TARGET_CPU_H
+#define TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUUniCore32State *env, target_ulong newsp)
+{
+    if (newsp) {
+        env->regs[29] = newsp;
+    }
+    env->regs[0] = 0;
+}
+
+static inline void cpu_set_tls(CPUUniCore32State *env, target_ulong newtls)
+{
+    env->regs[16] = newtls;
+}
+
+#endif
diff --git a/linux-user/x86_64/target_cpu.h b/linux-user/x86_64/target_cpu.h
new file mode 100644
index 0000000..9ec7cbb
--- /dev/null
+++ b/linux-user/x86_64/target_cpu.h
@@ -0,0 +1 @@
+#include "../i386/target_cpu.h"
diff --git a/memory.c b/memory.c
index 35553b5..c8f9a2b 100644
--- a/memory.c
+++ b/memory.c
@@ -838,9 +838,8 @@
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
 #endif
-    if (cpu_single_env != NULL) {
-        cpu_unassigned_access(ENV_GET_CPU(cpu_single_env),
-                              addr, false, false, 0, size);
+    if (current_cpu != NULL) {
+        cpu_unassigned_access(current_cpu, addr, false, false, 0, size);
     }
     return 0;
 }
@@ -851,9 +850,8 @@
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem write " TARGET_FMT_plx " = 0x%"PRIx64"\n", addr, val);
 #endif
-    if (cpu_single_env != NULL) {
-        cpu_unassigned_access(ENV_GET_CPU(cpu_single_env),
-                              addr, true, false, 0, size);
+    if (current_cpu != NULL) {
+        cpu_unassigned_access(current_cpu, addr, true, false, 0, size);
     }
 }
 
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 @@
     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 @@
 
 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_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/qom/cpu.c b/qom/cpu.c
index ee8f632..5c45ab5 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -22,6 +22,7 @@
 #include "qom/cpu.h"
 #include "sysemu/kvm.h"
 #include "qemu/notify.h"
+#include "qemu/log.h"
 #include "sysemu/sysemu.h"
 
 typedef struct CPUExistsArgs {
@@ -187,6 +188,13 @@
 
 static void cpu_common_reset(CPUState *cpu)
 {
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+
+    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+        qemu_log("CPU Reset (CPU %d)\n", cpu->cpu_index);
+        log_cpu_state(cpu, cc->reset_dump_flags);
+    }
+
     cpu->exit_request = 0;
     cpu->interrupt_request = 0;
     cpu->current_tb = NULL;
diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h
index 94e4a54..60125b1 100644
--- a/target-alpha/cpu-qom.h
+++ b/target-alpha/cpu-qom.h
@@ -67,7 +67,7 @@
 
 static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env)
 {
-    return ALPHA_CPU(container_of(env, AlphaCPU, env));
+    return container_of(env, AlphaCPU, env);
 }
 
 #define ENV_GET_CPU(e) CPU(alpha_env_get_cpu(e))
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 01f4ebb..066f032 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -498,22 +498,6 @@
     *pflags = flags;
 }
 
-#if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUAlphaState *env, target_ulong newsp)
-{
-    if (newsp) {
-        env->ir[IR_SP] = newsp;
-    }
-    env->ir[IR_V0] = 0;
-    env->ir[IR_A3] = 0;
-}
-
-static inline void cpu_set_tls(CPUAlphaState *env, target_ulong newtls)
-{
-    env->unique = newtls;
-}
-#endif
-
 static inline bool cpu_has_work(CPUState *cpu)
 {
     /* Here we are checking to see if the CPU should wake up from HALT.
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 4db16db..dd7f0fb 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3375,10 +3375,11 @@
     return ret;
 }
 
-static inline void gen_intermediate_code_internal(CPUAlphaState *env,
+static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
                                                   TranslationBlock *tb,
-                                                  int search_pc)
+                                                  bool search_pc)
 {
+    CPUAlphaState *env = &cpu->env;
     DisasContext ctx, *ctxp = &ctx;
     target_ulong pc_start;
     uint32_t insn;
@@ -3502,12 +3503,12 @@
 
 void gen_intermediate_code (CPUAlphaState *env, struct TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 0);
+    gen_intermediate_code_internal(alpha_env_get_cpu(env), tb, false);
 }
 
 void gen_intermediate_code_pc (CPUAlphaState *env, struct TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 1);
+    gen_intermediate_code_internal(alpha_env_get_cpu(env), tb, true);
 }
 
 void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, int pc_pos)
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index ef6261f..48ba605 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -127,7 +127,7 @@
 
 static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
 {
-    return ARM_CPU(container_of(env, ARMCPU, env));
+    return container_of(env, ARMCPU, env);
 }
 
 #define ENV_GET_CPU(e) CPU(arm_env_get_cpu(e))
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 1bc227e..be26acc 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -63,11 +63,6 @@
     ARMCPUClass *acc = ARM_CPU_GET_CLASS(cpu);
     CPUARMState *env = &cpu->env;
 
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
     acc->parent_reset(s);
 
     memset(env, 0, offsetof(CPUARMState, breakpoints));
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index abcc0b4..1369604 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -249,11 +249,6 @@
                               int mmu_idx);
 #define cpu_handle_mmu_fault cpu_arm_handle_mmu_fault
 
-static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
-{
-  env->cp15.c13_tls2 = newtls;
-}
-
 #define CPSR_M (0x1f)
 #define CPSR_T (1 << 5)
 #define CPSR_F (1 << 6)
@@ -734,15 +729,6 @@
     return (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR ? 1 : 0;
 }
 
-#if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
-{
-    if (newsp)
-        env->regs[13] = newsp;
-    env->regs[0] = 0;
-}
-#endif
-
 #include "exec/cpu-all.h"
 
 /* Bit usage in the TB flags field: */
diff --git a/target-arm/translate.c b/target-arm/translate.c
index af2aef2..9310c58 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9796,10 +9796,11 @@
 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
    basic block 'tb'. If search_pc is TRUE, also generate PC
    information for each intermediate instruction. */
-static inline void gen_intermediate_code_internal(CPUARMState *env,
+static inline void gen_intermediate_code_internal(ARMCPU *cpu,
                                                   TranslationBlock *tb,
-                                                  int search_pc)
+                                                  bool search_pc)
 {
+    CPUARMState *env = &cpu->env;
     DisasContext dc1, *dc = &dc1;
     CPUBreakpoint *bp;
     uint16_t *gen_opc_end;
@@ -10072,12 +10073,12 @@
 
 void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 0);
+    gen_intermediate_code_internal(arm_env_get_cpu(env), tb, false);
 }
 
 void gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 1);
+    gen_intermediate_code_internal(arm_env_get_cpu(env), tb, true);
 }
 
 static const char *cpu_mode_names[16] = {
diff --git a/target-cris/cpu-qom.h b/target-cris/cpu-qom.h
index e08bdb1..af7d14d 100644
--- a/target-cris/cpu-qom.h
+++ b/target-cris/cpu-qom.h
@@ -66,7 +66,7 @@
 
 static inline CRISCPU *cris_env_get_cpu(CPUCRISState *env)
 {
-    return CRIS_CPU(container_of(env, CRISCPU, env));
+    return container_of(env, CRISCPU, env);
 }
 
 #define ENV_GET_CPU(e) CPU(cris_env_get_cpu(e))
diff --git a/target-cris/cpu.c b/target-cris/cpu.c
index 6a3bdf0..2abb57f 100644
--- a/target-cris/cpu.c
+++ b/target-cris/cpu.c
@@ -34,11 +34,6 @@
     CPUCRISState *env = &cpu->env;
     uint32_t vr;
 
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
     ccc->parent_reset(s);
 
     vr = env->pregs[PR_VR];
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index dbd7d36..c12a8ca 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -247,20 +247,6 @@
                               int mmu_idx);
 #define cpu_handle_mmu_fault cpu_cris_handle_mmu_fault
 
-#if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUCRISState *env, target_ulong newsp)
-{
-    if (newsp)
-        env->regs[14] = newsp;
-    env->regs[10] = 0;
-}
-#endif
-
-static inline void cpu_set_tls(CPUCRISState *env, target_ulong newtls)
-{
-	env->pregs[PR_PID] = (env->pregs[PR_PID] & 0xff) | newtls;
-}
-
 /* Support function regs.  */
 #define SFR_RW_GC_CFG      0][0
 #define SFR_RW_MM_CFG      env->pregs[PR_SRS]][0
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 09d0d2b..1de9743 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3161,10 +3161,11 @@
  */
 
 /* generate intermediate code for basic block 'tb'.  */
-static void
-gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
-                               int search_pc)
+static inline void
+gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
+                               bool search_pc)
 {
+    CPUCRISState *env = &cpu->env;
     uint16_t *gen_opc_end;
     uint32_t pc_start;
     unsigned int insn_len;
@@ -3419,12 +3420,12 @@
 
 void gen_intermediate_code (CPUCRISState *env, struct TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 0);
+    gen_intermediate_code_internal(cris_env_get_cpu(env), tb, false);
 }
 
 void gen_intermediate_code_pc (CPUCRISState *env, struct TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 1);
+    gen_intermediate_code_internal(cris_env_get_cpu(env), tb, true);
 }
 
 void cris_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
index 83898cd..10dc228 100644
--- a/target-i386/arch_dump.c
+++ b/target-i386/arch_dump.c
@@ -35,7 +35,7 @@
 } x86_64_elf_prstatus;
 
 static int x86_64_write_elf64_note(WriteCoreDumpFunction f,
-                                   CPUArchState *env, int id,
+                                   CPUX86State *env, int id,
                                    void *opaque)
 {
     x86_64_user_regs_struct regs;
@@ -119,7 +119,7 @@
     char pad3[4];
 } x86_elf_prstatus;
 
-static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUArchState *env,
+static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUX86State *env,
                                   int id)
 {
     memset(prstatus, 0, sizeof(x86_elf_prstatus));
@@ -144,7 +144,7 @@
     prstatus->pid = id;
 }
 
-static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUArchState *env,
+static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env,
                                 int id, void *opaque)
 {
     x86_elf_prstatus prstatus;
@@ -185,7 +185,8 @@
     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);
@@ -273,7 +274,7 @@
     d->base = s->base;
 }
 
-static void qemu_get_cpustate(QEMUCPUState *s, CPUArchState *env)
+static void qemu_get_cpustate(QEMUCPUState *s, CPUX86State *env)
 {
     memset(s, 0, sizeof(QEMUCPUState));
 
@@ -320,7 +321,7 @@
 }
 
 static inline int cpu_write_qemu_note(WriteCoreDumpFunction f,
-                                      CPUArchState *env,
+                                      CPUX86State *env,
                                       void *opaque,
                                       int type)
 {
@@ -394,7 +395,9 @@
     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/cpu-qom.h b/target-i386/cpu-qom.h
index b7c70d6..7e55e5f 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -72,7 +72,7 @@
 
 static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
 {
-    return X86_CPU(container_of(env, X86CPU, env));
+    return container_of(env, X86CPU, env);
 }
 
 #define ENV_GET_CPU(e) CPU(x86_env_get_cpu(e))
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index b7416fe..e3f75a8 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2175,11 +2175,6 @@
     CPUX86State *env = &cpu->env;
     int i;
 
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
-        log_cpu_state(env, CPU_DUMP_FPU | CPU_DUMP_CCOP);
-    }
-
     xcc->parent_reset(s);
 
 
@@ -2523,6 +2518,7 @@
 
     xcc->parent_reset = cc->reset;
     cc->reset = x86_cpu_reset;
+    cc->reset_dump_flags = CPU_DUMP_FPU | CPU_DUMP_CCOP;
 
     cc->do_interrupt = x86_cpu_do_interrupt;
     cc->dump_state = x86_cpu_dump_state;
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 62e3547..2d005b3 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -1125,15 +1125,6 @@
 /* translate.c */
 void optimize_flags_init(void);
 
-#if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp)
-{
-    if (newsp)
-        env->regs[R_ESP] = newsp;
-    env->regs[R_EAX] = 0;
-}
-#endif
-
 #include "exec/cpu-all.h"
 #include "svm.h"
 
@@ -1229,7 +1220,7 @@
 /* seg_helper.c */
 void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw);
 
-void do_smm_enter(CPUX86State *env1);
+void do_smm_enter(X86CPU *cpu);
 
 void cpu_report_tpr_access(CPUX86State *env, TPRAccess access);
 
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 @@
                         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 @@
         .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 @@
         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 15da3d7..8315489 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -345,20 +345,22 @@
 
 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 @@
     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-i386/seg_helper.c b/target-i386/seg_helper.c
index 9c799e1..e789102 100644
--- a/target-i386/seg_helper.c
+++ b/target-i386/seg_helper.c
@@ -30,11 +30,11 @@
 
 #ifdef DEBUG_PCALL
 # define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__)
-# define LOG_PCALL_STATE(env)                                  \
-    log_cpu_state_mask(CPU_LOG_PCALL, (env), CPU_DUMP_CCOP)
+# define LOG_PCALL_STATE(cpu)                                  \
+    log_cpu_state_mask(CPU_LOG_PCALL, (cpu), CPU_DUMP_CCOP)
 #else
 # define LOG_PCALL(...) do { } while (0)
-# define LOG_PCALL_STATE(env) do { } while (0)
+# define LOG_PCALL_STATE(cpu) do { } while (0)
 #endif
 
 /* return non zero if error */
@@ -1160,9 +1160,11 @@
  * the int instruction. next_eip is the env->eip value AFTER the interrupt
  * instruction. It is only relevant if is_int is TRUE.
  */
-static void do_interrupt_all(CPUX86State *env, int intno, int is_int,
+static void do_interrupt_all(X86CPU *cpu, int intno, int is_int,
                              int error_code, target_ulong next_eip, int is_hw)
 {
+    CPUX86State *env = &cpu->env;
+
     if (qemu_loglevel_mask(CPU_LOG_INT)) {
         if ((env->cr[0] & CR0_PE_MASK)) {
             static int count;
@@ -1180,7 +1182,7 @@
                 qemu_log(" env->regs[R_EAX]=" TARGET_FMT_lx, env->regs[R_EAX]);
             }
             qemu_log("\n");
-            log_cpu_state(env, CPU_DUMP_CCOP);
+            log_cpu_state(CPU(cpu), CPU_DUMP_CCOP);
 #if 0
             {
                 int i;
@@ -1252,7 +1254,7 @@
     /* simulate a real cpu exception. On i386, it can
        trigger new exceptions, but we do not handle
        double or triple faults yet. */
-    do_interrupt_all(env, env->exception_index,
+    do_interrupt_all(cpu, env->exception_index,
                      env->exception_is_int,
                      env->error_code,
                      env->exception_next_eip, 0);
@@ -1263,7 +1265,7 @@
 
 void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw)
 {
-    do_interrupt_all(env, intno, 0, 0, 0, is_hw);
+    do_interrupt_all(x86_env_get_cpu(env), intno, 0, 0, 0, is_hw);
 }
 
 void helper_enter_level(CPUX86State *env, int level, int data32,
@@ -1684,7 +1686,7 @@
 
     next_eip = env->eip + next_eip_addend;
     LOG_PCALL("lcall %04x:%08x s=%d\n", new_cs, (uint32_t)new_eip, shift);
-    LOG_PCALL_STATE(env);
+    LOG_PCALL_STATE(CPU(x86_env_get_cpu(env)));
     if ((new_cs & 0xfffc) == 0) {
         raise_exception_err(env, EXCP0D_GPF, 0);
     }
@@ -2018,7 +2020,7 @@
     }
     LOG_PCALL("lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
               new_cs, new_eip, shift, addend);
-    LOG_PCALL_STATE(env);
+    LOG_PCALL_STATE(CPU(x86_env_get_cpu(env)));
     if ((new_cs & 0xfffc) == 0) {
         raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
     }
diff --git a/target-i386/smm_helper.c b/target-i386/smm_helper.c
index 2489573..6cb4551 100644
--- a/target-i386/smm_helper.c
+++ b/target-i386/smm_helper.c
@@ -24,7 +24,7 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_smm_enter(CPUX86State *env)
+void do_smm_enter(X86CPU *cpu)
 {
 }
 
@@ -40,14 +40,15 @@
 #define SMM_REVISION_ID 0x00020000
 #endif
 
-void do_smm_enter(CPUX86State *env)
+void do_smm_enter(X86CPU *cpu)
 {
+    CPUX86State *env = &cpu->env;
     target_ulong sm_state;
     SegmentCache *dt;
     int i, offset;
 
     qemu_log_mask(CPU_LOG_INT, "SMM: enter\n");
-    log_cpu_state_mask(CPU_LOG_INT, env, CPU_DUMP_CCOP);
+    log_cpu_state_mask(CPU_LOG_INT, CPU(cpu), CPU_DUMP_CCOP);
 
     env->hflags |= HF_SMM_MASK;
     cpu_smm_update(env);
@@ -179,6 +180,7 @@
 
 void helper_rsm(CPUX86State *env)
 {
+    X86CPU *cpu = x86_env_get_cpu(env);
     target_ulong sm_state;
     int i, offset;
     uint32_t val;
@@ -295,7 +297,7 @@
     cpu_smm_update(env);
 
     qemu_log_mask(CPU_LOG_INT, "SMM: after RSM\n");
-    log_cpu_state_mask(CPU_LOG_INT, env, CPU_DUMP_CCOP);
+    log_cpu_state_mask(CPU_LOG_INT, CPU(cpu), CPU_DUMP_CCOP);
 }
 
 #endif /* !CONFIG_USER_ONLY */
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 14b0298..6550c27 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -8251,10 +8251,11 @@
 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
    basic block 'tb'. If search_pc is TRUE, also generate PC
    information for each intermediate instruction. */
-static inline void gen_intermediate_code_internal(CPUX86State *env,
+static inline void gen_intermediate_code_internal(X86CPU *cpu,
                                                   TranslationBlock *tb,
-                                                  int search_pc)
+                                                  bool search_pc)
 {
+    CPUX86State *env = &cpu->env;
     DisasContext dc1, *dc = &dc1;
     target_ulong pc_ptr;
     uint16_t *gen_opc_end;
@@ -8428,12 +8429,12 @@
 
 void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 0);
+    gen_intermediate_code_internal(x86_env_get_cpu(env), tb, false);
 }
 
 void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 1);
+    gen_intermediate_code_internal(x86_env_get_cpu(env), tb, true);
 }
 
 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
diff --git a/target-lm32/cpu-qom.h b/target-lm32/cpu-qom.h
index 5ef884b..e3bb619 100644
--- a/target-lm32/cpu-qom.h
+++ b/target-lm32/cpu-qom.h
@@ -64,7 +64,7 @@
 
 static inline LM32CPU *lm32_env_get_cpu(CPULM32State *env)
 {
-    return LM32_CPU(container_of(env, LM32CPU, env));
+    return container_of(env, LM32CPU, env);
 }
 
 #define ENV_GET_CPU(e) CPU(lm32_env_get_cpu(e))
diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
index 02f8436..04327ac 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -29,11 +29,6 @@
     LM32CPUClass *lcc = LM32_CPU_GET_CLASS(cpu);
     CPULM32State *env = &cpu->env;
 
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
     lcc->parent_reset(s);
 
     /* reset cpu state */
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index bfb9150..856bdc7 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -215,20 +215,6 @@
                               int mmu_idx);
 #define cpu_handle_mmu_fault cpu_lm32_handle_mmu_fault
 
-#if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPULM32State *env, target_ulong newsp)
-{
-    if (newsp) {
-        env->regs[R_SP] = newsp;
-    }
-    env->regs[R_R1] = 0;
-}
-#endif
-
-static inline void cpu_set_tls(CPULM32State *env, target_ulong newtls)
-{
-}
-
 #include "exec/cpu-all.h"
 
 static inline void cpu_get_tb_cpu_state(CPULM32State *env, target_ulong *pc,
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index 03fa5fb..615b44e 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -70,7 +70,7 @@
         } else {
             env->pc = env->eba + (env->exception_index * 32);
         }
-        log_cpu_state_mask(CPU_LOG_INT, env, 0);
+        log_cpu_state_mask(CPU_LOG_INT, cs, 0);
         break;
     case EXCP_BREAKPOINT:
     case EXCP_WATCHPOINT:
@@ -79,7 +79,7 @@
         env->ie |= (env->ie & IE_IE) ? IE_BIE : 0;
         env->ie &= ~IE_IE;
         env->pc = env->deba + (env->exception_index * 32);
-        log_cpu_state_mask(CPU_LOG_INT, env, 0);
+        log_cpu_state_mask(CPU_LOG_INT, cs, 0);
         break;
     default:
         cpu_abort(env, "unhandled exception type=%d\n",
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index 227a801..ed12f50 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -1011,9 +1011,11 @@
 }
 
 /* generate intermediate code for basic block 'tb'.  */
-static void gen_intermediate_code_internal(CPULM32State *env,
-        TranslationBlock *tb, int search_pc)
+static inline
+void gen_intermediate_code_internal(LM32CPU *cpu,
+                                    TranslationBlock *tb, bool search_pc)
 {
+    CPULM32State *env = &cpu->env;
     struct DisasContext ctx, *dc = &ctx;
     uint16_t *gen_opc_end;
     uint32_t pc_start;
@@ -1133,12 +1135,12 @@
 
 void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 0);
+    gen_intermediate_code_internal(lm32_env_get_cpu(env), tb, false);
 }
 
 void gen_intermediate_code_pc(CPULM32State *env, struct TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 1);
+    gen_intermediate_code_internal(lm32_env_get_cpu(env), tb, true);
 }
 
 void lm32_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
diff --git a/target-m68k/cpu-qom.h b/target-m68k/cpu-qom.h
index 2436c13..858bf30 100644
--- a/target-m68k/cpu-qom.h
+++ b/target-m68k/cpu-qom.h
@@ -63,7 +63,7 @@
 
 static inline M68kCPU *m68k_env_get_cpu(CPUM68KState *env)
 {
-    return M68K_CPU(container_of(env, M68kCPU, env));
+    return container_of(env, M68kCPU, env);
 }
 
 #define ENV_GET_CPU(e) CPU(m68k_env_get_cpu(e))
diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index 799869f..1b6ef66 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -35,11 +35,6 @@
     M68kCPUClass *mcc = M68K_CPU_GET_CLASS(cpu);
     CPUM68KState *env = &cpu->env;
 
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
     mcc->parent_reset(s);
 
     memset(env, 0, offsetof(CPUM68KState, breakpoints));
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index c90c40c..9fdf89e 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -241,15 +241,6 @@
                               int mmu_idx);
 #define cpu_handle_mmu_fault cpu_m68k_handle_mmu_fault
 
-#if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUM68KState *env, target_ulong newsp)
-{
-    if (newsp)
-        env->aregs[7] = newsp;
-    env->dregs[0] = 0;
-}
-#endif
-
 #include "exec/cpu-all.h"
 
 static inline void cpu_get_tb_cpu_state(CPUM68KState *env, target_ulong *pc,
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 3752094..2d73af5 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2971,9 +2971,10 @@
 
 /* generate intermediate code for basic block 'tb'.  */
 static inline void
-gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
-                               int search_pc)
+gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
+                               bool search_pc)
 {
+    CPUM68KState *env = &cpu->env;
     DisasContext dc1, *dc = &dc1;
     uint16_t *gen_opc_end;
     CPUBreakpoint *bp;
@@ -3096,12 +3097,12 @@
 
 void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 0);
+    gen_intermediate_code_internal(m68k_env_get_cpu(env), tb, false);
 }
 
 void gen_intermediate_code_pc(CPUM68KState *env, TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 1);
+    gen_intermediate_code_internal(m68k_env_get_cpu(env), tb, true);
 }
 
 void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
diff --git a/target-microblaze/cpu-qom.h b/target-microblaze/cpu-qom.h
index 3e9c206..ec2b989 100644
--- a/target-microblaze/cpu-qom.h
+++ b/target-microblaze/cpu-qom.h
@@ -64,7 +64,7 @@
 
 static inline MicroBlazeCPU *mb_env_get_cpu(CPUMBState *env)
 {
-    return MICROBLAZE_CPU(container_of(env, MicroBlazeCPU, env));
+    return container_of(env, MicroBlazeCPU, env);
 }
 
 #define ENV_GET_CPU(e) CPU(mb_env_get_cpu(e))
diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
index a0fcdf4..dce1c7e 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -33,11 +33,6 @@
     MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(cpu);
     CPUMBState *env = &cpu->env;
 
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
     mcc->parent_reset(s);
 
     memset(env, 0, offsetof(CPUMBState, breakpoints));
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 75ae5ba..6c35475 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -331,20 +331,6 @@
                             int mmu_idx);
 #define cpu_handle_mmu_fault cpu_mb_handle_mmu_fault
 
-#if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUMBState *env, target_ulong newsp)
-{
-    if (newsp)
-        env->regs[R_SP] = newsp;
-    env->regs[3] = 0;
-}
-#endif
-
-static inline void cpu_set_tls(CPUMBState *env, target_ulong newtls)
-{
-    env->regs[21] = newtls;
-}
-
 static inline int cpu_interrupts_enabled(CPUMBState *env)
 {
     return env->sregs[SR_MSR] & MSR_IE;
diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c
index 01d4bbf..c6c96d4 100644
--- a/target-microblaze/helper.c
+++ b/target-microblaze/helper.c
@@ -152,7 +152,7 @@
                           "hw exception at pc=%x ear=%x esr=%x iflags=%x\n",
                           env->sregs[SR_PC], env->sregs[SR_EAR],
                           env->sregs[SR_ESR], env->iflags);
-            log_cpu_state_mask(CPU_LOG_INT, env, 0);
+            log_cpu_state_mask(CPU_LOG_INT, cs, 0);
             env->iflags &= ~(IMM_FLAG | D_FLAG);
             env->sregs[SR_PC] = cpu->base_vectors + 0x20;
             break;
@@ -175,7 +175,7 @@
                                   "bimm exception at pc=%x iflags=%x\n",
                                   env->sregs[SR_PC], env->iflags);
                     env->regs[17] -= 4;
-                    log_cpu_state_mask(CPU_LOG_INT, env, 0);
+                    log_cpu_state_mask(CPU_LOG_INT, cs, 0);
                 }
             } else if (env->iflags & IMM_FLAG) {
                 D(qemu_log("IMM_FLAG set at exception\n"));
@@ -192,7 +192,7 @@
             qemu_log_mask(CPU_LOG_INT,
                           "exception at pc=%x ear=%x iflags=%x\n",
                           env->sregs[SR_PC], env->sregs[SR_EAR], env->iflags);
-            log_cpu_state_mask(CPU_LOG_INT, env, 0);
+            log_cpu_state_mask(CPU_LOG_INT, cs, 0);
             env->iflags &= ~(IMM_FLAG | D_FLAG);
             env->sregs[SR_PC] = cpu->base_vectors + 0x20;
             break;
@@ -222,7 +222,7 @@
                          env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags,
                          sym);
 
-                    log_cpu_state(env, 0);
+                    log_cpu_state(cs, 0);
                 }
             }
 #endif
@@ -236,7 +236,7 @@
 
             env->regs[14] = env->sregs[SR_PC];
             env->sregs[SR_PC] = cpu->base_vectors + 0x10;
-            //log_cpu_state_mask(CPU_LOG_INT, env, 0);
+            //log_cpu_state_mask(CPU_LOG_INT, cs, 0);
             break;
 
         case EXCP_BREAK:
@@ -247,7 +247,7 @@
             qemu_log_mask(CPU_LOG_INT,
                         "break at pc=%x msr=%x %x iflags=%x\n",
                         env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags);
-            log_cpu_state_mask(CPU_LOG_INT, env, 0);
+            log_cpu_state_mask(CPU_LOG_INT, cs, 0);
             env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM);
             env->sregs[SR_MSR] |= t;
             env->sregs[SR_MSR] |= MSR_BIP;
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 54f439f..eba255b 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1737,10 +1737,11 @@
 }
 
 /* generate intermediate code for basic block 'tb'.  */
-static void
-gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
-                               int search_pc)
+static inline void
+gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
+                               bool search_pc)
 {
+    CPUMBState *env = &cpu->env;
     uint16_t *gen_opc_end;
     uint32_t pc_start;
     int j, lj;
@@ -1776,7 +1777,7 @@
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
 #if !SIM_COMPAT
         qemu_log("--------------\n");
-        log_cpu_state(env, 0);
+        log_cpu_state(CPU(cpu), 0);
 #endif
     }
 
@@ -1941,12 +1942,12 @@
 
 void gen_intermediate_code (CPUMBState *env, struct TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 0);
+    gen_intermediate_code_internal(mb_env_get_cpu(env), tb, false);
 }
 
 void gen_intermediate_code_pc (CPUMBState *env, struct TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 1);
+    gen_intermediate_code_internal(mb_env_get_cpu(env), tb, true);
 }
 
 void mb_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
diff --git a/target-mips/cpu-qom.h b/target-mips/cpu-qom.h
index a7ff9e6..654744a 100644
--- a/target-mips/cpu-qom.h
+++ b/target-mips/cpu-qom.h
@@ -67,7 +67,7 @@
 
 static inline MIPSCPU *mips_env_get_cpu(CPUMIPSState *env)
 {
-    return MIPS_CPU(container_of(env, MIPSCPU, env));
+    return container_of(env, MIPSCPU, env);
 }
 
 #define ENV_GET_CPU(e) CPU(mips_env_get_cpu(e))
diff --git a/target-mips/cpu.c b/target-mips/cpu.c
index b61e207..60a3faf 100644
--- a/target-mips/cpu.c
+++ b/target-mips/cpu.c
@@ -29,11 +29,6 @@
     MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu);
     CPUMIPSState *env = &cpu->env;
 
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
     mcc->parent_reset(s);
 
     memset(env, 0, offsetof(CPUMIPSState, breakpoints));
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index fa0f0d1..7ffd2e3 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -521,14 +521,6 @@
     return env->hflags & MIPS_HFLAG_KSU;
 }
 
-static inline void cpu_clone_regs(CPUMIPSState *env, target_ulong newsp)
-{
-    if (newsp)
-        env->active_tc.gpr[29] = newsp;
-    env->active_tc.gpr[7] = 0;
-    env->active_tc.gpr[2] = 0;
-}
-
 static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
 {
     int32_t pending;
@@ -679,11 +671,6 @@
     *flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
 }
 
-static inline void cpu_set_tls(CPUMIPSState *env, target_ulong newtls)
-{
-    env->tls_value = newtls;
-}
-
 static inline int mips_vpe_active(CPUMIPSState *env)
 {
     int active = 1;
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 36929dd..6983b92 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -276,7 +276,7 @@
     int ret = 0;
 
 #if 0
-    log_cpu_state(env, 0);
+    log_cpu_state(CPU(mips_env_get_cpu(env)), 0);
 #endif
     qemu_log("%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d mmu_idx %d\n",
               __func__, env->active_tc.PC, address, rw, mmu_idx);
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_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-mips/translate.c b/target-mips/translate.c
index 160c0c0..8246c20 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15540,9 +15540,10 @@
 }
 
 static inline void
-gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
-                                int search_pc)
+gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
+                               bool search_pc)
 {
+    CPUMIPSState *env = &cpu->env;
     DisasContext ctx;
     target_ulong pc_start;
     uint16_t *gen_opc_end;
@@ -15698,12 +15699,12 @@
 
 void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 0);
+    gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false);
 }
 
 void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 1);
+    gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true);
 }
 
 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
diff --git a/target-moxie/cpu.c b/target-moxie/cpu.c
index f3c0d22..92ca594 100644
--- a/target-moxie/cpu.c
+++ b/target-moxie/cpu.c
@@ -28,11 +28,6 @@
     MoxieCPUClass *mcc = MOXIE_CPU_GET_CLASS(cpu);
     CPUMoxieState *env = &cpu->env;
 
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
     mcc->parent_reset(s);
 
     memset(env, 0, offsetof(CPUMoxieState, breakpoints));
diff --git a/target-moxie/cpu.h b/target-moxie/cpu.h
index 374b24a..72d02c2 100644
--- a/target-moxie/cpu.h
+++ b/target-moxie/cpu.h
@@ -106,7 +106,7 @@
 
 static inline MoxieCPU *moxie_env_get_cpu(CPUMoxieState *env)
 {
-    return MOXIE_CPU(container_of(env, MoxieCPU, env));
+    return container_of(env, MoxieCPU, env);
 }
 
 #define ENV_GET_CPU(e) CPU(moxie_env_get_cpu(e))
diff --git a/target-moxie/translate.c b/target-moxie/translate.c
index b0ae38a..664d359 100644
--- a/target-moxie/translate.c
+++ b/target-moxie/translate.c
@@ -820,7 +820,7 @@
 }
 
 /* generate intermediate code for basic block 'tb'.  */
-static void
+static inline void
 gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
                                bool search_pc)
 {
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
index fd90d37..6d40f1b 100644
--- a/target-openrisc/cpu.c
+++ b/target-openrisc/cpu.c
@@ -26,11 +26,6 @@
     OpenRISCCPU *cpu = OPENRISC_CPU(s);
     OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu);
 
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
-        log_cpu_state(&cpu->env, 0);
-    }
-
     occ->parent_reset(s);
 
     memset(&cpu->env, 0, offsetof(CPUOpenRISCState, breakpoints));
@@ -96,12 +91,14 @@
 static ObjectClass *openrisc_cpu_class_by_name(const char *cpu_model)
 {
     ObjectClass *oc;
+    char *typename;
 
     if (cpu_model == NULL) {
         return NULL;
     }
 
-    oc = object_class_by_name(cpu_model);
+    typename = g_strdup_printf("%s-" TYPE_OPENRISC_CPU, cpu_model);
+    oc = object_class_by_name(typename);
     if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_OPENRISC_CPU) ||
                        object_class_is_abstract(oc))) {
         return NULL;
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 80a82df..0aff8f2 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -335,7 +335,7 @@
 
 static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env)
 {
-    return OPENRISC_CPU(container_of(env, OpenRISCCPU, env));
+    return container_of(env, OpenRISCCPU, env);
 }
 
 #define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e))
@@ -394,16 +394,6 @@
     return NULL;
 }
 
-#if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp)
-{
-    if (newsp) {
-        env->gpr[1] = newsp;
-    }
-    env->gpr[2] = 0;
-}
-#endif
-
 #include "exec/cpu-all.h"
 
 static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index c59fd02..f222834 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1684,7 +1684,7 @@
     dc->singlestep_enabled = cpu->env.singlestep_enabled;
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("-----------------------------------------\n");
-        log_cpu_state(&cpu->env, 0);
+        log_cpu_state(CPU(cpu), 0);
     }
 
     next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index 84ba105..7132599 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -91,7 +91,7 @@
 
 static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)
 {
-    return POWERPC_CPU(container_of(env, PowerPCCPU, env));
+    return container_of(env, PowerPCCPU, env);
 }
 
 #define ENV_GET_CPU(e) CPU(ppc_env_get_cpu(e))
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 0ede077..7a7b1bf 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1188,15 +1188,6 @@
     return env->mmu_idx;
 }
 
-#if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
-{
-    if (newsp)
-        env->gpr[1] = newsp;
-    env->gpr[3] = 0;
-}
-#endif
-
 #include "exec/cpu-all.h"
 
 /*****************************************************************************/
@@ -2036,17 +2027,6 @@
     *flags = env->hflags;
 }
 
-static inline void cpu_set_tls(CPUPPCState *env, target_ulong newtls)
-{
-#if defined(TARGET_PPC64)
-    /* The kernel checks TIF_32BIT here; we don't support loading 32-bit
-       binaries on PPC64 yet. */
-    env->gpr[13] = newtls;
-#else
-    env->gpr[2] = newtls;
-#endif
-}
-
 #if !defined(CONFIG_USER_ONLY)
 static inline int booke206_tlbm_id(CPUPPCState *env, ppcmas_tlb_t *tlbm)
 {
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 @@
 {
     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 @@
 
     /* 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/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c
index f6adf22..6a77dc4 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -29,10 +29,10 @@
 
 #ifdef DEBUG_MMU
 #  define LOG_MMU(...) qemu_log(__VA_ARGS__)
-#  define LOG_MMU_STATE(env) log_cpu_state((env), 0)
+#  define LOG_MMU_STATE(cpu) log_cpu_state((cpu), 0)
 #else
 #  define LOG_MMU(...) do { } while (0)
-#  define LOG_MMU_STATE(...) do { } while (0)
+#  define LOG_MMU_STATE(cpu) do { } while (0)
 #endif
 
 #ifdef DEBUG_BATS
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 5c67ec3..67fc1b5 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -28,10 +28,10 @@
 
 #ifdef DEBUG_MMU
 #  define LOG_MMU(...) qemu_log(__VA_ARGS__)
-#  define LOG_MMU_STATE(env) log_cpu_state((env), 0)
+#  define LOG_MMU_STATE(cpu) log_cpu_state((cpu), 0)
 #else
 #  define LOG_MMU(...) do { } while (0)
-#  define LOG_MMU_STATE(...) do { } while (0)
+#  define LOG_MMU_STATE(cpu) do { } while (0)
 #endif
 
 #ifdef DEBUG_SLB
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 385b67a..77102c4 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -32,10 +32,10 @@
 
 #ifdef DEBUG_MMU
 #  define LOG_MMU(...) qemu_log(__VA_ARGS__)
-#  define LOG_MMU_STATE(env) log_cpu_state((env), 0)
+#  define LOG_MMU_STATE(cpu) log_cpu_state((cpu), 0)
 #else
 #  define LOG_MMU(...) do { } while (0)
-#  define LOG_MMU_STATE(...) do { } while (0)
+#  define LOG_MMU_STATE(cpu) do { } while (0)
 #endif
 
 #ifdef DEBUG_SOFTWARE_TLB
@@ -1508,7 +1508,7 @@
                      mmu_idx, TARGET_PAGE_SIZE);
         ret = 0;
     } else if (ret < 0) {
-        LOG_MMU_STATE(env);
+        LOG_MMU_STATE(CPU(ppc_env_get_cpu(env)));
         if (access_type == ACCESS_CODE) {
             switch (ret) {
             case -1:
@@ -2890,7 +2890,7 @@
 void tlb_fill(CPUPPCState *env, target_ulong addr, int is_write, int mmu_idx,
               uintptr_t retaddr)
 {
-    CPUState *cpu = ENV_GET_CPU(env);
+    CPUState *cpu = CPU(ppc_env_get_cpu(env));
     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
     int ret;
 
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 3643863..eb96272 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9726,10 +9726,11 @@
 }
 
 /*****************************************************************************/
-static inline void gen_intermediate_code_internal(CPUPPCState *env,
+static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
                                                   TranslationBlock *tb,
-                                                  int search_pc)
+                                                  bool search_pc)
 {
+    CPUPPCState *env = &cpu->env;
     DisasContext ctx, *ctxp = &ctx;
     opc_handler_t **table, *handler;
     target_ulong pc_start;
@@ -9917,12 +9918,12 @@
 
 void gen_intermediate_code (CPUPPCState *env, struct TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 0);
+    gen_intermediate_code_internal(ppc_env_get_cpu(env), tb, false);
 }
 
 void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 1);
+    gen_intermediate_code_internal(ppc_env_get_cpu(env), tb, true);
 }
 
 void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, int pc_pos)
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 50e0ee5..b62f04a 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8171,11 +8171,6 @@
     CPUPPCState *env = &cpu->env;
     target_ulong msr;
 
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
     pcc->parent_reset(s);
 
     msr = (target_ulong)0;
diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h
index ec32d21..4c091e3 100644
--- a/target-s390x/cpu-qom.h
+++ b/target-s390x/cpu-qom.h
@@ -64,7 +64,7 @@
 
 static inline S390CPU *s390_env_get_cpu(CPUS390XState *env)
 {
-    return S390_CPU(container_of(env, S390CPU, env));
+    return container_of(env, S390CPU, env);
 }
 
 #define ENV_GET_CPU(e) CPU(s390_env_get_cpu(e))
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index c3697cd..1ef2fc0 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -65,11 +65,6 @@
     S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
     CPUS390XState *env = &cpu->env;
 
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
     s390_del_running_cpu(cpu);
 
     scc->parent_reset(s);
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 741c4e4..6462688 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -149,16 +149,6 @@
 
 #include "cpu-qom.h"
 
-#if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUS390XState *env, target_ulong newsp)
-{
-    if (newsp) {
-        env->regs[15] = newsp;
-    }
-    env->regs[2] = 0;
-}
-#endif
-
 /* distinguish between 24 bit and 31 bit addressing */
 #define HIGH_ORDER_BIT 0x80000000
 
@@ -515,12 +505,6 @@
 }
 #endif
 
-static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls)
-{
-    env->aregs[0] = newtls >> 32;
-    env->aregs[1] = newtls & 0xffffffffULL;
-}
-
 #define cpu_init(model) (&cpu_s390x_init(model)->env)
 #define cpu_exec cpu_s390x_exec
 #define cpu_gen_code cpu_s390x_gen_code
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 42f758f..60e94f8 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -469,7 +469,7 @@
     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. */
@@ -607,9 +607,10 @@
     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 @@
     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 @@
 
 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 @@
         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);
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index cd9880e..cba7b87 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -4736,10 +4736,11 @@
     return ret;
 }
 
-static inline void gen_intermediate_code_internal(CPUS390XState *env,
+static inline void gen_intermediate_code_internal(S390CPU *cpu,
                                                   TranslationBlock *tb,
-                                                  int search_pc)
+                                                  bool search_pc)
 {
+    CPUS390XState *env = &cpu->env;
     DisasContext dc;
     target_ulong pc_start;
     uint64_t next_page_start;
@@ -4872,12 +4873,12 @@
 
 void gen_intermediate_code (CPUS390XState *env, struct TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 0);
+    gen_intermediate_code_internal(s390_env_get_cpu(env), tb, false);
 }
 
 void gen_intermediate_code_pc (CPUS390XState *env, struct TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 1);
+    gen_intermediate_code_internal(s390_env_get_cpu(env), tb, true);
 }
 
 void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, int pc_pos)
diff --git a/target-sh4/cpu-qom.h b/target-sh4/cpu-qom.h
index 01d1637..c229a9a 100644
--- a/target-sh4/cpu-qom.h
+++ b/target-sh4/cpu-qom.h
@@ -76,7 +76,7 @@
 
 static inline SuperHCPU *sh_env_get_cpu(CPUSH4State *env)
 {
-    return SUPERH_CPU(container_of(env, SuperHCPU, env));
+    return container_of(env, SuperHCPU, env);
 }
 
 #define ENV_GET_CPU(e) CPU(sh_env_get_cpu(e))
diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c
index e739156..03487eb 100644
--- a/target-sh4/cpu.c
+++ b/target-sh4/cpu.c
@@ -31,11 +31,6 @@
     SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(cpu);
     CPUSH4State *env = &cpu->env;
 
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
     scc->parent_reset(s);
 
     memset(env, 0, offsetof(CPUSH4State, breakpoints));
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index fd7da92..c8df18b 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -220,11 +220,6 @@
 
 int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr);
 
-static inline void cpu_set_tls(CPUSH4State *env, target_ulong newtls)
-{
-  env->gbr = newtls;
-}
-
 void cpu_load_tlb(CPUSH4State * env);
 
 static inline CPUSH4State *cpu_init(const char *cpu_model)
@@ -250,15 +245,6 @@
     return (env->sr & SR_MD) == 0 ? 1 : 0;
 }
 
-#if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUSH4State *env, target_ulong newsp)
-{
-    if (newsp)
-        env->gregs[15] = newsp;
-    env->gregs[0] = 0;
-}
-#endif
-
 #include "exec/cpu-all.h"
 
 /* Memory access type */
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index ce10ca8..cb6a2d2 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -159,7 +159,7 @@
 	}
 	qemu_log("exception 0x%03x [%s] raised\n",
 		  irq_vector, expname);
-	log_cpu_state(env, 0);
+        log_cpu_state(cs, 0);
     }
 
     env->ssr = env->sr;
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 292c9e9..2fbe668 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -1846,9 +1846,10 @@
 }
 
 static inline void
-gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
-                               int search_pc)
+gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
+                               bool search_pc)
 {
+    CPUSH4State *env = &cpu->env;
     DisasContext ctx;
     target_ulong pc_start;
     static uint16_t *gen_opc_end;
@@ -1969,12 +1970,12 @@
 
 void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 0);
+    gen_intermediate_code_internal(sh_env_get_cpu(env), tb, false);
 }
 
 void gen_intermediate_code_pc(CPUSH4State * env, struct TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 1);
+    gen_intermediate_code_internal(sh_env_get_cpu(env), tb, true);
 }
 
 void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb, int pc_pos)
diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
index 97c1ec7..033a5b5 100644
--- a/target-sparc/cpu-qom.h
+++ b/target-sparc/cpu-qom.h
@@ -68,7 +68,7 @@
 
 static inline SPARCCPU *sparc_env_get_cpu(CPUSPARCState *env)
 {
-    return SPARC_CPU(container_of(env, SPARCCPU, env));
+    return container_of(env, SPARCCPU, env);
 }
 
 #define ENV_GET_CPU(e) CPU(sparc_env_get_cpu(e))
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 65ae6f7..87c3a50 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -30,11 +30,6 @@
     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
     CPUSPARCState *env = &cpu->env;
 
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
     scc->parent_reset(s);
 
     memset(env, 0, offsetof(CPUSPARCState, breakpoints));
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 021eb157..41b014a 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -690,18 +690,6 @@
 #endif
 }
 
-#if defined(CONFIG_USER_ONLY)
-static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp)
-{
-    if (newsp)
-        env->regwptr[22] = newsp;
-    env->regwptr[0] = 0;
-    /* FIXME: Do we also need to clear CF?  */
-    /* XXXXX */
-    printf ("HELPME: %s:%d\n", __FILE__, __LINE__);
-}
-#endif
-
 #include "exec/cpu-all.h"
 
 #ifdef TARGET_SPARC64
diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c
index 7221460..d532238 100644
--- a/target-sparc/int32_helper.c
+++ b/target-sparc/int32_helper.c
@@ -86,7 +86,7 @@
         }
 
         qemu_log("%6d: %s (v=%02x)\n", count, name, intno);
-        log_cpu_state(env, 0);
+        log_cpu_state(cs, 0);
 #if 0
         {
             int i;
diff --git a/target-sparc/int64_helper.c b/target-sparc/int64_helper.c
index f411884..bf7dd86 100644
--- a/target-sparc/int64_helper.c
+++ b/target-sparc/int64_helper.c
@@ -92,7 +92,7 @@
         }
 
         qemu_log("%6d: %s (v=%04x)\n", count, name, intno);
-        log_cpu_state(env, 0);
+        log_cpu_state(cs, 0);
 #if 0
         {
             int i;
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index eb6e800..5e771e5 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5219,9 +5219,11 @@
     }
 }
 
-static inline void gen_intermediate_code_internal(TranslationBlock * tb,
-                                                  int spc, CPUSPARCState *env)
+static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
+                                                  TranslationBlock *tb,
+                                                  bool spc)
 {
+    CPUSPARCState *env = &cpu->env;
     target_ulong pc_start, last_pc;
     uint16_t *gen_opc_end;
     DisasContext dc1, *dc = &dc1;
@@ -5347,12 +5349,12 @@
 
 void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
 {
-    gen_intermediate_code_internal(tb, 0, env);
+    gen_intermediate_code_internal(sparc_env_get_cpu(env), tb, false);
 }
 
 void gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
 {
-    gen_intermediate_code_internal(tb, 1, env);
+    gen_intermediate_code_internal(sparc_env_get_cpu(env), tb, true);
 }
 
 void gen_intermediate_code_init(CPUSPARCState *env)
diff --git a/target-unicore32/cpu-qom.h b/target-unicore32/cpu-qom.h
index 7eec448..350d480 100644
--- a/target-unicore32/cpu-qom.h
+++ b/target-unicore32/cpu-qom.h
@@ -53,7 +53,7 @@
 
 static inline UniCore32CPU *uc32_env_get_cpu(CPUUniCore32State *env)
 {
-    return UNICORE32_CPU(container_of(env, UniCore32CPU, env));
+    return container_of(env, UniCore32CPU, env);
 }
 
 #define ENV_GET_CPU(e) CPU(uc32_env_get_cpu(e))
diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
index 5b2b9d1..d4be525 100644
--- a/target-unicore32/cpu.h
+++ b/target-unicore32/cpu.h
@@ -142,19 +142,6 @@
     return (env->uncached_asr & ASR_M) == ASR_MODE_USER ? 1 : 0;
 }
 
-static inline void cpu_clone_regs(CPUUniCore32State *env, target_ulong newsp)
-{
-    if (newsp) {
-        env->regs[29] = newsp;
-    }
-    env->regs[0] = 0;
-}
-
-static inline void cpu_set_tls(CPUUniCore32State *env, target_ulong newtls)
-{
-    env->regs[16] = newtls;
-}
-
 #include "exec/cpu-all.h"
 #include "cpu-qom.h"
 #include "exec/exec-all.h"
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index e1fe4e6..d85185d 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -1876,9 +1876,10 @@
 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
    basic block 'tb'. If search_pc is TRUE, also generate PC
    information for each intermediate instruction. */
-static inline void gen_intermediate_code_internal(CPUUniCore32State *env,
-        TranslationBlock *tb, int search_pc)
+static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
+        TranslationBlock *tb, bool search_pc)
 {
+    CPUUniCore32State *env = &cpu->env;
     DisasContext dc1, *dc = &dc1;
     CPUBreakpoint *bp;
     uint16_t *gen_opc_end;
@@ -2065,12 +2066,12 @@
 
 void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 0);
+    gen_intermediate_code_internal(uc32_env_get_cpu(env), tb, false);
 }
 
 void gen_intermediate_code_pc(CPUUniCore32State *env, TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 1);
+    gen_intermediate_code_internal(uc32_env_get_cpu(env), tb, true);
 }
 
 static const char *cpu_mode_names[16] = {
diff --git a/target-xtensa/cpu-qom.h b/target-xtensa/cpu-qom.h
index 30506cf..31e7498 100644
--- a/target-xtensa/cpu-qom.h
+++ b/target-xtensa/cpu-qom.h
@@ -73,7 +73,7 @@
 
 static inline XtensaCPU *xtensa_env_get_cpu(const CPUXtensaState *env)
 {
-    return XTENSA_CPU(container_of(env, XtensaCPU, env));
+    return container_of(env, XtensaCPU, env);
 }
 
 #define ENV_GET_CPU(e) CPU(xtensa_env_get_cpu(e))
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index dcb90a5..e4cf828 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -2875,9 +2875,11 @@
     }
 }
 
-static void gen_intermediate_code_internal(
-        CPUXtensaState *env, TranslationBlock *tb, int search_pc)
+static inline
+void gen_intermediate_code_internal(XtensaCPU *cpu,
+                                    TranslationBlock *tb, bool search_pc)
 {
+    CPUXtensaState *env = &cpu->env;
     DisasContext dc;
     int insn_count = 0;
     int j, lj = -1;
@@ -3006,12 +3008,12 @@
 
 void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 0);
+    gen_intermediate_code_internal(xtensa_env_get_cpu(env), tb, false);
 }
 
 void gen_intermediate_code_pc(CPUXtensaState *env, TranslationBlock *tb)
 {
-    gen_intermediate_code_internal(env, tb, 1);
+    gen_intermediate_code_internal(xtensa_env_get_cpu(env), tb, true);
 }
 
 void xtensa_cpu_dump_state(CPUState *cs, FILE *f,
diff --git a/translate-all.c b/translate-all.c
index 9acb2b1..e8683d2 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -681,7 +681,7 @@
 /* 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 @@
     }
     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 @@
 /* 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 @@
 
     /* 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;
         }
@@ -999,8 +1003,10 @@
                                    int is_cpu_write_access)
 {
     TranslationBlock *tb, *tb_next, *saved_tb;
-    CPUArchState *env = cpu_single_env;
-    CPUState *cpu = NULL;
+    CPUState *cpu = current_cpu;
+#if defined(TARGET_HAS_PRECISE_SMC) || !defined(CONFIG_USER_ONLY)
+    CPUArchState *env = NULL;
+#endif
     tb_page_addr_t tb_start, tb_end;
     PageDesc *p;
     int n;
@@ -1023,9 +1029,11 @@
         /* build code bitmap */
         build_page_bitmap(p);
     }
-    if (env != NULL) {
-        cpu = ENV_GET_CPU(env);
+#if defined(TARGET_HAS_PRECISE_SMC) || !defined(CONFIG_USER_ONLY)
+    if (cpu != NULL) {
+        env = cpu->env_ptr;
     }
+#endif
 
     /* we remove all the TBs in the range [start, end[ */
     /* XXX: see if in some cases it could be faster to invalidate all
@@ -1147,8 +1155,8 @@
     int n;
 #ifdef TARGET_HAS_PRECISE_SMC
     TranslationBlock *current_tb = NULL;
-    CPUArchState *env = cpu_single_env;
-    CPUState *cpu = NULL;
+    CPUState *cpu = current_cpu;
+    CPUArchState *env = NULL;
     int current_tb_modified = 0;
     target_ulong current_pc = 0;
     target_ulong current_cs_base = 0;
@@ -1165,8 +1173,8 @@
     if (tb && pc != 0) {
         current_tb = tb_find_pc(pc);
     }
-    if (env != NULL) {
-        cpu = ENV_GET_CPU(env);
+    if (cpu != NULL) {
+        env = cpu->env_ptr;
     }
 #endif
     while (tb != NULL) {
diff --git a/user-exec.c b/user-exec.c
index 57c8e8d..d45ca8e 100644
--- a/user-exec.c
+++ b/user-exec.c
@@ -82,6 +82,7 @@
                                     int is_write, sigset_t *old_set,
                                     void *puc)
 {
+    CPUArchState *env;
     int ret;
 
 #if defined(DEBUG_SIGNAL)
@@ -94,9 +95,9 @@
         return 1;
     }
 
+    env = current_cpu->env_ptr;
     /* see if it is an MMU fault */
-    ret = cpu_handle_mmu_fault(cpu_single_env, address, is_write,
-                               MMU_USER_IDX);
+    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX);
     if (ret < 0) {
         return 0; /* not an MMU fault */
     }
@@ -104,12 +105,12 @@
         return 1; /* the MMU fault was handled without causing real CPU fault */
     }
     /* now we have a real cpu fault */
-    cpu_restore_state(cpu_single_env, pc);
+    cpu_restore_state(env, pc);
 
     /* we restore the process signal mask as the sigreturn should
        do it (XXX: use sigsetjmp) */
     sigprocmask(SIG_SETMASK, old_set, NULL);
-    exception_action(cpu_single_env);
+    exception_action(env);
 
     /* never comes here */
     return 1;