When an exception occurs, the current program flow is interrupted. The Processing Element (PE) will update the current state and branch to a location in the vector table. Usually this location will contain generic code to push the state of the current program onto the stack and then branch to further code. This is illustrated here:
The state that the processor is in when the exception is recognized is known as the state the exception is taken from. The state the PE is in immediately after the exception is the state the exception is taken to. For example, it is possible to take an exception from AArch32 EL0 to AArch64 EL1.
The Armv8-A architecture has instructions that trigger an exception return. In that case, the state that the PE is in when that instruction is executed is the state that the exception return from. The state after the exception return instruction has executed is the state that the exception return to.
Each exception type targets an Exception level. Asynchronous exceptions can be routed to different exception levels.
Taking an exception
When an exception is taken, the current state must be preserved so that it can be returned to. The PE will automatically preserve the exception return address and the current
The state stored in the general-purpose registers must be preserved by software. The PE will then update the current
PSTATE to the one defined in the architecture for that exception type, and branch to the exception handler in the vector table.
PSTATE the exception was taken from is stored in the System register
SPSR_ELx, where <x> is the number of the Exception level that the exception was taken to. The exception return address is stored in
ELR_ELx, where <x> is the Exception level that the exception was taken to.
Routing asynchronous exceptions
The three physical interrupt types can be independently routed to one of the privileged Exception levels, EL1, EL2 or EL3. The diagram below uses IRQs as an example:
This routing is configured using
HCR_EL2. Routing configurations made using
SCR_EL3 will override routing configurations made using
HCR_EL2. These controls allow different interrupt types to be routed to different software.
Exceptions that are routed to a lower Exception level than the level being executed are implicitly masked. The exception will be pended until the PE changes to an Exception level equal to, or lower than, the one routed to.
Determining which Execution state an exception is taken to
The Execution state of an Exception level that an exception is taken to is determined by a higher Exception level. Assuming all Exception levels are implemented the following table shows how the Execution state is determined.
|Exception level taken to:||Exception state determined by:|
|EL3||Reset state of EL3|
Returning from an exception
Software can initiate a return from an exception by executing an
ERET instruction from AArch64. This will cause the Exception level returned to be configured based on the value of
SPSR_ELx, where <x> is the level being returned from.
SPSR_ELx contains the target level to be returned to and the target Execution state.
Note that the Execution state specified in
SPSR_ELx must match the configuration in either
HCR_EL2.RW, or this will generate an illegal exception return.
On execution of the
ERET instruction, the state will be restored from
SPSR_ELx, and the program counter will be updated to the value in
ELR_ELx. These two updates will be performed atomically and indivisibly so that the PE will not be left in an undefined state.
When executing in AArch64, the architecture allows a choice of two stack pointer registers;
SP_ELx, where <x> is the current Exception level. For example, at EL1 it is possible to select
During general execution, it is expected that all code uses
SP_EL0. When taking an exception, S
P_ELx is initially selected. This allows a separate stack to be maintained for initial exception handling. This is useful for maintaining a valid stack when handling exceptions caused by stack overflows.