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,7 +772,8 @@ void cpu_dump_statistics (CPUState *env, FILE *f, | ||
772 | int (*cpu_fprintf)(FILE *f, const char *fmt, ...), | 772 | int (*cpu_fprintf)(FILE *f, const char *fmt, ...), |
773 | int flags); | 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 | extern CPUState *first_cpu; | 777 | extern CPUState *first_cpu; |
777 | extern CPUState *cpu_single_env; | 778 | extern CPUState *cpu_single_env; |
778 | extern int code_copy_enabled; | 779 | extern int code_copy_enabled; |
cpu-exec.c
@@ -279,9 +279,10 @@ int cpu_exec(CPUState *env1) | @@ -279,9 +279,10 @@ int cpu_exec(CPUState *env1) | ||
279 | #elif defined(TARGET_ARM) | 279 | #elif defined(TARGET_ARM) |
280 | if (env1->halted) { | 280 | if (env1->halted) { |
281 | /* An interrupt wakes the CPU even if the I and F CPSR bits are | 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 | env1->halted = 0; | 286 | env1->halted = 0; |
286 | } else { | 287 | } else { |
287 | return EXCP_HALTED; | 288 | return EXCP_HALTED; |
@@ -432,6 +433,15 @@ int cpu_exec(CPUState *env1) | @@ -432,6 +433,15 @@ int cpu_exec(CPUState *env1) | ||
432 | env->exception_index = EXCP_DEBUG; | 433 | env->exception_index = EXCP_DEBUG; |
433 | cpu_loop_exit(); | 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 | #if defined(TARGET_I386) | 445 | #if defined(TARGET_I386) |
436 | if ((interrupt_request & CPU_INTERRUPT_SMI) && | 446 | if ((interrupt_request & CPU_INTERRUPT_SMI) && |
437 | !(env->hflags & HF_SMM_MASK)) { | 447 | !(env->hflags & HF_SMM_MASK)) { |
@@ -514,12 +524,7 @@ int cpu_exec(CPUState *env1) | @@ -514,12 +524,7 @@ int cpu_exec(CPUState *env1) | ||
514 | } else if (interrupt_request & CPU_INTERRUPT_TIMER) { | 524 | } else if (interrupt_request & CPU_INTERRUPT_TIMER) { |
515 | //do_interrupt(0, 0, 0, 0, 0); | 525 | //do_interrupt(0, 0, 0, 0, 0); |
516 | env->interrupt_request &= ~CPU_INTERRUPT_TIMER; | 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 | #elif defined(TARGET_ARM) | 528 | #elif defined(TARGET_ARM) |
524 | if (interrupt_request & CPU_INTERRUPT_FIQ | 529 | if (interrupt_request & CPU_INTERRUPT_FIQ |
525 | && !(env->uncached_cpsr & CPSR_F)) { | 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,7 +247,8 @@ static void pxa2xx_clkpwr_write(void *opaque, int op2, int reg, int crm, | ||
247 | goto message; | 247 | goto message; |
248 | 248 | ||
249 | case 3: | 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 | s->env->cp15.c1_sys = 0; | 252 | s->env->cp15.c1_sys = 0; |
252 | s->env->cp15.c1_coproc = 0; | 253 | s->env->cp15.c1_coproc = 0; |
253 | s->env->cp15.c2 = 0; | 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,7 +1584,7 @@ static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn) | ||
1584 | 1584 | ||
1585 | /* Disassemble system coprocessor (cp15) instruction. Return nonzero if | 1585 | /* Disassemble system coprocessor (cp15) instruction. Return nonzero if |
1586 | instruction is not defined. */ | 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 | uint32_t rd; | 1589 | uint32_t rd; |
1590 | 1590 | ||
@@ -1610,8 +1610,13 @@ static int disas_cp15_insn(DisasContext *s, uint32_t insn) | @@ -1610,8 +1610,13 @@ static int disas_cp15_insn(DisasContext *s, uint32_t insn) | ||
1610 | } else { | 1610 | } else { |
1611 | gen_movl_T0_reg(s, rd); | 1611 | gen_movl_T0_reg(s, rd); |
1612 | gen_op_movl_cp15_T0(insn); | 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 | return 0; | 1620 | return 0; |
1616 | } | 1621 | } |
1617 | 1622 | ||
@@ -2927,7 +2932,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) | @@ -2927,7 +2932,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) | ||
2927 | goto illegal_op; | 2932 | goto illegal_op; |
2928 | break; | 2933 | break; |
2929 | case 15: | 2934 | case 15: |
2930 | - if (disas_cp15_insn (s, insn)) | 2935 | + if (disas_cp15_insn (env, s, insn)) |
2931 | goto illegal_op; | 2936 | goto illegal_op; |
2932 | break; | 2937 | break; |
2933 | default: | 2938 | default: |