mirror of
https://github.com/xemu-project/xemu.git
synced 2026-07-11 01:24:41 +02:00
rx: cpu: fix interrupts check in rx_cpu_do_interrupt()
Commit87511341c3broke interrupt handling, replacing interrupts fetch with a bool and then the remaining code attempting to check individual bits on that bool value, which effectively masked those interrupts. Fix it by checking individual interrupt bits directly instead of old 'fetch then check' approach. Fixes:87511341c3("add cpu_test_interrupt()/cpu_set_interrupt() helpers and use them tree wide") Reported-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Tested-by: Thomas Huth <thuth@redhat.com> Reviewed-by: Thomas Huth <thuth@redhat.com> Message-ID: <20251030165932.138512-1-imammedo@redhat.com> [PMD: Rebased on commitdde21df239"call plugin trap callbacks"] Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
This commit is contained in:
committed by
Philippe Mathieu-Daudé
parent
20aa05edc2
commit
6c5571e72a
+20
-25
@@ -41,11 +41,9 @@ void rx_cpu_unpack_psw(CPURXState *env, uint32_t psw, int rte)
|
||||
env->psw_c = FIELD_EX32(psw, PSW, C);
|
||||
}
|
||||
|
||||
#define INT_FLAGS (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIR)
|
||||
void rx_cpu_do_interrupt(CPUState *cs)
|
||||
{
|
||||
CPURXState *env = cpu_env(cs);
|
||||
int do_irq = cpu_test_interrupt(cs, INT_FLAGS);
|
||||
uint32_t save_psw;
|
||||
uint64_t last_pc = env->pc;
|
||||
|
||||
@@ -59,29 +57,26 @@ void rx_cpu_do_interrupt(CPUState *cs)
|
||||
save_psw = rx_cpu_pack_psw(env);
|
||||
env->psw_pm = env->psw_i = env->psw_u = 0;
|
||||
|
||||
if (do_irq) {
|
||||
if (do_irq & CPU_INTERRUPT_FIR) {
|
||||
env->bpc = env->pc;
|
||||
env->bpsw = save_psw;
|
||||
env->pc = env->fintv;
|
||||
env->psw_ipl = 15;
|
||||
cpu_reset_interrupt(cs, CPU_INTERRUPT_FIR);
|
||||
qemu_set_irq(env->ack, env->ack_irq);
|
||||
qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
|
||||
qemu_log_mask(CPU_LOG_INT, "fast interrupt raised\n");
|
||||
} else if (do_irq & CPU_INTERRUPT_HARD) {
|
||||
env->isp -= 4;
|
||||
cpu_stl_data(env, env->isp, save_psw);
|
||||
env->isp -= 4;
|
||||
cpu_stl_data(env, env->isp, env->pc);
|
||||
env->pc = cpu_ldl_data(env, env->intb + env->ack_irq * 4);
|
||||
env->psw_ipl = env->ack_ipl;
|
||||
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
qemu_set_irq(env->ack, env->ack_irq);
|
||||
qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
|
||||
qemu_log_mask(CPU_LOG_INT,
|
||||
"interrupt 0x%02x raised\n", env->ack_irq);
|
||||
}
|
||||
if (cpu_test_interrupt(cs, CPU_INTERRUPT_FIR)) {
|
||||
env->bpc = env->pc;
|
||||
env->bpsw = save_psw;
|
||||
env->pc = env->fintv;
|
||||
env->psw_ipl = 15;
|
||||
cpu_reset_interrupt(cs, CPU_INTERRUPT_FIR);
|
||||
qemu_set_irq(env->ack, env->ack_irq);
|
||||
qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
|
||||
qemu_log_mask(CPU_LOG_INT, "fast interrupt raised\n");
|
||||
} else if (cpu_test_interrupt(cs, CPU_INTERRUPT_HARD)) {
|
||||
env->isp -= 4;
|
||||
cpu_stl_data(env, env->isp, save_psw);
|
||||
env->isp -= 4;
|
||||
cpu_stl_data(env, env->isp, env->pc);
|
||||
env->pc = cpu_ldl_data(env, env->intb + env->ack_irq * 4);
|
||||
env->psw_ipl = env->ack_ipl;
|
||||
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
qemu_set_irq(env->ack, env->ack_irq);
|
||||
qemu_plugin_vcpu_interrupt_cb(cs, last_pc);
|
||||
qemu_log_mask(CPU_LOG_INT, "interrupt 0x%02x raised\n", env->ack_irq);
|
||||
} else {
|
||||
uint32_t vec = cs->exception_index;
|
||||
const char *expname = "unknown exception";
|
||||
|
||||
Reference in New Issue
Block a user