All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC qom-cpu-next 0/9] QOM CPUState, part 9: CPU_COMMON for interrupts
@ 2013-02-02 11:57 Andreas Färber
  2013-02-02 11:57 ` [Qemu-devel] [PATCH for-1.4? qom-cpu-next 1/9] target-s390x: Drop unused cpu_s390x_close() prototype Andreas Färber
                   ` (8 more replies)
  0 siblings, 9 replies; 12+ messages in thread
From: Andreas Färber @ 2013-02-02 11:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Alexander Graf, Blue Swirl, Michael Walle,
	Anthony Liguori, Edgar E. Iglesias, Andreas Färber,
	Aurélien Jarno, Richard Henderson

Hello,

Most of its prerequisites in v1.4.0-rc0 or in qom-cpu-next, this series
proceeds with moving fields from CPU_COMMON / CPU*State to CPUState.

For large Coding Style cleanups it seems too late now (Hard Freeze).
But the two function declarations might be considered an acceptable cleanup.

Posting this as an RFC only since I still don't like the x86 VMState version
restrictions since quite a few people on #qemu keep using really old versions.
I hope to tackle this by inserting my WIP VMState refactorings, using X86CPU,
which can - ugly but nontheless - access CPUState::halted field for version 5.
While that change would be pretty invasive, it'll be largely mechanical.

The final two patches are the main reason for posting this already:
They demonstrate that the do_interrupt() functions can be replaced by a
CPUClass hook, while not loosing too much performance since cpu_exec() can
obtain CPUClass once and reuse it for all calls rather than calling a wrapper
that would do this per call.
The final patch showcases for arm how the hook can be overridden for models.
A further candidate is cris once CRISCPU subclasses have been introduced.

Available for testing at:
git://github.com/afaerber/qemu-cpu.git qom-cpu-9.v1
https://github.com/afaerber/qemu-cpu/commits/qom-cpu-9.v1

Regards,
Andreas

Cc: Anthony Liguori <anthony@codemonkey.ws>
Cc: Blue Swirl <blauwirbel@gmail.com>
Cc: Aurélien Jarno <aurelien@aurel32.net>

Cc: Alexander Graf <agraf@suse.de>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Michael Walle <michael@walle.cc>

Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Edgar E. Iglesias <edgar.iglesias@gmail.com>

Andreas Färber (9):
  target-s390x: Drop unused cpu_s390x_close() prototype
  target-lm32: Drop unused cpu_lm32_close() prototype
  target-cris/helper.c: Update Coding Style
  target-i386: Drop version 5 CPU VMState support
  cpu: Move halted and interrupt_request fields to CPUState
  exec: Pass CPUState to cpu_reset_interrupt()
  cpu: Pass CPUState to cpu_interrupt()
  cpu: Replace do_interrupt() by CPUClass::do_interrupt method
  target-arm: Override do_interrupt for ARMv7-M profile

 cpu-exec.c                         |   70 ++++---
 cpus.c                             |    6 +-
 exec.c                             |   19 +-
 gdbstub.c                          |    2 +-
 hw/alpha_typhoon.c                 |   18 +-
 hw/apic.c                          |   25 +--
 hw/arm_pic.c                       |   20 +-
 hw/cris_pic_cpu.c                  |   14 +-
 hw/leon3.c                         |   12 +-
 hw/lm32_boards.c                   |    9 +-
 hw/lpc_ich9.c                      |    2 +-
 hw/microblaze_pic_cpu.c            |   15 +-
 hw/milkymist.c                     |    9 +-
 hw/mips_int.c                      |   10 +-
 hw/omap1.c                         |   11 +-
 hw/openrisc_pic.c                  |    5 +-
 hw/openrisc_timer.c                |    4 +-
 hw/pc.c                            |   14 +-
 hw/pc_piix.c                       |    3 +-
 hw/ppc.c                           |   34 +--
 hw/ppc/e500.c                      |   10 +-
 hw/ppc405_uc.c                     |    4 +-
 hw/ppce500_spin.c                  |    2 +-
 hw/puv3.c                          |   10 +-
 hw/pxa2xx.c                        |    7 +-
 hw/pxa2xx_gpio.c                   |    5 +-
 hw/pxa2xx_pic.c                    |   13 +-
 hw/s390x/s390-virtio.c             |   14 +-
 hw/sh_intc.c                       |   14 +-
 hw/spapr.c                         |   10 +-
 hw/spapr_hcall.c                   |    2 +-
 hw/spapr_rtas.c                    |    6 +-
 hw/sun4m.c                         |   35 ++--
 hw/sun4u.c                         |   26 ++-
 hw/xen_machine_pv.c                |    6 +-
 hw/xtensa_pic.c                    |   12 +-
 include/exec/cpu-all.h             |   15 --
 include/exec/cpu-defs.h            |    2 -
 include/qom/cpu.h                  |   39 ++++
 kvm-all.c                          |    6 +-
 qom/cpu.c                          |    7 +
 target-alpha/cpu-qom.h             |    2 +
 target-alpha/cpu.c                 |    1 +
 target-alpha/cpu.h                 |    5 +-
 target-alpha/helper.c              |    4 +-
 target-alpha/translate.c           |    3 +-
 target-arm/cpu-qom.h               |    3 +
 target-arm/cpu.c                   |   15 +-
 target-arm/cpu.h                   |    5 +-
 target-arm/helper.c                |   23 ++-
 target-arm/op_helper.c             |    4 +-
 target-cris/cpu-qom.h              |    2 +
 target-cris/cpu.c                  |    2 +
 target-cris/cpu.h                  |    5 +-
 target-cris/helper.c               |  402 ++++++++++++++++++------------------
 target-cris/translate.c            |    3 +-
 target-i386/cpu-qom.h              |    6 +
 target-i386/cpu.c                  |    4 +-
 target-i386/cpu.h                  |   23 ++-
 target-i386/helper.c               |   18 +-
 target-i386/kvm.c                  |   50 ++---
 target-i386/machine.c              |   10 +-
 target-i386/misc_helper.c          |   21 +-
 target-i386/seg_helper.c           |    5 +-
 target-i386/svm_helper.c           |    9 +-
 target-lm32/cpu-qom.h              |    2 +
 target-lm32/cpu.c                  |    2 +
 target-lm32/cpu.h                  |    6 +-
 target-lm32/helper.c               |    5 +-
 target-lm32/op_helper.c            |    4 +-
 target-m68k/cpu-qom.h              |    2 +
 target-m68k/cpu.c                  |    1 +
 target-m68k/cpu.h                  |    5 +-
 target-m68k/helper.c               |   10 +-
 target-m68k/op_helper.c            |   14 +-
 target-m68k/qregs.def              |    1 -
 target-m68k/translate.c            |    8 +-
 target-microblaze/cpu-qom.h        |    2 +
 target-microblaze/cpu.c            |    1 +
 target-microblaze/cpu.h            |    5 +-
 target-microblaze/helper.c         |    9 +-
 target-mips/cpu-qom.h              |    2 +
 target-mips/cpu.c                  |    2 +
 target-mips/cpu.h                  |    5 +-
 target-mips/helper.c               |    5 +-
 target-mips/op_helper.c            |   23 ++-
 target-mips/translate.c            |    4 +-
 target-openrisc/cpu.c              |    1 +
 target-openrisc/cpu.h              |    6 +-
 target-openrisc/interrupt.c        |    4 +-
 target-openrisc/interrupt_helper.c |    3 +-
 target-openrisc/sys_helper.c       |    3 +-
 target-ppc/cpu-qom.h               |    2 +
 target-ppc/cpu.h                   |    6 +-
 target-ppc/excp_helper.c           |   34 ++-
 target-ppc/helper_regs.h           |   11 +-
 target-ppc/kvm.c                   |   16 +-
 target-ppc/translate.c             |    3 +-
 target-ppc/translate_init.c        |    1 +
 target-s390x/cpu-qom.h             |    2 +
 target-s390x/cpu.c                 |    9 +-
 target-s390x/cpu.h                 |   13 +-
 target-s390x/helper.c              |   19 +-
 target-sh4/cpu-qom.h               |    2 +
 target-sh4/cpu.c                   |    1 +
 target-sh4/cpu.h                   |    5 +-
 target-sh4/helper.c                |   13 +-
 target-sh4/op_helper.c             |    4 +-
 target-sparc/cpu-qom.h             |    2 +
 target-sparc/cpu.c                 |    2 +
 target-sparc/cpu.h                 |    6 +-
 target-sparc/int32_helper.c        |    4 +-
 target-sparc/int64_helper.c        |    4 +-
 target-unicore32/cpu-qom.h         |    2 +
 target-unicore32/cpu.c             |    1 +
 target-unicore32/cpu.h             |    5 +-
 target-unicore32/helper.c          |    5 +-
 target-unicore32/softmmu.c         |    6 +-
 target-xtensa/cpu-qom.h            |    2 +
 target-xtensa/cpu.c                |    1 +
 target-xtensa/cpu.h                |    1 -
 target-xtensa/helper.c             |    5 +-
 target-xtensa/op_helper.c          |    5 +-
 translate-all.c                    |   18 +-
 xen-all.c                          |   10 +-
 125 Dateien geändert, 882 Zeilen hinzugefügt(+), 645 Zeilen entfernt(-)

-- 
1.7.10.4

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

* [Qemu-devel] [PATCH for-1.4? qom-cpu-next 1/9] target-s390x: Drop unused cpu_s390x_close() prototype
  2013-02-02 11:57 [Qemu-devel] [RFC qom-cpu-next 0/9] QOM CPUState, part 9: CPU_COMMON for interrupts Andreas Färber
@ 2013-02-02 11:57 ` Andreas Färber
  2013-02-02 11:57 ` [Qemu-devel] [PATCH for-1.4? qom-cpu-next 2/9] target-lm32: Drop unused cpu_lm32_close() prototype Andreas Färber
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Andreas Färber @ 2013-02-02 11:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Alexander Graf, Andreas Färber, Richard Henderson

It was never implemented.

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 target-s390x/cpu.h |    1 -
 1 Datei geändert, 1 Zeile entfernt(-)

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 01e59b9..0070c40 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -315,7 +315,6 @@ static inline int get_ilen(uint8_t opc)
 S390CPU *cpu_s390x_init(const char *cpu_model);
 void s390x_translate_init(void);
 int cpu_s390x_exec(CPUS390XState *s);
-void cpu_s390x_close(CPUS390XState *s);
 void do_interrupt (CPUS390XState *env);
 
 /* you can call this signal handler from your SIGBUS and SIGSEGV
-- 
1.7.10.4

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

* [Qemu-devel] [PATCH for-1.4? qom-cpu-next 2/9] target-lm32: Drop unused cpu_lm32_close() prototype
  2013-02-02 11:57 [Qemu-devel] [RFC qom-cpu-next 0/9] QOM CPUState, part 9: CPU_COMMON for interrupts Andreas Färber
  2013-02-02 11:57 ` [Qemu-devel] [PATCH for-1.4? qom-cpu-next 1/9] target-s390x: Drop unused cpu_s390x_close() prototype Andreas Färber
@ 2013-02-02 11:57 ` Andreas Färber
  2013-02-02 11:57 ` [Qemu-devel] [PATCH RESEND qom-cpu-next 3/9] target-cris/helper.c: Update Coding Style Andreas Färber
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Andreas Färber @ 2013-02-02 11:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Walle, Andreas Färber

It was never implemented.

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 target-lm32/cpu.h |    1 -
 1 Datei geändert, 1 Zeile entfernt(-)

diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index 4e202db..6948d0e 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -189,7 +189,6 @@ struct CPULM32State {
 LM32CPU *cpu_lm32_init(const char *cpu_model);
 void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf);
 int cpu_lm32_exec(CPULM32State *s);
-void cpu_lm32_close(CPULM32State *s);
 void do_interrupt(CPULM32State *env);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
-- 
1.7.10.4

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

* [Qemu-devel] [PATCH RESEND qom-cpu-next 3/9] target-cris/helper.c: Update Coding Style
  2013-02-02 11:57 [Qemu-devel] [RFC qom-cpu-next 0/9] QOM CPUState, part 9: CPU_COMMON for interrupts Andreas Färber
  2013-02-02 11:57 ` [Qemu-devel] [PATCH for-1.4? qom-cpu-next 1/9] target-s390x: Drop unused cpu_s390x_close() prototype Andreas Färber
  2013-02-02 11:57 ` [Qemu-devel] [PATCH for-1.4? qom-cpu-next 2/9] target-lm32: Drop unused cpu_lm32_close() prototype Andreas Färber
@ 2013-02-02 11:57 ` Andreas Färber
  2013-02-02 11:57 ` [Qemu-devel] [RFC qom-cpu-next 4/9] target-i386: Drop version 5 CPU VMState support Andreas Färber
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Andreas Färber @ 2013-02-02 11:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Edgar E. Iglesias, Andreas Färber

Reindent, add missing braces and drop/adjust whitespace.

Prepares for CPUArchState-to-CPUState field movements in
cpu_cris_handle_mmu_fault(), do_interruptv10() and do_interrupt().
The remaining functions were so minor that they can be fixed in one go.

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 target-cris/helper.c |  393 +++++++++++++++++++++++++-------------------------
 1 Datei geändert, 196 Zeilen hinzugefügt(+), 197 Zeilen entfernt(-)

diff --git a/target-cris/helper.c b/target-cris/helper.c
index 6e75e98..de04143 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -36,19 +36,19 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt (CPUCRISState *env)
+void do_interrupt(CPUCRISState *env)
 {
-	env->exception_index = -1;
-	env->pregs[PR_ERP] = env->pc;
+    env->exception_index = -1;
+    env->pregs[PR_ERP] = env->pc;
 }
 
 int cpu_cris_handle_mmu_fault(CPUCRISState * env, target_ulong address, int rw,
                               int mmu_idx)
 {
-	env->exception_index = 0xaa;
-	env->pregs[PR_EDA] = address;
-	cpu_dump_state(env, stderr, fprintf, 0);
-	return 1;
+    env->exception_index = 0xaa;
+    env->pregs[PR_EDA] = address;
+    cpu_dump_state(env, stderr, fprintf, 0);
+    return 1;
 }
 
 #else /* !CONFIG_USER_ONLY */
@@ -56,211 +56,210 @@ int cpu_cris_handle_mmu_fault(CPUCRISState * env, target_ulong address, int rw,
 
 static void cris_shift_ccs(CPUCRISState *env)
 {
-	uint32_t ccs;
-	/* Apply the ccs shift.  */
-	ccs = env->pregs[PR_CCS];
-	ccs = ((ccs & 0xc0000000) | ((ccs << 12) >> 2)) & ~0x3ff;
-	env->pregs[PR_CCS] = ccs;
+    uint32_t ccs;
+    /* Apply the ccs shift.  */
+    ccs = env->pregs[PR_CCS];
+    ccs = ((ccs & 0xc0000000) | ((ccs << 12) >> 2)) & ~0x3ff;
+    env->pregs[PR_CCS] = ccs;
 }
 
-int cpu_cris_handle_mmu_fault (CPUCRISState *env, target_ulong address, int rw,
-                               int mmu_idx)
+int cpu_cris_handle_mmu_fault(CPUCRISState *env, target_ulong address, int rw,
+                              int mmu_idx)
 {
-	struct cris_mmu_result res;
-	int prot, miss;
-	int r = -1;
-	target_ulong phy;
-
-	D(printf ("%s addr=%x pc=%x rw=%x\n", __func__, address, env->pc, rw));
-	miss = cris_mmu_translate(&res, env, address & TARGET_PAGE_MASK,
-				  rw, mmu_idx, 0);
-	if (miss)
-	{
-		if (env->exception_index == EXCP_BUSFAULT)
-			cpu_abort(env,
-				  "CRIS: Illegal recursive bus fault."
-				 "addr=%x rw=%d\n",
-				 address, rw);
-
-		env->pregs[PR_EDA] = address;
-		env->exception_index = EXCP_BUSFAULT;
-		env->fault_vector = res.bf_vec;
-		r = 1;
-	}
-	else
-	{
-		/*
-		 * Mask off the cache selection bit. The ETRAX busses do not
-		 * see the top bit.
-		 */
-		phy = res.phy & ~0x80000000;
-		prot = res.prot;
-		tlb_set_page(env, address & TARGET_PAGE_MASK, phy,
-                             prot, mmu_idx, TARGET_PAGE_SIZE);
-                r = 0;
-	}
-	if (r > 0)
-            D_LOG("%s returns %d irqreq=%x addr=%x phy=%x vec=%x pc=%x\n",
-                  __func__, r, env->interrupt_request, address, res.phy,
-                  res.bf_vec, env->pc);
-	return r;
+    struct cris_mmu_result res;
+    int prot, miss;
+    int r = -1;
+    target_ulong phy;
+
+    D(printf("%s addr=%x pc=%x rw=%x\n", __func__, address, env->pc, rw));
+    miss = cris_mmu_translate(&res, env, address & TARGET_PAGE_MASK,
+                              rw, mmu_idx, 0);
+    if (miss) {
+        if (env->exception_index == EXCP_BUSFAULT) {
+            cpu_abort(env,
+                      "CRIS: Illegal recursive bus fault."
+                      "addr=%x rw=%d\n",
+                      address, rw);
+        }
+
+        env->pregs[PR_EDA] = address;
+        env->exception_index = EXCP_BUSFAULT;
+        env->fault_vector = res.bf_vec;
+        r = 1;
+    } else {
+        /*
+         * Mask off the cache selection bit. The ETRAX busses do not
+         * see the top bit.
+         */
+        phy = res.phy & ~0x80000000;
+        prot = res.prot;
+        tlb_set_page(env, address & TARGET_PAGE_MASK, phy,
+                     prot, mmu_idx, TARGET_PAGE_SIZE);
+        r = 0;
+    }
+    if (r > 0) {
+        D_LOG("%s returns %d irqreq=%x addr=%x phy=%x vec=%x pc=%x\n",
+              __func__, r, env->interrupt_request, address, res.phy,
+              res.bf_vec, env->pc);
+    }
+    return r;
 }
 
 static void do_interruptv10(CPUCRISState *env)
 {
-	int ex_vec = -1;
-
-	D_LOG( "exception index=%d interrupt_req=%d\n",
-		   env->exception_index,
-		   env->interrupt_request);
-
-	assert(!(env->pregs[PR_CCS] & PFIX_FLAG));
-	switch (env->exception_index)
-	{
-		case EXCP_BREAK:
-			/* These exceptions are genereated by the core itself.
-			   ERP should point to the insn following the brk.  */
-			ex_vec = env->trap_vector;
-			env->pregs[PRV10_BRP] = env->pc;
-			break;
-
-		case EXCP_NMI:
-			/* NMI is hardwired to vector zero.  */
-			ex_vec = 0;
-			env->pregs[PR_CCS] &= ~M_FLAG_V10;
-			env->pregs[PRV10_BRP] = env->pc;
-			break;
-
-		case EXCP_BUSFAULT:
-                        cpu_abort(env, "Unhandled busfault");
-			break;
-
-		default:
-			/* The interrupt controller gives us the vector.  */
-			ex_vec = env->interrupt_vector;
-			/* Normal interrupts are taken between
-			   TB's.  env->pc is valid here.  */
-			env->pregs[PR_ERP] = env->pc;
-			break;
-	}
-
-	if (env->pregs[PR_CCS] & U_FLAG) {
-		/* Swap stack pointers.  */
-		env->pregs[PR_USP] = env->regs[R_SP];
-		env->regs[R_SP] = env->ksp;
-	}
-
-	/* Now that we are in kernel mode, load the handlers address.  */
-        env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
-	env->locked_irq = 1;
-	env->pregs[PR_CCS] |= F_FLAG_V10; /* set F.  */
-
-	qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n", 
-		      __func__, env->pc, ex_vec, 
-		      env->pregs[PR_CCS],
-		      env->pregs[PR_PID], 
-		      env->pregs[PR_ERP]);
+    int ex_vec = -1;
+
+    D_LOG("exception index=%d interrupt_req=%d\n",
+          env->exception_index,
+          env->interrupt_request);
+
+    assert(!(env->pregs[PR_CCS] & PFIX_FLAG));
+    switch (env->exception_index) {
+    case EXCP_BREAK:
+        /* These exceptions are genereated by the core itself.
+           ERP should point to the insn following the brk.  */
+        ex_vec = env->trap_vector;
+        env->pregs[PRV10_BRP] = env->pc;
+        break;
+
+    case EXCP_NMI:
+        /* NMI is hardwired to vector zero.  */
+        ex_vec = 0;
+        env->pregs[PR_CCS] &= ~M_FLAG_V10;
+        env->pregs[PRV10_BRP] = env->pc;
+        break;
+
+    case EXCP_BUSFAULT:
+        cpu_abort(env, "Unhandled busfault");
+        break;
+
+    default:
+        /* The interrupt controller gives us the vector.  */
+        ex_vec = env->interrupt_vector;
+        /* Normal interrupts are taken between
+           TB's.  env->pc is valid here.  */
+        env->pregs[PR_ERP] = env->pc;
+        break;
+    }
+
+    if (env->pregs[PR_CCS] & U_FLAG) {
+        /* Swap stack pointers.  */
+        env->pregs[PR_USP] = env->regs[R_SP];
+        env->regs[R_SP] = env->ksp;
+    }
+
+    /* Now that we are in kernel mode, load the handlers address.  */
+    env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
+    env->locked_irq = 1;
+    env->pregs[PR_CCS] |= F_FLAG_V10; /* set F.  */
+
+    qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
+                  __func__, env->pc, ex_vec,
+                  env->pregs[PR_CCS],
+                  env->pregs[PR_PID],
+                  env->pregs[PR_ERP]);
 }
 
 void do_interrupt(CPUCRISState *env)
 {
-	int ex_vec = -1;
-
-	if (env->pregs[PR_VR] < 32)
-		return do_interruptv10(env);
-
-	D_LOG( "exception index=%d interrupt_req=%d\n",
-		   env->exception_index,
-		   env->interrupt_request);
-
-	switch (env->exception_index)
-	{
-		case EXCP_BREAK:
-			/* These exceptions are genereated by the core itself.
-			   ERP should point to the insn following the brk.  */
-			ex_vec = env->trap_vector;
-			env->pregs[PR_ERP] = env->pc;
-			break;
-
-		case EXCP_NMI:
-			/* NMI is hardwired to vector zero.  */
-			ex_vec = 0;
-			env->pregs[PR_CCS] &= ~M_FLAG_V32;
-			env->pregs[PR_NRP] = env->pc;
-			break;
-
-		case EXCP_BUSFAULT:
-			ex_vec = env->fault_vector;
-			env->pregs[PR_ERP] = env->pc;
-			break;
-
-		default:
-			/* The interrupt controller gives us the vector.  */
-			ex_vec = env->interrupt_vector;
-			/* Normal interrupts are taken between
-			   TB's.  env->pc is valid here.  */
-			env->pregs[PR_ERP] = env->pc;
-			break;
-	}
-
-	/* Fill in the IDX field.  */
-	env->pregs[PR_EXS] = (ex_vec & 0xff) << 8;
-
-	if (env->dslot) {
-		D_LOG("excp isr=%x PC=%x ds=%d SP=%x"
-			  " ERP=%x pid=%x ccs=%x cc=%d %x\n",
-			  ex_vec, env->pc, env->dslot,
-			  env->regs[R_SP],
-			  env->pregs[PR_ERP], env->pregs[PR_PID],
-			  env->pregs[PR_CCS],
-			  env->cc_op, env->cc_mask);
-		/* We loose the btarget, btaken state here so rexec the
-		   branch.  */
-		env->pregs[PR_ERP] -= env->dslot;
-		/* Exception starts with dslot cleared.  */
-		env->dslot = 0;
-	}
+    int ex_vec = -1;
+
+    if (env->pregs[PR_VR] < 32) {
+        return do_interruptv10(env);
+    }
+
+    D_LOG("exception index=%d interrupt_req=%d\n",
+          env->exception_index,
+          env->interrupt_request);
+
+    switch (env->exception_index) {
+    case EXCP_BREAK:
+        /* These exceptions are genereated by the core itself.
+           ERP should point to the insn following the brk.  */
+        ex_vec = env->trap_vector;
+        env->pregs[PR_ERP] = env->pc;
+        break;
+
+    case EXCP_NMI:
+        /* NMI is hardwired to vector zero.  */
+        ex_vec = 0;
+        env->pregs[PR_CCS] &= ~M_FLAG_V32;
+        env->pregs[PR_NRP] = env->pc;
+        break;
+
+    case EXCP_BUSFAULT:
+        ex_vec = env->fault_vector;
+        env->pregs[PR_ERP] = env->pc;
+        break;
+
+    default:
+        /* The interrupt controller gives us the vector.  */
+        ex_vec = env->interrupt_vector;
+        /* Normal interrupts are taken between
+           TB's.  env->pc is valid here.  */
+        env->pregs[PR_ERP] = env->pc;
+        break;
+    }
+
+    /* Fill in the IDX field.  */
+    env->pregs[PR_EXS] = (ex_vec & 0xff) << 8;
+
+    if (env->dslot) {
+        D_LOG("excp isr=%x PC=%x ds=%d SP=%x"
+              " ERP=%x pid=%x ccs=%x cc=%d %x\n",
+              ex_vec, env->pc, env->dslot,
+              env->regs[R_SP],
+              env->pregs[PR_ERP], env->pregs[PR_PID],
+              env->pregs[PR_CCS],
+              env->cc_op, env->cc_mask);
+        /* We loose the btarget, btaken state here so rexec the
+           branch.  */
+        env->pregs[PR_ERP] -= env->dslot;
+        /* Exception starts with dslot cleared.  */
+        env->dslot = 0;
+    }
 	
-	if (env->pregs[PR_CCS] & U_FLAG) {
-		/* Swap stack pointers.  */
-		env->pregs[PR_USP] = env->regs[R_SP];
-		env->regs[R_SP] = env->ksp;
-	}
-
-	/* Apply the CRIS CCS shift. Clears U if set.  */
-	cris_shift_ccs(env);
-
-	/* Now that we are in kernel mode, load the handlers address.
-	   This load may not fault, real hw leaves that behaviour as
-	   undefined.  */
-        env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
-
-	/* Clear the excption_index to avoid spurios hw_aborts for recursive
-	   bus faults.  */
-	env->exception_index = -1;
-
-	D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
-		   __func__, env->pc, ex_vec,
-		   env->pregs[PR_CCS],
-		   env->pregs[PR_PID], 
-		   env->pregs[PR_ERP]);
+    if (env->pregs[PR_CCS] & U_FLAG) {
+        /* Swap stack pointers.  */
+        env->pregs[PR_USP] = env->regs[R_SP];
+        env->regs[R_SP] = env->ksp;
+    }
+
+    /* Apply the CRIS CCS shift. Clears U if set.  */
+    cris_shift_ccs(env);
+
+    /* Now that we are in kernel mode, load the handlers address.
+       This load may not fault, real hw leaves that behaviour as
+       undefined.  */
+    env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
+
+    /* Clear the excption_index to avoid spurios hw_aborts for recursive
+       bus faults.  */
+    env->exception_index = -1;
+
+    D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
+          __func__, env->pc, ex_vec,
+          env->pregs[PR_CCS],
+          env->pregs[PR_PID],
+          env->pregs[PR_ERP]);
 }
 
 hwaddr cpu_get_phys_page_debug(CPUCRISState * env, target_ulong addr)
 {
-	uint32_t phy = addr;
-	struct cris_mmu_result res;
-	int miss;
-
-	miss = cris_mmu_translate(&res, env, addr, 0, 0, 1);
-	/* If D TLB misses, try I TLB.  */
-	if (miss) {
-		miss = cris_mmu_translate(&res, env, addr, 2, 0, 1);
-	}
-
-	if (!miss)
-		phy = res.phy;
-	D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy));
-	return phy;
+    uint32_t phy = addr;
+    struct cris_mmu_result res;
+    int miss;
+
+    miss = cris_mmu_translate(&res, env, addr, 0, 0, 1);
+    /* If D TLB misses, try I TLB.  */
+    if (miss) {
+        miss = cris_mmu_translate(&res, env, addr, 2, 0, 1);
+    }
+
+    if (!miss) {
+        phy = res.phy;
+    }
+    D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy));
+    return phy;
 }
 #endif
-- 
1.7.10.4

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

* [Qemu-devel] [RFC qom-cpu-next 4/9] target-i386: Drop version 5 CPU VMState support
  2013-02-02 11:57 [Qemu-devel] [RFC qom-cpu-next 0/9] QOM CPUState, part 9: CPU_COMMON for interrupts Andreas Färber
                   ` (2 preceding siblings ...)
  2013-02-02 11:57 ` [Qemu-devel] [PATCH RESEND qom-cpu-next 3/9] target-cris/helper.c: Update Coding Style Andreas Färber
@ 2013-02-02 11:57 ` Andreas Färber
  2013-02-02 11:57   ` [Qemu-devel] " Andreas Färber
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Andreas Färber @ 2013-02-02 11:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Färber

Version 5 contained the halted field, that we are about to move from
CPUX86State to CPUState. To avoid inventing new VMSTATE macros for
calculating a negative offset from CPUX86State to the field in CPUState,
rather bump the minimum version from 3 to 6. We're at 12 currently.

Suggested-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
Reviewed-by: Juan Quintela <quintela@redhat.com>
---
 target-i386/machine.c |   10 ++--------
 1 Datei geändert, 2 Zeilen hinzugefügt(+), 8 Zeilen entfernt(-)

diff --git a/target-i386/machine.c b/target-i386/machine.c
index 8df6a6b..e154646 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -201,11 +201,6 @@ static bool fpregs_is_1_no_mmx(void *opaque, int version_id)
     VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_1_mmx, vmstate_fpreg_1_mmx, FPReg), \
     VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_1_no_mmx, vmstate_fpreg_1_no_mmx, FPReg)
 
-static bool version_is_5(void *opaque, int version_id)
-{
-    return version_id == 5;
-}
-
 #ifdef TARGET_X86_64
 static bool less_than_7(void *opaque, int version_id)
 {
@@ -386,8 +381,8 @@ static const VMStateDescription vmstate_msr_ia32_misc_enable = {
 static const VMStateDescription vmstate_cpu = {
     .name = "cpu",
     .version_id = CPU_SAVE_VERSION,
-    .minimum_version_id = 3,
-    .minimum_version_id_old = 3,
+    .minimum_version_id = 6,
+    .minimum_version_id_old = 6,
     .pre_save = cpu_pre_save,
     .post_load = cpu_post_load,
     .fields      = (VMStateField []) {
@@ -444,7 +439,6 @@ static const VMStateDescription vmstate_cpu = {
         VMSTATE_UINT64_V(pat, CPUX86State, 5),
         VMSTATE_UINT32_V(hflags2, CPUX86State, 5),
 
-        VMSTATE_UINT32_TEST(halted, CPUX86State, version_is_5),
         VMSTATE_UINT64_V(vm_hsave, CPUX86State, 5),
         VMSTATE_UINT64_V(vm_vmcb, CPUX86State, 5),
         VMSTATE_UINT64_V(tsc_offset, CPUX86State, 5),
-- 
1.7.10.4

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

* [RFC qom-cpu-next 5/9] cpu: Move halted and interrupt_request fields to CPUState
  2013-02-02 11:57 [Qemu-devel] [RFC qom-cpu-next 0/9] QOM CPUState, part 9: CPU_COMMON for interrupts Andreas Färber
@ 2013-02-02 11:57   ` Andreas Färber
  2013-02-02 11:57 ` [Qemu-devel] [PATCH for-1.4? qom-cpu-next 2/9] target-lm32: Drop unused cpu_lm32_close() prototype Andreas Färber
                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Andreas Färber @ 2013-02-02 11:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Guan Xuetao, open list:Overall, Gleb Natapov,
	Stefano Stabellini, Marcelo Tosatti, Alexander Graf,
	Fabien Chouteau, Blue Swirl, Max Filippov, Michael Walle,
	open list:X86, open list:e500, Paul Brook, Scott Wood,
	Edgar E. Iglesias, Richard Henderson, Andreas Färber,
	Aurelien Jarno, David Gibson

Both fields are used in VMState, thus need to be moved together.
Explicitly zero them on reset since they were located before
breakpoints.

Pass PowerPCCPU to kvmppc_handle_halt().

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 cpu-exec.c                         |   34 ++++++++++++------------
 cpus.c                             |    4 +--
 exec.c                             |   16 +++++++-----
 gdbstub.c                          |    2 +-
 hw/leon3.c                         |    5 ++--
 hw/omap1.c                         |    7 +++--
 hw/openrisc_timer.c                |    4 ++-
 hw/ppc.c                           |   22 ++++++++++------
 hw/ppc/e500.c                      |   10 +++++---
 hw/ppce500_spin.c                  |    2 +-
 hw/pxa2xx_gpio.c                   |    3 ++-
 hw/pxa2xx_pic.c                    |    3 ++-
 hw/s390x/s390-virtio.c             |   14 ++++++----
 hw/spapr.c                         |   10 +++++---
 hw/spapr_hcall.c                   |    2 +-
 hw/spapr_rtas.c                    |    6 ++---
 hw/sun4m.c                         |   21 ++++++++-------
 hw/sun4u.c                         |   15 +++++++----
 hw/xen_machine_pv.c                |    6 ++---
 hw/xtensa_pic.c                    |    8 +++---
 include/exec/cpu-defs.h            |    2 --
 include/qom/cpu.h                  |    4 +++
 kvm-all.c                          |    2 +-
 qom/cpu.c                          |    2 ++
 target-alpha/cpu.h                 |    4 +--
 target-alpha/translate.c           |    3 ++-
 target-arm/cpu.h                   |    4 +--
 target-arm/helper.c                |    4 ++-
 target-arm/op_helper.c             |    4 ++-
 target-cris/cpu.h                  |    4 +--
 target-cris/helper.c               |    9 ++++---
 target-cris/translate.c            |    3 ++-
 target-i386/cpu.c                  |    2 +-
 target-i386/cpu.h                  |   20 ++++++++-------
 target-i386/helper.c               |   12 +++++----
 target-i386/kvm.c                  |   50 +++++++++++++++++++-----------------
 target-i386/misc_helper.c          |   21 ++++++++++-----
 target-i386/svm_helper.c           |    9 ++++---
 target-lm32/cpu.h                  |    4 +--
 target-lm32/op_helper.c            |    4 ++-
 target-m68k/cpu.h                  |    4 +--
 target-m68k/op_helper.c            |    4 ++-
 target-m68k/qregs.def              |    1 -
 target-m68k/translate.c            |    8 +++++-
 target-microblaze/cpu.h            |    4 +--
 target-mips/cpu.h                  |    4 +--
 target-mips/op_helper.c            |   10 +++++---
 target-mips/translate.c            |    4 +--
 target-openrisc/cpu.h              |    4 +--
 target-openrisc/interrupt_helper.c |    3 ++-
 target-openrisc/sys_helper.c       |    3 ++-
 target-ppc/cpu.h                   |    5 ++--
 target-ppc/excp_helper.c           |   22 +++++++++++-----
 target-ppc/helper_regs.h           |   11 +++++---
 target-ppc/kvm.c                   |   16 +++++++-----
 target-ppc/translate.c             |    3 ++-
 target-s390x/cpu.c                 |    8 +++---
 target-s390x/cpu.h                 |    5 ++--
 target-s390x/helper.c              |    7 +++--
 target-sh4/cpu.h                   |    4 +--
 target-sh4/helper.c                |    5 ++--
 target-sh4/op_helper.c             |    4 ++-
 target-sparc/cpu.h                 |    5 ++--
 target-unicore32/cpu.h             |    4 +--
 target-unicore32/softmmu.c         |    3 ++-
 target-xtensa/op_helper.c          |    5 +++-
 translate-all.c                    |   10 ++++----
 xen-all.c                          |   10 +++++---
 68 Dateien geändert, 315 Zeilen hinzugefügt(+), 222 Zeilen entfernt(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index 83ddea4..191a19b 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -190,12 +190,12 @@ int cpu_exec(CPUArchState *env)
     uint8_t *tc_ptr;
     tcg_target_ulong next_tb;
 
-    if (env->halted) {
+    if (cpu->halted) {
         if (!cpu_has_work(cpu)) {
             return EXCP_HALTED;
         }
 
-        env->halted = 0;
+        cpu->halted = 0;
     }
 
     cpu_single_env = env;
@@ -265,14 +265,14 @@ int cpu_exec(CPUArchState *env)
 
             next_tb = 0; /* force lookup of first TB */
             for(;;) {
-                interrupt_request = env->interrupt_request;
+                interrupt_request = cpu->interrupt_request;
                 if (unlikely(interrupt_request)) {
                     if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
                         /* Mask out external interrupts for this step. */
                         interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
                     }
                     if (interrupt_request & CPU_INTERRUPT_DEBUG) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
+                        cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
                         env->exception_index = EXCP_DEBUG;
                         cpu_loop_exit(env);
                     }
@@ -280,8 +280,8 @@ int cpu_exec(CPUArchState *env)
     defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
     defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
                     if (interrupt_request & CPU_INTERRUPT_HALT) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
-                        env->halted = 1;
+                        cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
+                        cpu->halted = 1;
                         env->exception_index = EXCP_HLT;
                         cpu_loop_exit(env);
                     }
@@ -289,7 +289,7 @@ int cpu_exec(CPUArchState *env)
 #if defined(TARGET_I386)
 #if !defined(CONFIG_USER_ONLY)
                     if (interrupt_request & CPU_INTERRUPT_POLL) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_POLL;
+                        cpu->interrupt_request &= ~CPU_INTERRUPT_POLL;
                         apic_poll_irq(env->apic_state);
                     }
 #endif
@@ -306,17 +306,17 @@ int cpu_exec(CPUArchState *env)
                             !(env->hflags & HF_SMM_MASK)) {
                             cpu_svm_check_intercept_param(env, SVM_EXIT_SMI,
                                                           0);
-                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
+                            cpu->interrupt_request &= ~CPU_INTERRUPT_SMI;
                             do_smm_enter(env);
                             next_tb = 0;
                         } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
                                    !(env->hflags2 & HF2_NMI_MASK)) {
-                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
+                            cpu->interrupt_request &= ~CPU_INTERRUPT_NMI;
                             env->hflags2 |= HF2_NMI_MASK;
                             do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
                             next_tb = 0;
                         } else if (interrupt_request & CPU_INTERRUPT_MCE) {
-                            env->interrupt_request &= ~CPU_INTERRUPT_MCE;
+                            cpu->interrupt_request &= ~CPU_INTERRUPT_MCE;
                             do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
                             next_tb = 0;
                         } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
@@ -328,7 +328,8 @@ int cpu_exec(CPUArchState *env)
                             int intno;
                             cpu_svm_check_intercept_param(env, SVM_EXIT_INTR,
                                                           0);
-                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
+                            cpu->interrupt_request &= ~(CPU_INTERRUPT_HARD |
+                                                        CPU_INTERRUPT_VIRQ);
                             intno = cpu_get_pic_interrupt(env);
                             qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
                             do_interrupt_x86_hardirq(env, intno, 1);
@@ -346,7 +347,7 @@ int cpu_exec(CPUArchState *env)
                             intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
                             qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
                             do_interrupt_x86_hardirq(env, intno, 1);
-                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
+                            cpu->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
                             next_tb = 0;
 #endif
                         }
@@ -357,8 +358,9 @@ int cpu_exec(CPUArchState *env)
                     }
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
                         ppc_hw_interrupt(env);
-                        if (env->pending_interrupts == 0)
-                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+                        if (env->pending_interrupts == 0) {
+                            cpu->interrupt_request &= ~CPU_INTERRUPT_HARD;
+                        }
                         next_tb = 0;
                     }
 #elif defined(TARGET_LM32)
