Processor modes

From ARMwiki
Jump to: navigation, search

In the old days, you had a processor and it executed instructions. When an interrupt occured, the processor would save its current state and then branch to a specific place in order to service the interrupt. Thus, essentially, the processor had two 'modes' - dealing with an interrupt, and not.

Fast forward a few decades, processors are much more capable and something of great importance is the ability to multitask, to run numerous programs at the same time. Technically this isn't possible, the processor has one data bus and one address bus, and however many cores are inside it, each core can only do one thing at a time. However by breaking a program's execution into tiny chunks, the processor can switch between them many times a second, providing the illusion that they are all running at the same time.
This brings with it a number of additional requirements, namely that one program should not be able to mess around with the memory used by another program. Furthermore, none of the mere programs should be able to mess around with the operating system or the machine's hardware. This is managed, in part, by the use of an MMU or other memory management system, and in part by the use of privilege. It is the processor mode that provides the desired level of privilege.


Processor modes

There are seven processor modes:

Mode Bits Description Family
User usr %10000 Normal program execution, no privileges All
FIQ fiq %10001 Fast interrupt handling All
IRQ irq %10010 Normal interrupt handling All
Supervisor svc %10011 Privileged mode for the operating system All
Abort abt %10111 For virtual memory and memory protection ARMv3+
Undefined und %11011 Facilitates emulation of co-processors in hardware ARMv3+
System sys %11111 Runs programs with some privileges ARMv4+

User mode

This is the mode in which user application tasks should run. It has access to the base register set, and no privileges.

FIQ mode

The ARM processor supports two types of interrupt handling. There is the regular type of interrupt, and there is this, the fast interrupt. The difference is that fast interrupts can interrupt regular ones.

In comparison with the 6502 or the x86, an FIQ is similar to an NMI; the difference being that the ARM has no NMI (FIQs can be disabled). It is, however, the same concept of a two-level interrupt system where a more important interrupt can interrupt an interrupt!

FIQ mode provides a large number of shadow registers (R8 to R14, CPSR) and is useful for things that must complete extremely quickly or else data loss is a possibility. The original (8MHz) ARM used FIQ for networking and floppy disc which had to be serviced as soon as data was available. Modern ARMs would probably use FIQ for high speed DMA-style transfers.

IRQ mode

This is the other, regular, interrupt mode. Only R13, R14, and CPSR are shadowed. All interrupts that don't require extreme speed (clock ticks, screen VSync, keyboard, etc...) will use IRQ mode.

SVC mode

This is the privileged mode reserved for the operating system. R13, R14, and CPSR are shadowed.

OS calls (SWI) set the processor to SVC mode, and then the processor jumps to &8 (or &FFFF0008).

After system reset, the ARM begins processing at address &0 (or &FFFF0000 if high vectors configured), with interrupts disabled and in SVC mode. This address is the location of the Reset Vector, which should be a branch to the reset code.

Abort mode

An abort is signalled by the memory system as a result of a failure to load either an instruction (Prefetch Abort) or data (Data abort).

A Prefetch Abort occurs if the processor attempts to execute a failed instruction load (note - no abort happens if the processor fails to load an instruction, but said instruction is not executed due to a branch or suchlike).
In ARMv5 a Prefetch Abort can be generated programatically by the use of the breakpoint instruction.

A Data Abort occurs if the processor attempts to fetch data but the memory system says it is unable to. The abort occurs before the failed instruction alters the processor state.

In both cases, interrupts are disabled and the branch is taken (&C/&FFFF000C - Prefetch; &10/&FFFF0010 - Data).
To return after handling the aborted instruction, call:

  SUBS   PC, R14, #4

Or in the case of Data abort, if the failed instruction needs to be re-executed (i.e. virtual memory after swapping in data), use:

  SUBS   PC, R14, #8

Undefined mode

When an undefined instruction is encountered, the ARM will wait for a coprocessor to acknowledge that it can deal with the instruction (if in co-processor instruction space). If no coprocessor responds, or the instruction is one that is not defined, then the undefined instruction vector is taken. This will branch to &4 (or &FFFF0004) to allow such things as software emulation of coprocessors, or other extensions to the instruction set.

The difference being that coprocessor instruction space is that with bit 21 unset, and bits 24-27 set as %1100:

