On 6/29/22 16:16, Sven Schnelle wrote:
Thanks, that was very helpful. I added debugging and it turned out
that the TB is left because of a pending irq. The code then calls
s390_cpu_exec_interrupt:
bool s390_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
if (interrupt_request & CPU_INTERRUPT_HARD) {
S390CPU *cpu = S390_CPU(cs);
CPUS390XState *env = &cpu->env;
if (env->ex_value) {
/* Execution of the target insn is indivisible from
the parent EXECUTE insn. */
return false;
}
if (s390_cpu_has_int(cpu)) {
s390_cpu_do_interrupt(cs);
return true;
}
if (env->psw.mask & PSW_MASK_WAIT) {
/* Woken up because of a floating interrupt but it has already
* been delivered. Go back to sleep. */
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HALT);
}
}
return false;
}
Note the 'if (env->ex_value) { }' check. It looks like this function
just returns false in case tcg is executing an EX instruction. After
that the information that the TB should be exited because of an
interrupt is gone. So the TB's are never exited again, although the
interrupt wasn't handled. At least that's my assumption now, if i'm
wrong please tell me.
Ah, yes, I see.
We wanted to treat ex_value != 0 as if interrupts are disabled, because we have no way of
stacking that value for re-execution after the interrupt (which itself could use EXECUTE).
One solution might be to zap ex_value and arrange to re-execute the EXECUTE instruction
after the interrupt.
Another solution is to generate an exit from any TB translating ex_value, so that
interrupts are re-examined. This is probably cleanest. I'll prepare a patch.
r~