diff --git a/cpu-defs.h b/cpu-defs.h
index 4e1d2df..28ab06b 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -193,7 +193,6 @@ typedef struct CPUWatchpoint {
     int exception_index;                                                \
                                                                         \
     CPUArchState *next_cpu; /* next CPU sharing TB cache */                 \
-    int cpu_index; /* CPU index (informative) */                        \
     uint32_t host_tid; /* host thread ID */                             \
     int running; /* Nonzero if cpu is currently running(usermode).  */  \
     /* user data */                                                     \
diff --git a/cpus.c b/cpus.c
index 2b599e8..7da40c8 100644
--- a/cpus.c
+++ b/cpus.c
@@ -390,13 +390,15 @@ 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) {
-        fprintf(stderr, "CPU #%d:\n", env->cpu_index);
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        cpu = ENV_GET_CPU(env);
+        fprintf(stderr, "CPU #%d:\n", cpu->cpu_index);
         cpu_dump_state(env, stderr, fprintf, CPU_DUMP_FPU);
     }
     va_end(ap);
@@ -1166,7 +1168,7 @@ void set_numa_modes(void)
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         cpu = ENV_GET_CPU(env);
         for (i = 0; i < nb_numa_nodes; i++) {
-            if (test_bit(env->cpu_index, node_cpumask[i])) {
+            if (test_bit(cpu->cpu_index, node_cpumask[i])) {
                 cpu->numa_node = i;
             }
         }
@@ -1215,7 +1217,7 @@ CpuInfoList *qmp_query_cpus(Error **errp)
 
         info = g_malloc0(sizeof(*info));
         info->value = g_malloc0(sizeof(*info->value));
-        info->value->CPU = env->cpu_index;
+        info->value->CPU = cpu->cpu_index;
         info->value->current = (env == first_cpu);
         info->value->halted = env->halted;
         info->value->thread_id = cpu->thread_id;
@@ -1253,6 +1255,7 @@ void qmp_memsave(int64_t addr, int64_t size, const char *filename,
     FILE *f;
     uint32_t l;
     CPUArchState *env;
+    CPUState *cpu;
     uint8_t buf[1024];
 
     if (!has_cpu) {
@@ -1260,7 +1263,8 @@ void qmp_memsave(int64_t addr, int64_t size, const char *filename,
     }
 
     for (env = first_cpu; env; env = env->next_cpu) {
-        if (cpu_index == env->cpu_index) {
+        cpu = ENV_GET_CPU(env);
+        if (cpu_index == cpu->cpu_index) {
             break;
         }
     }
diff --git a/exec.c b/exec.c
index fc9326f..b364a33 100644
--- a/exec.c
+++ b/exec.c
@@ -244,13 +244,16 @@ static const VMStateDescription vmstate_cpu_common = {
 };
 #endif
 
-CPUArchState *qemu_get_cpu(int cpu)
+CPUArchState *qemu_get_cpu(int index)
 {
     CPUArchState *env = first_cpu;
+    CPUState *cpu;
 
     while (env) {
-        if (env->cpu_index == cpu)
+        cpu = ENV_GET_CPU(env);
+        if (cpu->cpu_index == index) {
             break;
+        }
         env = env->next_cpu;
     }
 
@@ -273,7 +276,7 @@ void cpu_exec_init(CPUArchState *env)
         penv = &(*penv)->next_cpu;
         cpu_index++;
     }
-    env->cpu_index = cpu_index;
+    cpu->cpu_index = cpu_index;
     cpu->numa_node = 0;
     QTAILQ_INIT(&env->breakpoints);
     QTAILQ_INIT(&env->watchpoints);
@@ -526,7 +529,6 @@ CPUArchState *cpu_copy(CPUArchState *env)
 {
     CPUArchState *new_env = cpu_init(env->cpu_model_str);
     CPUArchState *next_cpu = new_env->next_cpu;
-    int cpu_index = new_env->cpu_index;
 #if defined(TARGET_HAS_ICE)
     CPUBreakpoint *bp;
     CPUWatchpoint *wp;
@@ -534,9 +536,8 @@ CPUArchState *cpu_copy(CPUArchState *env)
 
     memcpy(new_env, env, sizeof(CPUArchState));
 
-    /* Preserve chaining and index. */
+    /* Preserve chaining. */
     new_env->next_cpu = next_cpu;
-    new_env->cpu_index = cpu_index;
 
     /* Clone all break/watchpoints.
        Note: Once we support ptrace with hw-debug register access, make sure
diff --git a/gdbstub.c b/gdbstub.c
index d02ec75..87ef1d6 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2383,9 +2383,10 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
             thread = strtoull(p+16, (char **)&p, 16);
             env = find_cpu(thread);
             if (env != NULL) {
+                CPUState *cpu = ENV_GET_CPU(env);
                 cpu_synchronize_state(env);
                 len = snprintf((char *)mem_buf, sizeof(mem_buf),
-                               "CPU#%d [%s]", env->cpu_index,
+                               "CPU#%d [%s]", cpu->cpu_index,
                                env->halted ? "halted " : "running");
                 memtohex(buf, mem_buf, len);
                 put_packet(s, buf);
diff --git a/gdbstub.h b/gdbstub.h
index 668de66..49231fe 100644
--- a/gdbstub.h
+++ b/gdbstub.h
@@ -35,7 +35,8 @@ static inline int cpu_index(CPUArchState *env)
 #if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL)
     return env->host_tid;
 #else
-    return env->cpu_index + 1;
+    CPUState *cpu = ENV_GET_CPU(env);
+    return cpu->cpu_index + 1;
 #endif
 }
 
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index 40b3a47..1bc6d34 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -75,6 +75,7 @@ static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
 {
     CPUAlphaState *env = cpu_single_env;
     TyphoonState *s = opaque;
+    CPUState *cpu;
     uint64_t ret = 0;
 
     if (addr & 4) {
@@ -95,7 +96,8 @@ static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
 
     case 0x0080:
         /* MISC: Miscellaneous Register.  */
-        ret = s->cchip.misc | (env->cpu_index & 3);
+        cpu = ENV_GET_CPU(env);
+        ret = s->cchip.misc | (cpu->cpu_index & 3);
         break;
 
     case 0x00c0:
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index b6062c4..b42b2ab 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -39,7 +39,8 @@ static const uint8_t gic_id[] = {
 static inline int gic_get_current_cpu(GICState *s)
 {
     if (s->num_cpu > 1) {
-        return cpu_single_env->cpu_index;
+        CPUState *cpu = ENV_GET_CPU(cpu_single_env);
+        return cpu->cpu_index;
     }
     return 0;
 }
diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c
index 6790832..0012b10 100644
--- a/hw/arm_mptimer.c
+++ b/hw/arm_mptimer.c
@@ -49,11 +49,13 @@ typedef struct {
 
 static inline int get_current_cpu(arm_mptimer_state *s)
 {
-    if (cpu_single_env->cpu_index >= s->num_cpu) {
+    CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
+
+    if (cpu_single_cpu->cpu_index >= s->num_cpu) {
         hw_error("arm_mptimer: num-cpu %d but this cpu is %d!\n",
-                 s->num_cpu, cpu_single_env->cpu_index);
+                 s->num_cpu, cpu_single_cpu->cpu_index);
     }
-    return cpu_single_env->cpu_index;
+    return cpu_single_cpu->cpu_index;
 }
 
 static inline void timerblock_update_irq(timerblock *tb)
diff --git a/hw/openpic.c b/hw/openpic.c
index 3cbcea8..37adb8d 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -157,7 +157,8 @@ static inline int test_bit(uint32_t *field, int bit)
 
 static int get_current_cpu(void)
 {
-  return cpu_single_env->cpu_index;
+    CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
+    return cpu_single_cpu->cpu_index;
 }
 
 static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 5592359..ba0ecd7 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -234,25 +234,28 @@ static int ppce500_load_device_tree(CPUPPCState *env,
     /* We need to generate the cpu nodes in reverse order, so Linux can pick
        the first node as boot node and be happy */
     for (i = smp_cpus - 1; i >= 0; i--) {
+        CPUState *cpu = NULL;
         char cpu_name[128];
         uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20);
 
         for (env = first_cpu; env != NULL; env = env->next_cpu) {
-            if (env->cpu_index == i) {
+            cpu = ENV_GET_CPU(env);
+            if (cpu->cpu_index == i) {
                 break;
             }
         }
 
-        if (!env) {
+        if (cpu == NULL) {
             continue;
         }
 
-        snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", env->cpu_index);
+        snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x",
+                 cpu->cpu_index);
         qemu_devtree_add_subnode(fdt, cpu_name);
         qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
         qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
         qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu");
-        qemu_devtree_setprop_cell(fdt, cpu_name, "reg", env->cpu_index);
+        qemu_devtree_setprop_cell(fdt, cpu_name, "reg", cpu->cpu_index);
         qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size",
                                   env->dcache_line_size);
         qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size",
@@ -260,7 +263,7 @@ static int ppce500_load_device_tree(CPUPPCState *env,
         qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000);
         qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000);
         qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0);
-        if (env->cpu_index) {
+        if (cpu->cpu_index) {
             qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled");
             qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table");
             qemu_devtree_setprop_u64(fdt, cpu_name, "cpu-release-addr",
@@ -474,6 +477,7 @@ void ppce500_init(PPCE500Params *params)
     irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
     for (i = 0; i < smp_cpus; i++) {
         PowerPCCPU *cpu;
+        CPUState *cs;
         qemu_irq *input;
 
         cpu = cpu_ppc_init(params->cpu_model);
@@ -482,6 +486,7 @@ void ppce500_init(PPCE500Params *params)
             exit(1);
         }
         env = &cpu->env;
+        cs = CPU(cpu);
 
         if (!firstenv) {
             firstenv = env;
@@ -491,7 +496,7 @@ void ppce500_init(PPCE500Params *params)
         input = (qemu_irq *)env->irq_inputs;
         irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
         irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
-        env->spr[SPR_BOOKE_PIR] = env->cpu_index = i;
+        env->spr[SPR_BOOKE_PIR] = cs->cpu_index = i;
         env->mpic_cpu_base = MPC8544_CCSRBAR_BASE +
                               MPC8544_MPIC_REGS_OFFSET + 0x20000;
 
diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
index c1a155b..c8f59e1 100644
--- a/hw/ppce500_spin.c
+++ b/hw/ppce500_spin.c
@@ -124,21 +124,23 @@ static void spin_write(void *opaque, hwaddr addr, uint64_t value,
     SpinState *s = opaque;
     int env_idx = addr / sizeof(SpinInfo);
     CPUPPCState *env;
+    CPUState *cpu = NULL;
     SpinInfo *curspin = &s->spin[env_idx];
     uint8_t *curspin_p = (uint8_t*)curspin;
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        if (env->cpu_index == env_idx) {
+        cpu = CPU(ppc_env_get_cpu(env));
+        if (cpu->cpu_index == env_idx) {
             break;
         }
     }
 
-    if (!env) {
+    if (cpu == NULL) {
         /* Unknown CPU */
         return;
     }
 
-    if (!env->cpu_index) {
+    if (cpu->cpu_index == 0) {
         /* primary CPU doesn't spin */
         return;
     }
diff --git a/hw/pxa.h b/hw/pxa.h
index 49ac820..fbe5f4c 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -69,7 +69,7 @@ DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu);
 
 /* pxa2xx_gpio.c */
 DeviceState *pxa2xx_gpio_init(hwaddr base,
-                CPUARMState *env, DeviceState *pic, int lines);
+                              ARMCPU *cpu, DeviceState *pic, int lines);
 void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler);
 
 /* pxa2xx_dma.c */
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index e616979..08665f9 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2045,7 +2045,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
                     qdev_get_gpio_in(s->pic, PXA27X_PIC_OST_4_11),
                     NULL);
 
-    s->gpio = pxa2xx_gpio_init(0x40e00000, &s->cpu->env, s->pic, 121);
+    s->gpio = pxa2xx_gpio_init(0x40e00000, s->cpu, s->pic, 121);
 
     dinfo = drive_get(IF_SD, 0, 0);
     if (!dinfo) {
@@ -2176,7 +2176,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 3),
                     NULL);
 
-    s->gpio = pxa2xx_gpio_init(0x40e00000, &s->cpu->env, s->pic, 85);
+    s->gpio = pxa2xx_gpio_init(0x40e00000, s->cpu, s->pic, 85);
 
     dinfo = drive_get(IF_SD, 0, 0);
     if (!dinfo) {
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index 7aaf409..b9f2d52 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -250,13 +250,14 @@ static const MemoryRegionOps pxa_gpio_ops = {
 };
 
 DeviceState *pxa2xx_gpio_init(hwaddr base,
-                CPUARMState *env, DeviceState *pic, int lines)
+                              ARMCPU *cpu, DeviceState *pic, int lines)
 {
+    CPUState *cs = CPU(cpu);
     DeviceState *dev;
 
     dev = qdev_create(NULL, "pxa2xx-gpio");
     qdev_prop_set_int32(dev, "lines", lines);
-    qdev_prop_set_int32(dev, "ncpu", env->cpu_index);
+    qdev_prop_set_int32(dev, "ncpu", cs->cpu_index);
     qdev_init_nofail(dev);
 
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
diff --git a/hw/spapr.c b/hw/spapr.c
index 084209e..1fec1aa 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -147,20 +147,20 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
     assert(spapr->cpu_model);
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu = ENV_GET_CPU(env);
+        cpu = CPU(ppc_env_get_cpu(env));
         uint32_t associativity[] = {cpu_to_be32(0x5),
                                     cpu_to_be32(0x0),
                                     cpu_to_be32(0x0),
                                     cpu_to_be32(0x0),
                                     cpu_to_be32(cpu->numa_node),
-                                    cpu_to_be32(env->cpu_index)};
+                                    cpu_to_be32(cpu->cpu_index)};
 
-        if ((env->cpu_index % smt) != 0) {
+        if ((cpu->cpu_index % smt) != 0) {
             continue;
         }
 
         snprintf(cpu_model, 32, "/cpus/%s@%x", spapr->cpu_model,
-                 env->cpu_index);
+                 cpu->cpu_index);
 
         offset = fdt_path_offset(fdt, cpu_model);
         if (offset < 0) {
@@ -309,7 +309,8 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
     spapr->cpu_model = g_strdup(modelname);
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        int index = env->cpu_index;
+        CPUState *cpu = CPU(ppc_env_get_cpu(env));
+        int index = cpu->cpu_index;
         uint32_t servers_prop[smp_threads];
         uint32_t gservers_prop[smp_threads * 2];
         char *nodename;
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index 63cadb8..3db09e9 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -469,9 +469,11 @@ static target_ulong h_register_vpa(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     target_ulong vpa = args[2];
     target_ulong ret = H_PARAMETER;
     CPUPPCState *tenv;
+    CPUState *tcpu;
 
     for (tenv = first_cpu; tenv; tenv = tenv->next_cpu) {
-        if (tenv->cpu_index == procno) {
+        tcpu = CPU(ppc_env_get_cpu(tenv));
+        if (tcpu->cpu_index == procno) {
             break;
         }
     }
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index e618c2d..c781159 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -131,6 +131,7 @@ static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
 {
     target_ulong id;
     CPUPPCState *env;
+    CPUState *cpu;
 
     if (nargs != 1 || nret != 2) {
         rtas_st(rets, 0, -3);
@@ -139,7 +140,8 @@ static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
 
     id = rtas_ld(args, 0);
     for (env = first_cpu; env; env = env->next_cpu) {
-        if (env->cpu_index != id) {
+        cpu = CPU(ppc_env_get_cpu(env));
+        if (cpu->cpu_index != id) {
             continue;
         }
 
@@ -176,9 +178,9 @@ static void rtas_start_cpu(sPAPREnvironment *spapr,
     r3 = rtas_ld(args, 2);
 
     for (env = first_cpu; env; env = env->next_cpu) {
-        cpu = ENV_GET_CPU(env);
+        cpu = CPU(ppc_env_get_cpu(env));
 
-        if (env->cpu_index != id) {
+        if (cpu->cpu_index != id) {
             continue;
         }
 
diff --git a/hw/xics.c b/hw/xics.c
index 55899ce..9ef0d61 100644
--- a/hw/xics.c
+++ b/hw/xics.c
@@ -357,10 +357,10 @@ void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi)
 static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                            target_ulong opcode, target_ulong *args)
 {
-    CPUPPCState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
     target_ulong cppr = args[0];
 
-    icp_set_cppr(spapr->icp, env->cpu_index, cppr);
+    icp_set_cppr(spapr->icp, cs->cpu_index, cppr);
     return H_SUCCESS;
 }
 
@@ -376,14 +376,13 @@ static target_ulong h_ipi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 
     icp_set_mfrr(spapr->icp, server, mfrr);
     return H_SUCCESS;
-
 }
 
 static target_ulong h_xirr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                            target_ulong opcode, target_ulong *args)
 {
-    CPUPPCState *env = &cpu->env;
-    uint32_t xirr = icp_accept(spapr->icp->ss + env->cpu_index);
+    CPUState *cs = CPU(cpu);
+    uint32_t xirr = icp_accept(spapr->icp->ss + cs->cpu_index);
 
     args[0] = xirr;
     return H_SUCCESS;
@@ -392,10 +391,10 @@ static target_ulong h_xirr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 static target_ulong h_eoi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                           target_ulong opcode, target_ulong *args)
 {
-    CPUPPCState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
     target_ulong xirr = args[0];
 
-    icp_eoi(spapr->icp, env->cpu_index, xirr);
+    icp_eoi(spapr->icp, cs->cpu_index, xirr);
     return H_SUCCESS;
 }
 
@@ -525,14 +524,16 @@ static void xics_reset(void *opaque)
 struct icp_state *xics_system_init(int nr_irqs)
 {
     CPUPPCState *env;
+    CPUState *cpu;
     int max_server_num;
     struct icp_state *icp;
     struct ics_state *ics;
 
     max_server_num = -1;
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        if (env->cpu_index > max_server_num) {
-            max_server_num = env->cpu_index;
+        cpu = CPU(ppc_env_get_cpu(env));
+        if (cpu->cpu_index > max_server_num) {
+            max_server_num = cpu->cpu_index;
         }
     }
 
@@ -541,7 +542,8 @@ struct icp_state *xics_system_init(int nr_irqs)
     icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state));
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        struct icp_server_state *ss = &icp->ss[env->cpu_index];
+        cpu = CPU(ppc_env_get_cpu(env));
+        struct icp_server_state *ss = &icp->ss[cpu->cpu_index];
 
         switch (PPC_INPUT(env)) {
         case PPC_FLAGS_INPUT_POWER7:
diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h
index 3146ccf..0fee271 100644
--- a/include/qemu/cpu.h
+++ b/include/qemu/cpu.h
@@ -57,6 +57,7 @@ struct kvm_run;
 
 /**
  * CPUState:
+ * @cpu_index: CPU index (informative).
  * @nr_cores: Number of cores within this CPU package.
  * @nr_threads: Number of threads within this CPU.
  * @numa_node: NUMA node this CPU is belonging to.
@@ -96,6 +97,7 @@ struct CPUState {
     struct kvm_run *kvm_run;
 
     /* TODO Move common fields from CPUArchState here. */
+    int cpu_index; /* used by alpha TCG */
 };
 
 
diff --git a/kvm-all.c b/kvm-all.c
index f687229..273197f 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -223,7 +223,7 @@ int kvm_init_vcpu(CPUArchState *env)
 
     DPRINTF("kvm_init_vcpu\n");
 
-    ret = kvm_vm_ioctl(s, KVM_CREATE_VCPU, env->cpu_index);
+    ret = kvm_vm_ioctl(s, KVM_CREATE_VCPU, cpu->cpu_index);
     if (ret < 0) {
         DPRINTF("kvm_create_vcpu failed\n");
         goto err;
diff --git a/monitor.c b/monitor.c
index 3c177ec..48e6e5e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -871,9 +871,11 @@ EventInfoList *qmp_query_events(Error **errp)
 int monitor_set_cpu(int cpu_index)
 {
     CPUArchState *env;
+    CPUState *cpu;
 
-    for(env = first_cpu; env != NULL; env = env->next_cpu) {
-        if (env->cpu_index == cpu_index) {
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        cpu = ENV_GET_CPU(env);
+        if (cpu->cpu_index == cpu_index) {
             cur_mon->mon_cpu = env;
             return 0;
         }
@@ -892,7 +894,8 @@ static CPUArchState *mon_get_cpu(void)
 
 int monitor_get_cpu_index(void)
 {
-    return mon_get_cpu()->cpu_index;
+    CPUState *cpu = ENV_GET_CPU(mon_get_cpu());
+    return cpu->cpu_index;
 }
 
 static void do_info_registers(Monitor *mon)
@@ -1790,7 +1793,7 @@ static void do_info_numa(Monitor *mon)
         for (env = first_cpu; env != NULL; env = env->next_cpu) {
             cpu = ENV_GET_CPU(env);
             if (cpu->numa_node == i) {
-                monitor_printf(mon, " %d", env->cpu_index);
+                monitor_printf(mon, " %d", cpu->cpu_index);
             }
         }
         monitor_printf(mon, "\n");
@@ -1992,6 +1995,7 @@ static void do_inject_mce(Monitor *mon, const QDict *qdict)
 {
     X86CPU *cpu;
     CPUX86State *cenv;
+    CPUState *cs;
     int cpu_index = qdict_get_int(qdict, "cpu_index");
     int bank = qdict_get_int(qdict, "bank");
     uint64_t status = qdict_get_int(qdict, "status");
@@ -2005,7 +2009,8 @@ static void do_inject_mce(Monitor *mon, const QDict *qdict)
     }
     for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
         cpu = x86_env_get_cpu(cenv);
-        if (cenv->cpu_index == cpu_index) {
+        cs = CPU(cpu);
+        if (cs->cpu_index == cpu_index) {
             cpu_x86_inject_mce(mon, cpu, bank, status, mcg_status, addr, misc,
                                flags);
             break;
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index dc0c97c..c02bccf 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1579,7 +1579,7 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
         case 0x3C:
             /* WHAMI */
             tcg_gen_ld32s_i64(cpu_ir[IR_V0], cpu_env,
-                              offsetof(CPUAlphaState, cpu_index));
+                -offsetof(AlphaCPU, env) + offsetof(CPUState, cpu_index));
             break;
 
         default:
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index b00f5fa..5d5c5c6 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -64,7 +64,7 @@ static void arm_cpu_reset(CPUState *s)
     CPUARMState *env = &cpu->env;
 
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
         log_cpu_state(env, 0);
     }
 
diff --git a/target-arm/helper.c b/target-arm/helper.c
index d2f2fb4..de30288 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -902,7 +902,8 @@ static const ARMCPRegInfo strongarm_cp_reginfo[] = {
 static int mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri,
                       uint64_t *value)
 {
-    uint32_t mpidr = env->cpu_index;
+    CPUState *cs = CPU(arm_env_get_cpu(env));
+    uint32_t mpidr = cs->cpu_index;
     /* We don't support setting cluster ID ([8..11])
      * so these bits always RAZ.
      */
diff --git a/target-cris/cpu.c b/target-cris/cpu.c
index c596609..3f64a57 100644
--- a/target-cris/cpu.c
+++ b/target-cris/cpu.c
@@ -35,7 +35,7 @@ static void cris_cpu_reset(CPUState *s)
     uint32_t vr;
 
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
         log_cpu_state(env, 0);
     }
 
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 8664ac2..37d9ebb 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1913,7 +1913,7 @@ static void x86_cpu_reset(CPUState *s)
     int i;
 
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
         log_cpu_state(env, CPU_DUMP_FPU | CPU_DUMP_CCOP);
     }
 
@@ -1987,7 +1987,7 @@ static void x86_cpu_reset(CPUState *s)
 
 #if !defined(CONFIG_USER_ONLY)
     /* We hard-wire the BSP to the first CPU. */
-    if (env->cpu_index == 0) {
+    if (s->cpu_index == 0) {
         apic_designate_bsp(env->apic_state);
     }
 
@@ -2098,6 +2098,7 @@ void x86_cpu_realize(Object *obj, Error **errp)
 
 static void x86_cpu_initfn(Object *obj)
 {
+    CPUState *cs = CPU(obj);
     X86CPU *cpu = X86_CPU(obj);
     CPUX86State *env = &cpu->env;
     static int inited;
@@ -2129,7 +2130,7 @@ static void x86_cpu_initfn(Object *obj)
                         x86_cpuid_get_tsc_freq,
                         x86_cpuid_set_tsc_freq, NULL, NULL, NULL);
 
-    env->cpuid_apic_id = env->cpu_index;
+    env->cpuid_apic_id = cs->cpu_index;
 
     /* init various static tables used in TCG mode */
     if (tcg_enabled() && !inited) {
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 00341c5..a2834be 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1059,7 +1059,7 @@ void breakpoint_handler(CPUX86State *env)
 
 typedef struct MCEInjectionParams {
     Monitor *mon;
-    CPUX86State *env;
+    X86CPU *cpu;
     int bank;
     uint64_t status;
     uint64_t mcg_status;
@@ -1071,7 +1071,8 @@ typedef struct MCEInjectionParams {
 static void do_inject_x86_mce(void *data)
 {
     MCEInjectionParams *params = data;
-    CPUX86State *cenv = params->env;
+    CPUX86State *cenv = &params->cpu->env;
+    CPUState *cpu = CPU(params->cpu);
     uint64_t *banks = cenv->mce_banks + 4 * params->bank;
 
     cpu_synchronize_state(cenv);
@@ -1094,7 +1095,7 @@ static void do_inject_x86_mce(void *data)
         if ((cenv->mcg_cap & MCG_CTL_P) && cenv->mcg_ctl != ~(uint64_t)0) {
             monitor_printf(params->mon,
                            "CPU %d: Uncorrected error reporting disabled\n",
-                           cenv->cpu_index);
+                           cpu->cpu_index);
             return;
         }
 
@@ -1106,7 +1107,7 @@ static void do_inject_x86_mce(void *data)
             monitor_printf(params->mon,
                            "CPU %d: Uncorrected error reporting disabled for"
                            " bank %d\n",
-                           cenv->cpu_index, params->bank);
+                           cpu->cpu_index, params->bank);
             return;
         }
 
@@ -1115,7 +1116,7 @@ static void do_inject_x86_mce(void *data)
             monitor_printf(params->mon,
                            "CPU %d: Previous MCE still in progress, raising"
                            " triple fault\n",
-                           cenv->cpu_index);
+                           cpu->cpu_index);
             qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
             qemu_system_reset_request();
             return;
@@ -1148,7 +1149,7 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
     CPUX86State *cenv = &cpu->env;
     MCEInjectionParams params = {
         .mon = mon,
-        .env = cenv,
+        .cpu = cpu,
         .bank = bank,
         .status = status,
         .mcg_status = mcg_status,
@@ -1188,7 +1189,7 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
             if (cenv == env) {
                 continue;
             }
-            params.env = env;
+            params.cpu = x86_env_get_cpu(env);
             run_on_cpu(CPU(cpu), do_inject_x86_mce, &params);
         }
     }
diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
index a020379..2a5f6e7 100644
--- a/target-i386/misc_helper.c
+++ b/target-i386/misc_helper.c
@@ -580,14 +580,17 @@ void helper_monitor(CPUX86State *env, target_ulong ptr)
 
 void helper_mwait(CPUX86State *env, int next_eip_addend)
 {
+    CPUState *cpu;
+
     if ((uint32_t)ECX != 0) {
         raise_exception(env, EXCP0D_GPF);
     }
     cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0);
     EIP += next_eip_addend;
 
+    cpu = CPU(x86_env_get_cpu(env));
     /* XXX: not complete but not completely erroneous */
-    if (env->cpu_index != 0 || env->next_cpu != NULL) {
+    if (cpu->cpu_index != 0 || env->next_cpu != NULL) {
         /* more than one CPU: do not sleep because another CPU may
            wake this one */
     } else {
diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
index caa4834..eca2dca 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -30,7 +30,7 @@ static void lm32_cpu_reset(CPUState *s)
     CPULM32State *env = &cpu->env;
 
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
         log_cpu_state(env, 0);
     }
 
diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index 3e70bb0..ce89674 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -35,7 +35,7 @@ static void m68k_cpu_reset(CPUState *s)
     CPUM68KState *env = &cpu->env;
 
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
         log_cpu_state(env, 0);
     }
 
diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
index 34b3a9b..0f858fd 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -32,7 +32,7 @@ static void mb_cpu_reset(CPUState *s)
     CPUMBState *env = &cpu->env;
 
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
         log_cpu_state(env, 0);
     }
 
diff --git a/target-mips/cpu.c b/target-mips/cpu.c
index 0044062..10ff46d 100644
--- a/target-mips/cpu.c
+++ b/target-mips/cpu.c
@@ -29,8 +29,16 @@ static void mips_cpu_reset(CPUState *s)
     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));
+    tlb_flush(env, 1);
+
     cpu_state_reset(env);
 }
 
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 65e6725..9a0e226 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15877,13 +15877,10 @@ MIPSCPU *cpu_mips_init(const char *cpu_model)
 
 void cpu_state_reset(CPUMIPSState *env)
 {
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
-    memset(env, 0, offsetof(CPUMIPSState, breakpoints));
-    tlb_flush(env, 1);
+#ifndef CONFIG_USER_ONLY
+    MIPSCPU *cpu = mips_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
+#endif
 
     /* Reset registers to their default values */
     env->CP0_PRid = env->cpu_model->CP0_PRid;
@@ -15952,7 +15949,7 @@ void cpu_state_reset(CPUMIPSState *env)
     env->CP0_Random = env->tlb->nb_tlb - 1;
     env->tlb->tlb_in_use = env->tlb->nb_tlb;
     env->CP0_Wired = 0;
-    env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
+    env->CP0_EBase = 0x80000000 | (cs->cpu_index & 0x3FF);
     env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
     /* vectored interrupts not implemented, timer on int 7,
        no performance counters. */
@@ -15975,13 +15972,13 @@ void cpu_state_reset(CPUMIPSState *env)
 
         /* Only TC0 on VPE 0 starts as active.  */
         for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
-            env->tcs[i].CP0_TCBind = env->cpu_index << CP0TCBd_CurVPE;
+            env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
             env->tcs[i].CP0_TCHalt = 1;
         }
         env->active_tc.CP0_TCHalt = 1;
         env->halted = 1;
 
-        if (!env->cpu_index) {
+        if (cs->cpu_index == 0) {
             /* VPE0 starts up enabled.  */
             env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
             env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
index ba35b17..56544d8 100644
--- a/target-openrisc/cpu.c
+++ b/target-openrisc/cpu.c
@@ -27,7 +27,7 @@ static void openrisc_cpu_reset(CPUState *s)
     OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu);
 
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", cpu->env.cpu_index);
+        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
         log_cpu_state(&cpu->env, 0);
     }
 
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index eb52b76..e065f30 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -766,8 +766,9 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
 
         dprintf("injected interrupt %d\n", irq);
         r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &irq);
-        if (r < 0)
-            printf("cpu %d fail inject %x\n", env->cpu_index, irq);
+        if (r < 0) {
+            printf("cpu %d fail inject %x\n", cs->cpu_index, irq);
+        }
 
         /* Always wake up soon in case the interrupt was level based */
         qemu_mod_timer(idle_timer, qemu_get_clock_ns(vm_clock) +
@@ -1238,14 +1239,15 @@ const ppc_def_t *kvmppc_host_cpu_def(void)
     return spec;
 }
 
-int kvmppc_fixup_cpu(CPUPPCState *env)
+int kvmppc_fixup_cpu(PowerPCCPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     int smt;
 
     /* Adjust cpu index for SMT */
     smt = kvmppc_smt_threads();
-    env->cpu_index = (env->cpu_index / smp_threads) * smt
-        + (env->cpu_index % smp_threads);
+    cs->cpu_index = (cs->cpu_index / smp_threads) * smt
+        + (cs->cpu_index % smp_threads);
 
     return 0;
 }
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 369c7fe..43e0e61 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -31,7 +31,7 @@ int kvmppc_reset_htab(int shift_hint);
 uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift);
 #endif /* !CONFIG_USER_ONLY */
 const ppc_def_t *kvmppc_host_cpu_def(void);
-int kvmppc_fixup_cpu(CPUPPCState *env);
+int kvmppc_fixup_cpu(PowerPCCPU *cpu);
 
 #else
 
@@ -120,7 +120,7 @@ static inline const ppc_def_t *kvmppc_host_cpu_def(void)
     return NULL;
 }
 
-static inline int kvmppc_fixup_cpu(CPUPPCState *env)
+static inline int kvmppc_fixup_cpu(PowerPCCPU *cpu)
 {
     return -1;
 }
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index e63627c..5b1d3af 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -10009,8 +10009,10 @@ static int gdb_set_spe_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int ppc_fixup_cpu(CPUPPCState *env)
+static int ppc_fixup_cpu(PowerPCCPU *cpu)
 {
+    CPUPPCState *env = &cpu->env;
+
     /* TCG doesn't (yet) emulate some groups of instructions that
      * are implemented on some otherwise supported CPUs (e.g. VSX
      * and decimal floating point instructions on POWER7).  We
@@ -10031,8 +10033,10 @@ static int ppc_fixup_cpu(CPUPPCState *env)
     return 0;
 }
 
-int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
+int cpu_ppc_register_internal(CPUPPCState *env, const ppc_def_t *def)
 {
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
     env->msr_mask = def->msr_mask;
     env->mmu_model = def->mmu_model;
     env->excp_model = def->excp_model;
@@ -10065,12 +10069,12 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
 #endif /* defined(TARGET_PPC64) */
 
     if (kvm_enabled()) {
-        if (kvmppc_fixup_cpu(env) != 0) {
+        if (kvmppc_fixup_cpu(cpu) != 0) {
             fprintf(stderr, "Unable to virtualize selected CPU with KVM\n");
             exit(1);
         }
     } else {
-        if (ppc_fixup_cpu(env) != 0) {
+        if (ppc_fixup_cpu(cpu) != 0) {
             fprintf(stderr, "Unable to emulate selected CPU with TCG\n");
             exit(1);
         }
@@ -10380,7 +10384,7 @@ static void ppc_cpu_reset(CPUState *s)
     target_ulong msr;
 
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
         log_cpu_state(env, 0);
     }
 
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index 619b202..81f4384 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -33,7 +33,7 @@ static void s390_cpu_reset(CPUState *s)
     CPUS390XState *env = &cpu->env;
 
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
         log_cpu_state(env, 0);
     }
 
diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c
index a1a177f..e4858a0 100644
--- a/target-sh4/cpu.c
+++ b/target-sh4/cpu.c
@@ -31,7 +31,7 @@ static void superh_cpu_reset(CPUState *s)
     CPUSH4State *env = &cpu->env;
 
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
         log_cpu_state(env, 0);
     }
 
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 882d306..f404aa8 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -31,7 +31,7 @@ static void sparc_cpu_reset(CPUState *s)
     CPUSPARCState *env = &cpu->env;
 
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
         log_cpu_state(env, 0);
     }
 
