Exception and Interrupt Model of Armv8/Armv9

Click the blue "Arm Selection" in the upper left corner and select "Set as Favorite"

1 Introduction

This article introduces the exception and privilege model in Armv8-A. It covers the different types of exceptions in the Arm architecture and the behavior of the processor when an exception is received. This article is relevant for developers working on low-level code, such as boot code or drivers, and is particularly pertinent for anyone writing code to set up or manage exceptions.

2 Privilege and Exception Model

Before discussing the details of the Armv8-A exception model, we first introduce the concept of privilege. Modern software is expected to be divided into different modules, each with different levels of access to system and processor resources. An example of this is the operating system kernel (which has high-level access to system resources) and user applications that have limited access to system resources.

Armv8-A achieves this separation by implementing different levels of privilege. The current privilege level can only be changed when the processor accepts an exception or returns from one. Therefore, these privilege levels are referred to as Exception Levels in the Armv8-A architecture. Each Exception Level is numbered, with higher privilege levels having larger numbers.

As shown in the figure below, the Exception Levels are referred to as EL, where x is a number between 0 and 3. For example, the lowest privilege level is called EL0.Exception and Interrupt Model of Armv8/Armv9A common usage model is that application code runs at EL0, while the operating system runs at EL1. EL2 is used by the hypervisor, and EL3 is used by Trusted Firmware.

Note: The architecture does not enforce this software model, but standard software adopts this model. For this reason, the remainder of this article assumes this usage model.

2.1. Types of Privilege

There are two types of privilege related to this. The first is privilege in the memory system, and the second is privilege from the perspective of accessing processor resources. Both are affected by the current Exception Level.

2.2. Memory Privilege

Armv8-A implements a virtual memory system where the Memory Management Unit (MMU) allows software to assign attributes to memory regions. These attributes include read/write permissions, which can be configured with two degrees of freedom. This configuration allows separate access permissions for privileged and non-privileged access.

When the processor executes in EL0, memory accesses initiated will be checked against non-privileged access permissions. Memory accesses from EL1, EL2, and EL3 will be checked against privileged access permissions.

Since this memory configuration is programmed by software using MMU translation tables, you should consider the privilege required to program these tables. MMU configurations are stored in system registers, and the ability to access these registers is also controlled by the current Exception Level.

2.3. Access to Registers

The configuration settings of the Armv8-A processor are stored in a set of registers known as system registers. The settings in the system registers define the current processor context. Access to system registers is controlled by the current Exception Level.

The names of the system registers indicate the lowest Exception Level that can access that register. For example, TTBR0_EL1 is the register that holds the base address of the translation table used by EL0 and EL1. This register cannot be accessed from EL0, and any attempt to do so will result in an exception being generated.

The architecture has many registers with conceptually similar functions, differing only in the Exception Level suffix. These are distinct, separate registers, each with its own encoding in the instruction set and will be implemented separately in hardware. For example, the following registers perform MMU configuration for different translation mechanisms. The registers have similar names to reflect their similar tasks, but they are completely independent registers with their own access semantics:

  • SCTLR_EL1 – Top level system control for EL0 and EL1

  • SCTLR_EL2 – Top level system control for EL2

  • SCTLR_EL3 – Top level system control for EL3

Note: EL1 and EL0 share the same MMU configuration, and control is limited to privileged code running at EL1. Therefore, there is no SCTLR_EL0, and all control comes from registers accessible at EL1. Other control registers typically follow this model.

Higher Exception Levels have the right to access registers of lower levels. For example, EL2 has the right to access SCTLR_EL1 when necessary. In general operation of the system, privileged Exception Levels typically control their own configuration. However, higher privilege levels may sometimes access registers associated with lower Exception Levels, such as when implementing virtualization features or during context switching or power management operations as part of saving and restoring a set of registers.

3 Execution State and Security State

The current state of the Armv8-A processor is determined by the Exception Level and two other important states. The current execution state defines the standard width of general-purpose registers and the available instruction set. The execution state also affects various aspects of the memory model and how exceptions are managed.

The current security state controls the currently effective Exception Level, the memory regions that can be accessed, and how these accesses are represented on the system memory bus.

The figure below shows the Exception Levels and security states, using different execution states:Exception and Interrupt Model of Armv8/Armv9

3.1. Execution States

Armv8-A provides two execution states:

  • AArch32: The 32-bit Execution state. Operation in this state is compatible with Armv7-A. There are two available instruction sets: T32 and A32. The standard register width is 32 bits.

  • AArch64: The 64-bit Execution state. There is one available instruction set: A64. The standard register width is 64 bits.

3.2. Security States

The Armv8-A architecture allows for the implementation of two security states. This allows for further partitioning of software to isolate and separate trusted software.

These two security states are:

  • Secure state: In this state, the Processing Element (PE) can access both secure and non-secure physical address spaces. In this state, the PE can access both secure and non-secure system registers. Software running in this state can only acknowledge secure interrupts.

  • Non-secure state: In this state, the PE can only access non-secure physical address space. The PE can also only access system registers that allow non-secure access. Software running in this state can only acknowledge non-secure interrupts.

