Commit a90b7318ba55b1aed71e299ec965bbd8f393b9b3

Authored by balrog
1 parent 4207117c

Implement power state changes (IDLE and SLEEP) for PXA.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2762 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-all.h
... ... @@ -772,7 +772,8 @@ void cpu_dump_statistics (CPUState *env, FILE *f,
772 772 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
773 773 int flags);
774 774  
775   -void cpu_abort(CPUState *env, const char *fmt, ...);
  775 +void cpu_abort(CPUState *env, const char *fmt, ...)
  776 + __attribute__ ((__format__ (__printf__, 2, 3)));
776 777 extern CPUState *first_cpu;
777 778 extern CPUState *cpu_single_env;
778 779 extern int code_copy_enabled;
... ...
cpu-exec.c
... ... @@ -279,9 +279,10 @@ int cpu_exec(CPUState *env1)
279 279 #elif defined(TARGET_ARM)
280 280 if (env1->halted) {
281 281 /* An interrupt wakes the CPU even if the I and F CPSR bits are
282   - set. */
283   - if (env1->interrupt_request
284   - & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) {
  282 + set. We use EXITTB to silently wake CPU without causing an
  283 + actual interrupt. */
  284 + if (env1->interrupt_request &
  285 + (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB)) {
285 286 env1->halted = 0;
286 287 } else {
287 288 return EXCP_HALTED;
... ... @@ -432,6 +433,15 @@ int cpu_exec(CPUState *env1)
432 433 env->exception_index = EXCP_DEBUG;
433 434 cpu_loop_exit();
434 435 }
  436 +#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
  437 + defined(TARGET_PPC) || defined(TARGET_ALPHA)
  438 + if (interrupt_request & CPU_INTERRUPT_HALT) {
  439 + env->interrupt_request &= ~CPU_INTERRUPT_HALT;
  440 + env->halted = 1;
  441 + env->exception_index = EXCP_HLT;
  442 + cpu_loop_exit();
  443 + }
  444 +#endif
435 445 #if defined(TARGET_I386)
436 446 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
437 447 !(env->hflags & HF_SMM_MASK)) {
... ... @@ -514,12 +524,7 @@ int cpu_exec(CPUState *env1)
514 524 } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
515 525 //do_interrupt(0, 0, 0, 0, 0);
516 526 env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
517   - } else if (interrupt_request & CPU_INTERRUPT_HALT) {
518   - env->interrupt_request &= ~CPU_INTERRUPT_HALT;
519   - env->halted = 1;
520   - env->exception_index = EXCP_HLT;
521   - cpu_loop_exit();
522   - }
  527 + }
523 528 #elif defined(TARGET_ARM)
524 529 if (interrupt_request & CPU_INTERRUPT_FIQ
525 530 && !(env->uncached_cpsr & CPSR_F)) {
... ...
hw/pxa2xx.c
... ... @@ -247,7 +247,8 @@ static void pxa2xx_clkpwr_write(void *opaque, int op2, int reg, int crm,
247 247 goto message;
248 248  
249 249 case 3:
250   - cpu_reset(s->env);
  250 + s->env->uncached_cpsr =
  251 + ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
251 252 s->env->cp15.c1_sys = 0;
252 253 s->env->cp15.c1_coproc = 0;
253 254 s->env->cp15.c2 = 0;
... ...
target-arm/translate.c
... ... @@ -1584,7 +1584,7 @@ static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
1584 1584  
1585 1585 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
1586 1586 instruction is not defined. */
1587   -static int disas_cp15_insn(DisasContext *s, uint32_t insn)
  1587 +static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
1588 1588 {
1589 1589 uint32_t rd;
1590 1590  
... ... @@ -1610,8 +1610,13 @@ static int disas_cp15_insn(DisasContext *s, uint32_t insn)
1610 1610 } else {
1611 1611 gen_movl_T0_reg(s, rd);
1612 1612 gen_op_movl_cp15_T0(insn);
  1613 + /* Normally we would always end the TB here, but Linux
  1614 + * arch/arm/mach-pxa/sleep.S expects two instructions following
  1615 + * an MMU enable to execute from cache. Imitate this behaviour. */
  1616 + if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
  1617 + (insn & 0x0fff0fff) != 0x0e010f10)
  1618 + gen_lookup_tb(s);
1613 1619 }
1614   - gen_lookup_tb(s);
1615 1620 return 0;
1616 1621 }
1617 1622  
... ... @@ -2927,7 +2932,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
2927 2932 goto illegal_op;
2928 2933 break;
2929 2934 case 15:
2930   - if (disas_cp15_insn (s, insn))
  2935 + if (disas_cp15_insn (env, s, insn))
2931 2936 goto illegal_op;
2932 2937 break;
2933 2938 default:
... ...