10.5. Interrupt handling

ARM commonly uses interrupt to mean interrupt signal. On ARM A-profile and R-profile processors, that means an external IRQ or FIQ interrupt signal. The architecture does not specify how these signals are used. FIQ is often reserved for secure interrupt sources. In earlier architecture versions, FIQ and IRQ were used to denote high and standard interrupt priority, but this is not the case in ARMv8-A.

When the processor takes an exception to AArch64 execution state, all of the PSTATE interrupt masks is set automatically. This means that further exceptions are disabled. If software is to support nested exceptions, for example, to allow a higher priority interrupt to interrupt the handling of a lower priority source, then software needs to explicitly re-enable interrupts.

For the following instruction:

  MSR DAIFClr, #imm

This immediate value is in fact a 4-bit field, as there are also masks for:

Figure 10.6. Interrupt handler in C code

To view this graphic, your browser must support the SVG format. Either install a browser with native support, or install an appropriate plugin such as Adobe SVG Viewer.


An example assembly language IRQ handler might look like this:

IRQ_Handler
                               // Stack all corruptible registers 
     STP X0, X1, [SP, #-16]!   // SP = SP -16
     ...
     STP X2, X3, [SP, #-16]!   // SP = SP - 16
                               // unlike in ARMv7, there is no STM instruction and so 
                               // we may need several STP instructions

   BL read_irq_source          // a function to work out why we took an interrupt 
                               // and clear the request
   BL C_irq_handler            // the C interrupt handler
                               // restore from stack the corruptible registers 
   LDP X2, X3, [SP], #16       // S = SP + 16
   LDP X0, X1, [SP], #16       // S = SP + 16
     … 
   ERET 

However, from a performance point of view, the following sequence might be preferable:

IRQ_Handler
     SUB SP, SP, #<frame_size> // SP = SP - <frame_size>
     STP X0, X1, [SP}          // Store X0 and X1 at the base of the frame
     STP X2, X3, [SP]          // Store X2 and X3 at the base of the frame + 16 bytes
     ...                       // more register storing
     ...
                               // Interrupt handling

   BL read_irq_source          // a function to work out why we took an interrupt 
                               // and clear the request
   BL C_irq_handler            // the C interrupt handler
                               // restore from stack the corruptible registers 
     LDP X0, X1, [SP]          // Load X0 and X1 at the base of the frame
     LDP X2, X3, [SP]          // Load X2 and X3 at the base of the frame + 16 bytes
     ...                       // more register loading
     ADD SP, SP, #<frame_size> // Restore SP at its original value
     … 
   ERET 

Figure 10.7. Handling nested interrupts

To view this graphic, your browser must support the SVG format. Either install a browser with native support, or install an appropriate plugin such as Adobe SVG Viewer.


The nested handler requires a little extra code. It must preserve on the stack the contents of SPSR_EL1 and ELR_EL1. We must also re-enable IRQs after determining (and clearing) the interrupt source. However (unlike in ARMv7-A), as the link register for subroutine calls is different to the link register for exceptions, we avoid having to do anything special with LR or modes.

Copyright © 2015 ARM. All rights reserved.ARM DEN0024A
Non-ConfidentialID050815