Search code examples
armthumb

Restoring Thumb state in user mode


I'm writing thread-switch code in which the kernel dumps relevant state to memory, but the actual thread switch occurs entirely in user mode.

This works fine, except in the case where the preemption point occurs inside a Thumb If-Then (IT) block. In that case, I cannot work out how to restore ITSTATE (i.e. bits [15:10] and [26:25] of the CPSR), since these bits are user RAZ/WI, and in any case it probably doesn't make sense given the semantics of ITSTATE.

What (if any) is the correct way to restore this state without trapping into the kernel?

I have considered rewinding execution and continuing from the IT instruction, but apart from being quite heavy-weight, I'm not sure if this is always possible.

EDIT: interested in ARMv7-A


Solution

  • Architecturally*, none of the execution state bits in the CPSR can be read or written in any mode (with the exception of the CPSR.E bit in privileged modes only, and even that is deprecated). The only way to modify them outside of normal execution is via the SPSR in an exception return, which anticipates returning directly to the relevant instruction inside the IT block.

    As you've mentioned, restarting the entire IT block is neither practical nor safe, mostly due to memory accesses - whilst in most cases you could probably statically analyse the instructions to reverse any register modifications, any shared memory could mean a repeated load returns a different value, or a repeated store could corrupt some other process that's read and modified the original value in the meantime. As for memory-mapped I/O, unexpectedly repeating any access could potentially be hazardous for any number of reasons.

    Another potential idea would be to JIT a new IT block based on ITSTATE from the SPSR and the remaining instructions at the return address, since Thumb-2 means you have LDR PC,... to get back to the original code from anywhere with registers intact. However, even that's still going to break things if the conditional instructions do any PC-relative calculations.

    * on anything that has a CPSR and supports Thumb-2, at any rate