diff --git a/cpu-all.h b/cpu-all.h index db1e947fec9b..0aa384354003 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -772,7 +772,8 @@ void cpu_dump_statistics (CPUState *env, FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...), int flags); -void cpu_abort(CPUState *env, const char *fmt, ...); +void cpu_abort(CPUState *env, const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); extern CPUState *first_cpu; extern CPUState *cpu_single_env; extern int code_copy_enabled; diff --git a/cpu-exec.c b/cpu-exec.c index 284cb92ae83a..4777babd2a08 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -279,9 +279,10 @@ int cpu_exec(CPUState *env1) #elif defined(TARGET_ARM) if (env1->halted) { /* An interrupt wakes the CPU even if the I and F CPSR bits are - set. */ - if (env1->interrupt_request - & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) { + set. We use EXITTB to silently wake CPU without causing an + actual interrupt. */ + if (env1->interrupt_request & + (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB)) { env1->halted = 0; } else { return EXCP_HALTED; @@ -432,6 +433,15 @@ int cpu_exec(CPUState *env1) env->exception_index = EXCP_DEBUG; cpu_loop_exit(); } +#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \ + defined(TARGET_PPC) || defined(TARGET_ALPHA) + if (interrupt_request & CPU_INTERRUPT_HALT) { + env->interrupt_request &= ~CPU_INTERRUPT_HALT; + env->halted = 1; + env->exception_index = EXCP_HLT; + cpu_loop_exit(); + } +#endif #if defined(TARGET_I386) if ((interrupt_request & CPU_INTERRUPT_SMI) && !(env->hflags & HF_SMM_MASK)) { @@ -514,12 +524,7 @@ int cpu_exec(CPUState *env1) } else if (interrupt_request & CPU_INTERRUPT_TIMER) { //do_interrupt(0, 0, 0, 0, 0); env->interrupt_request &= ~CPU_INTERRUPT_TIMER; - } else if (interrupt_request & CPU_INTERRUPT_HALT) { - env->interrupt_request &= ~CPU_INTERRUPT_HALT; - env->halted = 1; - env->exception_index = EXCP_HLT; - cpu_loop_exit(); - } + } #elif defined(TARGET_ARM) if (interrupt_request & CPU_INTERRUPT_FIQ && !(env->uncached_cpsr & CPSR_F)) { diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c index 2f5dc96062ae..43d40c7fd9b8 100644 --- a/hw/pxa2xx.c +++ b/hw/pxa2xx.c @@ -247,7 +247,8 @@ static void pxa2xx_clkpwr_write(void *opaque, int op2, int reg, int crm, goto message; case 3: - cpu_reset(s->env); + s->env->uncached_cpsr = + ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I; s->env->cp15.c1_sys = 0; s->env->cp15.c1_coproc = 0; s->env->cp15.c2 = 0; diff --git a/target-arm/translate.c b/target-arm/translate.c index 3d3dc3fd2688..364f4eadba9d 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -1584,7 +1584,7 @@ static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn) /* Disassemble system coprocessor (cp15) instruction. Return nonzero if instruction is not defined. */ -static int disas_cp15_insn(DisasContext *s, uint32_t insn) +static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn) { uint32_t rd; @@ -1610,8 +1610,13 @@ static int disas_cp15_insn(DisasContext *s, uint32_t insn) } else { gen_movl_T0_reg(s, rd); gen_op_movl_cp15_T0(insn); + /* Normally we would always end the TB here, but Linux + * arch/arm/mach-pxa/sleep.S expects two instructions following + * an MMU enable to execute from cache. Imitate this behaviour. */ + if (!arm_feature(env, ARM_FEATURE_XSCALE) || + (insn & 0x0fff0fff) != 0x0e010f10) + gen_lookup_tb(s); } - gen_lookup_tb(s); return 0; } @@ -2927,7 +2932,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) goto illegal_op; break; case 15: - if (disas_cp15_insn (s, insn)) + if (disas_cp15_insn (env, s, insn)) goto illegal_op; break; default: