Browse files

target-arm: Clear thumb state bit when popping PC during ARMV7M inter…

…rupt exit

An operating system (e.g. FreeRTOS) may create a task by setting up a stack
with a "simulated" stack frame containing the start address of the task.
The OS will then start the task by switching to the stack and doing an
interrupt return from within the service handler.  If the start address is a
function pointer, its thumb state bit (bit 0) will contain a 1 to indicate
the first instruction is a thumb instruction (and in the ARMV7M architecture,
all instructions are thumb instructions).  When the interrupt returns,
QEMU will pop the start address into the PC register.  QEMU expects the
PC register to be half-word aligned (which is enforced when branching),
and will not run properly when the PC is odd.

This patch clears bit 0 when restoring the PC during the ARMV7M interrupt exit.

Note that there is a bug open against QEMU for this problem:
  • Loading branch information...
beckus committed Oct 8, 2012
1 parent 8db972c commit 88a7608eba13ac882259341ca043c492f7be181c
Showing with 4 additions and 1 deletion.
  1. +4 −1 target-arm/helper.c
@@ -1712,7 +1712,10 @@ static void do_v7m_exception_exit(CPUARMState *env)
env->regs[3] = v7m_pop(env);
env->regs[12] = v7m_pop(env);
env->regs[14] = v7m_pop(env);
env->regs[15] = v7m_pop(env);
/* If this is a "simulated" stack frame built by an operating system, the
* thumb state bit (bit 0) may be set. We need to make sure it is cleared
* when restoring the program counter. */
env->regs[15] = v7m_pop(env) & 0xfffffffe;
xpsr = v7m_pop(env);
xpsr_write(env, xpsr, 0xfffffdff);
/* Undo stack alignment. */

0 comments on commit 88a7608

Please sign in to comment.