3.3. Changing Execution State

The PE can only change the execution state during reset or when changing Exception Levels.

The execution state at reset is determined by an IMPLEMENTATION DEFINED mechanism. Some implementations fix the execution state at reset. For example, Cortex-A32 will always reset to AArch32 state. In most implementations of Armv8-A, the execution state after reset is controlled by signals sampled at reset. This allows for on-chip system-level control of the reset execution state.

The execution state can also change when the PE transitions between Exception Levels. Transitions between AArch32 and AArch64 are only allowed under certain rules:

  • When moving from a lower Exception Level to a higher one, the execution state can remain unchanged or change to AArch64.

  • When moving from a higher Exception Level to a lower one, the execution state can remain unchanged or change to AArch32.

Putting these two rules together means that 64-bit can allow 32-bit, but not vice versa. For example, a 64-bit operating system kernel can host both 64-bit and 32-bit applications simultaneously, while a 32-bit operating system kernel can only host 32-bit applications.Exception and Interrupt Model of Armv8/Armv9In this example, we used operating systems and applications, but the same rules apply to all Exception Levels. For instance, a 32-bit hypervisor at EL2 can only host 32-bit virtual machines at EL1.

3.4. Changing Security State

EL3 is always considered to execute in a secure state. Using SCREL3, EL3 code can change the security state of all lower Exception Levels. If software uses SCREL3 to change the security state of lower Exception Levels, the PE will not change the security state until it changes to a lower Exception Level.

3.5. Implementation Defined Exception Levels and Execution States

The Armv8-A architecture allows implementations to choose whether to implement all Exception Levels and to select which execution states are allowed for each implemented Exception Level.

EL0 and EL1 are the only Exception Levels that must be implemented. EL2 and EL3 are optional. The choice not to implement EL3 or EL2 has significant implications.

EL3 is the only level that can change the security state. If an implementation chooses not to implement EL3, then that PE will not have access to any security state.

Similarly, EL2 contains many virtualization features. An implementation without EL2 cannot access these features. All current Arm implementations of the architecture implement all Exception Levels, and most standard software cannot be used without all Exception Levels.

Implementations can also choose the execution states that are valid for each Exception Level. If AArch32 is allowed at an Exception Level, it must be allowed at all lower Exception Levels. For example, if EL3 allows AArch32, then it must allow it at all lower Exception Levels.

Many implementations allow all execution states and all Exception Levels, but there are existing implementations with limitations. For example, Cortex-A32 only allows AArch32 at any Exception Level.

Some modern implementations, such as Cortex-A55, implement all Exception Levels but only allow AArch32 at EL0. (For example, refer to this article: Cortex-A76 only supports AArch32 at EL0.) Other Exception Levels EL1, EL2, and EL3 must be AArch64.

4 Types of Exceptions

An exception is any event that can cause the currently executing program to be suspended and lead to a change in state to execute code to handle that exception. Other processor architectures may describe this as an interrupt. In the Armv8-A architecture, an interrupt is an exception generated externally. The Armv8-A architecture classifies exceptions into two main categories: synchronous exceptions and asynchronous exceptions.

4.1. Synchronous Exceptions

Synchronous exceptions are exceptions that may be caused by or related to the instruction just executed. This means that synchronous exceptions are synchronized with the execution flow.

Attempting to execute an invalid instruction may lead to a synchronous exception, whether it is an instruction not allowed at the current Exception Level or an instruction that has been disabled.

Memory accesses may also lead to synchronous exceptions due to address misalignment or failure of one of the MMU permission checks. Since these errors are synchronous, exceptions can occur before attempting to access memory. Memory accesses can also generate asynchronous exceptions, which will be discussed in this section. Memory access errors are discussed in more detail in the memory management guidelines.

The Armv8-A architecture has a set of exception-generating instructions: SVC, HVC, and SMC. These instructions differ from simple invalid instructions because they target different Exception Levels and are treated differently when prioritizing exceptions. These instructions are used to implement system call interfaces, allowing lower privilege code to request services from higher privilege code.

Debug exceptions are also synchronous exceptions.

4.2. Asynchronous Exceptions

Certain types of exceptions are generated externally and are therefore not synchronized with the current instruction flow. This means that it cannot be accurately guaranteed when an asynchronous exception will occur. The Armv8-A architecture only requires that it occurs within a limited time. Asynchronous exceptions can also be temporarily masked. This means that asynchronous exceptions can be pending before they occur.

Types of asynchronous exceptions include:Physical interrupts• SError (System Error) • IRQ • FIQVirtual Interrupts• vSError (Virtual System Error) • vIRQ (Virtual IRQ) • vFIQ (Virtual FIQ)

Physical interrupts are generated in response to signals generated outside the PE. Virtual interrupts can be generated externally or by software executing at EL2.

