More data on interrupts
Having found some time to have a look at how interrupts are processed on some extra architectures, here are the results.
- This architecture’s reference manual is written and organized in a way that makes it particularly awful to read, so the chances of misunderstanding on my side are higher than for others : if you consider developing for PowerPC, better double-check what I say.
- There’s only one external interrupt, which centralizes input for external implementation-specific interrupt controllers.
- Location of the interrupted instruction and extremely limited status information (mostly related to operating modes) are saved in a pair of dedicated registers, the rest must be saved by the interrupt handler before use.
- Paging is disabled, both for code and data, and 64-bit mode is enabled.
- External interrupts and floating point interrupts are disabled.
- Depending on a flag’s value, the CPU may or may not switch to hypervisor mode (= kernel mode).
- The CPU fetches the interrupt’s handler location from a table at a fixed memory location and runs it.
- IMPORTANT NOTE : This is not the latest version of the Power architecture (2.06 at the time where I’ve wrote this article). Since then, apart from the name change, a split has occured between a server-oriented version of Power and an embedded-oriented version. In Power-E, there is a new external interrupt, the “critical” interrupt, that works in exactly the same way as FIQ on ARM (it has an independent vector and is able to preempt normal interrupts). Power-E also provides a way to relocate the interrupt vector table, much like many other architectures.
- An interrupt priority scheme is available for external interrupts. Priority cannot be changed, but the CPU may be set up to ignore interrupts below a certain priority treshold.
- Like on most other architectures, the CPU saves its state to begin with. However, it does it in a pretty original way : while on most other architectures, CPU state is saved either on a stack (PDP-11, VAX, MIPS, x86_64) or in a single set of dedicated registers (ARM, PowerPC), SPARC offers the hybrid solution of a stack of dedicated registers sets. As an example, a given implementation can have enough CPU registers to keep 4 CPU states saved at a given time. This compromise eases interrupt handler nesting, like stack-based approaches, while keeping the speed of register-based approaches. Overflows are managed.
- The amount of CPU state saved allows, unlike on PowerPC, to use most instructions comfortably without having to do additional register saving manually. This does not include general-purpose registers (GPRs), though, and care must be taken with those. SPARC provides an alternate set of GPRs for use by interrupt handlers, and automatically switches to it in the event of an interrupt, but there is only one of it : nested interrupt handlers must take care not to overwrite the GPRs of the interrupt handlers underneath.
- To keep optimal speed for non-nested interrupt handlers while offering ways to avoid GPR overwriting in the nested case, SPARC offers a way to set up different interrupt handlers for situations where the register stack is empty and situations where there’s something in it.
- The CPU is set to kernel mode and 64-bit mode.
- Interrupts are disabled.
- SPARC provides an option to use one interrupt vector per interrupt source directly connected to the CPU, but it is not hostile to single-vector operation, as it provides a way to read which interrupt source has ringed a bell in a CPU register, like MIPS and unlike x86 or ARM.
- The interrupt vector table is located at a location defined by the user in memory. Interrupt vectors are a sequence of instructions, that may either be a full interrupt handler (if not much space is needed) or branch to the actual interrupt handler.
I also got the manuals for IA-64 and Alpha, but haven’t got the time to look at them at the moment. Coming in an upcoming blog post…