31-28 27-24 23 22 21 20 19-16 15-12 11-8 7-0
cond 1 1 0 0 X X 0 X Rn CRd cp_num offset

While undefined instruction space is instructions where bit 4 is set and bits 27-25 are %011:

31-28 27-25 24-5 4 3-0
cond 0 1 1 x x x x x x x x x x x x x x x x x x x x 1 x x x x

Return using:

  MOVS   PC, R14

System mode

A problem with the original design of the ARM is that as processor vectors modify R14 with the return address, an exception handler (for example, IRQ) that calls subroutines cannot act in a re-entrant way; for if the IRQ handler is taken while in the IRQ handler and having called a subroutine to handle the (first) IRQ, the return address in R14 will be trashed by the second IRQ exception.

Ways around this involve clever coding to avoid an exception of the same type occurring, or to avoid taking subroutine calls, or switching to USR mode. Or in the case of interrupts, disabling them completely during the interrupt process.

As of ARMv4, an alternative is proposed. System mode. It is like a cross between SVC and USR. System mode offers the privileges of SVC mode, however it uses the USR registers.

It is not possible to enter System mode on an exception, the exception handler needs to modify the CPSR to enter System mode. In this way, an exception handler can safely deal with R14 and CPSR and re-entrancy is possible.
Here is a rough outline of how to handle interrupts in a re-entrant way.

  • When the IRQ vector is taken, IRQs are disabled and the previous CPSR is saved in SPSR_irq.
  • The return address (in R14) should be pushed to the IRQ stack.
  • As should registers used in the IRQ handler (i.e. R0-R3 or whatever), plus SPSR_irq.
  • The source of the interrupt should be interrogated. This is necessary at this stage in order to clear the interrupt.
  • Switch to System mode.
  • Save the User mode R14 and other necessary registers (i.e. R4-R7 etc) that may be corrupted by your handler.
  • Re-enable interrupts.
  • Your interrupt is handled here. As you are in System mode, you have the same degree of privilege as SVC mode.
  • [your handler exits]
  • Disable interrupts.
  • Restore the user mode registers that you previously saved.
  • Switch back to IRQ mode, ensuring to keep interrupts disabled.
  • Restore the SPSR_irq and the registers that you saved in IRQ mode.
  • Return from the interrupt.

In code, this would look like:

  SUB     R14, R14, #4       ; calculate the return address
  STMFD   R13!, {R14}        ; save it to IRQ stack
  MRS     R14, SPSR_irq      ; copy out the SPSR
  STMFD   R13!, {R0-R3, R14} ; save work registers and SPSR
  ; Here would be some code to detect and clear the interrupt.
  ; It is necessary to do both as quite a few interrupting
  ; devices are read-sensitive; so you can't clear the interrupt
  ; and then go back and read the status later.
  MSR     CPSR_c, #&9F       ; switch to SYS mode, IRQs disabled
  STMFD   R13!, {Rx-Ry, R14} ; save R14 and other necessary registers
  MSR     CPSR_c, #&1F       ; stay in SYS mode, IRQs now enabled
  BL      my_irq_handler     ; call your IRQ handler routine
  MSR     CPSR_c, #&9F       ; staying in SYS mode, IRQs now disabled
  LDMFD   R13!, {Rx-Ry, R14} ; restore user mode registers
  MSR     CPSR_c, #&92       ; back to IRQ mode, IRQs now disabled
  LDMFD   R13!, {R0-R3, R14} ; restore IRQ regs and retrieve SPSR_irq
  LDMFD   R13!, {PC}^        ; return from the IRQ (restoring CPSR)

26 bit processor modes

As the lower two bits of PC are the processor mode, the modes are as follows:

Mode Bits Description
User usr %00 Normal program execution, no privileges
FIQ fiq %01 Fast interrupt handling
IRQ irq %10 Normal interrupt handling
Supervisor svc %11 Privileged mode for the operating system

The register definitions are the same (i.e. R13-R14 shadowed for SYS and IRQ, R8-R14 for FIQ) with the architectural difference that there is no CPSR or SPSR. The flags are stored within PC, and accordingly, the preserved R14.
Additionally, there is no MRS/MSR so TEQP and TSTP are used to manipulate the flags.

Personal tools