4.3. IRQ and FIQ

The Armv8-A architecture has two types of exceptions, IRQ and FIQ, designed for generating peripheral interrupts. In other versions of the Arm architecture, FIQ was used as a higher priority fast interrupt. This is different in Armv8-A, whereFIQ has the same priority as IRQ.

IRQ and FIQ have independent routing controls, typically used to implement secure and non-secure interrupts, as described in the general interrupt controller guidelines.

4.4. SError

SError is a type of exception intended to be generated by the memory system in response to erroneous memory accesses. The typical use of SError is for what was previously known as external asynchronous aborts, such as memory accesses that have passed all MMU checks but encountered errors on the memory bus. This may be reported asynchronously since the instruction may have already exited. SError interrupts may also be triggered by parity or error-correcting code (ECC) checks on certain RAM, such as those in built-in caches.

5 Handling Exceptions

When an interrupt occurs, the Processing Element (PE) will update the current state and branch to a location in the vector table. Typically, this location will contain generic code to push the current program state onto the stack and then branch to further code.Exception and Interrupt Model of Armv8/Armv9

5.1. Exception Terminology

The state of the processor when an exception is recognized is referred to astaken from. The state that the PE is in immediately after the exception occurs istaken to. For example, an exception can be taken from AArch32 EL0 to AArch64 EL1.

The Armv8-A architecture has instructions that trigger exception returns. In that case, the state of the PE when executing that instruction isreturn from. The state after executing the exception return instruction isreturn to

Each type of exception targets a specific Exception Level. Asynchronous exceptions can be routed to different Exception Levels.

5.2. Taking an Exception

When an exception occurs, the current state must be preserved so that a return can be made. The PE automatically saves the exception return address and the current PSTATE.

The state stored in general-purpose registers must be saved by software. The PE then updates the current PSTATE to the PSTATE defined for that exception type in the architecture and jumps to the exception handler in the vector table.

The PSTATE taken from when the exception occurred is stored in the system register SPSRELx, whereis the number of taken to. The exception return address is stored in ELRELx, whereis the number of taken to.

5.3. Routing Asynchronous Exceptions

Three types of physical interrupts can be independently routed to one of the privileged Exception Levels, EL1, EL2, or EL3. The figure below illustrates this with IRQ:Exception and Interrupt Model of Armv8/Armv9This routing is configured using SCREL3 and HCREL2. Routing configurations made using SCREL3 will override those made using HCREL2. These controls allow different interrupt types to be routed to different software.

Exceptions routed to an Exception Level lower than the one currently executing are implicitly masked. The exception will be pending until the PE changes to an Exception Level equal to or lower than the routed Exception Level.

5.4. Determining Which Execution State an Exception is Taken To

The execution state of the Exception Level to which the exception is taken is determined by the higher Exception Level. Assuming all Exception Levels are implemented, the table below shows how to determine the execution state:Exception and Interrupt Model of Armv8/Armv9

5.5. Returning from an Exception

Software can initiate a return from an exception by executing the ERET instruction from AArch64. This will cause the exception level to return based on the value of SPSRELx, whereis the level from which it is returning. SPSRELx contains the target level and target execution state to return to.

Note that the Execution state specified in SPSRELx must match the configuration in SCREL3.RW or HCR_EL2.RW; otherwise, an illegal exception return will occur.

When executing the ERET instruction, the state will be restored from SPSRELx, and the PC will be updated to the value in ELRELx. These two updates will be performed atomically and indivisibly so that the PE does not enter an undefined state.

5.6. Exception Stacks

When executing in AArch64, the architecture allows for the selection of two stack pointer registers: SPEL0 or SPELx, whereis the current Exception Level. For example, at EL1, either SPEL0 or SPEL1 can be selected.

During general execution, it is expected that all code uses SPEL0. When an exception occurs, SPELx is initially selected. This allows for maintaining a separate stack for initial exception handling. This is useful for maintaining a valid stack when handling exceptions caused by stack overflows.

6 The Vector Tables

In Armv8-A, the vector table is a region of normal memory containing instructions. The Processing Element (PE) keeps the base address of the table in a system register, and each type of exception has a defined offset relative to that base address.

Each privileged Exception Level has its own vector table, defined by the Vector Base Address Register VBAR_ELx, whereis 1, 2, or 3.

The value of the VBAR register is undefined after reset, so it must be configured before interrupts are enabled.

The format of the vector table is as follows:Exception and Interrupt Model of Armv8/Armv9Each type of exception can lead to a jump to one of four locations, depending on the state from which the exception is taken.

Exception and Interrupt Model of Armv8/Armv9

Recommended Courses “From Beginner to Mastering Armv8/Armv9 Architecture” (Three Sessions)
“Trustzone/TEE/Security from Beginner to Master” Standard Edition
“Arm Selection – Platinum VIP Course”
🌍Consult via WeChat: sami01_2023

Leave a Comment