@@ -535,8 +537,8 @@ int cpu_exec(CPUArchState *env)
 #endif
                    /* Don't use the cached interrupt_request value,
                       do_interrupt may have updated the EXITTB flag. */
-                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
+                    if (cpu->interrupt_request & CPU_INTERRUPT_EXITTB) {
+                        cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
                         /* ensure that no TB jump will be modified as
                            the program flow was changed */
                         next_tb = 0;
diff --git a/cpus.c b/cpus.c
index 41779eb..8b5f426 100644
--- a/cpus.c
+++ b/cpus.c
@@ -72,7 +72,7 @@ static bool cpu_thread_is_idle(CPUArchState *env)
     if (cpu->stopped || !runstate_is_running()) {
         return true;
     }
-    if (!env->halted || qemu_cpu_has_work(cpu) ||
+    if (!cpu->halted || qemu_cpu_has_work(cpu) ||
         kvm_async_interrupts_enabled()) {
         return false;
     }
@@ -1219,7 +1219,7 @@ CpuInfoList *qmp_query_cpus(Error **errp)
         info->value = g_malloc0(sizeof(*info->value));
         info->value->CPU = cpu->cpu_index;
         info->value->current = (env == first_cpu);
-        info->value->halted = env->halted;
+        info->value->halted = cpu->halted;
         info->value->thread_id = cpu->thread_id;
 #if defined(TARGET_I386)
         info->value->has_pc = true;
diff --git a/exec.c b/exec.c
index a41bcb8..5ab7af4 100644
--- a/exec.c
+++ b/exec.c
@@ -223,12 +223,12 @@ void cpu_exec_init_all(void)
 
 static int cpu_common_post_load(void *opaque, int version_id)
 {
-    CPUArchState *env = opaque;
+    CPUState *cpu = opaque;
 
     /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
        version_id is increased. */
-    env->interrupt_request &= ~0x01;
-    tlb_flush(env, 1);
+    cpu->interrupt_request &= ~0x01;
+    tlb_flush(cpu->env_ptr, 1);
 
     return 0;
 }
@@ -240,8 +240,8 @@ static const VMStateDescription vmstate_cpu_common = {
     .minimum_version_id_old = 1,
     .post_load = cpu_common_post_load,
     .fields      = (VMStateField []) {
-        VMSTATE_UINT32(halted, CPUArchState),
-        VMSTATE_UINT32(interrupt_request, CPUArchState),
+        VMSTATE_UINT32(halted, CPUState),
+        VMSTATE_UINT32(interrupt_request, CPUState),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -291,7 +291,7 @@ void cpu_exec_init(CPUArchState *env)
     cpu_list_unlock();
 #endif
 #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
-    vmstate_register(NULL, cpu_index, &vmstate_cpu_common, env);
+    vmstate_register(NULL, cpu_index, &vmstate_cpu_common, cpu);
     register_savevm(NULL, "cpu", cpu_index, CPU_SAVE_VERSION,
                     cpu_save, cpu_load, env);
 #endif
@@ -487,7 +487,9 @@ void cpu_single_step(CPUArchState *env, int enabled)
 
 void cpu_reset_interrupt(CPUArchState *env, int mask)
 {
-    env->interrupt_request &= ~mask;
+    CPUState *cpu = ENV_GET_CPU(env);
+
+    cpu->interrupt_request &= ~mask;
 }
 
 void cpu_exit(CPUArchState *env)
diff --git a/gdbstub.c b/gdbstub.c
index 32dfea9..846de1c 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2408,7 +2408,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
                 cpu_synchronize_state(env);
                 len = snprintf((char *)mem_buf, sizeof(mem_buf),
                                "CPU#%d [%s]", cpu->cpu_index,
-                               env->halted ? "halted " : "running");
+                               cpu->halted ? "halted " : "running");
                 memtohex(buf, mem_buf, len);
                 put_packet(s, buf);
             }
diff --git a/hw/leon3.c b/hw/leon3.c
index f16a8bb..e971d5c 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -49,11 +49,12 @@ typedef struct ResetData {
 static void main_cpu_reset(void *opaque)
 {
     ResetData *s   = (ResetData *)opaque;
+    CPUState *cpu = CPU(s->cpu);
     CPUSPARCState  *env = &s->cpu->env;
 
-    cpu_reset(CPU(s->cpu));
+    cpu_reset(cpu);
 
-    env->halted = 0;
+    cpu->halted = 0;
     env->pc     = s->entry;
     env->npc    = s->entry + 4;
 }
diff --git a/hw/omap1.c b/hw/omap1.c
index 623b101..c36a330 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -1721,6 +1721,7 @@ static uint64_t omap_clkdsp_read(void *opaque, hwaddr addr,
                                  unsigned size)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    CPUState *cpu = CPU(s->cpu);
 
     if (size != 2) {
         return omap_badwidth_read16(opaque, addr);
@@ -1737,8 +1738,9 @@ static uint64_t omap_clkdsp_read(void *opaque, hwaddr addr,
         return s->clkm.dsp_rstct2;
 
     case 0x18:	/* DSP_SYSST */
+        cpu = CPU(s->cpu);
         return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
-                (s->cpu->env.halted << 6);      /* Quite useless... */
+                (cpu->halted << 6);      /* Quite useless... */
     }
 
     OMAP_BAD_REG(addr);
@@ -3754,8 +3756,9 @@ static void omap_setup_dsp_mapping(MemoryRegion *system_memory,
 void omap_mpu_wakeup(void *opaque, int irq, int req)
 {
     struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
+    CPUState *cpu = CPU(mpu->cpu);
 
-    if (mpu->cpu->env.halted) {
+    if (cpu->halted) {
         cpu_interrupt(&mpu->cpu->env, CPU_INTERRUPT_EXITTB);
     }
 }
diff --git a/hw/openrisc_timer.c b/hw/openrisc_timer.c
index d965be7..f9f116a 100644
--- a/hw/openrisc_timer.c
+++ b/hw/openrisc_timer.c
@@ -73,8 +73,10 @@ static void openrisc_timer_cb(void *opaque)
 
     if ((cpu->env.ttmr & TTMR_IE) &&
          qemu_timer_expired(cpu->env.timer, qemu_get_clock_ns(vm_clock))) {
+        CPUState *cs = CPU(cpu);
+
         cpu->env.ttmr |= TTMR_IP;
-        cpu->env.interrupt_request |= CPU_INTERRUPT_TIMER;
+        cs->interrupt_request |= CPU_INTERRUPT_TIMER;
     }
 
     switch (cpu->env.ttmr & TTMR_M) {
diff --git a/hw/ppc.c b/hw/ppc.c
index 89352be..400daab 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -72,7 +72,7 @@ void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
 
     LOG_IRQ("%s: %p n_IRQ %d level %d => pending %08" PRIx32
                 "req %08x\n", __func__, env, n_IRQ, level,
-                env->pending_interrupts, env->interrupt_request);
+                env->pending_interrupts, CPU(cpu)->interrupt_request);
 }
 
 /* PowerPC 6xx / 7xx internal IRQ controller */
@@ -87,6 +87,8 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
     cur_level = (env->irq_input_state >> pin) & 1;
     /* Don't generate spurious events */
     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        CPUState *cs = CPU(cpu);
+
         switch (pin) {
         case PPC6xx_INPUT_TBEN:
             /* Level sensitive - active high */
@@ -126,7 +128,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
             /* XXX: Note that the only way to restart the CPU is to reset it */
             if (level) {
                 LOG_IRQ("%s: stop the CPU\n", __func__);
-                env->halted = 1;
+                cs->halted = 1;
             }
             break;
         case PPC6xx_INPUT_HRESET:
@@ -174,6 +176,8 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
     cur_level = (env->irq_input_state >> pin) & 1;
     /* Don't generate spurious events */
     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        CPUState *cs = CPU(cpu);
+
         switch (pin) {
         case PPC970_INPUT_INT:
             /* Level sensitive - active high */
@@ -203,11 +207,11 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
             /* XXX: TODO: relay the signal to CKSTP_OUT pin */
             if (level) {
                 LOG_IRQ("%s: stop the CPU\n", __func__);
-                env->halted = 1;
+                cs->halted = 1;
             } else {
                 LOG_IRQ("%s: restart the CPU\n", __func__);
-                env->halted = 0;
-                qemu_cpu_kick(CPU(cpu));
+                cs->halted = 0;
+                qemu_cpu_kick(cs);
             }
             break;
         case PPC970_INPUT_HRESET:
@@ -295,6 +299,8 @@ static void ppc40x_set_irq(void *opaque, int pin, int level)
     cur_level = (env->irq_input_state >> pin) & 1;
     /* Don't generate spurious events */
     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        CPUState *cs = CPU(cpu);
+
         switch (pin) {
         case PPC40x_INPUT_RESET_SYS:
             if (level) {
@@ -332,11 +338,11 @@ static void ppc40x_set_irq(void *opaque, int pin, int level)
             /* Level sensitive - active low */
             if (level) {
                 LOG_IRQ("%s: stop the CPU\n", __func__);
-                env->halted = 1;
+                cs->halted = 1;
             } else {
                 LOG_IRQ("%s: restart the CPU\n", __func__);
-                env->halted = 0;
-                qemu_cpu_kick(CPU(cpu));
+                cs->halted = 0;
+                qemu_cpu_kick(cs);
             }
             break;
         case PPC40x_INPUT_DEBUG:
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index b7474c0..265d75c 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -425,26 +425,28 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env)
 static void ppce500_cpu_reset_sec(void *opaque)
 {
     PowerPCCPU *cpu = opaque;
+    CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
 
-    cpu_reset(CPU(cpu));
+    cpu_reset(cs);
 
     /* Secondary CPU starts in halted state for now. Needs to change when
        implementing non-kernel boot. */
-    env->halted = 1;
+    cs->halted = 1;
     env->exception_index = EXCP_HLT;
 }
 
 static void ppce500_cpu_reset(void *opaque)
 {
     PowerPCCPU *cpu = opaque;
+    CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
     struct boot_info *bi = env->load_info;
 
-    cpu_reset(CPU(cpu));
+    cpu_reset(cs);
 
     /* Set initial guest state. */
-    env->halted = 0;
+    cs->halted = 0;
     env->gpr[1] = (16<<20) - 8;
     env->gpr[3] = bi->dt_base;
     env->nip = bi->entry;
diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
index 7e90fb9..0d20a43 100644
--- a/hw/ppce500_spin.c
+++ b/hw/ppce500_spin.c
@@ -112,7 +112,7 @@ static void spin_kick(void *data)
     map_start = ldq_p(&curspin->addr) & ~(map_size - 1);
     mmubooke_create_initial_mapping(env, 0, map_start, map_size);
 
-    env->halted = 0;
+    cpu->halted = 0;
     env->exception_index = -1;
     cpu->stopped = false;
     qemu_cpu_kick(cpu);
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index 05d2ad2..f00d150 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -93,6 +93,7 @@ static const int pxa2xx_gpio_wake[PXA2XX_GPIO_BANKS] = {
 static void pxa2xx_gpio_set(void *opaque, int line, int level)
 {
     PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
+    CPUState *cpu = CPU(s->cpu);
     int bank;
     uint32_t mask;
 
@@ -118,7 +119,7 @@ static void pxa2xx_gpio_set(void *opaque, int line, int level)
         pxa2xx_gpio_irq_update(s);
 
     /* Wake-up GPIOs */
-    if (s->cpu->env.halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
+    if (cpu->halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
         cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
     }
 }
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 90b8fef..c73e709 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -46,8 +46,9 @@ static void pxa2xx_pic_update(void *opaque)
 {
     uint32_t mask[2];
     PXA2xxPICState *s = (PXA2xxPICState *) opaque;
+    CPUState *cpu = CPU(s->cpu);
 
-    if (s->cpu->env.halted) {
+    if (cpu->halted) {
         mask[0] = s->int_pending[0] & (s->int_enabled[0] | s->int_idle);
         mask[1] = s->int_pending[1] & (s->int_enabled[1] | s->int_idle);
         if (mask[0] || mask[1]) {
diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c
index e25c330..ca275bd 100644
--- a/hw/s390x/s390-virtio.c
+++ b/hw/s390x/s390-virtio.c
@@ -132,23 +132,25 @@ static unsigned s390_running_cpus;
 
 void s390_add_running_cpu(S390CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUS390XState *env = &cpu->env;
 
-    if (env->halted) {
+    if (cs->halted) {
         s390_running_cpus++;
-        env->halted = 0;
+        cs->halted = 0;
         env->exception_index = -1;
     }
 }
 
 unsigned s390_del_running_cpu(S390CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUS390XState *env = &cpu->env;
 
-    if (env->halted == 0) {
+    if (cs->halted == 0) {
         assert(s390_running_cpus >= 1);
         s390_running_cpus--;
-        env->halted = 1;
+        cs->halted = 1;
         env->exception_index = EXCP_HLT;
     }
     return s390_running_cpus;
@@ -183,11 +185,13 @@ void s390_init_cpus(const char *cpu_model, uint8_t *storage_keys)
 
     for (i = 0; i < smp_cpus; i++) {
         S390CPU *cpu;
+        CPUState *cs;
 
         cpu = cpu_s390x_init(cpu_model);
+        cs = CPU(cpu);
 
         ipi_states[i] = cpu;
-        cpu->env.halted = 1;
+        cs->halted = 1;
         cpu->env.exception_index = EXCP_HLT;
         cpu->env.storage_keys = storage_keys;
     }
diff --git a/hw/spapr.c b/hw/spapr.c
index e88a27a..da5181c 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -616,6 +616,8 @@ static void spapr_reset_htab(sPAPREnvironment *spapr)
 
 static void ppc_spapr_reset(void)
 {
+    CPUState *first_cpu_cpu;
+
     /* Reset the hash table & recalc the RMA */
     spapr_reset_htab(spapr);
 
@@ -626,9 +628,10 @@ static void ppc_spapr_reset(void)
                        spapr->rtas_size);
 
     /* Set up the entry state */
+    first_cpu_cpu = CPU(first_cpu);
     first_cpu->gpr[3] = spapr->fdt_addr;
     first_cpu->gpr[5] = 0;
-    first_cpu->halted = 0;
+    first_cpu_cpu->halted = 0;
     first_cpu->nip = spapr->entry_point;
 
 }
@@ -636,14 +639,15 @@ static void ppc_spapr_reset(void)
 static void spapr_cpu_reset(void *opaque)
 {
     PowerPCCPU *cpu = opaque;
+    CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
 
-    cpu_reset(CPU(cpu));
+    cpu_reset(cs);
 
     /* All CPUs start halted.  CPU0 is unhalted from the machine level
      * reset code and the rest are explicitly started up by the guest
      * using an RTAS call */
-    env->halted = 1;
+    cs->halted = 1;
 
     env->spr[SPR_HIOR] = 0;
 
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index af1db6e..7c28144 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -518,7 +518,7 @@ static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     env->msr |= (1ULL << MSR_EE);
     hreg_compute_hflags(env);
     if (!cpu_has_work(cs)) {
-        env->halted = 1;
+        cs->halted = 1;
         env->exception_index = EXCP_HLT;
         cs->exit_request = 1;
     }
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index 5ec787f..a24e853 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -145,7 +145,7 @@ static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
             continue;
         }
 
-        if (env->halted) {
+        if (cpu->halted) {
             rtas_st(rets, 1, 0);
         } else {
             rtas_st(rets, 1, 2);
@@ -184,7 +184,7 @@ static void rtas_start_cpu(sPAPREnvironment *spapr,
             continue;
         }
 
-        if (!env->halted) {
+        if (!cpu->halted) {
             rtas_st(rets, 0, -1);
             return;
         }
@@ -197,7 +197,7 @@ static void rtas_start_cpu(sPAPREnvironment *spapr,
         env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
         env->nip = start;
         env->gpr[3] = r3;
-        env->halted = 0;
+        cpu->halted = 0;
 
         qemu_cpu_kick(cpu);
 
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 9903f44..45f9441 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -256,10 +256,11 @@ void cpu_check_irqs(CPUSPARCState *env)
 static void cpu_kick_irq(SPARCCPU *cpu)
 {
     CPUSPARCState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
-    env->halted = 0;
+    cs->halted = 0;
     cpu_check_irqs(env);
-    qemu_cpu_kick(CPU(cpu));
+    qemu_cpu_kick(cs);
 }
 
 static void cpu_set_irq(void *opaque, int irq, int level)
@@ -285,19 +286,19 @@ static void dummy_cpu_set_irq(void *opaque, int irq, int level)
 static void main_cpu_reset(void *opaque)
 {
     SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
-    cpu_reset(CPU(cpu));
-    env->halted = 0;
+    cpu_reset(cs);
+    cs->halted = 0;
 }
 
 static void secondary_cpu_reset(void *opaque)
 {
     SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
-    cpu_reset(CPU(cpu));
-    env->halted = 1;
+    cpu_reset(cs);
+    cs->halted = 1;
 }
 
 static void cpu_halt_signal(void *opaque, int irq, int level)
@@ -826,6 +827,7 @@ static const TypeInfo ram_info = {
 static void cpu_devinit(const char *cpu_model, unsigned int id,
                         uint64_t prom_addr, qemu_irq **cpu_irqs)
 {
+    CPUState *cs;
     SPARCCPU *cpu;
     CPUSPARCState *env;
 
@@ -841,7 +843,8 @@ static void cpu_devinit(const char *cpu_model, unsigned int id,
         qemu_register_reset(main_cpu_reset, cpu);
     } else {
         qemu_register_reset(secondary_cpu_reset, cpu);
-        env->halted = 1;
+        cs = CPU(cpu);
+        cs->halted = 1;
     }
     *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS);
     env->prom_addr = prom_addr;
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 9fbda29..056bb4d 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -254,6 +254,7 @@ static uint64_t sun4u_load_kernel(const char *kernel_filename,
 
 void cpu_check_irqs(CPUSPARCState *env)
 {
+    CPUState *cs;
     uint32_t pil = env->pil_in |
                   (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));
 
@@ -261,6 +262,7 @@ void cpu_check_irqs(CPUSPARCState *env)
     if (env->ivec_status & 0x20) {
         return;
     }
+    cs = CPU(sparc_env_get_cpu(env));
     /* check if TM or SM in SOFTINT are set
        setting these also causes interrupt 14 */
     if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
@@ -270,7 +272,7 @@ void cpu_check_irqs(CPUSPARCState *env)
     /* The bit corresponding to psrpil is (1<< psrpil), the next bit
        is (2 << psrpil). */
     if (pil < (2 << env->psrpil)){
-        if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+        if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
             CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n",
                            env->interrupt_index);
             env->interrupt_index = 0;
@@ -302,7 +304,7 @@ void cpu_check_irqs(CPUSPARCState *env)
                 break;
             }
         }
-    } else if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+    } else if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
         CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x "
                        "current interrupt %x\n",
                        pil, env->pil_in, env->softint, env->interrupt_index);
@@ -313,22 +315,25 @@ void cpu_check_irqs(CPUSPARCState *env)
 
 static void cpu_kick_irq(SPARCCPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUSPARCState *env = &cpu->env;
 
-    env->halted = 0;
+    cs->halted = 0;
     cpu_check_irqs(env);
-    qemu_cpu_kick(CPU(cpu));
+    qemu_cpu_kick(cs);
 }
 
 static void cpu_set_ivec_irq(void *opaque, int irq, int level)
 {
     SPARCCPU *cpu = opaque;
     CPUSPARCState *env = &cpu->env;
+    CPUState *cs;
 
     if (level) {
         if (!(env->ivec_status & 0x20)) {
             CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
-            env->halted = 0;
+            cs = CPU(cpu);
+            cs->halted = 0;
             env->interrupt_index = TT_IVEC;
             env->ivec_status |= 0x20;
             env->ivec_data[0] = (0x1f << 6) | irq;
diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c
index 66e8981..4fec4fc 100644
--- a/hw/xen_machine_pv.c
+++ b/hw/xen_machine_pv.c
@@ -36,7 +36,7 @@ static void xen_init_pv(QEMUMachineInitArgs *args)
     const char *kernel_cmdline = args->kernel_cmdline;
     const char *initrd_filename = args->initrd_filename;
     X86CPU *cpu;
-    CPUX86State *env;
+    CPUState *cs;
     DriveInfo *dinfo;
     int i;
 
@@ -49,8 +49,8 @@ static void xen_init_pv(QEMUMachineInitArgs *args)
 #endif
     }
     cpu = cpu_x86_init(cpu_model);
-    env = &cpu->env;
-    env->halted = 1;
+    cs = CPU(cpu);
+    cs->halted = 1;
 
     /* Initialize backend core & drivers */
     if (xen_be_init() != 0) {
diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c
index 97d36be..dca15b4 100644
--- a/hw/xtensa_pic.c
+++ b/hw/xtensa_pic.c
@@ -47,6 +47,7 @@ void xtensa_advance_ccount(CPUXtensaState *env, uint32_t d)
 
 void check_interrupts(CPUXtensaState *env)
 {
+    CPUState *cs = CPU(xtensa_env_get_cpu(env));
     int minlevel = xtensa_get_cintlevel(env);
     uint32_t int_set_enabled = env->sregs[INTSET] & env->sregs[INTENABLE];
     int level;
@@ -54,7 +55,7 @@ void check_interrupts(CPUXtensaState *env)
     /* If the CPU is halted advance CCOUNT according to the vm_clock time
      * elapsed since the moment when it was advanced last time.
      */
-    if (env->halted) {
+    if (cs->halted) {
         int64_t now = qemu_get_clock_ns(vm_clock);
 
         xtensa_advance_ccount(env,
@@ -127,11 +128,12 @@ static void xtensa_ccompare_cb(void *opaque)
 {
     XtensaCPU *cpu = opaque;
     CPUXtensaState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
-    if (env->halted) {
+    if (cs->halted) {
         env->halt_clock = qemu_get_clock_ns(vm_clock);
         xtensa_advance_ccount(env, env->wake_ccount - env->sregs[CCOUNT]);
-        if (!cpu_has_work(CPU(cpu))) {
+        if (!cpu_has_work(cs)) {
             env->sregs[CCOUNT] = env->wake_ccount + 1;
             xtensa_rearm_ccompare_timer(env);
         }
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index ae64590..a4c6370 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -156,8 +156,6 @@ typedef struct CPUWatchpoint {
                             accessed */                                 \
     target_ulong mem_io_vaddr; /* target virtual addr at which the      \
                                      memory was accessed */             \
-    uint32_t halted; /* Nonzero if the CPU is in suspend state */       \
-    uint32_t interrupt_request;                                         \
     CPU_COMMON_TLB                                                      \
     struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE];           \
     /* buffer for temporaries in the code generator */                  \
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index ee1a7c8..9ad9822 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -69,6 +69,8 @@ struct kvm_run;
  * @host_tid: Host thread ID.
  * @running: #true if CPU is currently running (usermode).
  * @created: Indicates whether the CPU thread has been successfully created.
+ * @interrupt_request: Indicates a pending interrupt request.
+ * @halted: Nonzero if the CPU is in suspended state.
  * @stop: Indicates a pending stop request.
  * @stopped: Indicates the CPU has been artificially stopped.
  * @env_ptr: Pointer to subclass-specific CPUArchState field.
@@ -100,6 +102,7 @@ struct CPUState {
     bool stop;
     bool stopped;
     volatile sig_atomic_t exit_request;
+    uint32_t interrupt_request;
 
     void *env_ptr; /* CPUArchState */
     struct TranslationBlock *current_tb;
@@ -111,6 +114,7 @@ struct CPUState {
 
     /* TODO Move common fields from CPUArchState here. */
     int cpu_index; /* used by alpha TCG */
+    uint32_t halted; /* used by alpha, cris, ppc TCG */
 };
 
 
diff --git a/kvm-all.c b/kvm-all.c
index 4decfdc..2b761e0 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -830,7 +830,7 @@ static void kvm_handle_interrupt(CPUArchState *env, int mask)
 {
     CPUState *cpu = ENV_GET_CPU(env);
 
-    env->interrupt_request |= mask;
+    cpu->interrupt_request |= mask;
 
     if (!qemu_cpu_is_self(cpu)) {
         qemu_cpu_kick(cpu);
diff --git a/qom/cpu.c b/qom/cpu.c
index 0a2194d..0aa9be7 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -33,7 +33,9 @@ void cpu_reset(CPUState *cpu)
 static void cpu_common_reset(CPUState *cpu)
 {
     cpu->exit_request = 0;
+    cpu->interrupt_request = 0;
     cpu->current_tb = NULL;
+    cpu->halted = 0;
 }
 
 ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index f1db651..90f78ac 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -517,8 +517,6 @@ static inline void cpu_set_tls(CPUAlphaState *env, target_ulong newtls)
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUAlphaState *env = &ALPHA_CPU(cpu)->env;
-
     /* Here we are checking to see if the CPU should wake up from HALT.
        We will have gotten into this state only for WTINT from PALmode.  */
     /* ??? I'm not sure how the IPL state works with WTINT to keep a CPU
@@ -526,7 +524,7 @@ static inline bool cpu_has_work(CPUState *cpu)
        assume that if a CPU really wants to stay asleep, it will mask
        interrupts at the chipset level, which will prevent these bits
        from being set in the first place.  */
-    return env->interrupt_request & (CPU_INTERRUPT_HARD
+    return cpu->interrupt_request & (CPU_INTERRUPT_HARD
                                      | CPU_INTERRUPT_TIMER
                                      | CPU_INTERRUPT_SMP
                                      | CPU_INTERRUPT_MCHK);
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index f687b95..a4f72b8 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1687,7 +1687,8 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
     case 253:
         /* WAIT */
         tmp = tcg_const_i64(1);
-        tcg_gen_st32_i64(tmp, cpu_env, offsetof(CPUAlphaState, halted));
+        tcg_gen_st32_i64(tmp, cpu_env, -offsetof(AlphaCPU, env) +
+                                       offsetof(CPUState, halted));
         return gen_excp(ctx, EXCP_HLT, 0);
 
     case 252:
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 2902ba5..7c47467 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -721,9 +721,7 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUARMState *env = &ARM_CPU(cpu)->env;
-
-    return env->interrupt_request &
+    return cpu->interrupt_request &
         (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
 }
 
diff --git a/target-arm/helper.c b/target-arm/helper.c
index e63da57..31b7a3c 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1802,6 +1802,7 @@ static void do_interrupt_v7m(CPUARMState *env)
 /* Handle a CPU exception.  */
 void do_interrupt(CPUARMState *env)
 {
+    CPUState *cs;
     uint32_t addr;
     uint32_t mask;
     int new_mode;
@@ -1908,7 +1909,8 @@ void do_interrupt(CPUARMState *env)
     }
     env->regs[14] = env->regs[15] + offset;
     env->regs[15] = addr;
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+    cs = CPU(arm_env_get_cpu(env));
+    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
 
 /* Check section/page access permissions.
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 99610d7..7af5187 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -218,8 +218,10 @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift)
 
 void HELPER(wfi)(CPUARMState *env)
 {
+    CPUState *cs = CPU(arm_env_get_cpu(env));
+
     env->exception_index = EXCP_HLT;
-    env->halted = 1;
+    cs->halted = 1;
     cpu_loop_exit(env);
 }
 
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index ebf2d40..2fc7c5c 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -289,9 +289,7 @@ void cris_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUCRISState *env = &CRIS_CPU(cpu)->env;
-
-    return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
+    return cpu->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
 }
 
 #include "exec/exec-all.h"
diff --git a/target-cris/helper.c b/target-cris/helper.c
index de04143..51c9a9f 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -66,6 +66,7 @@ static void cris_shift_ccs(CPUCRISState *env)
 int cpu_cris_handle_mmu_fault(CPUCRISState *env, target_ulong address, int rw,
                               int mmu_idx)
 {
+    D(CPUState *cpu = CPU(cris_env_get_cpu(env)));
     struct cris_mmu_result res;
     int prot, miss;
     int r = -1;
@@ -99,7 +100,7 @@ int cpu_cris_handle_mmu_fault(CPUCRISState *env, target_ulong address, int rw,
     }
     if (r > 0) {
         D_LOG("%s returns %d irqreq=%x addr=%x phy=%x vec=%x pc=%x\n",
-              __func__, r, env->interrupt_request, address, res.phy,
+              __func__, r, cpu->interrupt_request, address, res.phy,
               res.bf_vec, env->pc);
     }
     return r;
@@ -107,11 +108,12 @@ int cpu_cris_handle_mmu_fault(CPUCRISState *env, target_ulong address, int rw,
 
 static void do_interruptv10(CPUCRISState *env)
 {
+    D(CPUState *cpu = CPU(cris_env_get_cpu(env)));
     int ex_vec = -1;
 
     D_LOG("exception index=%d interrupt_req=%d\n",
           env->exception_index,
-          env->interrupt_request);
+          cpu->interrupt_request);
 
     assert(!(env->pregs[PR_CCS] & PFIX_FLAG));
     switch (env->exception_index) {
@@ -162,6 +164,7 @@ static void do_interruptv10(CPUCRISState *env)
 
 void do_interrupt(CPUCRISState *env)
 {
+    D(CPUState *cpu = CPU(cris_env_get_cpu(env)));
     int ex_vec = -1;
 
     if (env->pregs[PR_VR] < 32) {
@@ -170,7 +173,7 @@ void do_interrupt(CPUCRISState *env)
 
     D_LOG("exception index=%d interrupt_req=%d\n",
           env->exception_index,
-          env->interrupt_request);
+          cpu->interrupt_request);
 
     switch (env->exception_index) {
     case EXCP_BREAK:
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 25a43fa..22e5e9f 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -2928,7 +2928,8 @@ static int dec_rfe_etc(CPUCRISState *env, DisasContext *dc)
     cris_cc_mask(dc, 0);
 
     if (dc->op2 == 15) {
-        t_gen_mov_env_TN(halted, tcg_const_tl(1));
+        tcg_gen_st_i32(tcg_const_i32(1), cpu_env,
+                       -offsetof(CRISCPU, env) + offsetof(CPUState, halted));
         tcg_gen_movi_tl(env_pc, dc->pc + 2);
         t_gen_raise_exception(EXCP_HLT);
         return 2;
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 8ad8f22..b892da0 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1980,7 +1980,7 @@ static void x86_cpu_reset(CPUState *s)
         apic_designate_bsp(env->apic_state);
     }
 
-    env->halted = !cpu_is_bsp(cpu);
+    s->halted = !cpu_is_bsp(cpu);
 #endif
 }
 
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 9e6e1a6..40cf246 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -956,6 +956,7 @@ static inline void cpu_x86_load_seg_cache(CPUX86State *env,
 static inline void cpu_x86_load_seg_cache_sipi(X86CPU *cpu,
                                                int sipi_vector)
 {
+    CPUState *cs = CPU(cpu);
     CPUX86State *env = &cpu->env;
 
     env->eip = 0;
@@ -963,7 +964,7 @@ static inline void cpu_x86_load_seg_cache_sipi(X86CPU *cpu,
                            sipi_vector << 12,
                            env->segs[R_CS].limit,
                            env->segs[R_CS].flags);
-    env->halted = 0;
+    cs->halted = 0;
 }
 
 int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
@@ -1157,17 +1158,18 @@ static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp)
 #include "hw/apic.h"
 #endif
 
-static inline bool cpu_has_work(CPUState *cpu)
+static inline bool cpu_has_work(CPUState *cs)
 {
-    CPUX86State *env = &X86_CPU(cpu)->env;
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
 
-    return ((env->interrupt_request & (CPU_INTERRUPT_HARD |
-                                       CPU_INTERRUPT_POLL)) &&
+    return ((cs->interrupt_request & (CPU_INTERRUPT_HARD |
+                                      CPU_INTERRUPT_POLL)) &&
             (env->eflags & IF_MASK)) ||
-           (env->interrupt_request & (CPU_INTERRUPT_NMI |
-                                      CPU_INTERRUPT_INIT |
-                                      CPU_INTERRUPT_SIPI |
-                                      CPU_INTERRUPT_MCE));
+           (cs->interrupt_request & (CPU_INTERRUPT_NMI |
+                                     CPU_INTERRUPT_INIT |
+                                     CPU_INTERRUPT_SIPI |
+                                     CPU_INTERRUPT_MCE));
 }
 
 #include "exec/exec-all.h"
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 1a872fa..808d879 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -171,6 +171,7 @@ done:
 void cpu_dump_state(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
                     int flags)
 {
+    CPUState *cs = CPU(x86_env_get_cpu(env));
     int eflags, i, nb;
     char cc_op_name[32];
     static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
@@ -214,7 +215,7 @@ void cpu_dump_state(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
                     (env->a20_mask >> 20) & 1,
                     (env->hflags >> HF_SMM_SHIFT) & 1,
-                    env->halted);
+                    cs->halted);
     } else
 #endif
     {
@@ -241,7 +242,7 @@ void cpu_dump_state(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
                     (env->a20_mask >> 20) & 1,
                     (env->hflags >> HF_SMM_SHIFT) & 1,
-                    env->halted);
+                    cs->halted);
     }
 
     for(i = 0; i < 6; i++) {
@@ -1294,12 +1295,13 @@ X86CPU *cpu_x86_init(const char *cpu_model)
 #if !defined(CONFIG_USER_ONLY)
 void do_cpu_init(X86CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUX86State *env = &cpu->env;
-    int sipi = env->interrupt_request & CPU_INTERRUPT_SIPI;
+    int sipi = cs->interrupt_request & CPU_INTERRUPT_SIPI;
     uint64_t pat = env->pat;
 
-    cpu_reset(CPU(cpu));
-    env->interrupt_request = sipi;
+    cpu_reset(cs);
+    cs->interrupt_request = sipi;
     env->pat = pat;
     apic_init_reset(env->apic_state);
 }
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0cf413d..df30fa6 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1460,17 +1460,18 @@ static int kvm_put_mp_state(X86CPU *cpu)
 
 static int kvm_get_mp_state(X86CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUX86State *env = &cpu->env;
     struct kvm_mp_state mp_state;
     int ret;
 
-    ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MP_STATE, &mp_state);
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_MP_STATE, &mp_state);
     if (ret < 0) {
         return ret;
     }
     env->mp_state = mp_state.mp_state;
     if (kvm_irqchip_in_kernel()) {
-        env->halted = (mp_state.mp_state == KVM_MP_STATE_HALTED);
+        cs->halted = (mp_state.mp_state == KVM_MP_STATE_HALTED);
     }
     return 0;
 }
@@ -1762,8 +1763,8 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
     int ret;
 
     /* Inject NMI */
-    if (env->interrupt_request & CPU_INTERRUPT_NMI) {
-        env->interrupt_request &= ~CPU_INTERRUPT_NMI;
+    if (cpu->interrupt_request & CPU_INTERRUPT_NMI) {
+        cpu->interrupt_request &= ~CPU_INTERRUPT_NMI;
         DPRINTF("injected NMI\n");
         ret = kvm_vcpu_ioctl(cpu, KVM_NMI);
         if (ret < 0) {
@@ -1775,18 +1776,18 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
     if (!kvm_irqchip_in_kernel()) {
         /* Force the VCPU out of its inner loop to process any INIT requests
          * or pending TPR access reports. */
-        if (env->interrupt_request &
+        if (cpu->interrupt_request &
             (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR)) {
             cpu->exit_request = 1;
         }
 
         /* Try to inject an interrupt if the guest can accept it */
         if (run->ready_for_interrupt_injection &&
-            (env->interrupt_request & CPU_INTERRUPT_HARD) &&
+            (cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
             (env->eflags & IF_MASK)) {
             int irq;
 
-            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+            cpu->interrupt_request &= ~CPU_INTERRUPT_HARD;
             irq = cpu_get_pic_interrupt(env);
             if (irq >= 0) {
                 struct kvm_interrupt intr;
@@ -1806,7 +1807,7 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
          * interrupt, request an interrupt window exit.  This will
          * cause a return to userspace as soon as the guest is ready to
          * receive interrupts. */
-        if ((env->interrupt_request & CPU_INTERRUPT_HARD)) {
+        if ((cpu->interrupt_request & CPU_INTERRUPT_HARD)) {
             run->request_interrupt_window = 1;
         } else {
             run->request_interrupt_window = 0;
@@ -1836,11 +1837,11 @@ int kvm_arch_process_async_events(CPUState *cs)
     X86CPU *cpu = X86_CPU(cs);
     CPUX86State *env = &cpu->env;
 
-    if (env->interrupt_request & CPU_INTERRUPT_MCE) {
+    if (cs->interrupt_request & CPU_INTERRUPT_MCE) {
         /* We must not raise CPU_INTERRUPT_MCE if it's not supported. */
         assert(env->mcg_cap);
 
-        env->interrupt_request &= ~CPU_INTERRUPT_MCE;
+        cs->interrupt_request &= ~CPU_INTERRUPT_MCE;
 
         kvm_cpu_synchronize_state(env);
 
@@ -1853,7 +1854,7 @@ int kvm_arch_process_async_events(CPUState *cs)
         env->exception_injected = EXCP12_MCHK;
         env->has_error_code = 0;
 
-        env->halted = 0;
+        cs->halted = 0;
         if (kvm_irqchip_in_kernel() && env->mp_state == KVM_MP_STATE_HALTED) {
             env->mp_state = KVM_MP_STATE_RUNNABLE;
         }
@@ -1863,41 +1864,42 @@ int kvm_arch_process_async_events(CPUState *cs)
         return 0;
     }
 
-    if (env->interrupt_request & CPU_INTERRUPT_POLL) {
-        env->interrupt_request &= ~CPU_INTERRUPT_POLL;
+    if (cs->interrupt_request & CPU_INTERRUPT_POLL) {
+        cs->interrupt_request &= ~CPU_INTERRUPT_POLL;
         apic_poll_irq(env->apic_state);
     }
-    if (((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+    if (((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
          (env->eflags & IF_MASK)) ||
-        (env->interrupt_request & CPU_INTERRUPT_NMI)) {
-        env->halted = 0;
+        (cs->interrupt_request & CPU_INTERRUPT_NMI)) {
+        cs->halted = 0;
     }
-    if (env->interrupt_request & CPU_INTERRUPT_INIT) {
+    if (cs->interrupt_request & CPU_INTERRUPT_INIT) {
         kvm_cpu_synchronize_state(env);
         do_cpu_init(cpu);
     }
-    if (env->interrupt_request & CPU_INTERRUPT_SIPI) {
+    if (cs->interrupt_request & CPU_INTERRUPT_SIPI) {
         kvm_cpu_synchronize_state(env);
         do_cpu_sipi(cpu);
     }
-    if (env->interrupt_request & CPU_INTERRUPT_TPR) {
-        env->interrupt_request &= ~CPU_INTERRUPT_TPR;
+    if (cs->interrupt_request & CPU_INTERRUPT_TPR) {
+        cs->interrupt_request &= ~CPU_INTERRUPT_TPR;
         kvm_cpu_synchronize_state(env);
         apic_handle_tpr_access_report(env->apic_state, env->eip,
                                       env->tpr_access_type);
     }
 
-    return env->halted;
+    return cs->halted;
 }
 
 static int kvm_handle_halt(X86CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUX86State *env = &cpu->env;
 
-    if (!((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+    if (!((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
           (env->eflags & IF_MASK)) &&
-        !(env->interrupt_request & CPU_INTERRUPT_NMI)) {
-        env->halted = 1;
+        !(cs->interrupt_request & CPU_INTERRUPT_NMI)) {
+        cs->halted = 1;
         return EXCP_HLT;
     }
 
diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
index b6d5740..dfbc07b 100644
--- a/target-i386/misc_helper.c
+++ b/target-i386/misc_helper.c
@@ -553,20 +553,25 @@ void helper_rdmsr(CPUX86State *env)
 }
 #endif
 
-static void do_hlt(CPUX86State *env)
+static void do_hlt(X86CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
+    CPUX86State *env = &cpu->env;
+
     env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
-    env->halted = 1;
+    cs->halted = 1;
     env->exception_index = EXCP_HLT;
     cpu_loop_exit(env);
 }
 
 void helper_hlt(CPUX86State *env, int next_eip_addend)
 {
+    X86CPU *cpu = x86_env_get_cpu(env);
+
     cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0);
     EIP += next_eip_addend;
 
-    do_hlt(env);
+    do_hlt(cpu);
 }
 
 void helper_monitor(CPUX86State *env, target_ulong ptr)
@@ -580,7 +585,8 @@ void helper_monitor(CPUX86State *env, target_ulong ptr)
 
 void helper_mwait(CPUX86State *env, int next_eip_addend)
 {
-    CPUState *cpu;
+    CPUState *cs;
+    X86CPU *cpu;
 
     if ((uint32_t)ECX != 0) {
         raise_exception(env, EXCP0D_GPF);
@@ -588,13 +594,14 @@ void helper_mwait(CPUX86State *env, int next_eip_addend)
     cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0);
     EIP += next_eip_addend;
 
-    cpu = CPU(x86_env_get_cpu(env));
+    cpu = x86_env_get_cpu(env);
+    cs = CPU(cpu);
     /* XXX: not complete but not completely erroneous */
-    if (cpu->cpu_index != 0 || env->next_cpu != NULL) {
+    if (cs->cpu_index != 0 || env->next_cpu != NULL) {
         /* more than one CPU: do not sleep because another CPU may
            wake this one */
     } else {
-        do_hlt(env);
+        do_hlt(cpu);
     }
 }
 
diff --git a/target-i386/svm_helper.c b/target-i386/svm_helper.c
index 3f246e9..c46a213 100644
--- a/target-i386/svm_helper.c
+++ b/target-i386/svm_helper.c
@@ -271,7 +271,9 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
     env->hflags2 |= HF2_GIF_MASK;
 
     if (int_ctl & V_IRQ_MASK) {
-        env->interrupt_request |= CPU_INTERRUPT_VIRQ;
+        CPUState *cs = CPU(x86_env_get_cpu(env));
+
+        cs->interrupt_request |= CPU_INTERRUPT_VIRQ;
     }
 
     /* maybe we need to inject an event */
@@ -548,6 +550,7 @@ void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param,
 /* Note: currently only 32 bits of exit_code are used */
 void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
 {
+    CPUState *cs = CPU(x86_env_get_cpu(env));
     uint32_t int_ctl;
 
     qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016"
@@ -594,7 +597,7 @@ void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
     int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
     int_ctl &= ~(V_TPR_MASK | V_IRQ_MASK);
     int_ctl |= env->v_tpr & V_TPR_MASK;
-    if (env->interrupt_request & CPU_INTERRUPT_VIRQ) {
+    if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) {
         int_ctl |= V_IRQ_MASK;
     }
     stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
@@ -615,7 +618,7 @@ void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
     env->hflags &= ~HF_SVMI_MASK;
     env->intercept = 0;
     env->intercept_exceptions = 0;
-    env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
+    cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
     env->tsc_offset = 0;
 
     env->gdt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb,
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index 6948d0e..d81f103 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -254,9 +254,7 @@ static inline void cpu_get_tb_cpu_state(CPULM32State *env, target_ulong *pc,
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPULM32State *env = &LM32_CPU(cpu)->env;
-
-    return env->interrupt_request & CPU_INTERRUPT_HARD;
+    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
 #include "exec/exec-all.h"
diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c
index 53410b1..ebc94a0 100644
--- a/target-lm32/op_helper.c
+++ b/target-lm32/op_helper.c
@@ -25,7 +25,9 @@ void helper_raise_exception(CPULM32State *env, uint32_t index)
 
 void helper_hlt(CPULM32State *env)
 {
-    env->halted = 1;
+    CPUState *cs = CPU(lm32_env_get_cpu(env));
+
+    cs->halted = 1;
     env->exception_index = EXCP_HLT;
     cpu_loop_exit(env);
 }
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 2672eae..bb2fbd6 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -265,9 +265,7 @@ static inline void cpu_get_tb_cpu_state(CPUM68KState *env, target_ulong *pc,
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUM68KState *env = &M68K_CPU(cpu)->env;
-
-    return env->interrupt_request & CPU_INTERRUPT_HARD;
+    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
 #include "exec/exec-all.h"
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 16df24c..e11f34b 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -84,6 +84,7 @@ static void do_rte(CPUM68KState *env)
 
 static void do_interrupt_all(CPUM68KState *env, int is_hw)
 {
+    CPUState *cs;
     uint32_t sp;
     uint32_t fmt;
     uint32_t retaddr;
@@ -108,7 +109,8 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
                 do_m68k_semihosting(env, env->dregs[0]);
                 return;
             }
-            env->halted = 1;
+            cs = CPU(m68k_env_get_cpu(env));
+            cs->halted = 1;
             env->exception_index = EXCP_HLT;
             cpu_loop_exit(env);
             return;
diff --git a/target-m68k/qregs.def b/target-m68k/qregs.def
index 49400c4..4235b02 100644
--- a/target-m68k/qregs.def
+++ b/target-m68k/qregs.def
@@ -8,6 +8,5 @@ DEFO32(CC_X, cc_x)
 DEFO32(DIV1, div1)
 DEFO32(DIV2, div2)
 DEFO32(EXCEPTION, exception_index)
-DEFO32(HALTED, halted)
 DEFO32(MACSR, macsr)
 DEFO32(MAC_MASK, mac_mask)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index e763195..aabd2d9 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -42,6 +42,8 @@
 #undef DEFO64
 #undef DEFF64
 
+static TCGv_i32 cpu_halted;
+
 static TCGv_ptr cpu_env;
 
 static char cpu_reg_names[3*8*3 + 5*4];
@@ -76,6 +78,10 @@ void m68k_tcg_init(void)
 #undef DEFO64
 #undef DEFF64
 
+    cpu_halted = tcg_global_mem_new_i32(TCG_AREG0,
+                                        -offsetof(M68kCPU, env) +
+                                        offsetof(CPUState, halted), "HALTED");
+
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
 
     p = cpu_reg_names;
@@ -2024,7 +2030,7 @@ DISAS_INSN(stop)
     s->pc += 2;
 
     gen_set_sr_im(s, ext, 0);
-    tcg_gen_movi_i32(QREG_HALTED, 1);
+    tcg_gen_movi_i32(cpu_halted, 1);
     gen_exception(s, s->pc, EXCP_HLT);
 }
 
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index c3dd7f6..7548aa9 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -374,9 +374,7 @@ void cpu_unassigned_access(CPUMBState *env1, hwaddr addr,
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUMBState *env = &MICROBLAZE_CPU(cpu)->env;
-
-    return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
+    return cpu->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
 }
 
 #include "exec/exec-all.h"
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 0e198b1..7434099 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -719,7 +719,7 @@ static inline bool cpu_has_work(CPUState *cpu)
     /* It is implementation dependent if non-enabled interrupts
        wake-up the CPU, however most of the implementations only
        check for interrupts that can be taken. */
-    if ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+    if ((cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
         cpu_mips_hw_interrupts_pending(env)) {
         has_work = true;
     }
@@ -728,7 +728,7 @@ static inline bool cpu_has_work(CPUState *cpu)
     if (env->CP0_Config3 & (1 << CP0C3_MT)) {
         /* The QEMU model will issue an _WAKE request whenever the CPUs
            should be woken up.  */
-        if (env->interrupt_request & CPU_INTERRUPT_WAKE) {
+        if (cpu->interrupt_request & CPU_INTERRUPT_WAKE) {
             has_work = true;
         }
 
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 526f84f..7992f0f 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -527,11 +527,12 @@ void helper_sdm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
 /* SMP helpers.  */
 static bool mips_vpe_is_wfi(MIPSCPU *c)
 {
+    CPUState *cpu = CPU(c);
     CPUMIPSState *env = &c->env;
 
     /* If the VPE is halted but otherwise active, it means it's waiting for
        an interrupt.  */
-    return env->halted && mips_vpe_active(env);
+    return cpu->halted && mips_vpe_active(env);
 }
 
 static inline void mips_vpe_wake(CPUMIPSState *c)
@@ -544,11 +545,12 @@ static inline void mips_vpe_wake(CPUMIPSState *c)
 
 static inline void mips_vpe_sleep(MIPSCPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUMIPSState *c = &cpu->env;
 
     /* The VPE was shut off, really go to bed.
        Reset any old _WAKE requests.  */
-    c->halted = 1;
+    cs->halted = 1;
     cpu_reset_interrupt(c, CPU_INTERRUPT_WAKE);
 }
 
@@ -2111,7 +2113,9 @@ void helper_pmon(CPUMIPSState *env, int function)
 
 void helper_wait(CPUMIPSState *env)
 {
-    env->halted = 1;
+    CPUState *cs = CPU(mips_env_get_cpu(env));
+
+    cs->halted = 1;
     cpu_reset_interrupt(env, CPU_INTERRUPT_WAKE);
     helper_raise_exception(env, EXCP_HLT);
 }
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 4ee9615..5cd3124 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -16020,7 +16020,7 @@ void cpu_state_reset(CPUMIPSState *env)
             env->tcs[i].CP0_TCHalt = 1;
         }
         env->active_tc.CP0_TCHalt = 1;
-        env->halted = 1;
+        cs->halted = 1;
 
         if (cs->cpu_index == 0) {
             /* VPE0 starts up enabled.  */
@@ -16028,7 +16028,7 @@ void cpu_state_reset(CPUMIPSState *env)
             env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
 
             /* TC0 starts up unhalted.  */
-            env->halted = 0;
+            cs->halted = 0;
             env->active_tc.CP0_TCHalt = 0;
             env->tcs[0].CP0_TCHalt = 0;
             /* With thread 0 active.  */
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 419f007..687c24f 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -421,9 +421,7 @@ static inline int cpu_mmu_index(CPUOpenRISCState *env)
 #define CPU_INTERRUPT_TIMER   CPU_INTERRUPT_TGT_INT_0
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUOpenRISCState *env = &OPENRISC_CPU(cpu)->env;
-
-    return env->interrupt_request & (CPU_INTERRUPT_HARD |
+    return cpu->interrupt_request & (CPU_INTERRUPT_HARD |
                                      CPU_INTERRUPT_TIMER);
 }
 
diff --git a/target-openrisc/interrupt_helper.c b/target-openrisc/interrupt_helper.c
index a176441..844648f 100644
--- a/target-openrisc/interrupt_helper.c
+++ b/target-openrisc/interrupt_helper.c
@@ -24,6 +24,7 @@
 void HELPER(rfe)(CPUOpenRISCState *env)
 {
     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
 #ifndef CONFIG_USER_ONLY
     int need_flush_tlb = (cpu->env.sr & (SR_SM | SR_IME | SR_DME)) ^
                          (cpu->env.esr & (SR_SM | SR_IME | SR_DME));
@@ -53,5 +54,5 @@ void HELPER(rfe)(CPUOpenRISCState *env)
         tlb_flush(&cpu->env, 1);
     }
 #endif
-    cpu->env.interrupt_request |= CPU_INTERRUPT_EXITTB;
+    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
index 3c5f45a..cccbc0e 100644
--- a/target-openrisc/sys_helper.c
+++ b/target-openrisc/sys_helper.c
@@ -31,6 +31,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
     int idx;
 
     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
 
     switch (spr) {
     case TO_SPR(0, 0): /* VR */
@@ -132,7 +133,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
                 env->ttmr = (rb & ~TTMR_IP) + ip;
             } else {    /* Clear IP bit.  */
                 env->ttmr = rb & ~TTMR_IP;
-                env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
+                cs->interrupt_request &= ~CPU_INTERRUPT_TIMER;
             }
 
             cpu_openrisc_count_update(cpu);
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 8c081db..75190f3 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -2215,9 +2215,10 @@ extern void (*cpu_ppc_hypercall)(PowerPCCPU *);
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUPPCState *env = &POWERPC_CPU(cpu)->env;
+    PowerPCCPU *ppc_cpu = POWERPC_CPU(cpu);
+    CPUPPCState *env = &ppc_cpu->env;
 
-    return msr_ee && (env->interrupt_request & CPU_INTERRUPT_HARD);
+    return msr_ee && (cpu->interrupt_request & CPU_INTERRUPT_HARD);
 }
 
 #include "exec/exec-all.h"
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 0a1ac86..79ce7bf 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -66,6 +66,7 @@ static inline void dump_syscall(CPUPPCState *env)
 static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
 {
     CPUPPCState *env = &cpu->env;
+    CPUState *cs;
     target_ulong msr, new_msr, vector;
     int srr0, srr1, asrr0, asrr1;
     int lpes0, lpes1, lev;
@@ -131,8 +132,9 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
                 fprintf(stderr, "Machine check while not allowed. "
                         "Entering checkstop state\n");
             }
-            env->halted = 1;
-            env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+            cs = CPU(cpu);
+            cs->halted = 1;
+            cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
         }
         if (0) {
             /* XXX: find a suitable condition to enable the hypervisor mode */
@@ -663,11 +665,12 @@ void ppc_hw_interrupt(CPUPPCState *env)
 {
     PowerPCCPU *cpu = ppc_env_get_cpu(env);
     int hdice;
-
 #if 0
+    CPUState *cs = CPU(cpu);
+
     qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
-                __func__, env, env->pending_interrupts,
-                env->interrupt_request, (int)msr_me, (int)msr_ee);
+                  __func__, env, env->pending_interrupts,
+                  cs->interrupt_request, (int)msr_me, (int)msr_ee);
 #endif
     /* External reset */
     if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
@@ -807,9 +810,12 @@ void helper_raise_exception(CPUPPCState *env, uint32_t exception)
 #if !defined(CONFIG_USER_ONLY)
 void helper_store_msr(CPUPPCState *env, target_ulong val)
 {
+    CPUState *cs;
+
     val = hreg_store_msr(env, val, 0);
     if (val != 0) {
-        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+        cs = CPU(ppc_env_get_cpu(env));
+        cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
         helper_raise_exception(env, val);
     }
 }
@@ -817,6 +823,8 @@ void helper_store_msr(CPUPPCState *env, target_ulong val)
 static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
                           target_ulong msrm, int keep_msrh)
 {
+    CPUState *cs = CPU(ppc_env_get_cpu(env));
+
 #if defined(TARGET_PPC64)
     if (msr_is_64bit(env, msr)) {
         nip = (uint64_t)nip;
@@ -841,7 +849,7 @@ static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
     /* No need to raise an exception here,
      * as rfi is always the last insn of a TB
      */
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
 
 void helper_rfi(CPUPPCState *env)
diff --git a/target-ppc/helper_regs.h b/target-ppc/helper_regs.h
index 3c98850..a6d5e2f 100644
--- a/target-ppc/helper_regs.h
+++ b/target-ppc/helper_regs.h
@@ -68,10 +68,13 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
                                  int alter_hv)
 {
     int excp;
+#if !defined(CONFIG_USER_ONLY)
+    CPUState *cs = CPU(ppc_env_get_cpu(env));
+#endif
 
     excp = 0;
     value &= env->msr_mask;
-#if !defined (CONFIG_USER_ONLY)
+#if !defined(CONFIG_USER_ONLY)
     if (!alter_hv) {
         /* mtmsr cannot alter the hypervisor state */
         value &= ~MSR_HVB;
@@ -82,7 +85,7 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
         /* Flush all tlb when changing translation mode */
         tlb_flush(env, 1);
         excp = POWERPC_EXCP_NONE;
-        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+        cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
     }
     if (unlikely((env->flags & POWERPC_FLAG_TGPR) &&
                  ((value ^ env->msr) & (1 << MSR_TGPR)))) {
@@ -96,10 +99,10 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
 #endif
     env->msr = value;
     hreg_compute_hflags(env);
-#if !defined (CONFIG_USER_ONLY)
+#if !defined(CONFIG_USER_ONLY)
     if (unlikely(msr_pow == 1)) {
         if ((*env->check_pow)(env)) {
-            env->halted = 1;
+            cs->halted = 1;
             excp = EXCP_HALTED;
         }
     }
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 2c64c63..ee935d8 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -760,7 +760,7 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
      * interrupt, reset, etc) in PPC-specific env->irq_input_state. */
     if (!cap_interrupt_level &&
         run->ready_for_interrupt_injection &&
-        (env->interrupt_request & CPU_INTERRUPT_HARD) &&
+        (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
         (env->irq_input_state & (1<<PPC_INPUT_INT)))
     {
         /* For now KVM disregards the 'irq' argument. However, in the
@@ -791,14 +791,16 @@ void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run)
 
 int kvm_arch_process_async_events(CPUState *cs)
 {
-    PowerPCCPU *cpu = POWERPC_CPU(cs);
-    return cpu->env.halted;
+    return cs->halted;
 }
 
-static int kvmppc_handle_halt(CPUPPCState *env)
+static int kvmppc_handle_halt(PowerPCCPU *cpu)
 {
-    if (!(env->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) {
-        env->halted = 1;
+    CPUState *cs = CPU(cpu);
+    CPUPPCState *env = &cpu->env;
+
+    if (!(cs->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) {
+        cs->halted = 1;
         env->exception_index = EXCP_HLT;
     }
 
@@ -840,7 +842,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
         break;
     case KVM_EXIT_HLT:
         dprintf("handle halt\n");
-        ret = kvmppc_handle_halt(env);
+        ret = kvmppc_handle_halt(cpu);
         break;
 #ifdef CONFIG_PSERIES
     case KVM_EXIT_PAPR_HCALL:
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 2ac5794..4d50198 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3243,7 +3243,8 @@ static void gen_sync(DisasContext *ctx)
 static void gen_wait(DisasContext *ctx)
 {
     TCGv_i32 t0 = tcg_temp_new_i32();
-    tcg_gen_st_i32(t0, cpu_env, offsetof(CPUPPCState, halted));
+    tcg_gen_st_i32(t0, cpu_env,
+                   -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
     tcg_temp_free_i32(t0);
     /* Stop translation, as the CPU is supposed to sleep from now */
     gen_exception_err(ctx, EXCP_HLT, 1);
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index b746547..738a0ad 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -80,10 +80,10 @@ static void s390_cpu_reset(CPUState *s)
     env->cregs[0] = CR0_RESET;
     env->cregs[14] = CR14_RESET;
     /* set halted to 1 to make sure we can add the cpu in
-     * s390_ipl_cpu code, where env->halted is set back to 0
+     * s390_ipl_cpu code, where CPUState::halted is set back to 0
      * after incrementing the cpu counter */
 #if !defined(CONFIG_USER_ONLY)
-    env->halted = 1;
+    s->halted = 1;
 #endif
     tlb_flush(env, 1);
 }
@@ -129,10 +129,10 @@ static void s390_cpu_initfn(Object *obj)
     env->tod_basetime = 0;
     env->tod_timer = qemu_new_timer_ns(vm_clock, s390x_tod_timer, cpu);
     env->cpu_timer = qemu_new_timer_ns(vm_clock, s390x_cpu_timer, cpu);
-    /* set env->halted state to 1 to avoid decrementing the running
+    /* set CPUState::halted state to 1 to avoid decrementing the running
      * cpu counter in s390_cpu_reset to a negative number at
      * initial ipl */
-    env->halted = 1;
+    cs->halted = 1;
 #endif
     env->cpu_num = cpu_num++;
     env->ext_index = -1;
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 0070c40..e6997ef 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -1039,9 +1039,10 @@ static inline void cpu_inject_crw_mchk(S390CPU *cpu)
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUS390XState *env = &S390_CPU(cpu)->env;
+    S390CPU *s390_cpu = S390_CPU(cpu);
+    CPUS390XState *env = &s390_cpu->env;
 
-    return (env->interrupt_request & CPU_INTERRUPT_HARD) &&
+    return (cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
         (env->psw.mask & PSW_MASK_EXT);
 }
 
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index bc6fc4c..3a54651 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -437,6 +437,7 @@ void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
 {
     if (mask & PSW_MASK_WAIT) {
         S390CPU *cpu = s390_env_get_cpu(env);
+        CPUState *cs = CPU(cpu);
         if (!(mask & (PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK))) {
             if (s390_del_running_cpu(cpu) == 0) {
 #ifndef CONFIG_USER_ONLY
@@ -444,7 +445,7 @@ void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
 #endif
             }
         }
-        env->halted = 1;
+        cs->halted = 1;
         env->exception_index = EXCP_HLT;
     }
 
@@ -734,6 +735,7 @@ static void do_mchk_interrupt(CPUS390XState *env)
 void do_interrupt(CPUS390XState *env)
 {
     S390CPU *cpu = s390_env_get_cpu(env);
+    CPUState *cs;
 
     qemu_log_mask(CPU_LOG_INT, "%s: %d at pc=%" PRIx64 "\n",
                   __func__, env->exception_index, env->psw.addr);
@@ -792,7 +794,8 @@ void do_interrupt(CPUS390XState *env)
     env->exception_index = -1;
 
     if (!env->pending_int) {
-        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+        cs = CPU(s390_env_get_cpu(env));
+        cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
     }
 }
 
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 49dcd9e..926ec41 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -372,9 +372,7 @@ static inline void cpu_get_tb_cpu_state(CPUSH4State *env, target_ulong *pc,
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUSH4State *env = &SUPERH_CPU(cpu)->env;
-
-    return env->interrupt_request & CPU_INTERRUPT_HARD;
+    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
 #include "exec/exec-all.h"
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index ddebc78..fd4efee 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -78,9 +78,10 @@ int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
 #define MMU_DADDR_ERROR_READ     (-12)
 #define MMU_DADDR_ERROR_WRITE    (-13)
 
-void do_interrupt(CPUSH4State * env)
+void do_interrupt(CPUSH4State *env)
 {
-    int do_irq = env->interrupt_request & CPU_INTERRUPT_HARD;
+    CPUState *cs = CPU(sh_env_get_cpu(env));
+    int do_irq = cs->interrupt_request & CPU_INTERRUPT_HARD;
     int do_exp, irq_vector = env->exception_index;
 
     /* prioritize exceptions over interrupts */
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index 09e3d23..e955e81 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -102,7 +102,9 @@ void helper_debug(CPUSH4State *env)
 
 void helper_sleep(CPUSH4State *env)
 {
-    env->halted = 1;
+    CPUState *cs = CPU(sh_env_get_cpu(env));
+
+    cs->halted = 1;
     env->in_sleep = 1;
     raise_exception(env, EXCP_HLT, 0);
 }
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 7389b03..95cbba0 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -761,9 +761,10 @@ static inline bool tb_am_enabled(int tb_flags)
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUSPARCState *env1 = &SPARC_CPU(cpu)->env;
+    SPARCCPU *sparc_cpu = SPARC_CPU(cpu);
+    CPUSPARCState *env1 = &sparc_cpu->env;
 
-    return (env1->interrupt_request & CPU_INTERRUPT_HARD) &&
+    return (cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
            cpu_interrupts_enabled(env1);
 }
 
diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
index ae9a9d6..58f1f20 100644
--- a/target-unicore32/cpu.h
+++ b/target-unicore32/cpu.h
@@ -181,9 +181,7 @@ void switch_mode(CPUUniCore32State *, int);
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUUniCore32State *env = &UNICORE32_CPU(cpu)->env;
-
-    return env->interrupt_request &
+    return cpu->interrupt_request &
         (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
 }
 
diff --git a/target-unicore32/softmmu.c b/target-unicore32/softmmu.c
index fc27100..1c4c7f5 100644
--- a/target-unicore32/softmmu.c
+++ b/target-unicore32/softmmu.c
@@ -74,6 +74,7 @@ void switch_mode(CPUUniCore32State *env, int mode)
 /* Handle a CPU exception.  */
 void do_interrupt(CPUUniCore32State *env)
 {
+    CPUState *cs = CPU(uc32_env_get_cpu(env));
     uint32_t addr;
     int new_mode;
 
@@ -112,7 +113,7 @@ void do_interrupt(CPUUniCore32State *env)
     /* The PC already points to the proper instruction.  */
     env->regs[30] = env->regs[31];
     env->regs[31] = addr;
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
 
 static int get_phys_addr_ucv2(CPUUniCore32State *env, uint32_t address,
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 3813a72..1037101 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -373,6 +373,8 @@ void HELPER(dump_state)(CPUXtensaState *env)
 
 void HELPER(waiti)(CPUXtensaState *env, uint32_t pc, uint32_t intlevel)
 {
+    CPUState *cpu;
+
     env->pc = pc;
     env->sregs[PS] = (env->sregs[PS] & ~PS_INTLEVEL) |
         (intlevel << PS_INTLEVEL_SHIFT);
@@ -382,8 +384,9 @@ void HELPER(waiti)(CPUXtensaState *env, uint32_t pc, uint32_t intlevel)
         return;
     }
 
+    cpu = CPU(xtensa_env_get_cpu(env));
     env->halt_clock = qemu_get_clock_ns(vm_clock);
-    env->halted = 1;
+    cpu->halted = 1;
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
         xtensa_rearm_ccompare_timer(env);
     }
diff --git a/translate-all.c b/translate-all.c
index 19bc414..2176132 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1087,8 +1087,8 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
             tb_phys_invalidate(tb, -1);
             if (cpu != NULL) {
                 cpu->current_tb = saved_tb;
-                if (env && env->interrupt_request && cpu->current_tb) {
-                    cpu_interrupt(env, env->interrupt_request);
+                if (env && cpu->interrupt_request && cpu->current_tb) {
+                    cpu_interrupt(env, cpu->interrupt_request);
                 }
             }
         }
@@ -1465,8 +1465,8 @@ static void tcg_handle_interrupt(CPUArchState *env, int mask)
     CPUState *cpu = ENV_GET_CPU(env);
     int old_mask;
 
-    old_mask = env->interrupt_request;
-    env->interrupt_request |= mask;
+    old_mask = cpu->interrupt_request;
+    cpu->interrupt_request |= mask;
 
     /*
      * If called from iothread context, wake the target cpu in
@@ -1626,7 +1626,7 @@ void cpu_interrupt(CPUArchState *env, int mask)
 {
     CPUState *cpu = ENV_GET_CPU(env);
 
-    env->interrupt_request |= mask;
+    cpu->interrupt_request |= mask;
     cpu_unlink_tb(cpu);
 }
 
diff --git a/xen-all.c b/xen-all.c
index 110f958..8c05843 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -578,16 +578,18 @@ void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
 
 static void xen_reset_vcpu(void *opaque)
 {
-    CPUArchState *env = opaque;
+    CPUState *cpu = opaque;
 
-    env->halted = 1;
+    cpu->halted = 1;
 }
 
 void xen_vcpu_init(void)
 {
     if (first_cpu != NULL) {
-        qemu_register_reset(xen_reset_vcpu, first_cpu);
-        xen_reset_vcpu(first_cpu);
+        CPUState *cpu = ENV_GET_CPU(first_cpu);
+
+        qemu_register_reset(xen_reset_vcpu, cpu);
+        xen_reset_vcpu(cpu);
     }
     /* if rtc_clock is left to default (host_clock), disable it */
     if (rtc_clock == host_clock) {
-- 
1.7.10.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

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

* [Qemu-devel] [RFC qom-cpu-next 5/9] cpu: Move halted and interrupt_request fields to CPUState
@ 2013-02-02 11:57   ` Andreas Färber
  0 siblings, 0 replies; 12+ messages in thread
From: Andreas Färber @ 2013-02-02 11:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Guan Xuetao, open list:Overall, Gleb Natapov,
	Stefano Stabellini, Marcelo Tosatti, Alexander Graf,
	Fabien Chouteau, Blue Swirl, Max Filippov, Michael Walle,
	open list:X86, open list:e500, Paul Brook, Scott Wood,
	Edgar E. Iglesias, Richard Henderson, Andreas Färber,
	Aurelien Jarno, David Gibson

Both fields are used in VMState, thus need to be moved together.
Explicitly zero them on reset since they were located before
breakpoints.

Pass PowerPCCPU to kvmppc_handle_halt().

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 cpu-exec.c                         |   34 ++++++++++++------------
 cpus.c                             |    4 +--
 exec.c                             |   16 +++++++-----
 gdbstub.c                          |    2 +-
 hw/leon3.c                         |    5 ++--
 hw/omap1.c                         |    7 +++--
 hw/openrisc_timer.c                |    4 ++-
 hw/ppc.c                           |   22 ++++++++++------
 hw/ppc/e500.c                      |   10 +++++---
 hw/ppce500_spin.c                  |    2 +-
 hw/pxa2xx_gpio.c                   |    3 ++-
 hw/pxa2xx_pic.c                    |    3 ++-
 hw/s390x/s390-virtio.c             |   14 ++++++----
 hw/spapr.c                         |   10 +++++---
 hw/spapr_hcall.c                   |    2 +-
 hw/spapr_rtas.c                    |    6 ++---
 hw/sun4m.c                         |   21 ++++++++-------
 hw/sun4u.c                         |   15 +++++++----
 hw/xen_machine_pv.c                |    6 ++---
 hw/xtensa_pic.c                    |    8 +++---
 include/exec/cpu-defs.h            |    2 --
 include/qom/cpu.h                  |    4 +++
 kvm-all.c                          |    2 +-
 qom/cpu.c                          |    2 ++
 target-alpha/cpu.h                 |    4 +--
 target-alpha/translate.c           |    3 ++-
 target-arm/cpu.h                   |    4 +--
 target-arm/helper.c                |    4 ++-
 target-arm/op_helper.c             |    4 ++-
 target-cris/cpu.h                  |    4 +--
 target-cris/helper.c               |    9 ++++---
 target-cris/translate.c            |    3 ++-
 target-i386/cpu.c                  |    2 +-
 target-i386/cpu.h                  |   20 ++++++++-------
 target-i386/helper.c               |   12 +++++----
 target-i386/kvm.c                  |   50 +++++++++++++++++++-----------------
 target-i386/misc_helper.c          |   21 ++++++++++-----
 target-i386/svm_helper.c           |    9 ++++---
 target-lm32/cpu.h                  |    4 +--
 target-lm32/op_helper.c            |    4 ++-
 target-m68k/cpu.h                  |    4 +--
 target-m68k/op_helper.c            |    4 ++-
 target-m68k/qregs.def              |    1 -
 target-m68k/translate.c            |    8 +++++-
 target-microblaze/cpu.h            |    4 +--
 target-mips/cpu.h                  |    4 +--
 target-mips/op_helper.c            |   10 +++++---
 target-mips/translate.c            |    4 +--
 target-openrisc/cpu.h              |    4 +--
 target-openrisc/interrupt_helper.c |    3 ++-
 target-openrisc/sys_helper.c       |    3 ++-
 target-ppc/cpu.h                   |    5 ++--
 target-ppc/excp_helper.c           |   22 +++++++++++-----
 target-ppc/helper_regs.h           |   11 +++++---
 target-ppc/kvm.c                   |   16 +++++++-----
 target-ppc/translate.c             |    3 ++-
 target-s390x/cpu.c                 |    8 +++---
 target-s390x/cpu.h                 |    5 ++--
 target-s390x/helper.c              |    7 +++--
 target-sh4/cpu.h                   |    4 +--
 target-sh4/helper.c                |    5 ++--
 target-sh4/op_helper.c             |    4 ++-
 target-sparc/cpu.h                 |    5 ++--
 target-unicore32/cpu.h             |    4 +--
 target-unicore32/softmmu.c         |    3 ++-
 target-xtensa/op_helper.c          |    5 +++-
 translate-all.c                    |   10 ++++----
 xen-all.c                          |   10 +++++---
 68 Dateien geändert, 315 Zeilen hinzugefügt(+), 222 Zeilen entfernt(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index 83ddea4..191a19b 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -190,12 +190,12 @@ int cpu_exec(CPUArchState *env)
     uint8_t *tc_ptr;
     tcg_target_ulong next_tb;
 
-    if (env->halted) {
+    if (cpu->halted) {
         if (!cpu_has_work(cpu)) {
             return EXCP_HALTED;
         }
 
-        env->halted = 0;
+        cpu->halted = 0;
     }
 
     cpu_single_env = env;
@@ -265,14 +265,14 @@ int cpu_exec(CPUArchState *env)
 
             next_tb = 0; /* force lookup of first TB */
             for(;;) {
-                interrupt_request = env->interrupt_request;
+                interrupt_request = cpu->interrupt_request;
                 if (unlikely(interrupt_request)) {
                     if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
                         /* Mask out external interrupts for this step. */
                         interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
                     }
                     if (interrupt_request & CPU_INTERRUPT_DEBUG) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
+                        cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
                         env->exception_index = EXCP_DEBUG;
                         cpu_loop_exit(env);
                     }
@@ -280,8 +280,8 @@ int cpu_exec(CPUArchState *env)
     defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
     defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
                     if (interrupt_request & CPU_INTERRUPT_HALT) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
-                        env->halted = 1;
+                        cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
+                        cpu->halted = 1;
                         env->exception_index = EXCP_HLT;
                         cpu_loop_exit(env);
                     }
@@ -289,7 +289,7 @@ int cpu_exec(CPUArchState *env)
 #if defined(TARGET_I386)
 #if !defined(CONFIG_USER_ONLY)
                     if (interrupt_request & CPU_INTERRUPT_POLL) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_POLL;
+                        cpu->interrupt_request &= ~CPU_INTERRUPT_POLL;
                         apic_poll_irq(env->apic_state);
                     }
 #endif
@@ -306,17 +306,17 @@ int cpu_exec(CPUArchState *env)
                             !(env->hflags & HF_SMM_MASK)) {
                             cpu_svm_check_intercept_param(env, SVM_EXIT_SMI,
                                                           0);
-                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
+                            cpu->interrupt_request &= ~CPU_INTERRUPT_SMI;
                             do_smm_enter(env);
                             next_tb = 0;
                         } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
                                    !(env->hflags2 & HF2_NMI_MASK)) {
-                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
+                            cpu->interrupt_request &= ~CPU_INTERRUPT_NMI;
                             env->hflags2 |= HF2_NMI_MASK;
                             do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
                             next_tb = 0;
                         } else if (interrupt_request & CPU_INTERRUPT_MCE) {
-                            env->interrupt_request &= ~CPU_INTERRUPT_MCE;
+                            cpu->interrupt_request &= ~CPU_INTERRUPT_MCE;
                             do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
                             next_tb = 0;
                         } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
@@ -328,7 +328,8 @@ int cpu_exec(CPUArchState *env)
                             int intno;
                             cpu_svm_check_intercept_param(env, SVM_EXIT_INTR,
                                                           0);
-                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
+                            cpu->interrupt_request &= ~(CPU_INTERRUPT_HARD |
+                                                        CPU_INTERRUPT_VIRQ);
                             intno = cpu_get_pic_interrupt(env);
                             qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
                             do_interrupt_x86_hardirq(env, intno, 1);
@@ -346,7 +347,7 @@ int cpu_exec(CPUArchState *env)
                             intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
                             qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
                             do_interrupt_x86_hardirq(env, intno, 1);
-                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
+                            cpu->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
                             next_tb = 0;
 #endif
                         }
@@ -357,8 +358,9 @@ int cpu_exec(CPUArchState *env)
                     }
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
                         ppc_hw_interrupt(env);
-                        if (env->pending_interrupts == 0)
-                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+                        if (env->pending_interrupts == 0) {
+                            cpu->interrupt_request &= ~CPU_INTERRUPT_HARD;
+                        }
                         next_tb = 0;
                     }
 #elif defined(TARGET_LM32)
@@ -535,8 +537,8 @@ int cpu_exec(CPUArchState *env)
 #endif
                    /* Don't use the cached interrupt_request value,
                       do_interrupt may have updated the EXITTB flag. */
-                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
+                    if (cpu->interrupt_request & CPU_INTERRUPT_EXITTB) {
+                        cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
                         /* ensure that no TB jump will be modified as
                            the program flow was changed */
                         next_tb = 0;
diff --git a/cpus.c b/cpus.c
index 41779eb..8b5f426 100644
--- a/cpus.c
+++ b/cpus.c
@@ -72,7 +72,7 @@ static bool cpu_thread_is_idle(CPUArchState *env)
     if (cpu->stopped || !runstate_is_running()) {
         return true;
     }
-    if (!env->halted || qemu_cpu_has_work(cpu) ||
+    if (!cpu->halted || qemu_cpu_has_work(cpu) ||
         kvm_async_interrupts_enabled()) {
         return false;
     }
@@ -1219,7 +1219,7 @@ CpuInfoList *qmp_query_cpus(Error **errp)
         info->value = g_malloc0(sizeof(*info->value));
         info->value->CPU = cpu->cpu_index;
         info->value->current = (env == first_cpu);
-        info->value->halted = env->halted;
+        info->value->halted = cpu->halted;
         info->value->thread_id = cpu->thread_id;
 #if defined(TARGET_I386)
         info->value->has_pc = true;
diff --git a/exec.c b/exec.c
index a41bcb8..5ab7af4 100644
--- a/exec.c
+++ b/exec.c
@@ -223,12 +223,12 @@ void cpu_exec_init_all(void)
 
 static int cpu_common_post_load(void *opaque, int version_id)
 {
-    CPUArchState *env = opaque;
+    CPUState *cpu = opaque;
 
     /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
        version_id is increased. */
-    env->interrupt_request &= ~0x01;
-    tlb_flush(env, 1);
+    cpu->interrupt_request &= ~0x01;
+    tlb_flush(cpu->env_ptr, 1);
 
     return 0;
 }
@@ -240,8 +240,8 @@ static const VMStateDescription vmstate_cpu_common = {
     .minimum_version_id_old = 1,
     .post_load = cpu_common_post_load,
     .fields      = (VMStateField []) {
-        VMSTATE_UINT32(halted, CPUArchState),
-        VMSTATE_UINT32(interrupt_request, CPUArchState),
+        VMSTATE_UINT32(halted, CPUState),
+        VMSTATE_UINT32(interrupt_request, CPUState),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -291,7 +291,7 @@ void cpu_exec_init(CPUArchState *env)
     cpu_list_unlock();
 #endif
 #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
-    vmstate_register(NULL, cpu_index, &vmstate_cpu_common, env);
+    vmstate_register(NULL, cpu_index, &vmstate_cpu_common, cpu);
     register_savevm(NULL, "cpu", cpu_index, CPU_SAVE_VERSION,
                     cpu_save, cpu_load, env);
 #endif
@@ -487,7 +487,9 @@ void cpu_single_step(CPUArchState *env, int enabled)
 
 void cpu_reset_interrupt(CPUArchState *env, int mask)
 {
-    env->interrupt_request &= ~mask;
+    CPUState *cpu = ENV_GET_CPU(env);
+
+    cpu->interrupt_request &= ~mask;
 }
 
 void cpu_exit(CPUArchState *env)
diff --git a/gdbstub.c b/gdbstub.c
index 32dfea9..846de1c 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2408,7 +2408,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
                 cpu_synchronize_state(env);
                 len = snprintf((char *)mem_buf, sizeof(mem_buf),
                                "CPU#%d [%s]", cpu->cpu_index,
-                               env->halted ? "halted " : "running");
+                               cpu->halted ? "halted " : "running");
                 memtohex(buf, mem_buf, len);
                 put_packet(s, buf);
             }
diff --git a/hw/leon3.c b/hw/leon3.c
index f16a8bb..e971d5c 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -49,11 +49,12 @@ typedef struct ResetData {
 static void main_cpu_reset(void *opaque)
 {
     ResetData *s   = (ResetData *)opaque;
+    CPUState *cpu = CPU(s->cpu);
     CPUSPARCState  *env = &s->cpu->env;
 
-    cpu_reset(CPU(s->cpu));
+    cpu_reset(cpu);
 
-    env->halted = 0;
+    cpu->halted = 0;
     env->pc     = s->entry;
     env->npc    = s->entry + 4;
 }
diff --git a/hw/omap1.c b/hw/omap1.c
index 623b101..c36a330 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -1721,6 +1721,7 @@ static uint64_t omap_clkdsp_read(void *opaque, hwaddr addr,
                                  unsigned size)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    CPUState *cpu = CPU(s->cpu);
 
     if (size != 2) {
         return omap_badwidth_read16(opaque, addr);
@@ -1737,8 +1738,9 @@ static uint64_t omap_clkdsp_read(void *opaque, hwaddr addr,
         return s->clkm.dsp_rstct2;
 
     case 0x18:	/* DSP_SYSST */
+        cpu = CPU(s->cpu);
         return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
-                (s->cpu->env.halted << 6);      /* Quite useless... */
+                (cpu->halted << 6);      /* Quite useless... */
     }
 
     OMAP_BAD_REG(addr);
@@ -3754,8 +3756,9 @@ static void omap_setup_dsp_mapping(MemoryRegion *system_memory,
 void omap_mpu_wakeup(void *opaque, int irq, int req)
 {
     struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
+    CPUState *cpu = CPU(mpu->cpu);
 
-    if (mpu->cpu->env.halted) {
+    if (cpu->halted) {
         cpu_interrupt(&mpu->cpu->env, CPU_INTERRUPT_EXITTB);
     }
 }
diff --git a/hw/openrisc_timer.c b/hw/openrisc_timer.c
index d965be7..f9f116a 100644
--- a/hw/openrisc_timer.c
+++ b/hw/openrisc_timer.c
@@ -73,8 +73,10 @@ static void openrisc_timer_cb(void *opaque)
 
     if ((cpu->env.ttmr & TTMR_IE) &&
          qemu_timer_expired(cpu->env.timer, qemu_get_clock_ns(vm_clock))) {
+        CPUState *cs = CPU(cpu);
+
         cpu->env.ttmr |= TTMR_IP;
-        cpu->env.interrupt_request |= CPU_INTERRUPT_TIMER;
+        cs->interrupt_request |= CPU_INTERRUPT_TIMER;
     }
 
     switch (cpu->env.ttmr & TTMR_M) {
diff --git a/hw/ppc.c b/hw/ppc.c
index 89352be..400daab 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -72,7 +72,7 @@ void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
 
     LOG_IRQ("%s: %p n_IRQ %d level %d => pending %08" PRIx32
                 "req %08x\n", __func__, env, n_IRQ, level,
-                env->pending_interrupts, env->interrupt_request);
+                env->pending_interrupts, CPU(cpu)->interrupt_request);
 }
 
 /* PowerPC 6xx / 7xx internal IRQ controller */
@@ -87,6 +87,8 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
     cur_level = (env->irq_input_state >> pin) & 1;
     /* Don't generate spurious events */
     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        CPUState *cs = CPU(cpu);
+
         switch (pin) {
         case PPC6xx_INPUT_TBEN:
             /* Level sensitive - active high */
@@ -126,7 +128,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
             /* XXX: Note that the only way to restart the CPU is to reset it */
             if (level) {
                 LOG_IRQ("%s: stop the CPU\n", __func__);
-                env->halted = 1;
+                cs->halted = 1;
             }
             break;
         case PPC6xx_INPUT_HRESET:
@@ -174,6 +176,8 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
     cur_level = (env->irq_input_state >> pin) & 1;
     /* Don't generate spurious events */
     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        CPUState *cs = CPU(cpu);
+
         switch (pin) {
         case PPC970_INPUT_INT:
             /* Level sensitive - active high */
@@ -203,11 +207,11 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
             /* XXX: TODO: relay the signal to CKSTP_OUT pin */
             if (level) {
                 LOG_IRQ("%s: stop the CPU\n", __func__);
-                env->halted = 1;
+                cs->halted = 1;
             } else {
                 LOG_IRQ("%s: restart the CPU\n", __func__);
-                env->halted = 0;
-                qemu_cpu_kick(CPU(cpu));
+                cs->halted = 0;
+                qemu_cpu_kick(cs);
             }
             break;
         case PPC970_INPUT_HRESET:
@@ -295,6 +299,8 @@ static void ppc40x_set_irq(void *opaque, int pin, int level)
     cur_level = (env->irq_input_state >> pin) & 1;
     /* Don't generate spurious events */
     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        CPUState *cs = CPU(cpu);
+
         switch (pin) {
         case PPC40x_INPUT_RESET_SYS:
             if (level) {
@@ -332,11 +338,11 @@ static void ppc40x_set_irq(void *opaque, int pin, int level)
             /* Level sensitive - active low */
             if (level) {
                 LOG_IRQ("%s: stop the CPU\n", __func__);
-                env->halted = 1;
+                cs->halted = 1;
             } else {
                 LOG_IRQ("%s: restart the CPU\n", __func__);
-                env->halted = 0;
-                qemu_cpu_kick(CPU(cpu));
+                cs->halted = 0;
+                qemu_cpu_kick(cs);
             }
             break;
         case PPC40x_INPUT_DEBUG:
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index b7474c0..265d75c 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -425,26 +425,28 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env)
 static void ppce500_cpu_reset_sec(void *opaque)
 {
     PowerPCCPU *cpu = opaque;
+    CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
 
-    cpu_reset(CPU(cpu));
+    cpu_reset(cs);
 
     /* Secondary CPU starts in halted state for now. Needs to change when
        implementing non-kernel boot. */
-    env->halted = 1;
+    cs->halted = 1;
     env->exception_index = EXCP_HLT;
 }
 
 static void ppce500_cpu_reset(void *opaque)
 {
     PowerPCCPU *cpu = opaque;
+    CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
     struct boot_info *bi = env->load_info;
 
-    cpu_reset(CPU(cpu));
+    cpu_reset(cs);
 
     /* Set initial guest state. */
-    env->halted = 0;
+    cs->halted = 0;
     env->gpr[1] = (16<<20) - 8;
     env->gpr[3] = bi->dt_base;
     env->nip = bi->entry;
diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
index 7e90fb9..0d20a43 100644
--- a/hw/ppce500_spin.c
+++ b/hw/ppce500_spin.c
@@ -112,7 +112,7 @@ static void spin_kick(void *data)
     map_start = ldq_p(&curspin->addr) & ~(map_size - 1);
     mmubooke_create_initial_mapping(env, 0, map_start, map_size);
 
-    env->halted = 0;
+    cpu->halted = 0;
     env->exception_index = -1;
     cpu->stopped = false;
     qemu_cpu_kick(cpu);
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index 05d2ad2..f00d150 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -93,6 +93,7 @@ static const int pxa2xx_gpio_wake[PXA2XX_GPIO_BANKS] = {
 static void pxa2xx_gpio_set(void *opaque, int line, int level)
 {
     PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
+    CPUState *cpu = CPU(s->cpu);
     int bank;
     uint32_t mask;
 
@@ -118,7 +119,7 @@ static void pxa2xx_gpio_set(void *opaque, int line, int level)
         pxa2xx_gpio_irq_update(s);
 
     /* Wake-up GPIOs */
-    if (s->cpu->env.halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
+    if (cpu->halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
         cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
     }
 }
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 90b8fef..c73e709 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -46,8 +46,9 @@ static void pxa2xx_pic_update(void *opaque)
 {
     uint32_t mask[2];
     PXA2xxPICState *s = (PXA2xxPICState *) opaque;
+    CPUState *cpu = CPU(s->cpu);
 
-    if (s->cpu->env.halted) {
+    if (cpu->halted) {
         mask[0] = s->int_pending[0] & (s->int_enabled[0] | s->int_idle);
         mask[1] = s->int_pending[1] & (s->int_enabled[1] | s->int_idle);
         if (mask[0] || mask[1]) {
diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c
index e25c330..ca275bd 100644
--- a/hw/s390x/s390-virtio.c
+++ b/hw/s390x/s390-virtio.c
@@ -132,23 +132,25 @@ static unsigned s390_running_cpus;
 
 void s390_add_running_cpu(S390CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUS390XState *env = &cpu->env;
 
-    if (env->halted) {
+    if (cs->halted) {
         s390_running_cpus++;
-        env->halted = 0;
+        cs->halted = 0;
         env->exception_index = -1;
     }
 }
 
 unsigned s390_del_running_cpu(S390CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUS390XState *env = &cpu->env;
 
-    if (env->halted == 0) {
+    if (cs->halted == 0) {
         assert(s390_running_cpus >= 1);
         s390_running_cpus--;
-        env->halted = 1;
+        cs->halted = 1;
         env->exception_index = EXCP_HLT;
     }
     return s390_running_cpus;
@@ -183,11 +185,13 @@ void s390_init_cpus(const char *cpu_model, uint8_t *storage_keys)
 
     for (i = 0; i < smp_cpus; i++) {
         S390CPU *cpu;
+        CPUState *cs;
 
         cpu = cpu_s390x_init(cpu_model);
+        cs = CPU(cpu);
 
         ipi_states[i] = cpu;
-        cpu->env.halted = 1;
+        cs->halted = 1;
         cpu->env.exception_index = EXCP_HLT;
         cpu->env.storage_keys = storage_keys;
     }
diff --git a/hw/spapr.c b/hw/spapr.c
index e88a27a..da5181c 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -616,6 +616,8 @@ static void spapr_reset_htab(sPAPREnvironment *spapr)
 
 static void ppc_spapr_reset(void)
 {
+    CPUState *first_cpu_cpu;
+
     /* Reset the hash table & recalc the RMA */
     spapr_reset_htab(spapr);
 
@@ -626,9 +628,10 @@ static void ppc_spapr_reset(void)
                        spapr->rtas_size);
 
     /* Set up the entry state */
+    first_cpu_cpu = CPU(first_cpu);
     first_cpu->gpr[3] = spapr->fdt_addr;
     first_cpu->gpr[5] = 0;
-    first_cpu->halted = 0;
+    first_cpu_cpu->halted = 0;
     first_cpu->nip = spapr->entry_point;
 
 }
@@ -636,14 +639,15 @@ static void ppc_spapr_reset(void)
 static void spapr_cpu_reset(void *opaque)
 {
     PowerPCCPU *cpu = opaque;
+    CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
 
-    cpu_reset(CPU(cpu));
+    cpu_reset(cs);
 
     /* All CPUs start halted.  CPU0 is unhalted from the machine level
      * reset code and the rest are explicitly started up by the guest
      * using an RTAS call */
-    env->halted = 1;
+    cs->halted = 1;
 
     env->spr[SPR_HIOR] = 0;
 
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index af1db6e..7c28144 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -518,7 +518,7 @@ static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     env->msr |= (1ULL << MSR_EE);
     hreg_compute_hflags(env);
     if (!cpu_has_work(cs)) {
-        env->halted = 1;
+        cs->halted = 1;
         env->exception_index = EXCP_HLT;
         cs->exit_request = 1;
     }
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index 5ec787f..a24e853 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -145,7 +145,7 @@ static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
             continue;
         }
 
-        if (env->halted) {
+        if (cpu->halted) {
             rtas_st(rets, 1, 0);
         } else {
             rtas_st(rets, 1, 2);
@@ -184,7 +184,7 @@ static void rtas_start_cpu(sPAPREnvironment *spapr,
             continue;
         }
 
-        if (!env->halted) {
+        if (!cpu->halted) {
             rtas_st(rets, 0, -1);
             return;
         }
@@ -197,7 +197,7 @@ static void rtas_start_cpu(sPAPREnvironment *spapr,
         env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
         env->nip = start;
         env->gpr[3] = r3;
-        env->halted = 0;
+        cpu->halted = 0;
 
         qemu_cpu_kick(cpu);
 
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 9903f44..45f9441 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -256,10 +256,11 @@ void cpu_check_irqs(CPUSPARCState *env)
 static void cpu_kick_irq(SPARCCPU *cpu)
 {
     CPUSPARCState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
-    env->halted = 0;
+    cs->halted = 0;
     cpu_check_irqs(env);
-    qemu_cpu_kick(CPU(cpu));
+    qemu_cpu_kick(cs);
 }
 
 static void cpu_set_irq(void *opaque, int irq, int level)
@@ -285,19 +286,19 @@ static void dummy_cpu_set_irq(void *opaque, int irq, int level)
 static void main_cpu_reset(void *opaque)
 {
     SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
-    cpu_reset(CPU(cpu));
-    env->halted = 0;
+    cpu_reset(cs);
+    cs->halted = 0;
 }
 
 static void secondary_cpu_reset(void *opaque)
 {
     SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
-    cpu_reset(CPU(cpu));
-    env->halted = 1;
+    cpu_reset(cs);
+    cs->halted = 1;
 }
 
 static void cpu_halt_signal(void *opaque, int irq, int level)
@@ -826,6 +827,7 @@ static const TypeInfo ram_info = {
 static void cpu_devinit(const char *cpu_model, unsigned int id,
                         uint64_t prom_addr, qemu_irq **cpu_irqs)
 {
+    CPUState *cs;
     SPARCCPU *cpu;
     CPUSPARCState *env;
 
@@ -841,7 +843,8 @@ static void cpu_devinit(const char *cpu_model, unsigned int id,
         qemu_register_reset(main_cpu_reset, cpu);
     } else {
         qemu_register_reset(secondary_cpu_reset, cpu);
-        env->halted = 1;
+        cs = CPU(cpu);
+        cs->halted = 1;
     }
     *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS);
     env->prom_addr = prom_addr;
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 9fbda29..056bb4d 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -254,6 +254,7 @@ static uint64_t sun4u_load_kernel(const char *kernel_filename,
 
 void cpu_check_irqs(CPUSPARCState *env)
 {
+    CPUState *cs;
     uint32_t pil = env->pil_in |
                   (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));
 
@@ -261,6 +262,7 @@ void cpu_check_irqs(CPUSPARCState *env)
     if (env->ivec_status & 0x20) {
         return;
     }
+    cs = CPU(sparc_env_get_cpu(env));
     /* check if TM or SM in SOFTINT are set
        setting these also causes interrupt 14 */
     if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
@@ -270,7 +272,7 @@ void cpu_check_irqs(CPUSPARCState *env)
     /* The bit corresponding to psrpil is (1<< psrpil), the next bit
        is (2 << psrpil). */
     if (pil < (2 << env->psrpil)){
-        if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+        if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
             CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n",
                            env->interrupt_index);
             env->interrupt_index = 0;
@@ -302,7 +304,7 @@ void cpu_check_irqs(CPUSPARCState *env)
                 break;
             }
         }
-    } else if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+    } else if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
         CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x "
                        "current interrupt %x\n",
                        pil, env->pil_in, env->softint, env->interrupt_index);
@@ -313,22 +315,25 @@ void cpu_check_irqs(CPUSPARCState *env)
 
 static void cpu_kick_irq(SPARCCPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUSPARCState *env = &cpu->env;
 
-    env->halted = 0;
+    cs->halted = 0;
     cpu_check_irqs(env);
-    qemu_cpu_kick(CPU(cpu));
+    qemu_cpu_kick(cs);
 }
 
 static void cpu_set_ivec_irq(void *opaque, int irq, int level)
 {
     SPARCCPU *cpu = opaque;
     CPUSPARCState *env = &cpu->env;
+    CPUState *cs;
 
     if (level) {
         if (!(env->ivec_status & 0x20)) {
             CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
-            env->halted = 0;
+            cs = CPU(cpu);
+            cs->halted = 0;
             env->interrupt_index = TT_IVEC;
             env->ivec_status |= 0x20;
             env->ivec_data[0] = (0x1f << 6) | irq;
diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c
index 66e8981..4fec4fc 100644
--- a/hw/xen_machine_pv.c
+++ b/hw/xen_machine_pv.c
@@ -36,7 +36,7 @@ static void xen_init_pv(QEMUMachineInitArgs *args)
     const char *kernel_cmdline = args->kernel_cmdline;
     const char *initrd_filename = args->initrd_filename;
     X86CPU *cpu;
-    CPUX86State *env;
+    CPUState *cs;
     DriveInfo *dinfo;
     int i;
 
@@ -49,8 +49,8 @@ static void xen_init_pv(QEMUMachineInitArgs *args)
 #endif
     }
     cpu = cpu_x86_init(cpu_model);
-    env = &cpu->env;
-    env->halted = 1;
+    cs = CPU(cpu);
+    cs->halted = 1;
 
     /* Initialize backend core & drivers */
     if (xen_be_init() != 0) {
diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c
index 97d36be..dca15b4 100644
--- a/hw/xtensa_pic.c
+++ b/hw/xtensa_pic.c
@@ -47,6 +47,7 @@ void xtensa_advance_ccount(CPUXtensaState *env, uint32_t d)
 
 void check_interrupts(CPUXtensaState *env)
 {
+    CPUState *cs = CPU(xtensa_env_get_cpu(env));
     int minlevel = xtensa_get_cintlevel(env);
     uint32_t int_set_enabled = env->sregs[INTSET] & env->sregs[INTENABLE];
     int level;
@@ -54,7 +55,7 @@ void check_interrupts(CPUXtensaState *env)
     /* If the CPU is halted advance CCOUNT according to the vm_clock time
      * elapsed since the moment when it was advanced last time.
      */
-    if (env->halted) {
+    if (cs->halted) {
         int64_t now = qemu_get_clock_ns(vm_clock);
 
         xtensa_advance_ccount(env,
@@ -127,11 +128,12 @@ static void xtensa_ccompare_cb(void *opaque)
 {
     XtensaCPU *cpu = opaque;
     CPUXtensaState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
-    if (env->halted) {
+    if (cs->halted) {
         env->halt_clock = qemu_get_clock_ns(vm_clock);
         xtensa_advance_ccount(env, env->wake_ccount - env->sregs[CCOUNT]);
-        if (!cpu_has_work(CPU(cpu))) {
+        if (!cpu_has_work(cs)) {
             env->sregs[CCOUNT] = env->wake_ccount + 1;
             xtensa_rearm_ccompare_timer(env);
         }
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index ae64590..a4c6370 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -156,8 +156,6 @@ typedef struct CPUWatchpoint {
                             accessed */                                 \
     target_ulong mem_io_vaddr; /* target virtual addr at which the      \
                                      memory was accessed */             \
-    uint32_t halted; /* Nonzero if the CPU is in suspend state */       \
-    uint32_t interrupt_request;                                         \
     CPU_COMMON_TLB                                                      \
     struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE];           \
     /* buffer for temporaries in the code generator */                  \
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index ee1a7c8..9ad9822 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -69,6 +69,8 @@ struct kvm_run;
  * @host_tid: Host thread ID.
  * @running: #true if CPU is currently running (usermode).
  * @created: Indicates whether the CPU thread has been successfully created.
+ * @interrupt_request: Indicates a pending interrupt request.
+ * @halted: Nonzero if the CPU is in suspended state.
  * @stop: Indicates a pending stop request.
  * @stopped: Indicates the CPU has been artificially stopped.
  * @env_ptr: Pointer to subclass-specific CPUArchState field.
@@ -100,6 +102,7 @@ struct CPUState {
     bool stop;
     bool stopped;
     volatile sig_atomic_t exit_request;
+    uint32_t interrupt_request;
 
     void *env_ptr; /* CPUArchState */
     struct TranslationBlock *current_tb;
@@ -111,6 +114,7 @@ struct CPUState {
 
     /* TODO Move common fields from CPUArchState here. */
     int cpu_index; /* used by alpha TCG */
+    uint32_t halted; /* used by alpha, cris, ppc TCG */
 };
 
 
diff --git a/kvm-all.c b/kvm-all.c
index 4decfdc..2b761e0 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -830,7 +830,7 @@ static void kvm_handle_interrupt(CPUArchState *env, int mask)
 {
     CPUState *cpu = ENV_GET_CPU(env);
 
-    env->interrupt_request |= mask;
+    cpu->interrupt_request |= mask;
 
     if (!qemu_cpu_is_self(cpu)) {
         qemu_cpu_kick(cpu);
diff --git a/qom/cpu.c b/qom/cpu.c
index 0a2194d..0aa9be7 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -33,7 +33,9 @@ void cpu_reset(CPUState *cpu)
 static void cpu_common_reset(CPUState *cpu)
 {
     cpu->exit_request = 0;
+    cpu->interrupt_request = 0;
     cpu->current_tb = NULL;
+    cpu->halted = 0;
 }
 
 ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index f1db651..90f78ac 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -517,8 +517,6 @@ static inline void cpu_set_tls(CPUAlphaState *env, target_ulong newtls)
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUAlphaState *env = &ALPHA_CPU(cpu)->env;
-
     /* Here we are checking to see if the CPU should wake up from HALT.
        We will have gotten into this state only for WTINT from PALmode.  */
     /* ??? I'm not sure how the IPL state works with WTINT to keep a CPU
@@ -526,7 +524,7 @@ static inline bool cpu_has_work(CPUState *cpu)
        assume that if a CPU really wants to stay asleep, it will mask
        interrupts at the chipset level, which will prevent these bits
        from being set in the first place.  */
-    return env->interrupt_request & (CPU_INTERRUPT_HARD
+    return cpu->interrupt_request & (CPU_INTERRUPT_HARD
                                      | CPU_INTERRUPT_TIMER
                                      | CPU_INTERRUPT_SMP
                                      | CPU_INTERRUPT_MCHK);
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index f687b95..a4f72b8 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1687,7 +1687,8 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
     case 253:
         /* WAIT */
         tmp = tcg_const_i64(1);
-        tcg_gen_st32_i64(tmp, cpu_env, offsetof(CPUAlphaState, halted));
+        tcg_gen_st32_i64(tmp, cpu_env, -offsetof(AlphaCPU, env) +
+                                       offsetof(CPUState, halted));
         return gen_excp(ctx, EXCP_HLT, 0);
 
     case 252:
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 2902ba5..7c47467 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -721,9 +721,7 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUARMState *env = &ARM_CPU(cpu)->env;
-
-    return env->interrupt_request &
+    return cpu->interrupt_request &
         (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
 }
 
diff --git a/target-arm/helper.c b/target-arm/helper.c
index e63da57..31b7a3c 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1802,6 +1802,7 @@ static void do_interrupt_v7m(CPUARMState *env)
 /* Handle a CPU exception.  */
 void do_interrupt(CPUARMState *env)
 {
+    CPUState *cs;
     uint32_t addr;
     uint32_t mask;
     int new_mode;
@@ -1908,7 +1909,8 @@ void do_interrupt(CPUARMState *env)
     }
     env->regs[14] = env->regs[15] + offset;
     env->regs[15] = addr;
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+    cs = CPU(arm_env_get_cpu(env));
+    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
 
 /* Check section/page access permissions.
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 99610d7..7af5187 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -218,8 +218,10 @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift)
 
 void HELPER(wfi)(CPUARMState *env)
 {
+    CPUState *cs = CPU(arm_env_get_cpu(env));
+
     env->exception_index = EXCP_HLT;
-    env->halted = 1;
+    cs->halted = 1;
     cpu_loop_exit(env);
 }
 
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index ebf2d40..2fc7c5c 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -289,9 +289,7 @@ void cris_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUCRISState *env = &CRIS_CPU(cpu)->env;
-
-    return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
+    return cpu->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
 }
 
 #include "exec/exec-all.h"
diff --git a/target-cris/helper.c b/target-cris/helper.c
index de04143..51c9a9f 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -66,6 +66,7 @@ static void cris_shift_ccs(CPUCRISState *env)
 int cpu_cris_handle_mmu_fault(CPUCRISState *env, target_ulong address, int rw,
                               int mmu_idx)
 {
+    D(CPUState *cpu = CPU(cris_env_get_cpu(env)));
     struct cris_mmu_result res;
     int prot, miss;
     int r = -1;
@@ -99,7 +100,7 @@ int cpu_cris_handle_mmu_fault(CPUCRISState *env, target_ulong address, int rw,
     }
     if (r > 0) {
         D_LOG("%s returns %d irqreq=%x addr=%x phy=%x vec=%x pc=%x\n",
-              __func__, r, env->interrupt_request, address, res.phy,
+              __func__, r, cpu->interrupt_request, address, res.phy,
               res.bf_vec, env->pc);
     }
     return r;
@@ -107,11 +108,12 @@ int cpu_cris_handle_mmu_fault(CPUCRISState *env, target_ulong address, int rw,
 
 static void do_interruptv10(CPUCRISState *env)
 {
+    D(CPUState *cpu = CPU(cris_env_get_cpu(env)));
     int ex_vec = -1;
 
     D_LOG("exception index=%d interrupt_req=%d\n",
           env->exception_index,
-          env->interrupt_request);
+          cpu->interrupt_request);
 
     assert(!(env->pregs[PR_CCS] & PFIX_FLAG));
     switch (env->exception_index) {
@@ -162,6 +164,7 @@ static void do_interruptv10(CPUCRISState *env)
 
 void do_interrupt(CPUCRISState *env)
 {
+    D(CPUState *cpu = CPU(cris_env_get_cpu(env)));
     int ex_vec = -1;
 
     if (env->pregs[PR_VR] < 32) {
@@ -170,7 +173,7 @@ void do_interrupt(CPUCRISState *env)
 
     D_LOG("exception index=%d interrupt_req=%d\n",
           env->exception_index,
-          env->interrupt_request);
+          cpu->interrupt_request);
 
     switch (env->exception_index) {
     case EXCP_BREAK:
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 25a43fa..22e5e9f 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -2928,7 +2928,8 @@ static int dec_rfe_etc(CPUCRISState *env, DisasContext *dc)
     cris_cc_mask(dc, 0);
 
     if (dc->op2 == 15) {
-        t_gen_mov_env_TN(halted, tcg_const_tl(1));
+        tcg_gen_st_i32(tcg_const_i32(1), cpu_env,
+                       -offsetof(CRISCPU, env) + offsetof(CPUState, halted));
         tcg_gen_movi_tl(env_pc, dc->pc + 2);
         t_gen_raise_exception(EXCP_HLT);
         return 2;
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 8ad8f22..b892da0 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1980,7 +1980,7 @@ static void x86_cpu_reset(CPUState *s)
         apic_designate_bsp(env->apic_state);
     }
 
-    env->halted = !cpu_is_bsp(cpu);
+    s->halted = !cpu_is_bsp(cpu);
 #endif
 }
 
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 9e6e1a6..40cf246 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -956,6 +956,7 @@ static inline void cpu_x86_load_seg_cache(CPUX86State *env,
 static inline void cpu_x86_load_seg_cache_sipi(X86CPU *cpu,
                                                int sipi_vector)
 {
+    CPUState *cs = CPU(cpu);
     CPUX86State *env = &cpu->env;
 
     env->eip = 0;
@@ -963,7 +964,7 @@ static inline void cpu_x86_load_seg_cache_sipi(X86CPU *cpu,
                            sipi_vector << 12,
                            env->segs[R_CS].limit,
                            env->segs[R_CS].flags);
-    env->halted = 0;
+    cs->halted = 0;
 }
 
 int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
@@ -1157,17 +1158,18 @@ static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp)
 #include "hw/apic.h"
 #endif
 
-static inline bool cpu_has_work(CPUState *cpu)
+static inline bool cpu_has_work(CPUState *cs)
 {
-    CPUX86State *env = &X86_CPU(cpu)->env;
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
 
-    return ((env->interrupt_request & (CPU_INTERRUPT_HARD |
-                                       CPU_INTERRUPT_POLL)) &&
+    return ((cs->interrupt_request & (CPU_INTERRUPT_HARD |
+                                      CPU_INTERRUPT_POLL)) &&
             (env->eflags & IF_MASK)) ||
-           (env->interrupt_request & (CPU_INTERRUPT_NMI |
-                                      CPU_INTERRUPT_INIT |
-                                      CPU_INTERRUPT_SIPI |
-                                      CPU_INTERRUPT_MCE));
+           (cs->interrupt_request & (CPU_INTERRUPT_NMI |
+                                     CPU_INTERRUPT_INIT |
+                                     CPU_INTERRUPT_SIPI |
+                                     CPU_INTERRUPT_MCE));
 }
 
 #include "exec/exec-all.h"
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 1a872fa..808d879 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -171,6 +171,7 @@ done:
 void cpu_dump_state(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
                     int flags)
 {
+    CPUState *cs = CPU(x86_env_get_cpu(env));
     int eflags, i, nb;
     char cc_op_name[32];
     static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
@@ -214,7 +215,7 @@ void cpu_dump_state(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
                     (env->a20_mask >> 20) & 1,
                     (env->hflags >> HF_SMM_SHIFT) & 1,
-                    env->halted);
+                    cs->halted);
     } else
 #endif
     {
@@ -241,7 +242,7 @@ void cpu_dump_state(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
                     (env->a20_mask >> 20) & 1,
                     (env->hflags >> HF_SMM_SHIFT) & 1,
-                    env->halted);
+                    cs->halted);
     }
 
     for(i = 0; i < 6; i++) {
@@ -1294,12 +1295,13 @@ X86CPU *cpu_x86_init(const char *cpu_model)
 #if !defined(CONFIG_USER_ONLY)
 void do_cpu_init(X86CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUX86State *env = &cpu->env;
-    int sipi = env->interrupt_request & CPU_INTERRUPT_SIPI;
+    int sipi = cs->interrupt_request & CPU_INTERRUPT_SIPI;
     uint64_t pat = env->pat;
 
-    cpu_reset(CPU(cpu));
-    env->interrupt_request = sipi;
+    cpu_reset(cs);
+    cs->interrupt_request = sipi;
     env->pat = pat;
     apic_init_reset(env->apic_state);
 }
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0cf413d..df30fa6 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1460,17 +1460,18 @@ static int kvm_put_mp_state(X86CPU *cpu)
 
 static int kvm_get_mp_state(X86CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUX86State *env = &cpu->env;
     struct kvm_mp_state mp_state;
     int ret;
 
-    ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MP_STATE, &mp_state);
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_MP_STATE, &mp_state);
     if (ret < 0) {
         return ret;
     }
     env->mp_state = mp_state.mp_state;
     if (kvm_irqchip_in_kernel()) {
-        env->halted = (mp_state.mp_state == KVM_MP_STATE_HALTED);
+        cs->halted = (mp_state.mp_state == KVM_MP_STATE_HALTED);
     }
     return 0;
 }
@@ -1762,8 +1763,8 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
     int ret;
 
     /* Inject NMI */
-    if (env->interrupt_request & CPU_INTERRUPT_NMI) {
-        env->interrupt_request &= ~CPU_INTERRUPT_NMI;
+    if (cpu->interrupt_request & CPU_INTERRUPT_NMI) {
+        cpu->interrupt_request &= ~CPU_INTERRUPT_NMI;
         DPRINTF("injected NMI\n");
         ret = kvm_vcpu_ioctl(cpu, KVM_NMI);
         if (ret < 0) {
@@ -1775,18 +1776,18 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
     if (!kvm_irqchip_in_kernel()) {
         /* Force the VCPU out of its inner loop to process any INIT requests
          * or pending TPR access reports. */
-        if (env->interrupt_request &
+        if (cpu->interrupt_request &
             (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR)) {
             cpu->exit_request = 1;
         }
 
         /* Try to inject an interrupt if the guest can accept it */
         if (run->ready_for_interrupt_injection &&
-            (env->interrupt_request & CPU_INTERRUPT_HARD) &&
+            (cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
             (env->eflags & IF_MASK)) {
             int irq;
 
-            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+            cpu->interrupt_request &= ~CPU_INTERRUPT_HARD;
             irq = cpu_get_pic_interrupt(env);
             if (irq >= 0) {
                 struct kvm_interrupt intr;
@@ -1806,7 +1807,7 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
          * interrupt, request an interrupt window exit.  This will
          * cause a return to userspace as soon as the guest is ready to
          * receive interrupts. */
-        if ((env->interrupt_request & CPU_INTERRUPT_HARD)) {
+        if ((cpu->interrupt_request & CPU_INTERRUPT_HARD)) {
             run->request_interrupt_window = 1;
         } else {
             run->request_interrupt_window = 0;
@@ -1836,11 +1837,11 @@ int kvm_arch_process_async_events(CPUState *cs)
     X86CPU *cpu = X86_CPU(cs);
     CPUX86State *env = &cpu->env;
 
-    if (env->interrupt_request & CPU_INTERRUPT_MCE) {
+    if (cs->interrupt_request & CPU_INTERRUPT_MCE) {
         /* We must not raise CPU_INTERRUPT_MCE if it's not supported. */
         assert(env->mcg_cap);
 
-        env->interrupt_request &= ~CPU_INTERRUPT_MCE;
+        cs->interrupt_request &= ~CPU_INTERRUPT_MCE;
 
         kvm_cpu_synchronize_state(env);
 
@@ -1853,7 +1854,7 @@ int kvm_arch_process_async_events(CPUState *cs)
         env->exception_injected = EXCP12_MCHK;
         env->has_error_code = 0;
 
-        env->halted = 0;
+        cs->halted = 0;
         if (kvm_irqchip_in_kernel() && env->mp_state == KVM_MP_STATE_HALTED) {
             env->mp_state = KVM_MP_STATE_RUNNABLE;
         }
@@ -1863,41 +1864,42 @@ int kvm_arch_process_async_events(CPUState *cs)
         return 0;
     }
 
-    if (env->interrupt_request & CPU_INTERRUPT_POLL) {
-        env->interrupt_request &= ~CPU_INTERRUPT_POLL;
+    if (cs->interrupt_request & CPU_INTERRUPT_POLL) {
+        cs->interrupt_request &= ~CPU_INTERRUPT_POLL;
         apic_poll_irq(env->apic_state);
     }
-    if (((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+    if (((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
          (env->eflags & IF_MASK)) ||
-        (env->interrupt_request & CPU_INTERRUPT_NMI)) {
-        env->halted = 0;
+        (cs->interrupt_request & CPU_INTERRUPT_NMI)) {
+        cs->halted = 0;
     }
-    if (env->interrupt_request & CPU_INTERRUPT_INIT) {
+    if (cs->interrupt_request & CPU_INTERRUPT_INIT) {
         kvm_cpu_synchronize_state(env);
         do_cpu_init(cpu);
     }
-    if (env->interrupt_request & CPU_INTERRUPT_SIPI) {
+    if (cs->interrupt_request & CPU_INTERRUPT_SIPI) {
         kvm_cpu_synchronize_state(env);
         do_cpu_sipi(cpu);
     }
-    if (env->interrupt_request & CPU_INTERRUPT_TPR) {
-        env->interrupt_request &= ~CPU_INTERRUPT_TPR;
+    if (cs->interrupt_request & CPU_INTERRUPT_TPR) {
+        cs->interrupt_request &= ~CPU_INTERRUPT_TPR;
         kvm_cpu_synchronize_state(env);
         apic_handle_tpr_access_report(env->apic_state, env->eip,
                                       env->tpr_access_type);
     }
 
-    return env->halted;
+    return cs->halted;
 }
 
 static int kvm_handle_halt(X86CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUX86State *env = &cpu->env;
 
-    if (!((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+    if (!((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
           (env->eflags & IF_MASK)) &&
-        !(env->interrupt_request & CPU_INTERRUPT_NMI)) {
-        env->halted = 1;
+        !(cs->interrupt_request & CPU_INTERRUPT_NMI)) {
+        cs->halted = 1;
         return EXCP_HLT;
     }
 
diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
index b6d5740..dfbc07b 100644
--- a/target-i386/misc_helper.c
+++ b/target-i386/misc_helper.c
@@ -553,20 +553,25 @@ void helper_rdmsr(CPUX86State *env)
 }
 #endif
 
-static void do_hlt(CPUX86State *env)
+static void do_hlt(X86CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
+    CPUX86State *env = &cpu->env;
+
     env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
-    env->halted = 1;
+    cs->halted = 1;
     env->exception_index = EXCP_HLT;
     cpu_loop_exit(env);
 }
 
 void helper_hlt(CPUX86State *env, int next_eip_addend)
 {
+    X86CPU *cpu = x86_env_get_cpu(env);
+
     cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0);
     EIP += next_eip_addend;
 
-    do_hlt(env);
+    do_hlt(cpu);
 }
 
 void helper_monitor(CPUX86State *env, target_ulong ptr)
@@ -580,7 +585,8 @@ void helper_monitor(CPUX86State *env, target_ulong ptr)
 
 void helper_mwait(CPUX86State *env, int next_eip_addend)
 {
-    CPUState *cpu;
+    CPUState *cs;
+    X86CPU *cpu;
 
     if ((uint32_t)ECX != 0) {
         raise_exception(env, EXCP0D_GPF);
@@ -588,13 +594,14 @@ void helper_mwait(CPUX86State *env, int next_eip_addend)
     cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0);
     EIP += next_eip_addend;
 
-    cpu = CPU(x86_env_get_cpu(env));
+    cpu = x86_env_get_cpu(env);
+    cs = CPU(cpu);
     /* XXX: not complete but not completely erroneous */
-    if (cpu->cpu_index != 0 || env->next_cpu != NULL) {
+    if (cs->cpu_index != 0 || env->next_cpu != NULL) {
         /* more than one CPU: do not sleep because another CPU may
            wake this one */
     } else {
-        do_hlt(env);
+        do_hlt(cpu);
     }
 }
 
diff --git a/target-i386/svm_helper.c b/target-i386/svm_helper.c
index 3f246e9..c46a213 100644
--- a/target-i386/svm_helper.c
+++ b/target-i386/svm_helper.c
@@ -271,7 +271,9 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
     env->hflags2 |= HF2_GIF_MASK;
 
     if (int_ctl & V_IRQ_MASK) {
-        env->interrupt_request |= CPU_INTERRUPT_VIRQ;
+        CPUState *cs = CPU(x86_env_get_cpu(env));
+
+        cs->interrupt_request |= CPU_INTERRUPT_VIRQ;
     }
 
     /* maybe we need to inject an event */
@@ -548,6 +550,7 @@ void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param,
 /* Note: currently only 32 bits of exit_code are used */
 void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
 {
+    CPUState *cs = CPU(x86_env_get_cpu(env));
     uint32_t int_ctl;
 
     qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016"
@@ -594,7 +597,7 @@ void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
     int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
     int_ctl &= ~(V_TPR_MASK | V_IRQ_MASK);
     int_ctl |= env->v_tpr & V_TPR_MASK;
-    if (env->interrupt_request & CPU_INTERRUPT_VIRQ) {
+    if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) {
         int_ctl |= V_IRQ_MASK;
     }
     stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
@@ -615,7 +618,7 @@ void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
     env->hflags &= ~HF_SVMI_MASK;
     env->intercept = 0;
     env->intercept_exceptions = 0;
-    env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
+    cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
     env->tsc_offset = 0;
 
     env->gdt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb,
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index 6948d0e..d81f103 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -254,9 +254,7 @@ static inline void cpu_get_tb_cpu_state(CPULM32State *env, target_ulong *pc,
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPULM32State *env = &LM32_CPU(cpu)->env;
-
-    return env->interrupt_request & CPU_INTERRUPT_HARD;
+    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
 #include "exec/exec-all.h"
diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c
index 53410b1..ebc94a0 100644
--- a/target-lm32/op_helper.c
+++ b/target-lm32/op_helper.c
@@ -25,7 +25,9 @@ void helper_raise_exception(CPULM32State *env, uint32_t index)
 
 void helper_hlt(CPULM32State *env)
 {
-    env->halted = 1;
+    CPUState *cs = CPU(lm32_env_get_cpu(env));
+
+    cs->halted = 1;
     env->exception_index = EXCP_HLT;
     cpu_loop_exit(env);
 }
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 2672eae..bb2fbd6 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -265,9 +265,7 @@ static inline void cpu_get_tb_cpu_state(CPUM68KState *env, target_ulong *pc,
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUM68KState *env = &M68K_CPU(cpu)->env;
-
-    return env->interrupt_request & CPU_INTERRUPT_HARD;
+    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
 #include "exec/exec-all.h"
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 16df24c..e11f34b 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -84,6 +84,7 @@ static void do_rte(CPUM68KState *env)
 
 static void do_interrupt_all(CPUM68KState *env, int is_hw)
 {
+    CPUState *cs;
     uint32_t sp;
     uint32_t fmt;
     uint32_t retaddr;
@@ -108,7 +109,8 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
                 do_m68k_semihosting(env, env->dregs[0]);
                 return;
             }
-            env->halted = 1;
+            cs = CPU(m68k_env_get_cpu(env));
+            cs->halted = 1;
             env->exception_index = EXCP_HLT;
             cpu_loop_exit(env);
             return;
diff --git a/target-m68k/qregs.def b/target-m68k/qregs.def
index 49400c4..4235b02 100644
--- a/target-m68k/qregs.def
+++ b/target-m68k/qregs.def
@@ -8,6 +8,5 @@ DEFO32(CC_X, cc_x)
 DEFO32(DIV1, div1)
 DEFO32(DIV2, div2)
 DEFO32(EXCEPTION, exception_index)
-DEFO32(HALTED, halted)
 DEFO32(MACSR, macsr)
 DEFO32(MAC_MASK, mac_mask)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index e763195..aabd2d9 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -42,6 +42,8 @@
 #undef DEFO64
 #undef DEFF64
 
+static TCGv_i32 cpu_halted;
+
 static TCGv_ptr cpu_env;
 
 static char cpu_reg_names[3*8*3 + 5*4];
@@ -76,6 +78,10 @@ void m68k_tcg_init(void)
 #undef DEFO64
 #undef DEFF64
 
+    cpu_halted = tcg_global_mem_new_i32(TCG_AREG0,
+                                        -offsetof(M68kCPU, env) +
+                                        offsetof(CPUState, halted), "HALTED");
+
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
 
     p = cpu_reg_names;
@@ -2024,7 +2030,7 @@ DISAS_INSN(stop)
     s->pc += 2;
 
     gen_set_sr_im(s, ext, 0);
-    tcg_gen_movi_i32(QREG_HALTED, 1);
+    tcg_gen_movi_i32(cpu_halted, 1);
     gen_exception(s, s->pc, EXCP_HLT);
 }
 
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index c3dd7f6..7548aa9 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -374,9 +374,7 @@ void cpu_unassigned_access(CPUMBState *env1, hwaddr addr,
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUMBState *env = &MICROBLAZE_CPU(cpu)->env;
-
-    return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
+    return cpu->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
 }
 
 #include "exec/exec-all.h"
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 0e198b1..7434099 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -719,7 +719,7 @@ static inline bool cpu_has_work(CPUState *cpu)
     /* It is implementation dependent if non-enabled interrupts
        wake-up the CPU, however most of the implementations only
        check for interrupts that can be taken. */
-    if ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+    if ((cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
         cpu_mips_hw_interrupts_pending(env)) {
         has_work = true;
     }
@@ -728,7 +728,7 @@ static inline bool cpu_has_work(CPUState *cpu)
     if (env->CP0_Config3 & (1 << CP0C3_MT)) {
         /* The QEMU model will issue an _WAKE request whenever the CPUs
            should be woken up.  */
-        if (env->interrupt_request & CPU_INTERRUPT_WAKE) {
+        if (cpu->interrupt_request & CPU_INTERRUPT_WAKE) {
             has_work = true;
         }
 
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 526f84f..7992f0f 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -527,11 +527,12 @@ void helper_sdm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
 /* SMP helpers.  */
 static bool mips_vpe_is_wfi(MIPSCPU *c)
 {
+    CPUState *cpu = CPU(c);
     CPUMIPSState *env = &c->env;
 
     /* If the VPE is halted but otherwise active, it means it's waiting for
        an interrupt.  */
-    return env->halted && mips_vpe_active(env);
+    return cpu->halted && mips_vpe_active(env);
 }
 
 static inline void mips_vpe_wake(CPUMIPSState *c)
@@ -544,11 +545,12 @@ static inline void mips_vpe_wake(CPUMIPSState *c)
 
 static inline void mips_vpe_sleep(MIPSCPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUMIPSState *c = &cpu->env;
 
     /* The VPE was shut off, really go to bed.
        Reset any old _WAKE requests.  */
-    c->halted = 1;
+    cs->halted = 1;
     cpu_reset_interrupt(c, CPU_INTERRUPT_WAKE);
 }
 
@@ -2111,7 +2113,9 @@ void helper_pmon(CPUMIPSState *env, int function)
 
 void helper_wait(CPUMIPSState *env)
 {
-    env->halted = 1;
+    CPUState *cs = CPU(mips_env_get_cpu(env));
+
+    cs->halted = 1;
     cpu_reset_interrupt(env, CPU_INTERRUPT_WAKE);
     helper_raise_exception(env, EXCP_HLT);
 }
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 4ee9615..5cd3124 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -16020,7 +16020,7 @@ void cpu_state_reset(CPUMIPSState *env)
             env->tcs[i].CP0_TCHalt = 1;
         }
         env->active_tc.CP0_TCHalt = 1;
-        env->halted = 1;
+        cs->halted = 1;
 
         if (cs->cpu_index == 0) {
             /* VPE0 starts up enabled.  */
@@ -16028,7 +16028,7 @@ void cpu_state_reset(CPUMIPSState *env)
             env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
 
             /* TC0 starts up unhalted.  */
-            env->halted = 0;
+            cs->halted = 0;
             env->active_tc.CP0_TCHalt = 0;
             env->tcs[0].CP0_TCHalt = 0;
             /* With thread 0 active.  */
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 419f007..687c24f 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -421,9 +421,7 @@ static inline int cpu_mmu_index(CPUOpenRISCState *env)
 #define CPU_INTERRUPT_TIMER   CPU_INTERRUPT_TGT_INT_0
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUOpenRISCState *env = &OPENRISC_CPU(cpu)->env;
-
-    return env->interrupt_request & (CPU_INTERRUPT_HARD |
+    return cpu->interrupt_request & (CPU_INTERRUPT_HARD |
                                      CPU_INTERRUPT_TIMER);
 }
 
diff --git a/target-openrisc/interrupt_helper.c b/target-openrisc/interrupt_helper.c
index a176441..844648f 100644
--- a/target-openrisc/interrupt_helper.c
+++ b/target-openrisc/interrupt_helper.c
@@ -24,6 +24,7 @@
 void HELPER(rfe)(CPUOpenRISCState *env)
 {
     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
 #ifndef CONFIG_USER_ONLY
     int need_flush_tlb = (cpu->env.sr & (SR_SM | SR_IME | SR_DME)) ^
                          (cpu->env.esr & (SR_SM | SR_IME | SR_DME));
@@ -53,5 +54,5 @@ void HELPER(rfe)(CPUOpenRISCState *env)
         tlb_flush(&cpu->env, 1);
     }
 #endif
-    cpu->env.interrupt_request |= CPU_INTERRUPT_EXITTB;
+    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
index 3c5f45a..cccbc0e 100644
--- a/target-openrisc/sys_helper.c
+++ b/target-openrisc/sys_helper.c
@@ -31,6 +31,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
     int idx;
 
     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
 
     switch (spr) {
     case TO_SPR(0, 0): /* VR */
@@ -132,7 +133,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
                 env->ttmr = (rb & ~TTMR_IP) + ip;
             } else {    /* Clear IP bit.  */
                 env->ttmr = rb & ~TTMR_IP;
-                env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
+                cs->interrupt_request &= ~CPU_INTERRUPT_TIMER;
             }
 
             cpu_openrisc_count_update(cpu);
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 8c081db..75190f3 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -2215,9 +2215,10 @@ extern void (*cpu_ppc_hypercall)(PowerPCCPU *);
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUPPCState *env = &POWERPC_CPU(cpu)->env;
+    PowerPCCPU *ppc_cpu = POWERPC_CPU(cpu);
+    CPUPPCState *env = &ppc_cpu->env;
 
-    return msr_ee && (env->interrupt_request & CPU_INTERRUPT_HARD);
+    return msr_ee && (cpu->interrupt_request & CPU_INTERRUPT_HARD);
 }
 
 #include "exec/exec-all.h"
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 0a1ac86..79ce7bf 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -66,6 +66,7 @@ static inline void dump_syscall(CPUPPCState *env)
 static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
 {
     CPUPPCState *env = &cpu->env;
+    CPUState *cs;
     target_ulong msr, new_msr, vector;
     int srr0, srr1, asrr0, asrr1;
     int lpes0, lpes1, lev;
@@ -131,8 +132,9 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
                 fprintf(stderr, "Machine check while not allowed. "
                         "Entering checkstop state\n");
             }
-            env->halted = 1;
-            env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+            cs = CPU(cpu);
+            cs->halted = 1;
+            cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
         }
         if (0) {
             /* XXX: find a suitable condition to enable the hypervisor mode */
@@ -663,11 +665,12 @@ void ppc_hw_interrupt(CPUPPCState *env)
 {
     PowerPCCPU *cpu = ppc_env_get_cpu(env);
     int hdice;
-
 #if 0
+    CPUState *cs = CPU(cpu);
+
     qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
-                __func__, env, env->pending_interrupts,
-                env->interrupt_request, (int)msr_me, (int)msr_ee);
+                  __func__, env, env->pending_interrupts,
+                  cs->interrupt_request, (int)msr_me, (int)msr_ee);
 #endif
     /* External reset */
     if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
@@ -807,9 +810,12 @@ void helper_raise_exception(CPUPPCState *env, uint32_t exception)
 #if !defined(CONFIG_USER_ONLY)
 void helper_store_msr(CPUPPCState *env, target_ulong val)
 {
+    CPUState *cs;
+
     val = hreg_store_msr(env, val, 0);
     if (val != 0) {
-        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+        cs = CPU(ppc_env_get_cpu(env));
+        cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
         helper_raise_exception(env, val);
     }
 }
@@ -817,6 +823,8 @@ void helper_store_msr(CPUPPCState *env, target_ulong val)
 static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
                           target_ulong msrm, int keep_msrh)
 {
+    CPUState *cs = CPU(ppc_env_get_cpu(env));
+
 #if defined(TARGET_PPC64)
     if (msr_is_64bit(env, msr)) {
         nip = (uint64_t)nip;
@@ -841,7 +849,7 @@ static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
     /* No need to raise an exception here,
      * as rfi is always the last insn of a TB
      */
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
 
 void helper_rfi(CPUPPCState *env)
diff --git a/target-ppc/helper_regs.h b/target-ppc/helper_regs.h
index 3c98850..a6d5e2f 100644
--- a/target-ppc/helper_regs.h
+++ b/target-ppc/helper_regs.h
@@ -68,10 +68,13 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
                                  int alter_hv)
 {
     int excp;
+#if !defined(CONFIG_USER_ONLY)
+    CPUState *cs = CPU(ppc_env_get_cpu(env));
+#endif
 
     excp = 0;
     value &= env->msr_mask;
-#if !defined (CONFIG_USER_ONLY)
+#if !defined(CONFIG_USER_ONLY)
     if (!alter_hv) {
         /* mtmsr cannot alter the hypervisor state */
         value &= ~MSR_HVB;
@@ -82,7 +85,7 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
         /* Flush all tlb when changing translation mode */
         tlb_flush(env, 1);
         excp = POWERPC_EXCP_NONE;
-        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+        cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
     }
     if (unlikely((env->flags & POWERPC_FLAG_TGPR) &&
                  ((value ^ env->msr) & (1 << MSR_TGPR)))) {
@@ -96,10 +99,10 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
 #endif
     env->msr = value;
     hreg_compute_hflags(env);
-#if !defined (CONFIG_USER_ONLY)
+#if !defined(CONFIG_USER_ONLY)
     if (unlikely(msr_pow == 1)) {
         if ((*env->check_pow)(env)) {
-            env->halted = 1;
+            cs->halted = 1;
             excp = EXCP_HALTED;
         }
     }
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 2c64c63..ee935d8 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -760,7 +760,7 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
      * interrupt, reset, etc) in PPC-specific env->irq_input_state. */
     if (!cap_interrupt_level &&
         run->ready_for_interrupt_injection &&
-        (env->interrupt_request & CPU_INTERRUPT_HARD) &&
+        (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
         (env->irq_input_state & (1<<PPC_INPUT_INT)))
     {
         /* For now KVM disregards the 'irq' argument. However, in the
@@ -791,14 +791,16 @@ void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run)
 
 int kvm_arch_process_async_events(CPUState *cs)
 {
-    PowerPCCPU *cpu = POWERPC_CPU(cs);
-    return cpu->env.halted;
+    return cs->halted;
 }
 
-static int kvmppc_handle_halt(CPUPPCState *env)
+static int kvmppc_handle_halt(PowerPCCPU *cpu)
 {
-    if (!(env->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) {
-        env->halted = 1;
+    CPUState *cs = CPU(cpu);
+    CPUPPCState *env = &cpu->env;
+
+    if (!(cs->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) {
+        cs->halted = 1;
         env->exception_index = EXCP_HLT;
     }
 
@@ -840,7 +842,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
         break;
     case KVM_EXIT_HLT:
         dprintf("handle halt\n");
-        ret = kvmppc_handle_halt(env);
+        ret = kvmppc_handle_halt(cpu);
         break;
 #ifdef CONFIG_PSERIES
     case KVM_EXIT_PAPR_HCALL:
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 2ac5794..4d50198 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3243,7 +3243,8 @@ static void gen_sync(DisasContext *ctx)
 static void gen_wait(DisasContext *ctx)
 {
     TCGv_i32 t0 = tcg_temp_new_i32();
-    tcg_gen_st_i32(t0, cpu_env, offsetof(CPUPPCState, halted));
+    tcg_gen_st_i32(t0, cpu_env,
+                   -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
     tcg_temp_free_i32(t0);
     /* Stop translation, as the CPU is supposed to sleep from now */
     gen_exception_err(ctx, EXCP_HLT, 1);
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index b746547..738a0ad 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -80,10 +80,10 @@ static void s390_cpu_reset(CPUState *s)
     env->cregs[0] = CR0_RESET;
     env->cregs[14] = CR14_RESET;
     /* set halted to 1 to make sure we can add the cpu in
-     * s390_ipl_cpu code, where env->halted is set back to 0
+     * s390_ipl_cpu code, where CPUState::halted is set back to 0
      * after incrementing the cpu counter */
 #if !defined(CONFIG_USER_ONLY)
-    env->halted = 1;
+    s->halted = 1;
 #endif
     tlb_flush(env, 1);
 }
@@ -129,10 +129,10 @@ static void s390_cpu_initfn(Object *obj)
     env->tod_basetime = 0;
     env->tod_timer = qemu_new_timer_ns(vm_clock, s390x_tod_timer, cpu);
     env->cpu_timer = qemu_new_timer_ns(vm_clock, s390x_cpu_timer, cpu);
-    /* set env->halted state to 1 to avoid decrementing the running
+    /* set CPUState::halted state to 1 to avoid decrementing the running
      * cpu counter in s390_cpu_reset to a negative number at
      * initial ipl */
-    env->halted = 1;
+    cs->halted = 1;
 #endif
     env->cpu_num = cpu_num++;
     env->ext_index = -1;
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 0070c40..e6997ef 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -1039,9 +1039,10 @@ static inline void cpu_inject_crw_mchk(S390CPU *cpu)
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUS390XState *env = &S390_CPU(cpu)->env;
+    S390CPU *s390_cpu = S390_CPU(cpu);
+    CPUS390XState *env = &s390_cpu->env;
 
-    return (env->interrupt_request & CPU_INTERRUPT_HARD) &&
+    return (cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
         (env->psw.mask & PSW_MASK_EXT);
 }
 
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index bc6fc4c..3a54651 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -437,6 +437,7 @@ void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
 {
     if (mask & PSW_MASK_WAIT) {
         S390CPU *cpu = s390_env_get_cpu(env);
+        CPUState *cs = CPU(cpu);
         if (!(mask & (PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK))) {
             if (s390_del_running_cpu(cpu) == 0) {
 #ifndef CONFIG_USER_ONLY
@@ -444,7 +445,7 @@ void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
 #endif
             }
         }
-        env->halted = 1;
+        cs->halted = 1;
         env->exception_index = EXCP_HLT;
     }
 
@@ -734,6 +735,7 @@ static void do_mchk_interrupt(CPUS390XState *env)
 void do_interrupt(CPUS390XState *env)
 {
     S390CPU *cpu = s390_env_get_cpu(env);
+    CPUState *cs;
 
     qemu_log_mask(CPU_LOG_INT, "%s: %d at pc=%" PRIx64 "\n",
                   __func__, env->exception_index, env->psw.addr);
@@ -792,7 +794,8 @@ void do_interrupt(CPUS390XState *env)
     env->exception_index = -1;
 
     if (!env->pending_int) {
-        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+        cs = CPU(s390_env_get_cpu(env));
+        cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
     }
 }
 
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 49dcd9e..926ec41 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -372,9 +372,7 @@ static inline void cpu_get_tb_cpu_state(CPUSH4State *env, target_ulong *pc,
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUSH4State *env = &SUPERH_CPU(cpu)->env;
-
-    return env->interrupt_request & CPU_INTERRUPT_HARD;
+    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
 #include "exec/exec-all.h"
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index ddebc78..fd4efee 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -78,9 +78,10 @@ int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
 #define MMU_DADDR_ERROR_READ     (-12)
 #define MMU_DADDR_ERROR_WRITE    (-13)
 
-void do_interrupt(CPUSH4State * env)
+void do_interrupt(CPUSH4State *env)
 {
-    int do_irq = env->interrupt_request & CPU_INTERRUPT_HARD;
+    CPUState *cs = CPU(sh_env_get_cpu(env));
+    int do_irq = cs->interrupt_request & CPU_INTERRUPT_HARD;
     int do_exp, irq_vector = env->exception_index;
 
     /* prioritize exceptions over interrupts */
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index 09e3d23..e955e81 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -102,7 +102,9 @@ void helper_debug(CPUSH4State *env)
 
 void helper_sleep(CPUSH4State *env)
 {
-    env->halted = 1;
+    CPUState *cs = CPU(sh_env_get_cpu(env));
+
+    cs->halted = 1;
     env->in_sleep = 1;
     raise_exception(env, EXCP_HLT, 0);
 }
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 7389b03..95cbba0 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -761,9 +761,10 @@ static inline bool tb_am_enabled(int tb_flags)
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUSPARCState *env1 = &SPARC_CPU(cpu)->env;
+    SPARCCPU *sparc_cpu = SPARC_CPU(cpu);
+    CPUSPARCState *env1 = &sparc_cpu->env;
 
-    return (env1->interrupt_request & CPU_INTERRUPT_HARD) &&
+    return (cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
            cpu_interrupts_enabled(env1);
 }
 
diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
index ae9a9d6..58f1f20 100644
--- a/target-unicore32/cpu.h
+++ b/target-unicore32/cpu.h
@@ -181,9 +181,7 @@ void switch_mode(CPUUniCore32State *, int);
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUUniCore32State *env = &UNICORE32_CPU(cpu)->env;
-
-    return env->interrupt_request &
+    return cpu->interrupt_request &
         (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
 }
 
diff --git a/target-unicore32/softmmu.c b/target-unicore32/softmmu.c
index fc27100..1c4c7f5 100644
--- a/target-unicore32/softmmu.c
+++ b/target-unicore32/softmmu.c
@@ -74,6 +74,7 @@ void switch_mode(CPUUniCore32State *env, int mode)
 /* Handle a CPU exception.  */
 void do_interrupt(CPUUniCore32State *env)
 {
+    CPUState *cs = CPU(uc32_env_get_cpu(env));
     uint32_t addr;
     int new_mode;
 
@@ -112,7 +113,7 @@ void do_interrupt(CPUUniCore32State *env)
     /* The PC already points to the proper instruction.  */
     env->regs[30] = env->regs[31];
     env->regs[31] = addr;
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
 
 static int get_phys_addr_ucv2(CPUUniCore32State *env, uint32_t address,
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 3813a72..1037101 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -373,6 +373,8 @@ void HELPER(dump_state)(CPUXtensaState *env)
 
 void HELPER(waiti)(CPUXtensaState *env, uint32_t pc, uint32_t intlevel)
 {
+    CPUState *cpu;
+
     env->pc = pc;
     env->sregs[PS] = (env->sregs[PS] & ~PS_INTLEVEL) |
         (intlevel << PS_INTLEVEL_SHIFT);
@@ -382,8 +384,9 @@ void HELPER(waiti)(CPUXtensaState *env, uint32_t pc, uint32_t intlevel)
         return;
     }
 
+    cpu = CPU(xtensa_env_get_cpu(env));
     env->halt_clock = qemu_get_clock_ns(vm_clock);
-    env->halted = 1;
+    cpu->halted = 1;
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
         xtensa_rearm_ccompare_timer(env);
     }
diff --git a/translate-all.c b/translate-all.c
index 19bc414..2176132 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1087,8 +1087,8 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
             tb_phys_invalidate(tb, -1);
             if (cpu != NULL) {
                 cpu->current_tb = saved_tb;
-                if (env && env->interrupt_request && cpu->current_tb) {
-                    cpu_interrupt(env, env->interrupt_request);
+                if (env && cpu->interrupt_request && cpu->current_tb) {
+                    cpu_interrupt(env, cpu->interrupt_request);
                 }
             }
         }
@@ -1465,8 +1465,8 @@ static void tcg_handle_interrupt(CPUArchState *env, int mask)
     CPUState *cpu = ENV_GET_CPU(env);
     int old_mask;
 
-    old_mask = env->interrupt_request;
-    env->interrupt_request |= mask;
+    old_mask = cpu->interrupt_request;
+    cpu->interrupt_request |= mask;
 
     /*
      * If called from iothread context, wake the target cpu in
@@ -1626,7 +1626,7 @@ void cpu_interrupt(CPUArchState *env, int mask)
 {
     CPUState *cpu = ENV_GET_CPU(env);
 
-    env->interrupt_request |= mask;
+    cpu->interrupt_request |= mask;
     cpu_unlink_tb(cpu);
 }
 
diff --git a/xen-all.c b/xen-all.c
index 110f958..8c05843 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -578,16 +578,18 @@ void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
 
 static void xen_reset_vcpu(void *opaque)
 {
-    CPUArchState *env = opaque;
+    CPUState *cpu = opaque;
 
-    env->halted = 1;
+    cpu->halted = 1;
 }
 
 void xen_vcpu_init(void)
 {
     if (first_cpu != NULL) {
-        qemu_register_reset(xen_reset_vcpu, first_cpu);
-        xen_reset_vcpu(first_cpu);
+        CPUState *cpu = ENV_GET_CPU(first_cpu);
+
+        qemu_register_reset(xen_reset_vcpu, cpu);
+        xen_reset_vcpu(cpu);
     }
     /* if rtc_clock is left to default (host_clock), disable it */
     if (rtc_clock == host_clock) {
-- 
1.7.10.4

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

* [Qemu-devel] [RFC qom-cpu-next 6/9] exec: Pass CPUState to cpu_reset_interrupt()
  2013-02-02 11:57 [Qemu-devel] [RFC qom-cpu-next 0/9] QOM CPUState, part 9: CPU_COMMON for interrupts Andreas Färber
                   ` (4 preceding siblings ...)
  2013-02-02 11:57   ` [Qemu-devel] " Andreas Färber
@ 2013-02-02 11:57 ` Andreas Färber
  2013-02-02 11:57   ` [Qemu-devel] " Andreas Färber
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Andreas Färber @ 2013-02-02 11:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Anthony Liguori, Fabien Chouteau, Blue Swirl, Michael Walle,
	Paul Brook, Guan Xuetao, Andreas Färber, Aurelien Jarno

Move it to qom/cpu.c to avoid build failures depending on include order
of cpu-qom.h and exec/cpu-all.h.

Change opaques of various ..._irq_handler() functions to the
appropriate CPU type to facilitate using cpu_reset_interrupt().

Fix Coding Style issues while at it (missing braces, indentation).

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 exec.c                  |    7 -------
 hw/alpha_typhoon.c      |    8 +++++---
 hw/apic.c               |    4 ++--
 hw/arm_pic.c            |   15 +++++++++------
 hw/cris_pic_cpu.c       |   13 ++++++++-----
 hw/leon3.c              |    4 +++-
 hw/lm32_boards.c        |    8 +++++---
 hw/microblaze_pic_cpu.c |   14 +++++++++-----
 hw/milkymist.c          |    8 +++++---
 hw/mips_int.c           |    8 +++++---
 hw/openrisc_pic.c       |    3 ++-
 hw/pc.c                 |    8 +++++---
 hw/ppc.c                |    6 ++++--
 hw/puv3.c               |    9 ++++++---
 hw/pxa2xx_pic.c         |    4 ++--
 hw/sh_intc.c            |    9 +++++----
 hw/sun4m.c              |    5 ++++-
 hw/sun4u.c              |    7 ++++---
 hw/xtensa_pic.c         |    2 +-
 include/exec/cpu-all.h  |    2 --
 include/qom/cpu.h       |    9 +++++++++
 qom/cpu.c               |    5 +++++
 target-m68k/helper.c    |    8 +++++---
 target-mips/op_helper.c |    5 ++---
 24 Dateien geändert, 105 Zeilen hinzugefügt(+), 66 Zeilen entfernt(-)

diff --git a/exec.c b/exec.c
index 5ab7af4..d14dbe7 100644
--- a/exec.c
+++ b/exec.c
@@ -485,13 +485,6 @@ void cpu_single_step(CPUArchState *env, int enabled)
 #endif
 }
 
-void cpu_reset_interrupt(CPUArchState *env, int mask)
-{
-    CPUState *cpu = ENV_GET_CPU(env);
-
-    cpu->interrupt_request &= ~mask;
-}
-
 void cpu_exit(CPUArchState *env)
 {
     CPUState *cpu = ENV_GET_CPU(env);
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index bf9aabf..dfb10c7 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -63,10 +63,11 @@ static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
     /* If there are any non-masked interrupts, tell the cpu.  */
     if (cpu != NULL) {
         CPUAlphaState *env = &cpu->env;
+        CPUState *cs = CPU(cpu);
         if (req) {
             cpu_interrupt(env, CPU_INTERRUPT_HARD);
         } else {
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
         }
     }
 }
@@ -359,16 +360,17 @@ static void cchip_write(void *opaque, hwaddr addr,
                 AlphaCPU *cpu = s->cchip.cpu[i];
                 if (cpu != NULL) {
                     CPUAlphaState *env = &cpu->env;
+                    CPUState *cs = CPU(cpu);
                     /* IPI can be either cleared or set by the write.  */
                     if (newval & (1 << (i + 8))) {
                         cpu_interrupt(env, CPU_INTERRUPT_SMP);
                     } else {
-                        cpu_reset_interrupt(env, CPU_INTERRUPT_SMP);
+                        cpu_reset_interrupt(cs, CPU_INTERRUPT_SMP);
                     }
 
                     /* ITI can only be cleared by the write.  */
                     if ((newval & (1 << (i + 4))) == 0) {
-                        cpu_reset_interrupt(env, CPU_INTERRUPT_TIMER);
+                        cpu_reset_interrupt(cs, CPU_INTERRUPT_TIMER);
                     }
                 }
             }
diff --git a/hw/apic.c b/hw/apic.c
index fd14b73..e113c11 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -187,7 +187,7 @@ void apic_deliver_pic_intr(DeviceState *d, int level)
             reset_bit(s->irr, lvt & 0xff);
             /* fall through */
         case APIC_DM_EXTINT:
-            cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+            cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_HARD);
             break;
         }
     }
@@ -485,7 +485,7 @@ void apic_sipi(DeviceState *d)
 {
     APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
 
-    cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_SIPI);
+    cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI);
 
     if (!s->wait_for_sipi)
         return;
diff --git a/hw/arm_pic.c b/hw/arm_pic.c
index ffb4d41..ddf3f0b 100644
--- a/hw/arm_pic.c
+++ b/hw/arm_pic.c
@@ -15,19 +15,22 @@ static void arm_pic_cpu_handler(void *opaque, int irq, int level)
 {
     ARMCPU *cpu = opaque;
     CPUARMState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
     switch (irq) {
     case ARM_PIC_CPU_IRQ:
-        if (level)
+        if (level) {
             cpu_interrupt(env, CPU_INTERRUPT_HARD);
-        else
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        } else {
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+        }
         break;
     case ARM_PIC_CPU_FIQ:
-        if (level)
+        if (level) {
             cpu_interrupt(env, CPU_INTERRUPT_FIQ);
-        else
-            cpu_reset_interrupt(env, CPU_INTERRUPT_FIQ);
+        } else {
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_FIQ);
+        }
         break;
     default:
         hw_error("arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
diff --git a/hw/cris_pic_cpu.c b/hw/cris_pic_cpu.c
index 3da0e86..46630aa 100644
--- a/hw/cris_pic_cpu.c
+++ b/hw/cris_pic_cpu.c
@@ -30,16 +30,19 @@
 
 static void cris_pic_cpu_handler(void *opaque, int irq, int level)
 {
-    CPUCRISState *env = (CPUCRISState *)opaque;
+    CRISCPU *cpu = opaque;
+    CPUCRISState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
     int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
 
-    if (level)
+    if (level) {
         cpu_interrupt(env, type);
-    else
-        cpu_reset_interrupt(env, type);
+    } else {
+        cpu_reset_interrupt(cs, type);
+    }
 }
 
 qemu_irq *cris_pic_init_cpu(CPUCRISState *env)
 {
-    return qemu_allocate_irqs(cris_pic_cpu_handler, env, 2);
+    return qemu_allocate_irqs(cris_pic_cpu_handler, cris_env_get_cpu(env), 2);
 }
diff --git a/hw/leon3.c b/hw/leon3.c
index e971d5c..ba92994 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -67,6 +67,7 @@ void leon3_irq_ack(void *irq_manager, int intno)
 static void leon3_set_pil_in(void *opaque, uint32_t pil_in)
 {
     CPUSPARCState *env = (CPUSPARCState *)opaque;
+    CPUState *cs;
 
     assert(env != NULL);
 
@@ -89,9 +90,10 @@ static void leon3_set_pil_in(void *opaque, uint32_t pil_in)
             }
         }
     } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
+        cs = CPU(sparc_env_get_cpu(env));
         trace_leon3_reset_irq(env->interrupt_index & 15);
         env->interrupt_index = 0;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
 }
 
diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
index 2bc06d7..388a0ae 100644
--- a/hw/lm32_boards.c
+++ b/hw/lm32_boards.c
@@ -41,12 +41,14 @@ typedef struct {
 
 static void cpu_irq_handler(void *opaque, int irq, int level)
 {
-    CPULM32State *env = opaque;
+    LM32CPU *cpu = opaque;
+    CPULM32State *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
     if (level) {
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
     } else {
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
 }
 
@@ -117,7 +119,7 @@ static void lm32_evr_init(QEMUMachineInitArgs *args)
                           0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
 
     /* create irq lines */
-    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
+    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, cpu, 1);
     env->pic_state = lm32_pic_init(*cpu_irq);
     for (i = 0; i < 32; i++) {
         irq[i] = qdev_get_gpio_in(env->pic_state, i);
diff --git a/hw/microblaze_pic_cpu.c b/hw/microblaze_pic_cpu.c
index ff36a52..2234bfb 100644
--- a/hw/microblaze_pic_cpu.c
+++ b/hw/microblaze_pic_cpu.c
@@ -29,16 +29,20 @@
 
 static void microblaze_pic_cpu_handler(void *opaque, int irq, int level)
 {
-    CPUMBState *env = (CPUMBState *)opaque;
+    MicroBlazeCPU *cpu = opaque;
+    CPUMBState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
     int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
 
-    if (level)
+    if (level) {
         cpu_interrupt(env, type);
-    else
-        cpu_reset_interrupt(env, type);
+    } else {
+        cpu_reset_interrupt(cs, type);
+    }
 }
 
 qemu_irq *microblaze_pic_init_cpu(CPUMBState *env)
 {
-    return qemu_allocate_irqs(microblaze_pic_cpu_handler, env, 2);
+    return qemu_allocate_irqs(microblaze_pic_cpu_handler, mb_env_get_cpu(env),
+                              2);
 }
diff --git a/hw/milkymist.c b/hw/milkymist.c
index c04eb35..dcadc07 100644
--- a/hw/milkymist.c
+++ b/hw/milkymist.c
@@ -46,12 +46,14 @@ typedef struct {
 
 static void cpu_irq_handler(void *opaque, int irq, int level)
 {
-    CPULM32State *env = opaque;
+    LM32CPU *cpu = opaque;
+    CPULM32State *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
     if (level) {
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
     } else {
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
 }
 
@@ -123,7 +125,7 @@ milkymist_init(QEMUMachineInitArgs *args)
                           0x00, 0x89, 0x00, 0x1d, 1);
 
     /* create irq lines */
-    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
+    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, cpu, 1);
     env->pic_state = lm32_pic_init(*cpu_irq);
     for (i = 0; i < 32; i++) {
         irq[i] = qdev_get_gpio_in(env->pic_state, i);
diff --git a/hw/mips_int.c b/hw/mips_int.c
index 6423fd0..a6f0c52 100644
--- a/hw/mips_int.c
+++ b/hw/mips_int.c
@@ -26,7 +26,9 @@
 
 static void cpu_mips_irq_request(void *opaque, int irq, int level)
 {
-    CPUMIPSState *env = (CPUMIPSState *)opaque;
+    MIPSCPU *cpu = opaque;
+    CPUMIPSState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
     if (irq < 0 || irq > 7)
         return;
@@ -40,7 +42,7 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
     if (env->CP0_Cause & CP0Ca_IP_mask) {
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
     } else {
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
 }
 
@@ -49,7 +51,7 @@ void cpu_mips_irq_init_cpu(CPUMIPSState *env)
     qemu_irq *qi;
     int i;
 
-    qi = qemu_allocate_irqs(cpu_mips_irq_request, env, 8);
+    qi = qemu_allocate_irqs(cpu_mips_irq_request, mips_env_get_cpu(env), 8);
     for (i = 0; i < 8; i++) {
         env->irq[i] = qi[i];
     }
diff --git a/hw/openrisc_pic.c b/hw/openrisc_pic.c
index aaeb9a9..935dce3 100644
--- a/hw/openrisc_pic.c
+++ b/hw/openrisc_pic.c
@@ -25,6 +25,7 @@
 static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
 {
     OpenRISCCPU *cpu = (OpenRISCCPU *)opaque;
+    CPUState *cs = CPU(cpu);
     int i;
     uint32_t irq_bit = 1 << irq;
 
@@ -42,7 +43,7 @@ static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
         if ((cpu->env.picsr && (1 << i)) && (cpu->env.picmr && (1 << i))) {
             cpu_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
         } else {
-            cpu_reset_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
             cpu->env.picsr &= ~(1 << i);
         }
     }
diff --git a/hw/pc.c b/hw/pc.c
index 53cc173..ef72628 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -190,10 +190,12 @@ static void pic_irq_request(void *opaque, int irq, int level)
             env = env->next_cpu;
         }
     } else {
-        if (level)
+        CPUState *cs = CPU(x86_env_get_cpu(env));
+        if (level) {
             cpu_interrupt(env, CPU_INTERRUPT_HARD);
-        else
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        } else {
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+        }
     }
 }
 
diff --git a/hw/ppc.c b/hw/ppc.c
index 400daab..8d58774 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -52,6 +52,7 @@ static void cpu_ppc_tb_start (CPUPPCState *env);
 
 void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
 {
+    CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
     unsigned int old_pending = env->pending_interrupts;
 
@@ -60,8 +61,9 @@ void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
     } else {
         env->pending_interrupts &= ~(1 << n_IRQ);
-        if (env->pending_interrupts == 0)
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        if (env->pending_interrupts == 0) {
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+        }
     }
 
     if (old_pending != env->pending_interrupts) {
diff --git a/hw/puv3.c b/hw/puv3.c
index c722510..6a1e10e 100644
--- a/hw/puv3.c
+++ b/hw/puv3.c
@@ -26,13 +26,15 @@
 
 static void puv3_intc_cpu_handler(void *opaque, int irq, int level)
 {
-    CPUUniCore32State *env = opaque;
+    UniCore32CPU *cpu = opaque;
+    CPUUniCore32State *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
     assert(irq == 0);
     if (level) {
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
     } else {
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
 }
 
@@ -44,7 +46,8 @@ static void puv3_soc_init(CPUUniCore32State *env)
     int i;
 
     /* Initialize interrupt controller */
-    cpu_intc = qemu_allocate_irqs(puv3_intc_cpu_handler, env, 1);
+    cpu_intc = qemu_allocate_irqs(puv3_intc_cpu_handler,
+                                  uc32_env_get_cpu(env), 1);
     dev = sysbus_create_simple("puv3_intc", PUV3_INTC_BASE, *cpu_intc);
     for (i = 0; i < PUV3_IRQS_NR; i++) {
         irqs[i] = qdev_get_gpio_in(dev, i);
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index c73e709..45ee7cb 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -62,13 +62,13 @@ static void pxa2xx_pic_update(void *opaque)
     if ((mask[0] & s->is_fiq[0]) || (mask[1] & s->is_fiq[1])) {
         cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
     } else {
-        cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
+        cpu_reset_interrupt(cpu, CPU_INTERRUPT_FIQ);
     }
 
     if ((mask[0] & ~s->is_fiq[0]) || (mask[1] & ~s->is_fiq[1])) {
         cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
     } else {
-        cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+        cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
     }
 }
 
diff --git a/hw/sh_intc.c b/hw/sh_intc.c
index c3f77d5..dded2a4 100644
--- a/hw/sh_intc.c
+++ b/hw/sh_intc.c
@@ -42,15 +42,16 @@ void sh_intc_toggle_source(struct intc_source *source,
         pending_changed = 1;
 
     if (pending_changed) {
+        CPUState *cpu = CPU(sh_env_get_cpu(first_cpu));
         if (source->pending) {
             source->parent->pending++;
 	    if (source->parent->pending == 1)
                 cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD);
-	}
-	else {
+        } else {
             source->parent->pending--;
-	    if (source->parent->pending == 0)
-                cpu_reset_interrupt(first_cpu, CPU_INTERRUPT_HARD);
+            if (source->parent->pending == 0) {
+                cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
+            }
 	}
     }
 
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 45f9441..fe82bd6 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -230,6 +230,8 @@ void sun4m_irq_info(Monitor *mon, const QDict *qdict)
 
 void cpu_check_irqs(CPUSPARCState *env)
 {
+    CPUState *cs;
+
     if (env->pil_in && (env->interrupt_index == 0 ||
                         (env->interrupt_index & ~15) == TT_EXTINT)) {
         unsigned int i;
@@ -247,9 +249,10 @@ void cpu_check_irqs(CPUSPARCState *env)
             }
         }
     } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
+        cs = CPU(sparc_env_get_cpu(env));
         trace_sun4m_cpu_reset_interrupt(env->interrupt_index & 15);
         env->interrupt_index = 0;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
 }
 
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 056bb4d..dde82cf 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -276,7 +276,7 @@ void cpu_check_irqs(CPUSPARCState *env)
             CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n",
                            env->interrupt_index);
             env->interrupt_index = 0;
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
         }
         return;
     }
@@ -309,7 +309,7 @@ void cpu_check_irqs(CPUSPARCState *env)
                        "current interrupt %x\n",
                        pil, env->pil_in, env->softint, env->interrupt_index);
         env->interrupt_index = 0;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
 }
 
@@ -344,8 +344,9 @@ static void cpu_set_ivec_irq(void *opaque, int irq, int level)
     } else {
         if (env->ivec_status & 0x20) {
             CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
+            cs = CPU(cpu);
             env->ivec_status &= ~0x20;
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
         }
     }
 }
diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c
index dca15b4..7c8c386 100644
--- a/hw/xtensa_pic.c
+++ b/hw/xtensa_pic.c
@@ -80,7 +80,7 @@ void check_interrupts(CPUXtensaState *env)
         }
     }
     env->pending_irq_level = 0;
-    cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
 }
 
 static void xtensa_set_irq(void *opaque, int irq, int active)
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 249e046..5218a53 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -434,8 +434,6 @@ static inline void cpu_interrupt(CPUArchState *s, int mask)
 void cpu_interrupt(CPUArchState *env, int mask);
 #endif /* USER_ONLY */
 
-void cpu_reset_interrupt(CPUArchState *env, int mask);
-
 void cpu_exit(CPUArchState *s);
 
 /* Breakpoint/watchpoint flags */
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 9ad9822..7d16540 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -194,5 +194,14 @@ void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data);
  */
 CPUState *qemu_get_cpu(int index);
 
+/**
+ * cpu_reset_interrupt:
+ * @cpu: The CPU to clear the interrupt on.
+ * @mask: The interrupt mask to clear.
+ *
+ * Resets interrupts on the vCPU @cpu.
+ */
+void cpu_reset_interrupt(CPUState *cpu, int mask);
+
 
 #endif
diff --git a/qom/cpu.c b/qom/cpu.c
index 0aa9be7..e242dcb 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -21,6 +21,11 @@
 #include "qom/cpu.h"
 #include "qemu-common.h"
 
+void cpu_reset_interrupt(CPUState *cpu, int mask)
+{
+    cpu->interrupt_request &= ~mask;
+}
+
 void cpu_reset(CPUState *cpu)
 {
     CPUClass *klass = CPU_GET_CLASS(cpu);
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 1bae3ab..d9c8374 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -312,14 +312,16 @@ int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw,
    simplicitly we calculate it when the interrupt is signalled.  */
 void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
 {
+    CPUState *cs = CPU(cpu);
     CPUM68KState *env = &cpu->env;
 
     env->pending_level = level;
     env->pending_vector = vector;
-    if (level)
+    if (level) {
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    else
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+    }
 }
 
 #endif
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 7992f0f..6bde5b4 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -546,12 +546,11 @@ static inline void mips_vpe_wake(CPUMIPSState *c)
 static inline void mips_vpe_sleep(MIPSCPU *cpu)
 {
     CPUState *cs = CPU(cpu);
-    CPUMIPSState *c = &cpu->env;
 
     /* The VPE was shut off, really go to bed.
        Reset any old _WAKE requests.  */
     cs->halted = 1;
-    cpu_reset_interrupt(c, CPU_INTERRUPT_WAKE);
+    cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
 }
 
 static inline void mips_tc_wake(MIPSCPU *cpu, int tc)
@@ -2116,7 +2115,7 @@ void helper_wait(CPUMIPSState *env)
     CPUState *cs = CPU(mips_env_get_cpu(env));
 
     cs->halted = 1;
-    cpu_reset_interrupt(env, CPU_INTERRUPT_WAKE);
+    cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
     helper_raise_exception(env, EXCP_HLT);
 }
 
-- 
1.7.10.4

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

* [RFC qom-cpu-next 7/9] cpu: Pass CPUState to cpu_interrupt()
  2013-02-02 11:57 [Qemu-devel] [RFC qom-cpu-next 0/9] QOM CPUState, part 9: CPU_COMMON for interrupts Andreas Färber
@ 2013-02-02 11:57   ` Andreas Färber
  2013-02-02 11:57 ` [Qemu-devel] [PATCH for-1.4? qom-cpu-next 2/9] target-lm32: Drop unused cpu_lm32_close() prototype Andreas Färber
                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Andreas Färber @ 2013-02-02 11:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Andreas Färber, Fabien Chouteau, Michael Walle,
	Peter Maydell, Anthony Liguori, Guan Xuetao, Blue Swirl,
	Gleb Natapov, Marcelo Tosatti, Paul Brook, Aurelien Jarno,
	Alexander Graf, Richard Henderson, open list:Overall,
	open list:PowerPC

Move it to qom/cpu.h to avoid issues with include order.

Change pc_acpi_smi_interrupt() opaque to X86CPU.

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 cpus.c                   |    2 +-
 exec.c                   |    2 +-
 hw/alpha_typhoon.c       |   10 ++++------
 hw/apic.c                |   21 +++++++++++----------
 hw/arm_pic.c             |    5 ++---
 hw/cris_pic_cpu.c        |    3 +--
 hw/leon3.c               |    3 ++-
 hw/lm32_boards.c         |    3 +--
 hw/lpc_ich9.c            |    2 +-
 hw/microblaze_pic_cpu.c  |    3 +--
 hw/milkymist.c           |    3 +--
 hw/mips_int.c            |    2 +-
 hw/omap1.c               |    4 ++--
 hw/openrisc_pic.c        |    2 +-
 hw/pc.c                  |    6 +++---
 hw/pc_piix.c             |    3 ++-
 hw/ppc.c                 |    6 +++---
 hw/ppc405_uc.c           |    4 ++--
 hw/puv3.c                |    3 +--
 hw/pxa2xx.c              |    7 ++++---
 hw/pxa2xx_gpio.c         |    2 +-
 hw/pxa2xx_pic.c          |    6 +++---
 hw/sh_intc.c             |    5 +++--
 hw/sun4m.c               |    9 ++++++---
 hw/sun4u.c               |    4 ++--
 hw/xtensa_pic.c          |    2 +-
 include/exec/cpu-all.h   |   13 -------------
 include/qom/cpu.h        |   24 ++++++++++++++++++++++++
 kvm-all.c                |    4 +---
 target-arm/helper.c      |    2 +-
 target-i386/helper.c     |    6 +++---
 target-m68k/helper.c     |    2 +-
 target-mips/op_helper.c  |    8 ++++----
 target-ppc/excp_helper.c |    2 +-
 target-s390x/cpu.h       |    6 +++---
 target-s390x/helper.c    |    4 ++--
 translate-all.c          |   12 +++++-------
 37 Dateien geändert, 106 Zeilen hinzugefügt(+), 99 Zeilen entfernt(-)

diff --git a/cpus.c b/cpus.c
index 8b5f426..df2a363 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1335,7 +1335,7 @@ void qmp_inject_nmi(Error **errp)
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         if (!env->apic_state) {
-            cpu_interrupt(env, CPU_INTERRUPT_NMI);
+            cpu_interrupt(CPU(x86_env_get_cpu(env)), CPU_INTERRUPT_NMI);
         } else {
             apic_deliver_nmi(env->apic_state);
         }
diff --git a/exec.c b/exec.c
index d14dbe7..c335c3f 100644
--- a/exec.c
+++ b/exec.c
@@ -1460,7 +1460,7 @@ static void check_watchpoint(int offset, int len_mask, int flags)
         /* We re-entered the check after replacing the TB. Now raise
          * the debug interrupt so that is will trigger after the
          * current instruction. */
-        cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
+        cpu_interrupt(ENV_GET_CPU(env), CPU_INTERRUPT_DEBUG);
         return;
     }
     vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index dfb10c7..3b15b30 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -62,10 +62,9 @@ static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
 {
     /* If there are any non-masked interrupts, tell the cpu.  */
     if (cpu != NULL) {
-        CPUAlphaState *env = &cpu->env;
         CPUState *cs = CPU(cpu);
         if (req) {
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
         } else {
             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
         }
@@ -359,11 +358,10 @@ static void cchip_write(void *opaque, hwaddr addr,
             for (i = 0; i < 4; ++i) {
                 AlphaCPU *cpu = s->cchip.cpu[i];
                 if (cpu != NULL) {
-                    CPUAlphaState *env = &cpu->env;
                     CPUState *cs = CPU(cpu);
                     /* IPI can be either cleared or set by the write.  */
                     if (newval & (1 << (i + 8))) {
-                        cpu_interrupt(env, CPU_INTERRUPT_SMP);
+                        cpu_interrupt(cs, CPU_INTERRUPT_SMP);
                     } else {
                         cpu_reset_interrupt(cs, CPU_INTERRUPT_SMP);
                     }
@@ -687,7 +685,7 @@ static void typhoon_set_timer_irq(void *opaque, int irq, int level)
                 /* Set the ITI bit for this cpu.  */
                 s->cchip.misc |= 1 << (i + 4);
                 /* And signal the interrupt.  */
-                cpu_interrupt(&cpu->env, CPU_INTERRUPT_TIMER);
+                cpu_interrupt(CPU(cpu), CPU_INTERRUPT_TIMER);
             }
         }
     }
@@ -700,7 +698,7 @@ static void typhoon_alarm_timer(void *opaque)
 
     /* Set the ITI bit for this cpu.  */
     s->cchip.misc |= 1 << (cpu + 4);
-    cpu_interrupt(&s->cchip.cpu[cpu]->env, CPU_INTERRUPT_TIMER);
+    cpu_interrupt(CPU(s->cchip.cpu[cpu]), CPU_INTERRUPT_TIMER);
 }
 
 PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
diff --git a/hw/apic.c b/hw/apic.c
index e113c11..f7cb8b1 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -151,15 +151,15 @@ static void apic_local_deliver(APICCommonState *s, int vector)
 
     switch ((lvt >> 8) & 7) {
     case APIC_DM_SMI:
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_SMI);
+        cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_SMI);
         break;
 
     case APIC_DM_NMI:
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_NMI);
+        cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_NMI);
         break;
 
     case APIC_DM_EXTINT:
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HARD);
         break;
 
     case APIC_DM_FIXED:
@@ -248,20 +248,20 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask,
 
         case APIC_DM_SMI:
             foreach_apic(apic_iter, deliver_bitmask,
-                cpu_interrupt(&apic_iter->cpu->env, CPU_INTERRUPT_SMI)
+                cpu_interrupt(CPU(apic_iter->cpu), CPU_INTERRUPT_SMI)
             );
             return;
 
         case APIC_DM_NMI:
             foreach_apic(apic_iter, deliver_bitmask,
-                cpu_interrupt(&apic_iter->cpu->env, CPU_INTERRUPT_NMI)
+                cpu_interrupt(CPU(apic_iter->cpu), CPU_INTERRUPT_NMI)
             );
             return;
 
         case APIC_DM_INIT:
             /* normal INIT IPI sent to processors */
             foreach_apic(apic_iter, deliver_bitmask,
-                         cpu_interrupt(&apic_iter->cpu->env,
+                         cpu_interrupt(CPU(apic_iter->cpu),
                                        CPU_INTERRUPT_INIT)
             );
             return;
@@ -363,15 +363,16 @@ static int apic_irq_pending(APICCommonState *s)
 /* signal the CPU if an irq is pending */
 static void apic_update_irq(APICCommonState *s)
 {
-    CPUState *cpu = CPU(s->cpu);
+    CPUState *cpu;
 
     if (!(s->spurious_vec & APIC_SV_ENABLE)) {
         return;
     }
+    cpu = CPU(s->cpu);
     if (!qemu_cpu_is_self(cpu)) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_POLL);
+        cpu_interrupt(cpu, CPU_INTERRUPT_POLL);
     } else if (apic_irq_pending(s) > 0) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cpu, CPU_INTERRUPT_HARD);
     }
 }
 
@@ -478,7 +479,7 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
 static void apic_startup(APICCommonState *s, int vector_num)
 {
     s->sipi_vector = vector_num;
-    cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_SIPI);
+    cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI);
 }
 
 void apic_sipi(DeviceState *d)
diff --git a/hw/arm_pic.c b/hw/arm_pic.c
index ddf3f0b..a3e63d1 100644
--- a/hw/arm_pic.c
+++ b/hw/arm_pic.c
@@ -14,20 +14,19 @@
 static void arm_pic_cpu_handler(void *opaque, int irq, int level)
 {
     ARMCPU *cpu = opaque;
-    CPUARMState *env = &cpu->env;
     CPUState *cs = CPU(cpu);
 
     switch (irq) {
     case ARM_PIC_CPU_IRQ:
         if (level) {
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
         } else {
             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
         }
         break;
     case ARM_PIC_CPU_FIQ:
         if (level) {
-            cpu_interrupt(env, CPU_INTERRUPT_FIQ);
+            cpu_interrupt(cs, CPU_INTERRUPT_FIQ);
         } else {
             cpu_reset_interrupt(cs, CPU_INTERRUPT_FIQ);
         }
diff --git a/hw/cris_pic_cpu.c b/hw/cris_pic_cpu.c
index 46630aa..edda325 100644
--- a/hw/cris_pic_cpu.c
+++ b/hw/cris_pic_cpu.c
@@ -31,12 +31,11 @@
 static void cris_pic_cpu_handler(void *opaque, int irq, int level)
 {
     CRISCPU *cpu = opaque;
-    CPUCRISState *env = &cpu->env;
     CPUState *cs = CPU(cpu);
     int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
 
     if (level) {
-        cpu_interrupt(env, type);
+        cpu_interrupt(cs, type);
     } else {
         cpu_reset_interrupt(cs, type);
     }
diff --git a/hw/leon3.c b/hw/leon3.c
index ba92994..2effe6a 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -83,8 +83,9 @@ static void leon3_set_pil_in(void *opaque, uint32_t pil_in)
 
                 env->interrupt_index = TT_EXTINT | i;
                 if (old_interrupt != env->interrupt_index) {
+                    cs = CPU(sparc_env_get_cpu(env));
                     trace_leon3_set_irq(i);
-                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+                    cpu_interrupt(cs, CPU_INTERRUPT_HARD);
                 }
                 break;
             }
diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
index 388a0ae..dd6c5fad 100644
--- a/hw/lm32_boards.c
+++ b/hw/lm32_boards.c
@@ -42,11 +42,10 @@ typedef struct {
 static void cpu_irq_handler(void *opaque, int irq, int level)
 {
     LM32CPU *cpu = opaque;
-    CPULM32State *env = &cpu->env;
     CPUState *cs = CPU(cpu);
 
     if (level) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
index e25689b..0a7ce8d 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -381,7 +381,7 @@ static void ich9_apm_ctrl_changed(uint32_t val, void *arg)
 
     /* SMI_EN = PMBASE + 30. SMI control and enable register */
     if (lpc->pm.smi_en & ICH9_PMIO_SMI_EN_APMC_EN) {
-        cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
+        cpu_interrupt(CPU(x86_env_get_cpu(first_cpu)), CPU_INTERRUPT_SMI);
     }
 }
 
diff --git a/hw/microblaze_pic_cpu.c b/hw/microblaze_pic_cpu.c
index 2234bfb..bc40ebe 100644
--- a/hw/microblaze_pic_cpu.c
+++ b/hw/microblaze_pic_cpu.c
@@ -30,12 +30,11 @@
 static void microblaze_pic_cpu_handler(void *opaque, int irq, int level)
 {
     MicroBlazeCPU *cpu = opaque;
-    CPUMBState *env = &cpu->env;
     CPUState *cs = CPU(cpu);
     int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
 
     if (level) {
-        cpu_interrupt(env, type);
+        cpu_interrupt(cs, type);
     } else {
         cpu_reset_interrupt(cs, type);
     }
diff --git a/hw/milkymist.c b/hw/milkymist.c
index dcadc07..bdffd31 100644
--- a/hw/milkymist.c
+++ b/hw/milkymist.c
@@ -47,11 +47,10 @@ typedef struct {
 static void cpu_irq_handler(void *opaque, int irq, int level)
 {
     LM32CPU *cpu = opaque;
-    CPULM32State *env = &cpu->env;
     CPUState *cs = CPU(cpu);
 
     if (level) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
diff --git a/hw/mips_int.c b/hw/mips_int.c
index a6f0c52..36962e5 100644
--- a/hw/mips_int.c
+++ b/hw/mips_int.c
@@ -40,7 +40,7 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
     }
 
     if (env->CP0_Cause & CP0Ca_IP_mask) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
diff --git a/hw/omap1.c b/hw/omap1.c
index c36a330..1f95b79 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -1523,7 +1523,7 @@ static inline void omap_clkm_idlect1_update(struct omap_mpu_state_s *s,
     omap_clk clk;
 
     if (value & (1 << 11)) {                            /* SETARM_IDLE */
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+        cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT);
     }
     if (!(value & (1 << 10)))				/* WKUP_MODE */
         qemu_system_shutdown_request();	/* XXX: disable wakeup from IRQ */
@@ -3759,7 +3759,7 @@ void omap_mpu_wakeup(void *opaque, int irq, int req)
     CPUState *cpu = CPU(mpu->cpu);
 
     if (cpu->halted) {
-        cpu_interrupt(&mpu->cpu->env, CPU_INTERRUPT_EXITTB);
+        cpu_interrupt(cpu, CPU_INTERRUPT_EXITTB);
     }
 }
 
diff --git a/hw/openrisc_pic.c b/hw/openrisc_pic.c
index 935dce3..979a513 100644
--- a/hw/openrisc_pic.c
+++ b/hw/openrisc_pic.c
@@ -41,7 +41,7 @@ static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
 
     for (i = 0; i < 32; i++) {
         if ((cpu->env.picsr && (1 << i)) && (cpu->env.picmr && (1 << i))) {
-            cpu_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
         } else {
             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
             cpu->env.picsr &= ~(1 << i);
diff --git a/hw/pc.c b/hw/pc.c
index ef72628..150134b 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -192,7 +192,7 @@ static void pic_irq_request(void *opaque, int irq, int level)
     } else {
         CPUState *cs = CPU(x86_env_get_cpu(env));
         if (level) {
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
         } else {
             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
         }
@@ -856,10 +856,10 @@ DeviceState *cpu_get_current_apic(void)
 
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
 {
-    CPUX86State *s = opaque;
+    X86CPU *cpu = opaque;
 
     if (level) {
-        cpu_interrupt(s, CPU_INTERRUPT_SMI);
+        cpu_interrupt(CPU(cpu), CPU_INTERRUPT_SMI);
     }
 }
 
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 0af436c..1d57827 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -205,7 +205,8 @@ static void pc_init1(MemoryRegion *system_memory,
     if (pci_enabled && acpi_enabled) {
         i2c_bus *smbus;
 
-        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
+        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt,
+                                     x86_env_get_cpu(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/ppc.c b/hw/ppc.c
index 8d58774..a55c4ff 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -58,7 +58,7 @@ void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
 
     if (level) {
         env->pending_interrupts |= 1 << n_IRQ;
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         env->pending_interrupts &= ~(1 << n_IRQ);
         if (env->pending_interrupts == 0) {
@@ -137,7 +137,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
             /* Level sensitive - active low */
             if (level) {
                 LOG_IRQ("%s: reset the CPU\n", __func__);
-                cpu_interrupt(env, CPU_INTERRUPT_RESET);
+                cpu_interrupt(cs, CPU_INTERRUPT_RESET);
             }
             break;
         case PPC6xx_INPUT_SRESET:
@@ -219,7 +219,7 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
         case PPC970_INPUT_HRESET:
             /* Level sensitive - active low */
             if (level) {
-                cpu_interrupt(env, CPU_INTERRUPT_RESET);
+                cpu_interrupt(cs, CPU_INTERRUPT_RESET);
             }
             break;
         case PPC970_INPUT_SRESET:
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index d8cbe87..57a5f2b 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -1776,7 +1776,7 @@ void ppc40x_core_reset(PowerPCCPU *cpu)
     target_ulong dbsr;
 
     printf("Reset PowerPC core\n");
-    cpu_interrupt(env, CPU_INTERRUPT_RESET);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_RESET);
     dbsr = env->spr[SPR_40x_DBSR];
     dbsr &= ~0x00000300;
     dbsr |= 0x00000100;
@@ -1789,7 +1789,7 @@ void ppc40x_chip_reset(PowerPCCPU *cpu)
     target_ulong dbsr;
 
     printf("Reset PowerPC chip\n");
-    cpu_interrupt(env, CPU_INTERRUPT_RESET);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_RESET);
     /* XXX: TODO reset all internal peripherals */
     dbsr = env->spr[SPR_40x_DBSR];
     dbsr &= ~0x00000300;
diff --git a/hw/puv3.c b/hw/puv3.c
index 6a1e10e..ec5c741 100644
--- a/hw/puv3.c
+++ b/hw/puv3.c
@@ -27,12 +27,11 @@
 static void puv3_intc_cpu_handler(void *opaque, int irq, int level)
 {
     UniCore32CPU *cpu = opaque;
-    CPUUniCore32State *env = &cpu->env;
     CPUState *cs = CPU(cpu);
 
     assert(irq == 0);
     if (level) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 373d061..7ab885e 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -263,14 +263,14 @@ static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
     case 1:
         /* Idle */
         if (!(s->cm_regs[CCCR >> 2] & (1 << 31))) { /* CPDIS */
-            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+            cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT);
             break;
         }
         /* Fall through.  */
 
     case 2:
         /* Deep-Idle */
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+        cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT);
         s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
         goto message;
 
@@ -301,7 +301,8 @@ static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
 #endif
 
         /* Suspend */
-        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
+        cpu_interrupt(CPU(arm_env_get_cpu(cpu_single_env)),
+                      CPU_INTERRUPT_HALT);
 
         goto message;
 
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index f00d150..e0638b2 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -120,7 +120,7 @@ static void pxa2xx_gpio_set(void *opaque, int line, int level)
 
     /* Wake-up GPIOs */
     if (cpu->halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
+        cpu_interrupt(cpu, CPU_INTERRUPT_EXITTB);
     }
 }
 
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 45ee7cb..8acd4a4 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -52,7 +52,7 @@ static void pxa2xx_pic_update(void *opaque)
         mask[0] = s->int_pending[0] & (s->int_enabled[0] | s->int_idle);
         mask[1] = s->int_pending[1] & (s->int_enabled[1] | s->int_idle);
         if (mask[0] || mask[1]) {
-            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
+            cpu_interrupt(cpu, CPU_INTERRUPT_EXITTB);
         }
     }
 
@@ -60,13 +60,13 @@ static void pxa2xx_pic_update(void *opaque)
     mask[1] = s->int_pending[1] & s->int_enabled[1];
 
     if ((mask[0] & s->is_fiq[0]) || (mask[1] & s->is_fiq[1])) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
+        cpu_interrupt(cpu, CPU_INTERRUPT_FIQ);
     } else {
         cpu_reset_interrupt(cpu, CPU_INTERRUPT_FIQ);
     }
 
     if ((mask[0] & ~s->is_fiq[0]) || (mask[1] & ~s->is_fiq[1])) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cpu, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
     }
diff --git a/hw/sh_intc.c b/hw/sh_intc.c
index dded2a4..2b41013 100644
--- a/hw/sh_intc.c
+++ b/hw/sh_intc.c
@@ -45,8 +45,9 @@ void sh_intc_toggle_source(struct intc_source *source,
         CPUState *cpu = CPU(sh_env_get_cpu(first_cpu));
         if (source->pending) {
             source->parent->pending++;
-	    if (source->parent->pending == 1)
-                cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD);
+            if (source->parent->pending == 1) {
+                cpu_interrupt(cpu, CPU_INTERRUPT_HARD);
+            }
         } else {
             source->parent->pending--;
             if (source->parent->pending == 0) {
diff --git a/hw/sun4m.c b/hw/sun4m.c
index fe82bd6..d83d42c 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -242,8 +242,9 @@ void cpu_check_irqs(CPUSPARCState *env)
 
                 env->interrupt_index = TT_EXTINT | i;
                 if (old_interrupt != env->interrupt_index) {
+                    cs = CPU(sparc_env_get_cpu(env));
                     trace_sun4m_cpu_interrupt(i);
-                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+                    cpu_interrupt(cs, CPU_INTERRUPT_HARD);
                 }
                 break;
             }
@@ -306,8 +307,10 @@ static void secondary_cpu_reset(void *opaque)
 
 static void cpu_halt_signal(void *opaque, int irq, int level)
 {
-    if (level && cpu_single_env)
-        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
+    if (level && cpu_single_env) {
+        cpu_interrupt(CPU(sparc_env_get_cpu(cpu_single_env)),
+                      CPU_INTERRUPT_HALT);
+    }
 }
 
 static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
diff --git a/hw/sun4u.c b/hw/sun4u.c
index dde82cf..38ebe15 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -299,7 +299,7 @@ void cpu_check_irqs(CPUSPARCState *env)
                     env->interrupt_index = new_interrupt;
                     CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i,
                                    old_interrupt, new_interrupt);
-                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+                    cpu_interrupt(cs, CPU_INTERRUPT_HARD);
                 }
                 break;
             }
@@ -339,7 +339,7 @@ static void cpu_set_ivec_irq(void *opaque, int irq, int level)
             env->ivec_data[0] = (0x1f << 6) | irq;
             env->ivec_data[1] = 0;
             env->ivec_data[2] = 0;
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
         }
     } else {
         if (env->ivec_status & 0x20) {
diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c
index 7c8c386..2c4360f 100644
--- a/hw/xtensa_pic.c
+++ b/hw/xtensa_pic.c
@@ -66,7 +66,7 @@ void check_interrupts(CPUXtensaState *env)
     for (level = env->config->nlevel; level > minlevel; --level) {
         if (env->config->level_mask[level] & int_set_enabled) {
             env->pending_irq_level = level;
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
             qemu_log_mask(CPU_LOG_INT,
                     "%s level = %d, cintlevel = %d, "
                     "pc = %08x, a0 = %08x, ps = %08x, "
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 5218a53..e9c3717 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -421,19 +421,6 @@ DECLARE_TLS(CPUArchState *,cpu_single_env);
      | CPU_INTERRUPT_TGT_EXT_3   \
      | CPU_INTERRUPT_TGT_EXT_4)
 
-#ifndef CONFIG_USER_ONLY
-typedef void (*CPUInterruptHandler)(CPUArchState *, int);
-
-extern CPUInterruptHandler cpu_interrupt_handler;
-
-static inline void cpu_interrupt(CPUArchState *s, int mask)
-{
-    cpu_interrupt_handler(s, mask);
-}
-#else /* USER_ONLY */
-void cpu_interrupt(CPUArchState *env, int mask);
-#endif /* USER_ONLY */
-
 void cpu_exit(CPUArchState *s);
 
 /* Breakpoint/watchpoint flags */
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 7d16540..1f8f2cf 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -194,6 +194,30 @@ void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data);
  */
 CPUState *qemu_get_cpu(int index);
 
+#ifndef CONFIG_USER_ONLY
+
+typedef void (*CPUInterruptHandler)(CPUState *, int);
+
+extern CPUInterruptHandler cpu_interrupt_handler;
+
+/**
+ * cpu_interrupt:
+ * @cpu: The CPU to set an interrupt on.
+ * @mask: The interupts to set.
+ *
+ * Invokes the interrupt handler.
+ */
+static inline void cpu_interrupt(CPUState *cpu, int mask)
+{
+    cpu_interrupt_handler(cpu, mask);
+}
+
+#else /* USER_ONLY */
+
+void cpu_interrupt(CPUState *cpu, int mask);
+
+#endif /* USER_ONLY */
+
 /**
  * cpu_reset_interrupt:
  * @cpu: The CPU to clear the interrupt on.
diff --git a/kvm-all.c b/kvm-all.c
index 2b761e0..9b433d3 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -826,10 +826,8 @@ static MemoryListener kvm_io_listener = {
     .priority = 10,
 };
 
-static void kvm_handle_interrupt(CPUArchState *env, int mask)
+static void kvm_handle_interrupt(CPUState *cpu, int mask)
 {
-    CPUState *cpu = ENV_GET_CPU(env);
-
     cpu->interrupt_request |= mask;
 
     if (!qemu_cpu_is_self(cpu)) {
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 31b7a3c..543d091 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -764,7 +764,7 @@ static int omap_wfi_write(CPUARMState *env, const ARMCPRegInfo *ri,
                           uint64_t value)
 {
     /* Wait-for-interrupt (deprecated) */
-    cpu_interrupt(env, CPU_INTERRUPT_HALT);
+    cpu_interrupt(CPU(arm_env_get_cpu(env)), CPU_INTERRUPT_HALT);
     return 0;
 }
 
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 808d879..4630ac0 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -378,7 +378,7 @@ void x86_cpu_set_a20(X86CPU *cpu, int a20_state)
 #endif
         /* if the cpu is currently executing code, we must unlink it and
            all the potentially executing TB */
-        cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
+        cpu_interrupt(CPU(cpu), CPU_INTERRUPT_EXITTB);
 
         /* when a20 is changed, all the MMU mappings are invalid, so
            we must flush everything */
@@ -1158,7 +1158,7 @@ static void do_inject_x86_mce(void *data)
         banks[3] = params->misc;
         cenv->mcg_status = params->mcg_status;
         banks[1] = params->status;
-        cpu_interrupt(cenv, CPU_INTERRUPT_MCE);
+        cpu_interrupt(cpu, CPU_INTERRUPT_MCE);
     } else if (!(banks[1] & MCI_STATUS_VAL)
                || !(banks[1] & MCI_STATUS_UC)) {
         if (banks[1] & MCI_STATUS_VAL) {
@@ -1230,7 +1230,7 @@ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
     if (kvm_enabled()) {
         env->tpr_access_type = access;
 
-        cpu_interrupt(env, CPU_INTERRUPT_TPR);
+        cpu_interrupt(CPU(x86_env_get_cpu(env)), CPU_INTERRUPT_TPR);
     } else {
         cpu_restore_state(env, env->mem_io_pc);
 
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index d9c8374..54fa419 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -318,7 +318,7 @@ void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
     env->pending_level = level;
     env->pending_vector = vector;
     if (level) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 6bde5b4..dc95027 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -535,12 +535,12 @@ static bool mips_vpe_is_wfi(MIPSCPU *c)
     return cpu->halted && mips_vpe_active(env);
 }
 
-static inline void mips_vpe_wake(CPUMIPSState *c)
+static inline void mips_vpe_wake(MIPSCPU *c)
 {
     /* Dont set ->halted = 0 directly, let it be done via cpu_has_work
        because there might be other conditions that state that c should
        be sleeping.  */
-    cpu_interrupt(c, CPU_INTERRUPT_WAKE);
+    cpu_interrupt(CPU(c), CPU_INTERRUPT_WAKE);
 }
 
 static inline void mips_vpe_sleep(MIPSCPU *cpu)
@@ -559,7 +559,7 @@ static inline void mips_tc_wake(MIPSCPU *cpu, int tc)
 
     /* FIXME: TC reschedule.  */
     if (mips_vpe_active(c) && !mips_vpe_is_wfi(cpu)) {
-        mips_vpe_wake(c);
+        mips_vpe_wake(cpu);
     }
 }
 
@@ -1737,7 +1737,7 @@ target_ulong helper_evpe(CPUMIPSState *env)
             && !mips_vpe_is_wfi(other_cpu)) {
             /* Enable the VPE.  */
             other_cpu_env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
-            mips_vpe_wake(other_cpu_env); /* And wake it up.  */
+            mips_vpe_wake(other_cpu); /* And wake it up.  */
         }
         other_cpu_env = other_cpu_env->next_cpu;
     } while (other_cpu_env);
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 79ce7bf..d176734 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -991,7 +991,7 @@ void helper_msgsnd(target_ulong rb)
     for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
         if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
             cenv->pending_interrupts |= 1 << irq;
-            cpu_interrupt(cenv, CPU_INTERRUPT_HARD);
+            cpu_interrupt(CPU(ppc_env_get_cpu(cenv)), CPU_INTERRUPT_HARD);
         }
     }
 }
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index e6997ef..46e2255 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -992,7 +992,7 @@ static inline void cpu_inject_ext(S390CPU *cpu, uint32_t code, uint32_t param,
     env->ext_queue[env->ext_index].param64 = param64;
 
     env->pending_int |= INTERRUPT_EXT;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 
 static inline void cpu_inject_io(S390CPU *cpu, uint16_t subchannel_id,
@@ -1016,7 +1016,7 @@ static inline void cpu_inject_io(S390CPU *cpu, uint16_t subchannel_id,
     env->io_queue[env->io_index[isc]][isc].word = io_int_word;
 
     env->pending_int |= INTERRUPT_IO;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 
 static inline void cpu_inject_crw_mchk(S390CPU *cpu)
@@ -1034,7 +1034,7 @@ static inline void cpu_inject_crw_mchk(S390CPU *cpu)
     env->mchk_queue[env->mchk_index].type = 1;
 
     env->pending_int |= INTERRUPT_MCHK;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 
 static inline bool cpu_has_work(CPUState *cpu)
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 3a54651..a65e6c7 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -57,7 +57,7 @@ void s390x_tod_timer(void *opaque)
     CPUS390XState *env = &cpu->env;
 
     env->pending_int |= INTERRUPT_TOD;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 
 void s390x_cpu_timer(void *opaque)
@@ -66,7 +66,7 @@ void s390x_cpu_timer(void *opaque)
     CPUS390XState *env = &cpu->env;
 
     env->pending_int |= INTERRUPT_CPUTIMER;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 #endif
 
diff --git a/translate-all.c b/translate-all.c
index 2176132..1dc646a 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1087,8 +1087,8 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
             tb_phys_invalidate(tb, -1);
             if (cpu != NULL) {
                 cpu->current_tb = saved_tb;
-                if (env && cpu->interrupt_request && cpu->current_tb) {
-                    cpu_interrupt(env, cpu->interrupt_request);
+                if (cpu->interrupt_request && cpu->current_tb) {
+                    cpu_interrupt(cpu, cpu->interrupt_request);
                 }
             }
         }
@@ -1460,9 +1460,9 @@ void tb_check_watchpoint(CPUArchState *env)
 
 #ifndef CONFIG_USER_ONLY
 /* mask must never be zero, except for A20 change call */
-static void tcg_handle_interrupt(CPUArchState *env, int mask)
+static void tcg_handle_interrupt(CPUState *cpu, int mask)
 {
-    CPUState *cpu = ENV_GET_CPU(env);
+    CPUArchState *env = cpu->env_ptr;
     int old_mask;
 
     old_mask = cpu->interrupt_request;
@@ -1622,10 +1622,8 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
 
 #else /* CONFIG_USER_ONLY */
 
-void cpu_interrupt(CPUArchState *env, int mask)
+void cpu_interrupt(CPUState *cpu, int mask)
 {
-    CPUState *cpu = ENV_GET_CPU(env);
-
     cpu->interrupt_request |= mask;
     cpu_unlink_tb(cpu);
 }
-- 
1.7.10.4


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

* [Qemu-devel] [RFC qom-cpu-next 7/9] cpu: Pass CPUState to cpu_interrupt()
@ 2013-02-02 11:57   ` Andreas Färber
  0 siblings, 0 replies; 12+ messages in thread
From: Andreas Färber @ 2013-02-02 11:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Anthony Liguori, open list:Overall, Gleb Natapov,
	Marcelo Tosatti, Alexander Graf, Fabien Chouteau, Blue Swirl,
	Michael Walle, open list:PowerPC, Paul Brook, Guan Xuetao,
	Andreas Färber, Aurelien Jarno, Richard Henderson

Move it to qom/cpu.h to avoid issues with include order.

Change pc_acpi_smi_interrupt() opaque to X86CPU.

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 cpus.c                   |    2 +-
 exec.c                   |    2 +-
 hw/alpha_typhoon.c       |   10 ++++------
 hw/apic.c                |   21 +++++++++++----------
 hw/arm_pic.c             |    5 ++---
 hw/cris_pic_cpu.c        |    3 +--
 hw/leon3.c               |    3 ++-
 hw/lm32_boards.c         |    3 +--
 hw/lpc_ich9.c            |    2 +-
 hw/microblaze_pic_cpu.c  |    3 +--
 hw/milkymist.c           |    3 +--
 hw/mips_int.c            |    2 +-
 hw/omap1.c               |    4 ++--
 hw/openrisc_pic.c        |    2 +-
 hw/pc.c                  |    6 +++---
 hw/pc_piix.c             |    3 ++-
 hw/ppc.c                 |    6 +++---
 hw/ppc405_uc.c           |    4 ++--
 hw/puv3.c                |    3 +--
 hw/pxa2xx.c              |    7 ++++---
 hw/pxa2xx_gpio.c         |    2 +-
 hw/pxa2xx_pic.c          |    6 +++---
 hw/sh_intc.c             |    5 +++--
 hw/sun4m.c               |    9 ++++++---
 hw/sun4u.c               |    4 ++--
 hw/xtensa_pic.c          |    2 +-
 include/exec/cpu-all.h   |   13 -------------
 include/qom/cpu.h        |   24 ++++++++++++++++++++++++
 kvm-all.c                |    4 +---
 target-arm/helper.c      |    2 +-
 target-i386/helper.c     |    6 +++---
 target-m68k/helper.c     |    2 +-
 target-mips/op_helper.c  |    8 ++++----
 target-ppc/excp_helper.c |    2 +-
 target-s390x/cpu.h       |    6 +++---
 target-s390x/helper.c    |    4 ++--
 translate-all.c          |   12 +++++-------
 37 Dateien geändert, 106 Zeilen hinzugefügt(+), 99 Zeilen entfernt(-)

diff --git a/cpus.c b/cpus.c
index 8b5f426..df2a363 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1335,7 +1335,7 @@ void qmp_inject_nmi(Error **errp)
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         if (!env->apic_state) {
-            cpu_interrupt(env, CPU_INTERRUPT_NMI);
+            cpu_interrupt(CPU(x86_env_get_cpu(env)), CPU_INTERRUPT_NMI);
         } else {
             apic_deliver_nmi(env->apic_state);
         }
diff --git a/exec.c b/exec.c
index d14dbe7..c335c3f 100644
--- a/exec.c
+++ b/exec.c
@@ -1460,7 +1460,7 @@ static void check_watchpoint(int offset, int len_mask, int flags)
         /* We re-entered the check after replacing the TB. Now raise
          * the debug interrupt so that is will trigger after the
          * current instruction. */
-        cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
+        cpu_interrupt(ENV_GET_CPU(env), CPU_INTERRUPT_DEBUG);
         return;
     }
     vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index dfb10c7..3b15b30 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -62,10 +62,9 @@ static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
 {
     /* If there are any non-masked interrupts, tell the cpu.  */
     if (cpu != NULL) {
-        CPUAlphaState *env = &cpu->env;
         CPUState *cs = CPU(cpu);
         if (req) {
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
         } else {
             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
         }
@@ -359,11 +358,10 @@ static void cchip_write(void *opaque, hwaddr addr,
             for (i = 0; i < 4; ++i) {
                 AlphaCPU *cpu = s->cchip.cpu[i];
                 if (cpu != NULL) {
-                    CPUAlphaState *env = &cpu->env;
                     CPUState *cs = CPU(cpu);
                     /* IPI can be either cleared or set by the write.  */
                     if (newval & (1 << (i + 8))) {
-                        cpu_interrupt(env, CPU_INTERRUPT_SMP);
+                        cpu_interrupt(cs, CPU_INTERRUPT_SMP);
                     } else {
                         cpu_reset_interrupt(cs, CPU_INTERRUPT_SMP);
                     }
@@ -687,7 +685,7 @@ static void typhoon_set_timer_irq(void *opaque, int irq, int level)
                 /* Set the ITI bit for this cpu.  */
                 s->cchip.misc |= 1 << (i + 4);
                 /* And signal the interrupt.  */
-                cpu_interrupt(&cpu->env, CPU_INTERRUPT_TIMER);
+                cpu_interrupt(CPU(cpu), CPU_INTERRUPT_TIMER);
             }
         }
     }
@@ -700,7 +698,7 @@ static void typhoon_alarm_timer(void *opaque)
 
     /* Set the ITI bit for this cpu.  */
     s->cchip.misc |= 1 << (cpu + 4);
-    cpu_interrupt(&s->cchip.cpu[cpu]->env, CPU_INTERRUPT_TIMER);
+    cpu_interrupt(CPU(s->cchip.cpu[cpu]), CPU_INTERRUPT_TIMER);
 }
 
 PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
diff --git a/hw/apic.c b/hw/apic.c
index e113c11..f7cb8b1 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -151,15 +151,15 @@ static void apic_local_deliver(APICCommonState *s, int vector)
 
     switch ((lvt >> 8) & 7) {
     case APIC_DM_SMI:
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_SMI);
+        cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_SMI);
         break;
 
     case APIC_DM_NMI:
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_NMI);
+        cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_NMI);
         break;
 
     case APIC_DM_EXTINT:
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HARD);
         break;
 
     case APIC_DM_FIXED:
@@ -248,20 +248,20 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask,
 
         case APIC_DM_SMI:
             foreach_apic(apic_iter, deliver_bitmask,
-                cpu_interrupt(&apic_iter->cpu->env, CPU_INTERRUPT_SMI)
+                cpu_interrupt(CPU(apic_iter->cpu), CPU_INTERRUPT_SMI)
             );
             return;
 
         case APIC_DM_NMI:
             foreach_apic(apic_iter, deliver_bitmask,
-                cpu_interrupt(&apic_iter->cpu->env, CPU_INTERRUPT_NMI)
+                cpu_interrupt(CPU(apic_iter->cpu), CPU_INTERRUPT_NMI)
             );
             return;
 
         case APIC_DM_INIT:
             /* normal INIT IPI sent to processors */
             foreach_apic(apic_iter, deliver_bitmask,
-                         cpu_interrupt(&apic_iter->cpu->env,
+                         cpu_interrupt(CPU(apic_iter->cpu),
                                        CPU_INTERRUPT_INIT)
             );
             return;
@@ -363,15 +363,16 @@ static int apic_irq_pending(APICCommonState *s)
 /* signal the CPU if an irq is pending */
 static void apic_update_irq(APICCommonState *s)
 {
-    CPUState *cpu = CPU(s->cpu);
+    CPUState *cpu;
 
     if (!(s->spurious_vec & APIC_SV_ENABLE)) {
         return;
     }
+    cpu = CPU(s->cpu);
     if (!qemu_cpu_is_self(cpu)) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_POLL);
+        cpu_interrupt(cpu, CPU_INTERRUPT_POLL);
     } else if (apic_irq_pending(s) > 0) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cpu, CPU_INTERRUPT_HARD);
     }
 }
 
@@ -478,7 +479,7 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
 static void apic_startup(APICCommonState *s, int vector_num)
 {
     s->sipi_vector = vector_num;
-    cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_SIPI);
+    cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI);
 }
 
 void apic_sipi(DeviceState *d)
diff --git a/hw/arm_pic.c b/hw/arm_pic.c
index ddf3f0b..a3e63d1 100644
--- a/hw/arm_pic.c
+++ b/hw/arm_pic.c
@@ -14,20 +14,19 @@
 static void arm_pic_cpu_handler(void *opaque, int irq, int level)
 {
     ARMCPU *cpu = opaque;
-    CPUARMState *env = &cpu->env;
     CPUState *cs = CPU(cpu);
 
     switch (irq) {
     case ARM_PIC_CPU_IRQ:
         if (level) {
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
         } else {
             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
         }
         break;
     case ARM_PIC_CPU_FIQ:
         if (level) {
-            cpu_interrupt(env, CPU_INTERRUPT_FIQ);
+            cpu_interrupt(cs, CPU_INTERRUPT_FIQ);
         } else {
             cpu_reset_interrupt(cs, CPU_INTERRUPT_FIQ);
         }
diff --git a/hw/cris_pic_cpu.c b/hw/cris_pic_cpu.c
index 46630aa..edda325 100644
--- a/hw/cris_pic_cpu.c
+++ b/hw/cris_pic_cpu.c
@@ -31,12 +31,11 @@
 static void cris_pic_cpu_handler(void *opaque, int irq, int level)
 {
     CRISCPU *cpu = opaque;
-    CPUCRISState *env = &cpu->env;
     CPUState *cs = CPU(cpu);
     int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
 
     if (level) {
-        cpu_interrupt(env, type);
+        cpu_interrupt(cs, type);
     } else {
         cpu_reset_interrupt(cs, type);
     }
diff --git a/hw/leon3.c b/hw/leon3.c
index ba92994..2effe6a 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -83,8 +83,9 @@ static void leon3_set_pil_in(void *opaque, uint32_t pil_in)
 
                 env->interrupt_index = TT_EXTINT | i;
                 if (old_interrupt != env->interrupt_index) {
+                    cs = CPU(sparc_env_get_cpu(env));
                     trace_leon3_set_irq(i);
-                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+                    cpu_interrupt(cs, CPU_INTERRUPT_HARD);
                 }
                 break;
             }
diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
index 388a0ae..dd6c5fad 100644
--- a/hw/lm32_boards.c
+++ b/hw/lm32_boards.c
@@ -42,11 +42,10 @@ typedef struct {
 static void cpu_irq_handler(void *opaque, int irq, int level)
 {
     LM32CPU *cpu = opaque;
-    CPULM32State *env = &cpu->env;
     CPUState *cs = CPU(cpu);
 
     if (level) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
index e25689b..0a7ce8d 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -381,7 +381,7 @@ static void ich9_apm_ctrl_changed(uint32_t val, void *arg)
 
     /* SMI_EN = PMBASE + 30. SMI control and enable register */
     if (lpc->pm.smi_en & ICH9_PMIO_SMI_EN_APMC_EN) {
-        cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
+        cpu_interrupt(CPU(x86_env_get_cpu(first_cpu)), CPU_INTERRUPT_SMI);
     }
 }
 
diff --git a/hw/microblaze_pic_cpu.c b/hw/microblaze_pic_cpu.c
index 2234bfb..bc40ebe 100644
--- a/hw/microblaze_pic_cpu.c
+++ b/hw/microblaze_pic_cpu.c
@@ -30,12 +30,11 @@
 static void microblaze_pic_cpu_handler(void *opaque, int irq, int level)
 {
     MicroBlazeCPU *cpu = opaque;
-    CPUMBState *env = &cpu->env;
     CPUState *cs = CPU(cpu);
     int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
 
     if (level) {
-        cpu_interrupt(env, type);
+        cpu_interrupt(cs, type);
     } else {
         cpu_reset_interrupt(cs, type);
     }
diff --git a/hw/milkymist.c b/hw/milkymist.c
index dcadc07..bdffd31 100644
--- a/hw/milkymist.c
+++ b/hw/milkymist.c
@@ -47,11 +47,10 @@ typedef struct {
 static void cpu_irq_handler(void *opaque, int irq, int level)
 {
     LM32CPU *cpu = opaque;
-    CPULM32State *env = &cpu->env;
     CPUState *cs = CPU(cpu);
 
     if (level) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
diff --git a/hw/mips_int.c b/hw/mips_int.c
index a6f0c52..36962e5 100644
--- a/hw/mips_int.c
+++ b/hw/mips_int.c
@@ -40,7 +40,7 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
     }
 
     if (env->CP0_Cause & CP0Ca_IP_mask) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
diff --git a/hw/omap1.c b/hw/omap1.c
index c36a330..1f95b79 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -1523,7 +1523,7 @@ static inline void omap_clkm_idlect1_update(struct omap_mpu_state_s *s,
     omap_clk clk;
 
     if (value & (1 << 11)) {                            /* SETARM_IDLE */
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+        cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT);
     }
     if (!(value & (1 << 10)))				/* WKUP_MODE */
         qemu_system_shutdown_request();	/* XXX: disable wakeup from IRQ */
@@ -3759,7 +3759,7 @@ void omap_mpu_wakeup(void *opaque, int irq, int req)
     CPUState *cpu = CPU(mpu->cpu);
 
     if (cpu->halted) {
-        cpu_interrupt(&mpu->cpu->env, CPU_INTERRUPT_EXITTB);
+        cpu_interrupt(cpu, CPU_INTERRUPT_EXITTB);
     }
 }
 
diff --git a/hw/openrisc_pic.c b/hw/openrisc_pic.c
index 935dce3..979a513 100644
--- a/hw/openrisc_pic.c
+++ b/hw/openrisc_pic.c
@@ -41,7 +41,7 @@ static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
 
     for (i = 0; i < 32; i++) {
         if ((cpu->env.picsr && (1 << i)) && (cpu->env.picmr && (1 << i))) {
-            cpu_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
         } else {
             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
             cpu->env.picsr &= ~(1 << i);
diff --git a/hw/pc.c b/hw/pc.c
index ef72628..150134b 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -192,7 +192,7 @@ static void pic_irq_request(void *opaque, int irq, int level)
     } else {
         CPUState *cs = CPU(x86_env_get_cpu(env));
         if (level) {
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
         } else {
             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
         }
@@ -856,10 +856,10 @@ DeviceState *cpu_get_current_apic(void)
 
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
 {
-    CPUX86State *s = opaque;
+    X86CPU *cpu = opaque;
 
     if (level) {
-        cpu_interrupt(s, CPU_INTERRUPT_SMI);
+        cpu_interrupt(CPU(cpu), CPU_INTERRUPT_SMI);
     }
 }
 
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 0af436c..1d57827 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -205,7 +205,8 @@ static void pc_init1(MemoryRegion *system_memory,
     if (pci_enabled && acpi_enabled) {
         i2c_bus *smbus;
 
-        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
+        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt,
+                                     x86_env_get_cpu(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/ppc.c b/hw/ppc.c
index 8d58774..a55c4ff 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -58,7 +58,7 @@ void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
 
     if (level) {
         env->pending_interrupts |= 1 << n_IRQ;
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         env->pending_interrupts &= ~(1 << n_IRQ);
         if (env->pending_interrupts == 0) {
@@ -137,7 +137,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
             /* Level sensitive - active low */
             if (level) {
                 LOG_IRQ("%s: reset the CPU\n", __func__);
-                cpu_interrupt(env, CPU_INTERRUPT_RESET);
+                cpu_interrupt(cs, CPU_INTERRUPT_RESET);
             }
             break;
         case PPC6xx_INPUT_SRESET:
@@ -219,7 +219,7 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
         case PPC970_INPUT_HRESET:
             /* Level sensitive - active low */
             if (level) {
-                cpu_interrupt(env, CPU_INTERRUPT_RESET);
+                cpu_interrupt(cs, CPU_INTERRUPT_RESET);
             }
             break;
         case PPC970_INPUT_SRESET:
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index d8cbe87..57a5f2b 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -1776,7 +1776,7 @@ void ppc40x_core_reset(PowerPCCPU *cpu)
     target_ulong dbsr;
 
     printf("Reset PowerPC core\n");
-    cpu_interrupt(env, CPU_INTERRUPT_RESET);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_RESET);
     dbsr = env->spr[SPR_40x_DBSR];
     dbsr &= ~0x00000300;
     dbsr |= 0x00000100;
@@ -1789,7 +1789,7 @@ void ppc40x_chip_reset(PowerPCCPU *cpu)
     target_ulong dbsr;
 
     printf("Reset PowerPC chip\n");
-    cpu_interrupt(env, CPU_INTERRUPT_RESET);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_RESET);
     /* XXX: TODO reset all internal peripherals */
     dbsr = env->spr[SPR_40x_DBSR];
     dbsr &= ~0x00000300;
diff --git a/hw/puv3.c b/hw/puv3.c
index 6a1e10e..ec5c741 100644
--- a/hw/puv3.c
+++ b/hw/puv3.c
@@ -27,12 +27,11 @@
 static void puv3_intc_cpu_handler(void *opaque, int irq, int level)
 {
     UniCore32CPU *cpu = opaque;
-    CPUUniCore32State *env = &cpu->env;
     CPUState *cs = CPU(cpu);
 
     assert(irq == 0);
     if (level) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 373d061..7ab885e 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -263,14 +263,14 @@ static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
     case 1:
         /* Idle */
         if (!(s->cm_regs[CCCR >> 2] & (1 << 31))) { /* CPDIS */
-            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+            cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT);
             break;
         }
         /* Fall through.  */
 
     case 2:
         /* Deep-Idle */
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+        cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT);
         s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
         goto message;
 
@@ -301,7 +301,8 @@ static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
 #endif
 
         /* Suspend */
-        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
+        cpu_interrupt(CPU(arm_env_get_cpu(cpu_single_env)),
+                      CPU_INTERRUPT_HALT);
 
         goto message;
 
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index f00d150..e0638b2 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -120,7 +120,7 @@ static void pxa2xx_gpio_set(void *opaque, int line, int level)
 
     /* Wake-up GPIOs */
     if (cpu->halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
+        cpu_interrupt(cpu, CPU_INTERRUPT_EXITTB);
     }
 }
 
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 45ee7cb..8acd4a4 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -52,7 +52,7 @@ static void pxa2xx_pic_update(void *opaque)
         mask[0] = s->int_pending[0] & (s->int_enabled[0] | s->int_idle);
         mask[1] = s->int_pending[1] & (s->int_enabled[1] | s->int_idle);
         if (mask[0] || mask[1]) {
-            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
+            cpu_interrupt(cpu, CPU_INTERRUPT_EXITTB);
         }
     }
 
@@ -60,13 +60,13 @@ static void pxa2xx_pic_update(void *opaque)
     mask[1] = s->int_pending[1] & s->int_enabled[1];
 
     if ((mask[0] & s->is_fiq[0]) || (mask[1] & s->is_fiq[1])) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
+        cpu_interrupt(cpu, CPU_INTERRUPT_FIQ);
     } else {
         cpu_reset_interrupt(cpu, CPU_INTERRUPT_FIQ);
     }
 
     if ((mask[0] & ~s->is_fiq[0]) || (mask[1] & ~s->is_fiq[1])) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cpu, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
     }
diff --git a/hw/sh_intc.c b/hw/sh_intc.c
index dded2a4..2b41013 100644
--- a/hw/sh_intc.c
+++ b/hw/sh_intc.c
@@ -45,8 +45,9 @@ void sh_intc_toggle_source(struct intc_source *source,
         CPUState *cpu = CPU(sh_env_get_cpu(first_cpu));
         if (source->pending) {
             source->parent->pending++;
-	    if (source->parent->pending == 1)
-                cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD);
+            if (source->parent->pending == 1) {
+                cpu_interrupt(cpu, CPU_INTERRUPT_HARD);
+            }
         } else {
             source->parent->pending--;
             if (source->parent->pending == 0) {
diff --git a/hw/sun4m.c b/hw/sun4m.c
index fe82bd6..d83d42c 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -242,8 +242,9 @@ void cpu_check_irqs(CPUSPARCState *env)
 
                 env->interrupt_index = TT_EXTINT | i;
                 if (old_interrupt != env->interrupt_index) {
+                    cs = CPU(sparc_env_get_cpu(env));
                     trace_sun4m_cpu_interrupt(i);
-                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+                    cpu_interrupt(cs, CPU_INTERRUPT_HARD);
                 }
                 break;
             }
@@ -306,8 +307,10 @@ static void secondary_cpu_reset(void *opaque)
 
 static void cpu_halt_signal(void *opaque, int irq, int level)
 {
-    if (level && cpu_single_env)
-        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
+    if (level && cpu_single_env) {
+        cpu_interrupt(CPU(sparc_env_get_cpu(cpu_single_env)),
+                      CPU_INTERRUPT_HALT);
+    }
 }
 
 static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
diff --git a/hw/sun4u.c b/hw/sun4u.c
index dde82cf..38ebe15 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -299,7 +299,7 @@ void cpu_check_irqs(CPUSPARCState *env)
                     env->interrupt_index = new_interrupt;
                     CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i,
                                    old_interrupt, new_interrupt);
-                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+                    cpu_interrupt(cs, CPU_INTERRUPT_HARD);
                 }
                 break;
             }
@@ -339,7 +339,7 @@ static void cpu_set_ivec_irq(void *opaque, int irq, int level)
             env->ivec_data[0] = (0x1f << 6) | irq;
             env->ivec_data[1] = 0;
             env->ivec_data[2] = 0;
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
         }
     } else {
         if (env->ivec_status & 0x20) {
diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c
index 7c8c386..2c4360f 100644
--- a/hw/xtensa_pic.c
+++ b/hw/xtensa_pic.c
@@ -66,7 +66,7 @@ void check_interrupts(CPUXtensaState *env)
     for (level = env->config->nlevel; level > minlevel; --level) {
         if (env->config->level_mask[level] & int_set_enabled) {
             env->pending_irq_level = level;
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
             qemu_log_mask(CPU_LOG_INT,
                     "%s level = %d, cintlevel = %d, "
                     "pc = %08x, a0 = %08x, ps = %08x, "
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 5218a53..e9c3717 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -421,19 +421,6 @@ DECLARE_TLS(CPUArchState *,cpu_single_env);
      | CPU_INTERRUPT_TGT_EXT_3   \
      | CPU_INTERRUPT_TGT_EXT_4)
 
-#ifndef CONFIG_USER_ONLY
-typedef void (*CPUInterruptHandler)(CPUArchState *, int);
-
-extern CPUInterruptHandler cpu_interrupt_handler;
-
-static inline void cpu_interrupt(CPUArchState *s, int mask)
-{
-    cpu_interrupt_handler(s, mask);
-}
-#else /* USER_ONLY */
-void cpu_interrupt(CPUArchState *env, int mask);
-#endif /* USER_ONLY */
-
 void cpu_exit(CPUArchState *s);
 
 /* Breakpoint/watchpoint flags */
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 7d16540..1f8f2cf 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -194,6 +194,30 @@ void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data);
  */
 CPUState *qemu_get_cpu(int index);
 
+#ifndef CONFIG_USER_ONLY
+
+typedef void (*CPUInterruptHandler)(CPUState *, int);
+
+extern CPUInterruptHandler cpu_interrupt_handler;
+
+/**
+ * cpu_interrupt:
+ * @cpu: The CPU to set an interrupt on.
+ * @mask: The interupts to set.
+ *
+ * Invokes the interrupt handler.
+ */
+static inline void cpu_interrupt(CPUState *cpu, int mask)
+{
+    cpu_interrupt_handler(cpu, mask);
+}
+
+#else /* USER_ONLY */
+
+void cpu_interrupt(CPUState *cpu, int mask);
+
+#endif /* USER_ONLY */
+
 /**
  * cpu_reset_interrupt:
  * @cpu: The CPU to clear the interrupt on.
diff --git a/kvm-all.c b/kvm-all.c
index 2b761e0..9b433d3 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -826,10 +826,8 @@ static MemoryListener kvm_io_listener = {
     .priority = 10,
 };
 
-static void kvm_handle_interrupt(CPUArchState *env, int mask)
+static void kvm_handle_interrupt(CPUState *cpu, int mask)
 {
-    CPUState *cpu = ENV_GET_CPU(env);
-
     cpu->interrupt_request |= mask;
 
     if (!qemu_cpu_is_self(cpu)) {
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 31b7a3c..543d091 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -764,7 +764,7 @@ static int omap_wfi_write(CPUARMState *env, const ARMCPRegInfo *ri,
                           uint64_t value)
 {
     /* Wait-for-interrupt (deprecated) */
-    cpu_interrupt(env, CPU_INTERRUPT_HALT);
+    cpu_interrupt(CPU(arm_env_get_cpu(env)), CPU_INTERRUPT_HALT);
     return 0;
 }
 
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 808d879..4630ac0 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -378,7 +378,7 @@ void x86_cpu_set_a20(X86CPU *cpu, int a20_state)
 #endif
         /* if the cpu is currently executing code, we must unlink it and
            all the potentially executing TB */
-        cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
+        cpu_interrupt(CPU(cpu), CPU_INTERRUPT_EXITTB);
 
         /* when a20 is changed, all the MMU mappings are invalid, so
            we must flush everything */
@@ -1158,7 +1158,7 @@ static void do_inject_x86_mce(void *data)
         banks[3] = params->misc;
         cenv->mcg_status = params->mcg_status;
         banks[1] = params->status;
-        cpu_interrupt(cenv, CPU_INTERRUPT_MCE);
+        cpu_interrupt(cpu, CPU_INTERRUPT_MCE);
     } else if (!(banks[1] & MCI_STATUS_VAL)
                || !(banks[1] & MCI_STATUS_UC)) {
         if (banks[1] & MCI_STATUS_VAL) {
@@ -1230,7 +1230,7 @@ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
     if (kvm_enabled()) {
         env->tpr_access_type = access;
 
-        cpu_interrupt(env, CPU_INTERRUPT_TPR);
+        cpu_interrupt(CPU(x86_env_get_cpu(env)), CPU_INTERRUPT_TPR);
     } else {
         cpu_restore_state(env, env->mem_io_pc);
 
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index d9c8374..54fa419 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -318,7 +318,7 @@ void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
     env->pending_level = level;
     env->pending_vector = vector;
     if (level) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 6bde5b4..dc95027 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -535,12 +535,12 @@ static bool mips_vpe_is_wfi(MIPSCPU *c)
     return cpu->halted && mips_vpe_active(env);
 }
 
-static inline void mips_vpe_wake(CPUMIPSState *c)
+static inline void mips_vpe_wake(MIPSCPU *c)
 {
     /* Dont set ->halted = 0 directly, let it be done via cpu_has_work
        because there might be other conditions that state that c should
        be sleeping.  */
-    cpu_interrupt(c, CPU_INTERRUPT_WAKE);
+    cpu_interrupt(CPU(c), CPU_INTERRUPT_WAKE);
 }
 
 static inline void mips_vpe_sleep(MIPSCPU *cpu)
@@ -559,7 +559,7 @@ static inline void mips_tc_wake(MIPSCPU *cpu, int tc)
 
     /* FIXME: TC reschedule.  */
     if (mips_vpe_active(c) && !mips_vpe_is_wfi(cpu)) {
-        mips_vpe_wake(c);
+        mips_vpe_wake(cpu);
     }
 }
 
@@ -1737,7 +1737,7 @@ target_ulong helper_evpe(CPUMIPSState *env)
             && !mips_vpe_is_wfi(other_cpu)) {
             /* Enable the VPE.  */
             other_cpu_env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
-            mips_vpe_wake(other_cpu_env); /* And wake it up.  */
+            mips_vpe_wake(other_cpu); /* And wake it up.  */
         }
         other_cpu_env = other_cpu_env->next_cpu;
     } while (other_cpu_env);
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 79ce7bf..d176734 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -991,7 +991,7 @@ void helper_msgsnd(target_ulong rb)
     for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
         if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
             cenv->pending_interrupts |= 1 << irq;
-            cpu_interrupt(cenv, CPU_INTERRUPT_HARD);
+            cpu_interrupt(CPU(ppc_env_get_cpu(cenv)), CPU_INTERRUPT_HARD);
         }
     }
 }
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index e6997ef..46e2255 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -992,7 +992,7 @@ static inline void cpu_inject_ext(S390CPU *cpu, uint32_t code, uint32_t param,
     env->ext_queue[env->ext_index].param64 = param64;
 
     env->pending_int |= INTERRUPT_EXT;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 
 static inline void cpu_inject_io(S390CPU *cpu, uint16_t subchannel_id,
@@ -1016,7 +1016,7 @@ static inline void cpu_inject_io(S390CPU *cpu, uint16_t subchannel_id,
     env->io_queue[env->io_index[isc]][isc].word = io_int_word;
 
     env->pending_int |= INTERRUPT_IO;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 
 static inline void cpu_inject_crw_mchk(S390CPU *cpu)
@@ -1034,7 +1034,7 @@ static inline void cpu_inject_crw_mchk(S390CPU *cpu)
     env->mchk_queue[env->mchk_index].type = 1;
 
     env->pending_int |= INTERRUPT_MCHK;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 
 static inline bool cpu_has_work(CPUState *cpu)
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 3a54651..a65e6c7 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -57,7 +57,7 @@ void s390x_tod_timer(void *opaque)
     CPUS390XState *env = &cpu->env;
 
     env->pending_int |= INTERRUPT_TOD;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 
 void s390x_cpu_timer(void *opaque)
@@ -66,7 +66,7 @@ void s390x_cpu_timer(void *opaque)
     CPUS390XState *env = &cpu->env;
 
     env->pending_int |= INTERRUPT_CPUTIMER;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 #endif
 
diff --git a/translate-all.c b/translate-all.c
index 2176132..1dc646a 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1087,8 +1087,8 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
             tb_phys_invalidate(tb, -1);
             if (cpu != NULL) {
                 cpu->current_tb = saved_tb;
-                if (env && cpu->interrupt_request && cpu->current_tb) {
-                    cpu_interrupt(env, cpu->interrupt_request);
+                if (cpu->interrupt_request && cpu->current_tb) {
+                    cpu_interrupt(cpu, cpu->interrupt_request);
                 }
             }
         }
@@ -1460,9 +1460,9 @@ void tb_check_watchpoint(CPUArchState *env)
 
 #ifndef CONFIG_USER_ONLY
 /* mask must never be zero, except for A20 change call */
-static void tcg_handle_interrupt(CPUArchState *env, int mask)
+static void tcg_handle_interrupt(CPUState *cpu, int mask)
 {
-    CPUState *cpu = ENV_GET_CPU(env);
+    CPUArchState *env = cpu->env_ptr;
     int old_mask;
 
     old_mask = cpu->interrupt_request;
@@ -1622,10 +1622,8 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
 
 #else /* CONFIG_USER_ONLY */
 
-void cpu_interrupt(CPUArchState *env, int mask)
+void cpu_interrupt(CPUState *cpu, int mask)
 {
-    CPUState *cpu = ENV_GET_CPU(env);
-
     cpu->interrupt_request |= mask;
     cpu_unlink_tb(cpu);
 }
-- 
1.7.10.4

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

* [Qemu-devel] [RFC qom-cpu-next 8/9] cpu: Replace do_interrupt() by CPUClass::do_interrupt method
  2013-02-02 11:57 [Qemu-devel] [RFC qom-cpu-next 0/9] QOM CPUState, part 9: CPU_COMMON for interrupts Andreas Färber
                   ` (6 preceding siblings ...)
  2013-02-02 11:57   ` [Qemu-devel] " Andreas Färber
@ 2013-02-02 11:57 ` Andreas Färber
  2013-02-02 11:57 ` [Qemu-devel] [RFC qom-cpu-next 9/9] target-arm: Override do_interrupt for ARMv7-M profile Andreas Färber
  8 siblings, 0 replies; 12+ messages in thread
From: Andreas Färber @ 2013-02-02 11:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Alexander Graf, Blue Swirl, Max Filippov,
	Michael Walle, open list:PowerPC, Paul Brook, Edgar E. Iglesias,
	Guan Xuetao, Andreas Färber, Aurelien Jarno,
	Richard Henderson

This removes a global per-target function and thus takes us one step
closer to compiling multiple targets into one executable.

It will also allow to override the interrupt handling for certain CPU
families.

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 cpu-exec.c                  |   36 ++++++++++++++++++++----------------
 include/qom/cpu.h           |    2 ++
 target-alpha/cpu-qom.h      |    2 ++
 target-alpha/cpu.c          |    1 +
 target-alpha/cpu.h          |    1 -
 target-alpha/helper.c       |    4 +++-
 target-arm/cpu-qom.h        |    2 ++
 target-arm/cpu.c            |    1 +
 target-arm/cpu.h            |    1 -
 target-arm/helper.c         |   11 +++++++----
 target-cris/cpu-qom.h       |    2 ++
 target-cris/cpu.c           |    2 ++
 target-cris/cpu.h           |    1 -
 target-cris/helper.c        |   12 ++++++++----
 target-i386/cpu-qom.h       |    6 ++++++
 target-i386/cpu.c           |    2 ++
 target-i386/cpu.h           |    3 +--
 target-i386/seg_helper.c    |    5 ++++-
 target-lm32/cpu-qom.h       |    2 ++
 target-lm32/cpu.c           |    2 ++
 target-lm32/cpu.h           |    1 -
 target-lm32/helper.c        |    5 ++++-
 target-m68k/cpu-qom.h       |    2 ++
 target-m68k/cpu.c           |    1 +
 target-m68k/cpu.h           |    1 -
 target-m68k/op_helper.c     |   10 ++++++++--
 target-microblaze/cpu-qom.h |    2 ++
 target-microblaze/cpu.c     |    1 +
 target-microblaze/cpu.h     |    1 -
 target-microblaze/helper.c  |    9 +++++++--
 target-mips/cpu-qom.h       |    2 ++
 target-mips/cpu.c           |    2 ++
 target-mips/cpu.h           |    1 -
 target-mips/helper.c        |    5 +++--
 target-openrisc/cpu.c       |    1 +
 target-openrisc/cpu.h       |    2 +-
 target-openrisc/interrupt.c |    4 +++-
 target-ppc/cpu-qom.h        |    2 ++
 target-ppc/cpu.h            |    1 -
 target-ppc/excp_helper.c    |   10 +++++++---
 target-ppc/translate_init.c |    1 +
 target-s390x/cpu-qom.h      |    2 ++
 target-s390x/cpu.c          |    1 +
 target-s390x/cpu.h          |    1 -
 target-s390x/helper.c       |   12 +++++++-----
 target-sh4/cpu-qom.h        |    2 ++
 target-sh4/cpu.c            |    1 +
 target-sh4/cpu.h            |    1 -
 target-sh4/helper.c         |   12 ++++++++----
 target-sparc/cpu-qom.h      |    2 ++
 target-sparc/cpu.c          |    2 ++
 target-sparc/cpu.h          |    1 -
 target-sparc/int32_helper.c |    4 +++-
 target-sparc/int64_helper.c |    4 +++-
 target-unicore32/cpu-qom.h  |    2 ++
 target-unicore32/cpu.c      |    1 +
 target-unicore32/cpu.h      |    1 -
 target-unicore32/helper.c   |    5 ++++-
 target-unicore32/softmmu.c  |    5 +++--
 target-xtensa/cpu-qom.h     |    2 ++
 target-xtensa/cpu.c         |    1 +
 target-xtensa/cpu.h         |    1 -
 target-xtensa/helper.c      |    5 ++++-
 63 Dateien geändert, 162 Zeilen hinzugefügt(+), 68 Zeilen entfernt(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index 191a19b..c823f2a 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -185,6 +185,10 @@ volatile sig_atomic_t exit_request;
 int cpu_exec(CPUArchState *env)
 {
     CPUState *cpu = ENV_GET_CPU(env);
+#if !(defined(CONFIG_USER_ONLY) && \
+      (defined(TARGET_M68K) || defined(TARGET_PPC) || defined(TARGET_S390X)))
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+#endif
     int ret, interrupt_request;
     TranslationBlock *tb;
     uint8_t *tc_ptr;
@@ -252,12 +256,12 @@ int cpu_exec(CPUArchState *env)
                        which will be handled outside the cpu execution
                        loop */
 #if defined(TARGET_I386)
-                    do_interrupt(env);
+                    cc->do_interrupt(cpu);
 #endif
                     ret = env->exception_index;
                     break;
 #else
-                    do_interrupt(env);
+                    cc->do_interrupt(cpu);
                     env->exception_index = -1;
 #endif
                 }
@@ -367,7 +371,7 @@ int cpu_exec(CPUArchState *env)
                     if ((interrupt_request & CPU_INTERRUPT_HARD)
                         && (env->ie & IE_IE)) {
                         env->exception_index = EXCP_IRQ;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_MICROBLAZE)
@@ -376,7 +380,7 @@ int cpu_exec(CPUArchState *env)
                         && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
                         && !(env->iflags & (D_FLAG | IMM_FLAG))) {
                         env->exception_index = EXCP_IRQ;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_MIPS)
@@ -385,7 +389,7 @@ int cpu_exec(CPUArchState *env)
                         /* Raise it */
                         env->exception_index = EXCP_EXT_INTERRUPT;
                         env->error_code = 0;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_OPENRISC)
@@ -401,7 +405,7 @@ int cpu_exec(CPUArchState *env)
                         }
                         if (idx >= 0) {
                             env->exception_index = idx;
-                            do_interrupt(env);
+                            cc->do_interrupt(cpu);
                             next_tb = 0;
                         }
                     }
@@ -416,7 +420,7 @@ int cpu_exec(CPUArchState *env)
                                   cpu_pil_allowed(env, pil)) ||
                                   type != TT_EXTINT) {
                                 env->exception_index = env->interrupt_index;
-                                do_interrupt(env);
+                                cc->do_interrupt(cpu);
                                 next_tb = 0;
                             }
                         }
@@ -425,7 +429,7 @@ int cpu_exec(CPUArchState *env)
                     if (interrupt_request & CPU_INTERRUPT_FIQ
                         && !(env->uncached_cpsr & CPSR_F)) {
                         env->exception_index = EXCP_FIQ;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
                     /* ARMv7-M interrupt return works by loading a magic value
@@ -441,19 +445,19 @@ int cpu_exec(CPUArchState *env)
                         && ((IS_M(env) && env->regs[15] < 0xfffffff0)
                             || !(env->uncached_cpsr & CPSR_I))) {
                         env->exception_index = EXCP_IRQ;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_UNICORE32)
                     if (interrupt_request & CPU_INTERRUPT_HARD
                         && !(env->uncached_asr & ASR_I)) {
                         env->exception_index = UC32_EXCP_INTR;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_SH4)
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_ALPHA)
@@ -484,7 +488,7 @@ int cpu_exec(CPUArchState *env)
                         if (idx >= 0) {
                             env->exception_index = idx;
                             env->error_code = 0;
-                            do_interrupt(env);
+                            cc->do_interrupt(cpu);
                             next_tb = 0;
                         }
                     }
@@ -493,7 +497,7 @@ int cpu_exec(CPUArchState *env)
                         && (env->pregs[PR_CCS] & I_FLAG)
                         && !env->locked_irq) {
                         env->exception_index = EXCP_IRQ;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
                     if (interrupt_request & CPU_INTERRUPT_NMI) {
@@ -505,7 +509,7 @@ int cpu_exec(CPUArchState *env)
                         }
                         if ((env->pregs[PR_CCS] & m_flag_archval)) {
                             env->exception_index = EXCP_NMI;
-                            do_interrupt(env);
+                            cc->do_interrupt(cpu);
                             next_tb = 0;
                         }
                     }
@@ -525,13 +529,13 @@ int cpu_exec(CPUArchState *env)
 #elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                         (env->psw.mask & PSW_MASK_EXT)) {
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_XTENSA)
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
                         env->exception_index = EXC_IRQ;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #endif
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 1f8f2cf..10a2ad9 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -44,6 +44,7 @@ typedef struct CPUState CPUState;
  * @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.
+ * @do_interrupt: Callback for interrupt handling.
  *
  * Represents a CPU family or model.
  */
@@ -55,6 +56,7 @@ typedef struct CPUClass {
     ObjectClass *(*class_by_name)(const char *cpu_model);
 
     void (*reset)(CPUState *cpu);
+    void (*do_interrupt)(CPUState *cpu);
 } CPUClass;
 
 struct KVMState;
diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h
index c0f6c6d..4198cdd 100644
--- a/target-alpha/cpu-qom.h
+++ b/target-alpha/cpu-qom.h
@@ -72,5 +72,7 @@ static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env)
 
 #define ENV_GET_CPU(e) CPU(alpha_env_get_cpu(e))
 
+void alpha_cpu_do_interrupt(CPUState *cpu);
+
 
 #endif
diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c
index cec9989..cad1716 100644
--- a/target-alpha/cpu.c
+++ b/target-alpha/cpu.c
@@ -263,6 +263,7 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
     dc->realize = alpha_cpu_realizefn;
 
     cc->class_by_name = alpha_cpu_class_by_name;
+    cc->do_interrupt = alpha_cpu_do_interrupt;
 }
 
 static const TypeInfo alpha_cpu_type_info = {
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 90f78ac..2156a1e 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -449,7 +449,6 @@ int cpu_alpha_signal_handler(int host_signum, void *pinfo,
 int cpu_alpha_handle_mmu_fault (CPUAlphaState *env, uint64_t address, int rw,
                                 int mmu_idx);
 #define cpu_handle_mmu_fault cpu_alpha_handle_mmu_fault
-void do_interrupt (CPUAlphaState *env);
 void do_restore_state(CPUAlphaState *, uintptr_t retaddr);
 void QEMU_NORETURN dynamic_excp(CPUAlphaState *, uintptr_t, int, int);
 void QEMU_NORETURN arith_excp(CPUAlphaState *, uintptr_t, int, uint64_t);
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 22c9c6e..5741ec2 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -345,8 +345,10 @@ int cpu_alpha_handle_mmu_fault(CPUAlphaState *env, target_ulong addr, int rw,
 }
 #endif /* USER_ONLY */
 
-void do_interrupt (CPUAlphaState *env)
+void alpha_cpu_do_interrupt(CPUState *cs)
 {
+    AlphaCPU *cpu = ALPHA_CPU(cs);
+    CPUAlphaState *env = &cpu->env;
     int i = env->exception_index;
 
     if (qemu_loglevel_mask(CPU_LOG_INT)) {
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index aff7bf3..a2cd047 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -111,4 +111,6 @@ static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
 
 void register_cp_regs_for_features(ARMCPU *cpu);
 
+void arm_cpu_do_interrupt(CPUState *cpu);
+
 #endif
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 5dfcb74..aeaa3b7 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -802,6 +802,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
     cc->reset = arm_cpu_reset;
 
     cc->class_by_name = arm_cpu_class_by_name;
+    cc->do_interrupt = arm_cpu_do_interrupt;
 }
 
 static void cpu_register(const ARMCPUInfo *info)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 7c47467..971a2d8 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -236,7 +236,6 @@ ARMCPU *cpu_arm_init(const char *cpu_model);
 void arm_translate_init(void);
 void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu);
 int cpu_arm_exec(CPUARMState *s);
-void do_interrupt(CPUARMState *);
 void switch_mode(CPUARMState *, int);
 uint32_t do_arm_semihosting(CPUARMState *env);
 
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 543d091..7b3e943 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1567,8 +1567,11 @@ uint32_t HELPER(rbit)(uint32_t x)
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt (CPUARMState *env)
+void arm_cpu_do_interrupt(CPUState *cs)
 {
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+
     env->exception_index = -1;
 }
 
@@ -1800,9 +1803,10 @@ static void do_interrupt_v7m(CPUARMState *env)
 }
 
 /* Handle a CPU exception.  */
-void do_interrupt(CPUARMState *env)
+void arm_cpu_do_interrupt(CPUState *cs)
 {
-    CPUState *cs;
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
     uint32_t addr;
     uint32_t mask;
     int new_mode;
@@ -1909,7 +1913,6 @@ void do_interrupt(CPUARMState *env)
     }
     env->regs[14] = env->regs[15] + offset;
     env->regs[15] = addr;
-    cs = CPU(arm_env_get_cpu(env));
     cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
 
diff --git a/target-cris/cpu-qom.h b/target-cris/cpu-qom.h
index 7ad8398..528ba4b 100644
--- a/target-cris/cpu-qom.h
+++ b/target-cris/cpu-qom.h
@@ -68,5 +68,7 @@ static inline CRISCPU *cris_env_get_cpu(CPUCRISState *env)
 
 #define ENV_GET_CPU(e) CPU(cris_env_get_cpu(e))
 
+void cris_cpu_do_interrupt(CPUState *cpu);
+
 
 #endif
diff --git a/target-cris/cpu.c b/target-cris/cpu.c
index 0bcc139..e4aa050 100644
--- a/target-cris/cpu.c
+++ b/target-cris/cpu.c
@@ -97,6 +97,8 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
 
     ccc->parent_reset = cc->reset;
     cc->reset = cris_cpu_reset;
+
+    cc->do_interrupt = cris_cpu_do_interrupt;
 }
 
 static const TypeInfo cris_cpu_type_info = {
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index 2fc7c5c..dbd7d36 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -175,7 +175,6 @@ typedef struct CPUCRISState {
 
 CRISCPU *cpu_cris_init(const char *cpu_model);
 int cpu_cris_exec(CPUCRISState *s);
-void do_interrupt(CPUCRISState *env);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
    is returned if the signal was handled by the virtual CPU.  */
diff --git a/target-cris/helper.c b/target-cris/helper.c
index 51c9a9f..bee774c 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -36,8 +36,11 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt(CPUCRISState *env)
+void cris_cpu_do_interrupt(CPUState *cs)
 {
+    CRISCPU *cpu = CRIS_CPU(cs);
+    CPUCRISState *env = &cpu->env;
+
     env->exception_index = -1;
     env->pregs[PR_ERP] = env->pc;
 }
@@ -162,9 +165,10 @@ static void do_interruptv10(CPUCRISState *env)
                   env->pregs[PR_ERP]);
 }
 
-void do_interrupt(CPUCRISState *env)
+void cris_cpu_do_interrupt(CPUState *cs)
 {
-    D(CPUState *cpu = CPU(cris_env_get_cpu(env)));
+    CRISCPU *cpu = CRIS_CPU(cs);
+    CPUCRISState *env = &cpu->env;
     int ex_vec = -1;
 
     if (env->pregs[PR_VR] < 32) {
@@ -173,7 +177,7 @@ void do_interrupt(CPUCRISState *env)
 
     D_LOG("exception index=%d interrupt_req=%d\n",
           env->exception_index,
-          cpu->interrupt_request);
+          cs->interrupt_request);
 
     switch (env->exception_index) {
     case EXCP_BREAK:
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 48e6b54..f7383b9 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -74,5 +74,11 @@ static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
 
 #define ENV_GET_CPU(e) CPU(x86_env_get_cpu(e))
 
+/**
+ * x86_cpu_do_interrupt:
+ * @cpu: vCPU the interrupt is to be handled by.
+ */
+void x86_cpu_do_interrupt(CPUState *cpu);
+
 
 #endif
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index b892da0..edf6c70 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2215,6 +2215,8 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
 
     xcc->parent_reset = cc->reset;
     cc->reset = x86_cpu_reset;
+
+    cc->do_interrupt = x86_cpu_do_interrupt;
 }
 
 static const TypeInfo x86_cpu_type_info = {
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 40cf246..a1eac0a 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -1243,8 +1243,7 @@ void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type,
                                    uint64_t param);
 void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1);
 
-/* op_helper.c */
-void do_interrupt(CPUX86State *env);
+/* seg_helper.c */
 void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw);
 
 void do_smm_enter(CPUX86State *env1);
diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c
index 3247dee..906e4f3 100644
--- a/target-i386/seg_helper.c
+++ b/target-i386/seg_helper.c
@@ -1231,8 +1231,11 @@ static void do_interrupt_all(CPUX86State *env, int intno, int is_int,
 #endif
 }
 
-void do_interrupt(CPUX86State *env)
+void x86_cpu_do_interrupt(CPUState *cs)
 {
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
+
 #if defined(CONFIG_USER_ONLY)
     /* if user mode only, we simulate a fake exception
        which will be handled outside the cpu execution
diff --git a/target-lm32/cpu-qom.h b/target-lm32/cpu-qom.h
index d7525b3..f938ba4 100644
--- a/target-lm32/cpu-qom.h
+++ b/target-lm32/cpu-qom.h
@@ -69,5 +69,7 @@ static inline LM32CPU *lm32_env_get_cpu(CPULM32State *env)
 
 #define ENV_GET_CPU(e) CPU(lm32_env_get_cpu(e))
 
+void lm32_cpu_do_interrupt(CPUState *cpu);
+
 
 #endif
diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
index a2badb5..a4692b7 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -83,6 +83,8 @@ static void lm32_cpu_class_init(ObjectClass *oc, void *data)
 
     lcc->parent_reset = cc->reset;
     cc->reset = lm32_cpu_reset;
+
+    cc->do_interrupt = lm32_cpu_do_interrupt;
 }
 
 static const TypeInfo lm32_cpu_type_info = {
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index d81f103..1be9778 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -189,7 +189,6 @@ struct CPULM32State {
 LM32CPU *cpu_lm32_init(const char *cpu_model);
 void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf);
 int cpu_lm32_exec(CPULM32State *s);
-void do_interrupt(CPULM32State *env);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
    is returned if the signal was handled by the virtual CPU.  */
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index 47ae7e7..a0a8399 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -42,8 +42,11 @@ hwaddr cpu_get_phys_page_debug(CPULM32State *env, target_ulong addr)
     return addr & TARGET_PAGE_MASK;
 }
 
-void do_interrupt(CPULM32State *env)
+void lm32_cpu_do_interrupt(CPUState *cs)
 {
+    LM32CPU *cpu = LM32_CPU(cs);
+    CPULM32State *env = &cpu->env;
+
     qemu_log_mask(CPU_LOG_INT,
             "exception at pc=%x type=%x\n", env->pc, env->exception_index);
 
diff --git a/target-m68k/cpu-qom.h b/target-m68k/cpu-qom.h
index 20e5684..d31b19b 100644
--- a/target-m68k/cpu-qom.h
+++ b/target-m68k/cpu-qom.h
@@ -68,5 +68,7 @@ static inline M68kCPU *m68k_env_get_cpu(CPUM68KState *env)
 
 #define ENV_GET_CPU(e) CPU(m68k_env_get_cpu(e))
 
+void m68k_cpu_do_interrupt(CPUState *cpu);
+
 
 #endif
diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index f5a1098..3c65b4e 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -186,6 +186,7 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
     cc->reset = m68k_cpu_reset;
 
     cc->class_by_name = m68k_cpu_class_by_name;
+    cc->do_interrupt = m68k_cpu_do_interrupt;
     dc->vmsd = &vmstate_m68k_cpu;
 }
 
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index bb2fbd6..c90c40c 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -119,7 +119,6 @@ void m68k_tcg_init(void);
 void m68k_cpu_init_gdb(M68kCPU *cpu);
 M68kCPU *cpu_m68k_init(const char *cpu_model);
 int cpu_m68k_exec(CPUM68KState *s);
-void do_interrupt(CPUM68KState *env1);
 void do_interrupt_m68k_hardirq(CPUM68KState *env1);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index e11f34b..30f7d8b 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -21,8 +21,11 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt(CPUM68KState *env)
+void m68k_cpu_do_interrupt(CPUState *cs)
 {
+    M68kCPU *cpu = M68K_CPU(cs);
+    CPUM68KState *env = &cpu->env;
+
     env->exception_index = -1;
 }
 
@@ -149,8 +152,11 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
     env->pc = cpu_ldl_kernel(env, env->vbr + vector);
 }
 
-void do_interrupt(CPUM68KState *env)
+void m68k_cpu_do_interrupt(CPUState *cs)
 {
+    M68kCPU *cpu = M68K_CPU(cs);
+    CPUM68KState *env = &cpu->env;
+
     do_interrupt_all(env, 0);
 }
 
diff --git a/target-microblaze/cpu-qom.h b/target-microblaze/cpu-qom.h
index 5ea911c..2f73970 100644
--- a/target-microblaze/cpu-qom.h
+++ b/target-microblaze/cpu-qom.h
@@ -68,5 +68,7 @@ static inline MicroBlazeCPU *mb_env_get_cpu(CPUMBState *env)
 
 #define ENV_GET_CPU(e) CPU(mb_env_get_cpu(e))
 
+void mb_cpu_do_interrupt(CPUState *cs);
+
 
 #endif
diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
index 81359db..0f4293d 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -131,6 +131,7 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
     mcc->parent_reset = cc->reset;
     cc->reset = mb_cpu_reset;
 
+    cc->do_interrupt = mb_cpu_do_interrupt;
     dc->vmsd = &vmstate_mb_cpu;
 }
 
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 7548aa9..1813939 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -275,7 +275,6 @@ struct CPUMBState {
 void mb_tcg_init(void);
 MicroBlazeCPU *cpu_mb_init(const char *cpu_model);
 int cpu_mb_exec(CPUMBState *s);
-void do_interrupt(CPUMBState *env);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
    is returned if the signal was handled by the virtual CPU.  */
diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c
index 97aedc5..a0416d0 100644
--- a/target-microblaze/helper.c
+++ b/target-microblaze/helper.c
@@ -26,8 +26,11 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt (CPUMBState *env)
+void mb_cpu_do_interrupt(CPUState *cs)
 {
+    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
+    CPUMBState *env = &cpu->env;
+
     env->exception_index = -1;
     env->res_addr = RES_ADDR_NONE;
     env->regs[14] = env->sregs[SR_PC];
@@ -109,8 +112,10 @@ int cpu_mb_handle_mmu_fault (CPUMBState *env, target_ulong address, int rw,
     return r;
 }
 
-void do_interrupt(CPUMBState *env)
+void mb_cpu_do_interrupt(CPUState *cs)
 {
+    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
+    CPUMBState *env = &cpu->env;
     uint32_t t;
 
     /* IMM flag cannot propagate across a branch and into the dslot.  */
diff --git a/target-mips/cpu-qom.h b/target-mips/cpu-qom.h
index 55aa692..249fb4b 100644
--- a/target-mips/cpu-qom.h
+++ b/target-mips/cpu-qom.h
@@ -72,5 +72,7 @@ static inline MIPSCPU *mips_env_get_cpu(CPUMIPSState *env)
 
 #define ENV_GET_CPU(e) CPU(mips_env_get_cpu(e))
 
+void mips_cpu_do_interrupt(CPUState *cpu);
+
 
 #endif
diff --git a/target-mips/cpu.c b/target-mips/cpu.c
index 4d62031..5315f7b 100644
--- a/target-mips/cpu.c
+++ b/target-mips/cpu.c
@@ -78,6 +78,8 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
 
     mcc->parent_reset = cc->reset;
     cc->reset = mips_cpu_reset;
+
+    cc->do_interrupt = mips_cpu_do_interrupt;
 }
 
 static const TypeInfo mips_cpu_type_info = {
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 7434099..c6d055d 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -660,7 +660,6 @@ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level);
 int cpu_mips_handle_mmu_fault (CPUMIPSState *env, target_ulong address, int rw,
                                int mmu_idx);
 #define cpu_handle_mmu_fault cpu_mips_handle_mmu_fault
-void do_interrupt (CPUMIPSState *env);
 #if !defined(CONFIG_USER_ONLY)
 void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra);
 hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address,
diff --git a/target-mips/helper.c b/target-mips/helper.c
index e877b8d..3a54acf 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -396,10 +396,11 @@ static void set_hflags_for_handler (CPUMIPSState *env)
 }
 #endif
 
-void do_interrupt (CPUMIPSState *env)
+void mips_cpu_do_interrupt(CPUState *cs)
 {
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
 #if !defined(CONFIG_USER_ONLY)
-    MIPSCPU *cpu = mips_env_get_cpu(env);
     target_ulong offset;
     int cause = -1;
     const char *name;
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
index 72d5e8d..ffe14f3 100644
--- a/target-openrisc/cpu.c
+++ b/target-openrisc/cpu.c
@@ -148,6 +148,7 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
     cc->reset = openrisc_cpu_reset;
 
     cc->class_by_name = openrisc_cpu_class_by_name;
+    cc->do_interrupt = openrisc_cpu_do_interrupt;
 }
 
 static void cpu_register(const OpenRISCCPUInfo *info)
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 687c24f..0e33240 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -344,7 +344,7 @@ OpenRISCCPU *cpu_openrisc_init(const char *cpu_model);
 
 void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
 int cpu_openrisc_exec(CPUOpenRISCState *s);
-void do_interrupt(CPUOpenRISCState *env);
+void openrisc_cpu_do_interrupt(CPUState *cpu);
 void openrisc_translate_init(void);
 int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env,
                                   target_ulong address,
diff --git a/target-openrisc/interrupt.c b/target-openrisc/interrupt.c
index 7f2c025..16ef4b3 100644
--- a/target-openrisc/interrupt.c
+++ b/target-openrisc/interrupt.c
@@ -25,8 +25,10 @@
 #include "hw/loader.h"
 #endif
 
-void do_interrupt(CPUOpenRISCState *env)
+void openrisc_cpu_do_interrupt(CPUState *cs)
 {
+    OpenRISCCPU *cpu = OPENRISC_CPU(cs);
+    CPUOpenRISCState *env = &cpu->env;
 #ifndef CONFIG_USER_ONLY
     if (env->flags & D_FLAG) { /* Delay Slot insn */
         env->flags &= ~D_FLAG;
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index 2b82cdb..6f13454 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -80,5 +80,7 @@ static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)
 
 PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr);
 
+void ppc_cpu_do_interrupt(CPUState *cpu);
+
 
 #endif
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 75190f3..2753dc6 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1144,7 +1144,6 @@ int cpu_ppc_signal_handler (int host_signum, void *pinfo,
 int cpu_ppc_handle_mmu_fault (CPUPPCState *env, target_ulong address, int rw,
                               int mmu_idx);
 #define cpu_handle_mmu_fault cpu_ppc_handle_mmu_fault
-void do_interrupt (CPUPPCState *env);
 void ppc_hw_interrupt (CPUPPCState *env);
 
 #if !defined(CONFIG_USER_ONLY)
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index d176734..4a0fc6d 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -38,8 +38,11 @@ void (*cpu_ppc_hypercall)(PowerPCCPU *);
 /*****************************************************************************/
 /* Exception processing */
 #if defined(CONFIG_USER_ONLY)
-void do_interrupt(CPUPPCState *env)
+void ppc_cpu_do_interrupt(CPUState *cs)
 {
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
+
     env->exception_index = POWERPC_EXCP_NONE;
     env->error_code = 0;
 }
@@ -654,9 +657,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
     }
 }
 
-void do_interrupt(CPUPPCState *env)
+void ppc_cpu_do_interrupt(CPUState *cs)
 {
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
 
     powerpc_excp(cpu, env->excp_model, env->exception_index);
 }
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 4af9123..91a0534 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -10587,6 +10587,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
     cc->reset = ppc_cpu_reset;
 
     cc->class_by_name = ppc_cpu_class_by_name;
+    cc->do_interrupt = ppc_cpu_do_interrupt;
 }
 
 static const TypeInfo ppc_cpu_type_info = {
diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h
index 237184f..f541a78 100644
--- a/target-s390x/cpu-qom.h
+++ b/target-s390x/cpu-qom.h
@@ -69,5 +69,7 @@ static inline S390CPU *s390_env_get_cpu(CPUS390XState *env)
 
 #define ENV_GET_CPU(e) CPU(s390_env_get_cpu(e))
 
+void s390_cpu_do_interrupt(CPUState *cpu);
+
 
 #endif
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index 738a0ad..23fe51f 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -169,6 +169,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
     scc->parent_reset = cc->reset;
     cc->reset = s390_cpu_reset;
 
+    cc->do_interrupt = s390_cpu_do_interrupt;
     dc->vmsd = &vmstate_s390_cpu;
 }
 
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 46e2255..eb8d70b 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -315,7 +315,6 @@ static inline int get_ilen(uint8_t opc)
 S390CPU *cpu_s390x_init(const char *cpu_model);
 void s390x_translate_init(void);
 int cpu_s390x_exec(CPUS390XState *s);
-void do_interrupt (CPUS390XState *env);
 
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index a65e6c7..b1b2cf8 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -86,8 +86,11 @@ S390CPU *cpu_s390x_init(const char *cpu_model)
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt(CPUS390XState *env)
+void s390_cpu_do_interrupt(CPUState *cs)
 {
+    S390CPU *cpu = S390_CPU(cs);
+    CPUS390XState *env = &cpu->env;
+
     env->exception_index = -1;
 }
 
@@ -732,10 +735,10 @@ static void do_mchk_interrupt(CPUS390XState *env)
     load_psw(env, mask, addr);
 }
 
-void do_interrupt(CPUS390XState *env)
+void s390_cpu_do_interrupt(CPUState *cs)
 {
-    S390CPU *cpu = s390_env_get_cpu(env);
-    CPUState *cs;
+    S390CPU *cpu = S390_CPU(cs);
+    CPUS390XState *env = &cpu->env;
 
     qemu_log_mask(CPU_LOG_INT, "%s: %d at pc=%" PRIx64 "\n",
                   __func__, env->exception_index, env->psw.addr);
@@ -794,7 +797,6 @@ void do_interrupt(CPUS390XState *env)
     env->exception_index = -1;
 
     if (!env->pending_int) {
-        cs = CPU(s390_env_get_cpu(env));
         cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
     }
 }
diff --git a/target-sh4/cpu-qom.h b/target-sh4/cpu-qom.h
index d368db1..fbbae9b 100644
--- a/target-sh4/cpu-qom.h
+++ b/target-sh4/cpu-qom.h
@@ -68,5 +68,7 @@ static inline SuperHCPU *sh_env_get_cpu(CPUSH4State *env)
 
 #define ENV_GET_CPU(e) CPU(sh_env_get_cpu(e))
 
+void superh_cpu_do_interrupt(CPUState *cpu);
+
 
 #endif
diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c
index ef0e621..f9cb92e 100644
--- a/target-sh4/cpu.c
+++ b/target-sh4/cpu.c
@@ -98,6 +98,7 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
     scc->parent_reset = cc->reset;
     cc->reset = superh_cpu_reset;
 
+    cc->do_interrupt = superh_cpu_do_interrupt;
     dc->vmsd = &vmstate_sh_cpu;
 }
 
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 926ec41..c971fa9 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -199,7 +199,6 @@ int cpu_sh4_signal_handler(int host_signum, void *pinfo,
 int cpu_sh4_handle_mmu_fault(CPUSH4State * env, target_ulong address, int rw,
                              int mmu_idx);
 #define cpu_handle_mmu_fault cpu_sh4_handle_mmu_fault
-void do_interrupt(CPUSH4State * env);
 
 void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 #if !defined(CONFIG_USER_ONLY)
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index fd4efee..0a9cb3a 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -31,9 +31,12 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt (CPUSH4State *env)
+void superh_cpu_do_interrupt(CPUState *cs)
 {
-  env->exception_index = -1;
+    SuperHCPU *cpu = SUPERH_CPU(cs);
+    CPUSH4State *env = &cpu->env;
+
+    env->exception_index = -1;
 }
 
 int cpu_sh4_handle_mmu_fault(CPUSH4State * env, target_ulong address, int rw,
@@ -78,9 +81,10 @@ int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
 #define MMU_DADDR_ERROR_READ     (-12)
 #define MMU_DADDR_ERROR_WRITE    (-13)
 
-void do_interrupt(CPUSH4State *env)
+void superh_cpu_do_interrupt(CPUState *cs)
 {
-    CPUState *cs = CPU(sh_env_get_cpu(env));
+    SuperHCPU *cpu = SUPERH_CPU(cs);
+    CPUSH4State *env = &cpu->env;
     int do_irq = cs->interrupt_request & CPU_INTERRUPT_HARD;
     int do_exp, irq_vector = env->exception_index;
 
diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
index 89cd1cf..8323731 100644
--- a/target-sparc/cpu-qom.h
+++ b/target-sparc/cpu-qom.h
@@ -73,5 +73,7 @@ static inline SPARCCPU *sparc_env_get_cpu(CPUSPARCState *env)
 
 #define ENV_GET_CPU(e) CPU(sparc_env_get_cpu(e))
 
+void sparc_cpu_do_interrupt(CPUState *cpu);
+
 
 #endif
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index ef52df6..339d54a 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -891,6 +891,8 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
 
     scc->parent_reset = cc->reset;
     cc->reset = sparc_cpu_reset;
+
+    cc->do_interrupt = sparc_cpu_do_interrupt;
 }
 
 static const TypeInfo sparc_cpu_type_info = {
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 95cbba0..0b41837 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -552,7 +552,6 @@ int cpu_cwp_dec(CPUSPARCState *env1, int cwp);
 void cpu_set_cwp(CPUSPARCState *env1, int new_cwp);
 
 /* int_helper.c */
-void do_interrupt(CPUSPARCState *env);
 void leon3_irq_manager(CPUSPARCState *env, void *irq_manager, int intno);
 
 /* sun4m.c, sun4u.c */
diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c
index c35f522..7221460 100644
--- a/target-sparc/int32_helper.c
+++ b/target-sparc/int32_helper.c
@@ -58,8 +58,10 @@ static const char * const excp_names[0x80] = {
 };
 #endif
 
-void do_interrupt(CPUSPARCState *env)
+void sparc_cpu_do_interrupt(CPUState *cs)
 {
+    SPARCCPU *cpu = SPARC_CPU(cs);
+    CPUSPARCState *env = &cpu->env;
     int cwp, intno = env->exception_index;
 
     /* Compute PSR before exposing state.  */
diff --git a/target-sparc/int64_helper.c b/target-sparc/int64_helper.c
index df37aa1..f411884 100644
--- a/target-sparc/int64_helper.c
+++ b/target-sparc/int64_helper.c
@@ -59,8 +59,10 @@ static const char * const excp_names[0x80] = {
 };
 #endif
 
-void do_interrupt(CPUSPARCState *env)
+void sparc_cpu_do_interrupt(CPUState *cs)
 {
+    SPARCCPU *cpu = SPARC_CPU(cs);
+    CPUSPARCState *env = &cpu->env;
     int intno = env->exception_index;
     trap_state *tsptr;
 
diff --git a/target-unicore32/cpu-qom.h b/target-unicore32/cpu-qom.h
index 625c614..5dae295 100644
--- a/target-unicore32/cpu-qom.h
+++ b/target-unicore32/cpu-qom.h
@@ -58,5 +58,7 @@ static inline UniCore32CPU *uc32_env_get_cpu(CPUUniCore32State *env)
 
 #define ENV_GET_CPU(e) CPU(uc32_env_get_cpu(e))
 
+void uc32_cpu_do_interrupt(CPUState *cpu);
+
 
 #endif
diff --git a/target-unicore32/cpu.c b/target-unicore32/cpu.c
index b7024c8..66a1a74 100644
--- a/target-unicore32/cpu.c
+++ b/target-unicore32/cpu.c
@@ -132,6 +132,7 @@ static void uc32_cpu_class_init(ObjectClass *oc, void *data)
     dc->realize = uc32_cpu_realizefn;
 
     cc->class_by_name = uc32_cpu_class_by_name;
+    cc->do_interrupt = uc32_cpu_do_interrupt;
     dc->vmsd = &vmstate_uc32_cpu;
 }
 
diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
index 58f1f20..5b2b9d1 100644
--- a/target-unicore32/cpu.h
+++ b/target-unicore32/cpu.h
@@ -176,7 +176,6 @@ static inline void cpu_get_tb_cpu_state(CPUUniCore32State *env, target_ulong *pc
 }
 
 void uc32_translate_init(void);
-void do_interrupt(CPUUniCore32State *);
 void switch_mode(CPUUniCore32State *, int);
 
 static inline bool cpu_has_work(CPUState *cpu)
diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c
index 7eeb9bc..61eb2c3 100644
--- a/target-unicore32/helper.c
+++ b/target-unicore32/helper.c
@@ -242,8 +242,11 @@ void switch_mode(CPUUniCore32State *env, int mode)
     }
 }
 
-void do_interrupt(CPUUniCore32State *env)
+void uc32_cpu_do_interrupt(CPUState *cs)
 {
+    UniCore32CPU *cpu = UNICORE32_CPU(cs);
+    CPUUniCore32State *env = &cpu->env;
+
     cpu_abort(env, "NO interrupt in user mode\n");
 }
 
diff --git a/target-unicore32/softmmu.c b/target-unicore32/softmmu.c
index 1c4c7f5..eadaeb1 100644
--- a/target-unicore32/softmmu.c
+++ b/target-unicore32/softmmu.c
@@ -72,9 +72,10 @@ void switch_mode(CPUUniCore32State *env, int mode)
 }
 
 /* Handle a CPU exception.  */
-void do_interrupt(CPUUniCore32State *env)
+void uc32_cpu_do_interrupt(CPUState *cs)
 {
-    CPUState *cs = CPU(uc32_env_get_cpu(env));
+    UniCore32CPU *cpu = UNICORE32_CPU(cs);
+    CPUUniCore32State *env = &cpu->env;
     uint32_t addr;
     int new_mode;
 
diff --git a/target-xtensa/cpu-qom.h b/target-xtensa/cpu-qom.h
index 270de16..93ec0ba 100644
--- a/target-xtensa/cpu-qom.h
+++ b/target-xtensa/cpu-qom.h
@@ -78,5 +78,7 @@ static inline XtensaCPU *xtensa_env_get_cpu(const CPUXtensaState *env)
 
 #define ENV_GET_CPU(e) CPU(xtensa_env_get_cpu(e))
 
+void xtensa_cpu_do_interrupt(CPUState *cpu);
+
 
 #endif
diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
index 785e56d..6e93dd8 100644
--- a/target-xtensa/cpu.c
+++ b/target-xtensa/cpu.c
@@ -101,6 +101,7 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
     xcc->parent_reset = cc->reset;
     cc->reset = xtensa_cpu_reset;
 
+    cc->do_interrupt = xtensa_cpu_do_interrupt;
     dc->vmsd = &vmstate_xtensa_cpu;
 }
 
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index dece224..6c9fc35 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -388,7 +388,6 @@ void xtensa_translate_init(void);
 void xtensa_breakpoint_handler(CPUXtensaState *env);
 int cpu_xtensa_exec(CPUXtensaState *s);
 void xtensa_register_core(XtensaConfigList *node);
-void do_interrupt(CPUXtensaState *s);
 void check_interrupts(CPUXtensaState *s);
 void xtensa_irq_init(CPUXtensaState *env);
 void *xtensa_get_extint(CPUXtensaState *env, unsigned extint);
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index a8a6493..6f613c66 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -178,8 +178,11 @@ static void handle_interrupt(CPUXtensaState *env)
     }
 }
 
-void do_interrupt(CPUXtensaState *env)
+void xtensa_cpu_do_interrupt(CPUState *cs)
 {
+    XtensaCPU *cpu = XTENSA_CPU(cs);
+    CPUXtensaState *env = &cpu->env;
+
     if (env->exception_index == EXC_IRQ) {
         qemu_log_mask(CPU_LOG_INT,
                 "%s(EXC_IRQ) level = %d, cintlevel = %d, "
-- 
1.7.10.4

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

* [Qemu-devel] [RFC qom-cpu-next 9/9] target-arm: Override do_interrupt for ARMv7-M profile
  2013-02-02 11:57 [Qemu-devel] [RFC qom-cpu-next 0/9] QOM CPUState, part 9: CPU_COMMON for interrupts Andreas Färber
                   ` (7 preceding siblings ...)
  2013-02-02 11:57 ` [Qemu-devel] [RFC qom-cpu-next 8/9] cpu: Replace do_interrupt() by CPUClass::do_interrupt method Andreas Färber
@ 2013-02-02 11:57 ` Andreas Färber
  8 siblings, 0 replies; 12+ messages in thread
From: Andreas Färber @ 2013-02-02 11:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Andreas Färber, Paul Brook

Enable ARMCPUInfo to specify a custom class_init functions.
Introduce arm_v7m_class_init() and use it for "cortex-m3" model.

Instead of forwarding from arm_cpu_do_interrupt() to do_interrupt_v7m(),
override CPUClass::do_interrupt with arm_v7m_cpu_do_interrupt()
in arm_v7m_class_init().

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 target-arm/cpu-qom.h |    1 +
 target-arm/cpu.c     |   14 +++++++++++++-
 target-arm/helper.c  |   10 +++++-----
 3 Dateien geändert, 19 Zeilen hinzugefügt(+), 6 Zeilen entfernt(-)

diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index a2cd047..dbdd5d9 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -112,5 +112,6 @@ static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
 void register_cp_regs_for_features(ARMCPU *cpu);
 
 void arm_cpu_do_interrupt(CPUState *cpu);
+void arm_v7m_cpu_do_interrupt(CPUState *cpu);
 
 #endif
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index aeaa3b7..a1e9093 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -412,6 +412,15 @@ static void cortex_m3_initfn(Object *obj)
     cpu->midr = 0x410fc231;
 }
 
+static void arm_v7m_class_init(ObjectClass *oc, void *data)
+{
+#ifndef CONFIG_USER_ONLY
+    CPUClass *cc = CPU_CLASS(oc);
+
+    cc->do_interrupt = arm_v7m_cpu_do_interrupt;
+#endif
+}
+
 static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
     { .name = "L2LOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 0,
       .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
@@ -752,6 +761,7 @@ static void arm_any_initfn(Object *obj)
 typedef struct ARMCPUInfo {
     const char *name;
     void (*initfn)(Object *obj);
+    void (*class_init)(ObjectClass *oc, void *data);
 } ARMCPUInfo;
 
 static const ARMCPUInfo arm_cpus[] = {
@@ -766,7 +776,8 @@ static const ARMCPUInfo arm_cpus[] = {
     { .name = "arm1136",     .initfn = arm1136_initfn },
     { .name = "arm1176",     .initfn = arm1176_initfn },
     { .name = "arm11mpcore", .initfn = arm11mpcore_initfn },
-    { .name = "cortex-m3",   .initfn = cortex_m3_initfn },
+    { .name = "cortex-m3",   .initfn = cortex_m3_initfn,
+                             .class_init = arm_v7m_class_init },
     { .name = "cortex-a8",   .initfn = cortex_a8_initfn },
     { .name = "cortex-a9",   .initfn = cortex_a9_initfn },
     { .name = "cortex-a15",  .initfn = cortex_a15_initfn },
@@ -812,6 +823,7 @@ static void cpu_register(const ARMCPUInfo *info)
         .instance_size = sizeof(ARMCPU),
         .instance_init = info->initfn,
         .class_size = sizeof(ARMCPUClass),
+        .class_init = info->class_init,
     };
 
     type_info.name = g_strdup_printf("%s-" TYPE_ARM_CPU, info->name);
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 7b3e943..dd0b861 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1726,8 +1726,10 @@ static void do_v7m_exception_exit(CPUARMState *env)
        pointer.  */
 }
 
-static void do_interrupt_v7m(CPUARMState *env)
+void arm_v7m_cpu_do_interrupt(CPUState *cs)
 {
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
     uint32_t xpsr = xpsr_read(env);
     uint32_t lr;
     uint32_t addr;
@@ -1812,10 +1814,8 @@ void arm_cpu_do_interrupt(CPUState *cs)
     int new_mode;
     uint32_t offset;
 
-    if (IS_M(env)) {
-        do_interrupt_v7m(env);
-        return;
-    }
+    assert(!IS_M(env));
+
     /* TODO: Vectored interrupt controller.  */
     switch (env->exception_index) {
     case EXCP_UDEF:
-- 
1.7.10.4

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

end of thread, other threads:[~2013-02-02 11:58 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-02 11:57 [Qemu-devel] [RFC qom-cpu-next 0/9] QOM CPUState, part 9: CPU_COMMON for interrupts Andreas Färber
2013-02-02 11:57 ` [Qemu-devel] [PATCH for-1.4? qom-cpu-next 1/9] target-s390x: Drop unused cpu_s390x_close() prototype Andreas Färber
2013-02-02 11:57 ` [Qemu-devel] [PATCH for-1.4? qom-cpu-next 2/9] target-lm32: Drop unused cpu_lm32_close() prototype Andreas Färber
2013-02-02 11:57 ` [Qemu-devel] [PATCH RESEND qom-cpu-next 3/9] target-cris/helper.c: Update Coding Style Andreas Färber
2013-02-02 11:57 ` [Qemu-devel] [RFC qom-cpu-next 4/9] target-i386: Drop version 5 CPU VMState support Andreas Färber
2013-02-02 11:57 ` [RFC qom-cpu-next 5/9] cpu: Move halted and interrupt_request fields to CPUState Andreas Färber
2013-02-02 11:57   ` [Qemu-devel] " Andreas Färber
2013-02-02 11:57 ` [Qemu-devel] [RFC qom-cpu-next 6/9] exec: Pass CPUState to cpu_reset_interrupt() Andreas Färber
2013-02-02 11:57 ` [RFC qom-cpu-next 7/9] cpu: Pass CPUState to cpu_interrupt() Andreas Färber
2013-02-02 11:57   ` [Qemu-devel] " Andreas Färber
2013-02-02 11:57 ` [Qemu-devel] [RFC qom-cpu-next 8/9] cpu: Replace do_interrupt() by CPUClass::do_interrupt method Andreas Färber
2013-02-02 11:57 ` [Qemu-devel] [RFC qom-cpu-next 9/9] target-arm: Override do_interrupt for ARMv7-M profile Andreas Färber

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.