Commit a90b7318ba55b1aed71e299ec965bbd8f393b9b3
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
Showing
4 changed files
with
26 additions
and
14 deletions
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: | ... | ... |