aboutsummaryrefslogtreecommitdiff
path: root/docs/processor-modes-explained.md
blob: 6631655bc9e2937fd8b8debf1a972cabfbb1d3db (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# Processor modes

ARMv7-A core can be executing in one of several modes (not to be confused with instruction set states or endianness execution state). Those are:

1. User
2. FIQ
3. IRQ
4. Supervisor
5. Abort
6. Undefined
7. System

In fact, there are more if the processor implements some extensions, but this is irrelevant here.

Current processor mode is encoded in the lowest five bits of the [CPSR](./PSRs-explained.txt) register.

Processor can operate in one of 2 privilege levels (although, again, extensions exist, that add more levels):

1. PL0 - privilege level 0
2. PL1 - privilege level 1

Processor modes have their assigned privilege levels. User mode has privilege level 0 and all other modes have privilege level 1. Code executing in one of privileged modes is allowed to do more things, than user mode code, i.e. writing and reading some of the coprocessor registers, executing some privileged instructions (i.e. mrs and msr, when used to reference CPSR, as well as other modes' registers), accessing privileged memory and changing the mode (without causing an interrupt). Attempts to perform those actions in user mode result either in undefined (within some limits) behaviour or an exception (depending on what action is considered).

User mode is the one, in which application programs usually run. Other modes are usually used by the operating system's kernel. Lack of privileges in user mode allows PL1 code to control execution of PL0 code.

While code executing in PL1 can freely (except switching from system to user mode, which produces undefined behaviour) change mode by either writing the CPRS or executing cps instruction, user mode can only be exitted by means of an interrupt.

Some ARM core registers (i.e. r0 - r7) are shared between modes, while some are not. In this case, separate modes have their private copies of those registers. For example, lr and sp in supervisor mode are different from lr and sp in user mode. For full information about shared and not shared (banked) registers, see paragraph B9.2.1 in [armv7-a manual](https://static.docs.arm.com/ddi0406/c/DDI0406C_C_arm_architecture_reference_manual.pdf). The most important things are that user mode and system mode share all registers with each other and they don't have their own SPSR (which is used for returning from [exceptions](./Exception-vector-explained.txt) and exceptions are never taken to those 2 modes) and that all other modes have their own SPSR, sp and lr.

The reason for having multiple copies of the same register in different modes is that it simplifies writing interrupt handlers. I.e. supervisor mode code can safely use sp and lr without destroying the contents of user mode's sp and lr.

The big number of PL1 modes is supposed to aid in handling of interrupts. Each kind of interrupt is taken to it's specific mode, as detailed in [here](./Exception-vector-explained.txt).

Supervisor mode, in addition to being the mode supervisor calls are taken to, is the mode the processor is in when the kernel boots.

System mode, which uses the same registers as user mode, is said to have been added to ARM architecture to ease accessing the unprivileged registers. For example, setting user mode's sp from supervisor mode can be done by switching to system mode, setting the sp and switching back to supervisor mode. Other modes' registers can alternatively be accessed with the use of mrs and msr assembly instructions (but not from user mode).

Despite the name, system mode doesn't have to be the mode used most often by operating system's kernel. In fact, prohibition of direct switching from system mode to user mode would make extensive use of system mode impractical. This project, for example, uses supervisor mode for most of the privileged tasks.