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>
This commit is contained in:
Max Filippov 2011-10-10 06:25:04 +04:00 committed by Blue Swirl
parent 9870a5e6cd
commit 890c6333b2
4 changed files with 93 additions and 16 deletions

View file

@ -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);
}