Public bug reported: On ARMv7M interrupts handlers will be called even if emulated code executes "cpsid i" instruction.
Underlying cause described below: In cpu-exec.c:cpu_exec there is a block of code that determines if an interrupt should be raised or not: /* ARMv7-M interrupt return works by loading a magic value into the PC. On real hardware the load causes the return to occur. The qemu implementation performs the jump normally, then does the exception return when the CPU tries to execute code at the magic address. This will cause the magic PC value to be pushed to the stack if an interrupt occurred at the wrong time. We avoid this by disabling interrupts when pc contains a magic address. */ if (interrupt_request & CPU_INTERRUPT_HARD && ((IS_M(env) && env->regs[15] < 0xfffffff0) || !(env->uncached_cpsr & CPSR_I))) { env->exception_index = EXCP_IRQ; cc->do_interrupt(cpu); next_tb = 0; } I'm not convinced the logic is correct. The logic for ARMv7M should be: If an interrupt is pending (interrupt_request & CPU_INTERRUPT_HARD) AND Interrupts are not disabled ( !(env->uncached_cpsr & CPSR_I) ) AND PC doesn't have a magic value (env->regs[15] < 0xfffffff0) The current logic seems fires the interrupt if interrupts are enabled OR the PC isn't magic, which is basically all the time. I'm not sure what the cleanest patch for this would be. ** Affects: qemu Importance: Undecided Status: New ** Tags: armv7m -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1226531 Title: Incorrect logic in ARMv7M interrupt handler Status in QEMU: New Bug description: On ARMv7M interrupts handlers will be called even if emulated code executes "cpsid i" instruction. Underlying cause described below: In cpu-exec.c:cpu_exec there is a block of code that determines if an interrupt should be raised or not: /* ARMv7-M interrupt return works by loading a magic value into the PC. On real hardware the load causes the return to occur. The qemu implementation performs the jump normally, then does the exception return when the CPU tries to execute code at the magic address. This will cause the magic PC value to be pushed to the stack if an interrupt occurred at the wrong time. We avoid this by disabling interrupts when pc contains a magic address. */ if (interrupt_request & CPU_INTERRUPT_HARD && ((IS_M(env) && env->regs[15] < 0xfffffff0) || !(env->uncached_cpsr & CPSR_I))) { env->exception_index = EXCP_IRQ; cc->do_interrupt(cpu); next_tb = 0; } I'm not convinced the logic is correct. The logic for ARMv7M should be: If an interrupt is pending (interrupt_request & CPU_INTERRUPT_HARD) AND Interrupts are not disabled ( !(env->uncached_cpsr & CPSR_I) ) AND PC doesn't have a magic value (env->regs[15] < 0xfffffff0) The current logic seems fires the interrupt if interrupts are enabled OR the PC isn't magic, which is basically all the time. I'm not sure what the cleanest patch for this would be. To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1226531/+subscriptions