The ARM exception return is a key mechanism that allows ARM processors to handle exceptions and interrupts efficiently. When an exception or interrupt occurs, the processor needs to save its current state, handle the exception, and then return to where it left off. The exception return handles the return step, restoring the previous state so that normal program execution can resume.
What Triggers an Exception Return
On ARM processors, exceptions and interrupts trigger exception entries. This causes the processor to:
- Save program state like register contents and program counter
- Jump to an exception handler routine
After the exception handler runs, it finishes by performing an exception return. This exception return jumps back to the main program and restores the saved program state. The processor can then resume normal execution.
Exception Return Instructions
The ARM instruction set provides several instructions to perform exception returns:
- ERET – Exception Return
- DRPS – Debug Return PS
- RFEDA – Return From Debug using Address
- RFEIA – Return From Exception using Increment After
- RFEIB – Return From Exception using Increment Before
The most common exception return instruction is ERET. This restores registers like LR, SP, and PC to return to the point where the exception occurred.
ERET Instruction
The ERET instruction is used when returning from most exceptions and interrupts. ERET does the following:
- Restores LR from SPSR to PC, resuming execution at point of exception
- Restores CPSR from SPSR, restoring processor state
- Restores registers like SP from banked registers to undo stacking
This efficiently unwinds the changes made when entering the exception, so it looks like the exception never occurred.
ERET Pseudocode
PC = SPSR.LR CPSR = SPSR Restore banked registers like SP Resume execution at LR
Debug Exception Returns
Debug exceptions have some additional requirements for the exception return mechanism. For example, debug exceptions need to avoid changing system state when resuming. The debug return instructions support this:
- DRPS – Returns to normal execution mode for stepping
- RFEDA – Restores a specific PC value for breakpoints
- RFEIA/RFEIB – Special SP incrementing modes
Conditional Exception Returns
Some exception returns may need to conditionally alter state before resuming normal execution. For this, ARMv6 introduced conditional execution of exception returns: ERETCOND condition
This allows checking condition codes after the exception handler but before ERET. For example, this can be used to switch processor modes only if certain error conditions occurred.
Chaining Exception Returns
In some cases, exceptions may occur back-to-back. The processor may take another exception while handling the first one. To handle this cleanly, ARM supports chaining exception returns.
When a nested exception occurs, the processor stacks multiple exception frames. The first ERET simply returns to the next stacked frame. A subsequent ERET is needed to fully unwind back to the original code.
Usage in ARM Cortex-M
The ARM Cortex-M family of processors are very popular in microcontrollers and deeply embedded applications. These processors use exception returns extensively:
- Use ERET to return from NMI, HardFault, and other exceptions
- Support conditional ERET to set the FAIL bits on errors
- Allow tail-chaining exceptions for minimal latency
The Cortex-M exception model relies heavily on ERET to restore state during exception dispatch and return sequences.
Cortex-M ERET Examples
Here is some example code using ERET on a Cortex-M processor: // Exception handler void NMI_Handler() { // Handle NMI // Return to interrupted code __asm(“ERET”); } // Application code int main() { // ERET unwinds stack to here // after NMI handler completes }
Usage in ARM Linux
The Linux kernel running on ARM also uses exception returns. On Linux, ERET handles returns from:
- IRQ interrupts from devices
- Synchronous abort exceptions
- FIQs for fast interrupts
Linux registers custom exception handlers that then return via ERET. This allows handling exceptions while keeping the kernel state intact.
Linux ERET Examples
Here is sample code from the Linux 5.x kernel using ERET: // arch/arm64/kernel/entry.S irq_handler: // … handle IRQ exception_exit: ERET nop
This demonstrates ERET being used to return from a standard IRQ handler.
Summary
The exception return is a key capability allowing ARM processors to handle asynchronous events efficiently. Using exception returns like ERET allows the processor to:
- Save state on exception entry
- Restore state after handling exception
- Resume where the program left off
This provides low overhead exception dispatch and return, while keeping the main program state intact. Exception returns are thus vital for exceptions and interrupts to work well on ARM platforms.