Programmable Interrupt Controllers: A New Architecture

A programmable interrupt controller is an IP block that collates many sources of interrupt one one or more CPU lines, as well as submitting a level of priority to the interrupt outputs. It’s fair to say that almost every SoC needs an interrupt controller to handle all of the interrupt sources. For example, ARM processors only have two interrupt signal inputs whereas a controller can manage much more than that.

ARM’s GIC (General Interrupt Controller) architecture provides an efficient and standardized approach for handling interrupts in multi-core ARM based systems. Like the ARM architecture, it is a functional specification, meaning it doesn’t describe the implementation of the architecture, just the programmer’s model and functional model. It defines what registers the interrupt controller has, what they’re for, how software interacts with the interrupt controller, how to program it up, and then to later deal with interrupts.

A generic programmable interrupt controller is a good idea because it simplifies the software involved. For OS development you don’t want to have to write multiple drivers for multiple controllers, especially when it is unlikely to be the differentiating factor in a complex SoC. It makes sense for hardware people and software people to agree on a standard, and a couple of years ago ARM introduced the GIC architecture. This blog is an introduction to the latest version of the architecture; GICv3.

It’s designed for multi-core systems where we have a single interrupt controller shared across what could potentially be a large number of cores.

What's changed in GICv3?

GICv2 to GICv3

A high level view of the new features that GIC v3 provides

The headline change is that GICv3 can support far more than the 8 cores supported in GICv2. In mobile SoCs, support for 8 cores is enough for the vast majority but for areas like servers or networking there is a need to support a higher core count. Managing all of this via one interrupt controller increases system efficiency. I’ll go through the other changes in some detail below. ARM offers an implementation of the GICv3 architecture, the CoreLink GIC-500 General Interrupt Controller, that includes all of the latest updates in the GICv3 architecture. The ARM CoreLink GIC-500 supports for up to 128 cores which provides the ability to virtualize up to 480 shared peripheral interrupt signals.

System Register Interface

Traditionally in GICv1 and v2, all the GIC registers were memory mapped. That meant when you are programming or handling an interrupt, load store instructions were used to communicate with the interrupt controller. That is still true for many instructions in GICv3, for configuring the interrupt sources, they are mostly memory mapped registers. But those registers used while handling interrupts (ie the ones most commonly used) can now be system registers which means that software, rather than load-store, will perform MSR and MRS instructions. In order for these to be supported there needs to be support built into the core. ARM processors such as the Cortex®-A72, Cortex-A53 and Cortex-A57 all have the required support.

What's the advantage?

There is an advantage to change the most commonly used memory maps to system register interfaces as it provides certainty for the registers’ location (ie they won’t be at different addresses in different systems). Also, in certain cases it gives a more reliable set of timings than going through every memory interface.

Security Groups

In GICv3 there are three security groups which are configured individually for each interrupt, an increase from the two that were in GICv2. This change provides a better match with the ARMv8-A architecture in the security and exception model. Just as before there are secure and non-secure interrupts based on different OSes, but there is a new state that lets you distinguish between interrupts for the Secure Monitor and interrupts for the Secure Kernel.

Now that the CPU interface is a part of the processor, we can be a bit more intelligent with how we handle processor exceptions (FIQ and IRQ). In GICv3, FIQ becomes either an interrupt for ER3, or an interrupt for non-cant security state.

Group 0 Secure Group 1 Non-secure Group 1
Group 0 interrupts are always secure Signalled as FIQ if core is in Non-secure state Signalled as FIQ if core is in Secure state
Signalled as FIQ, regardless of current Security state Signalled as IRQ if core is in Secure state Signalled as IRQ if core is in Non-secure state
Typically used for interrupts for the firmware running at EL3 Typically used for interrupts for the trusted OS Typically used for interrupts for the rich OS or Hypervisor

Below is a diagram that gives a bit of a visual example into how this could all work together.

GICv3 Routing Example

**EDIT** This routing example diagram may not represent the typical routing model for some Trusted OS implementations. In Trusted OS, Non-Secure Group 1 interrupts can be routed to Secure-EL1 (not EL3) when executing in the secure state. This is to allow the Trusted OS take action (e.g. move the pre-empted task to a different core) before allowing the normal world to handle the interrupt. An SMC interface is used by the Trusted OS to notify the normal world that it has been pre-empted and by the normal world to tell the Trusted OS to resume its pre-empted activity.

Support for Larger Systems

GICv3 introduces Redistributors that hold the settings for the private interrupts. These are interrupts that are private to the core so each core can have its own settings for those interrupts. There is a Redistributor per-connected core, holding settings for private interrupts (PPIs and SGIs).

Why do we do this?

In short, it allows for distributed designs with Redistributors kept close to each target core. If you have a large design with many cores, private interrupts will typically be generated close to the core that they are private to. We don’t want to transport this onto the other side of the chip where the interrupt controller is located to work out all the settings, it’s inefficient. The redistributors allow for distributed design where the logic is physically close to the CPU and can hold the settings close to its connected core and reduce the travel distance for these private interrupts.

Affinity Levels and Routing

One of the consequences of this is that we need to rethink how we target interrupts at a particular core. One way of doing this is affinity, which is a way of identifying a core in a hierarchical structure. It’s a matching system for each core made up of four 8-bit fields (similar to an IP address) and has been changed to increase the scalability of the architecture, allowing for the handling of far more cores than GICv2 was capable of. Shared peripheral interrupts can be separately configured to be sent to any connected core, or to a specific core by using its affinity coordinates.

Message-based Interrupts

The new architecture adds support for message-based interrupts whereby instead of requiring a dedicated signal, a peripheral writes a register in the GIC to register an interrupt. It’s done to reduce the number of wires needed for all of the interrupt signals and ease routing congestion. It’s a form of future-proofing for when systems become larger and the number of interrupt sources increases accordingly.

The Interrupt Translation Service is another way of improving the efficiency of message-based interrupts, acting as a dispatcher and also mapping interrupts to INTIDs and Redistributors.

GIC Interrupt Translation Service

Why use an ITS?

To move a block of interrupts from one RD to another is inefficient as users have to update each individual peripheral with the new redistributor’s address, which could be time consuming if there are a lot of interrupt sources being moved.

Instead all peripherals can be configured to write to the ITS, which forwards them on to the correct place.  Moving interrupts from one RD to another then becomes just a matter of updating the ITS’s tables.  The ITS also handles the issuing of the commands to RDs which are required to move an interrupt. It’s controlled by a command queue in memory, and software can map or remap interrupts by adding commands to the queue.

GICv3 is a scalable architecture

There are a number of new innovations in the GICv3 architecture that offer a scalable infrastructure for the interrupt handling of larger systems. The changes will help to manage an increased core count, increased message congestion and will provide a faster and more efficient way for interrupts to be handled across SoCs. The ARM CoreLink GIC-500 is an interrupt controller designed by ARM that harnesses all of the benefits of the GICv3 architecture to improve interrupt efficiency and allow for greater virtualization on-chip.

For more information you can register to view a webinar delivered by ARM’s Chris Shore and Martin Weidmann that goes into more detail and answers some viewer’s questions. Register by clicking on the button below.

Register for webinar