summaryrefslogtreecommitdiffstats
path: root/target-xtensa
diff options
context:
space:
mode:
authorMax Filippov2011-10-10 04:25:04 +0200
committerBlue Swirl2011-10-15 23:03:03 +0200
commit890c6333b28a4dcbf2a26a5a17b0e71304d5a851 (patch)
treed9243ab3e1a3eab793184eb49134b9c1d9c6fa87 /target-xtensa
parentDrop obsolete nographic timer (diff)
downloadqemu-890c6333b28a4dcbf2a26a5a17b0e71304d5a851.tar.gz
qemu-890c6333b28a4dcbf2a26a5a17b0e71304d5a851.tar.xz
qemu-890c6333b28a4dcbf2a26a5a17b0e71304d5a851.zip
target-xtensa: fix guest hang on masked CCOMPARE interrupt
QEMU timer is used to post CCOMPARE interrupt when the core is halted. If that CCOMPARE interrupt is masked off then the timer must be rearmed in the callback, otherwise it will be rearmed next time the core goes to halt by the waiti instruction. Add test case into timer testsuite. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Diffstat (limited to 'target-xtensa')
-rw-r--r--target-xtensa/cpu.h1
-rw-r--r--target-xtensa/op_helper.c18
2 files changed, 4 insertions, 15 deletions
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 339075dda1..966f515249 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -313,6 +313,7 @@ void check_interrupts(CPUXtensaState *s);
void xtensa_irq_init(CPUState *env);
void xtensa_advance_ccount(CPUState *env, uint32_t d);
void xtensa_timer_irq(CPUState *env, uint32_t id, uint32_t active);
+void xtensa_rearm_ccompare_timer(CPUState *env);
int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
void xtensa_sync_window_from_phys(CPUState *env);
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 64847fc8e6..0605611031 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -370,23 +370,11 @@ void HELPER(waiti)(uint32_t pc, uint32_t intlevel)
return;
}
- if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
- int i;
- uint32_t wake_ccount = env->sregs[CCOUNT] - 1;
-
- for (i = 0; i < env->config->nccompare; ++i) {
- if (env->sregs[CCOMPARE + i] - env->sregs[CCOUNT] <
- wake_ccount - env->sregs[CCOUNT]) {
- wake_ccount = env->sregs[CCOMPARE + i];
- }
- }
- env->wake_ccount = wake_ccount;
- qemu_mod_timer(env->ccompare_timer, qemu_get_clock_ns(vm_clock) +
- muldiv64(wake_ccount - env->sregs[CCOUNT],
- 1000000, env->config->clock_freq_khz));
- }
env->halt_clock = qemu_get_clock_ns(vm_clock);
env->halted = 1;
+ if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
+ xtensa_rearm_ccompare_timer(env);
+ }
HELPER(exception)(EXCP_HLT);
}