HomeARM CourseDay 5
DAY 5 · FOUNDATIONS

Operating Modes & Exception Levels

By EcrioniX · Updated Jun 6, 2026

Why can't your app just reformat the disk or read another app's memory? Because the CPU runs code at different privilege levels. Today we learn how ARM separates "trusted system code" from "ordinary apps" — the foundation of every OS, hypervisor and security feature.

1. Why privilege exists

Imagine if any app could reprogram the interrupt controller, disable memory protection, or peek at your banking app's memory. Chaos. So the CPU runs code at two broad trust levels:

An app that wants something powerful (open a file, allocate memory) must ask the OS via a system call, which traps up into privileged code. The CPU enforces this in hardware — an app literally cannot execute privileged operations.

💡 Analogy

A hotel. Guests (apps) can enter their own room. Staff (the OS) have master keys to every room and the control systems. A guest who needs something restricted calls the front desk (a system call) — they don't get a master key.

2. AArch64: four Exception Levels (EL0–EL3)

Modern 64-bit ARM organises privilege into four clean Exception Levels. Higher number = more privilege. Code "traps up" to a higher level to handle exceptions:

EL3
Secure Monitor — switches between Normal & Secure worlds (TrustZone). Most privileged.
EL2
Hypervisor — runs virtual machines; hosts multiple OSes.
EL1
OS Kernel — Linux, Android, an RTOS. Manages memory, drivers, scheduling.
EL0
Applications — your apps. Unprivileged. The least-trusted level.

A typical phone uses EL0 (apps) → EL1 (the OS kernel) → and EL3 for secure-world switching. EL2 appears when virtualization is in play. Not every system uses all four — but the ladder is always there.

3. AArch32: the classic processor modes

Older 32-bit ARM expresses privilege as named modes instead of numbered levels. The CPU switches mode automatically when an exception happens:

ModeEntered when…Privilege
User (USR)normal application codeUnprivileged
Supervisor (SVC)a system call (SVC) / on resetPrivileged
IRQa normal interrupt firesPrivileged
FIQa fast interrupt firesPrivileged
Abort (ABT)a memory access faultPrivileged
Undefined (UND)an illegal instructionPrivileged
System (SYS)privileged code sharing User registersPrivileged

Banked registers: several modes get their own private copies of some registers (notably SP and LR, and FIQ gets extra). That's why an interrupt handler has its own stack pointer without clobbering the app's — the hardware swaps in the banked copy on entry. (Remember the CPSR mode bits from Day 3? They record which mode you're in.)

4. Cortex-M is refreshingly simple

Microcontrollers don't need that whole ladder, so Cortex-M (M-profile) drops it for just two modes:

Code can additionally be privileged or unprivileged, and there are two stack pointers (MSP/PSP). That's it — simple, fast and deterministic, exactly what a microcontroller wants. (The interrupt machinery, the NVIC, is Day 18.)

✅ The mental model

Privilege is a ladder of trust. Apps sit at the bottom (EL0 / User / Thread). The OS and handlers sit higher. The CPU automatically climbs the ladder when an exception or system call happens, runs the trusted handler, then climbs back down. This single mechanism powers multitasking, security and virtualization.

🎯 Day 5 takeaways

Quick check

  1. Which exception level runs the Linux kernel — EL0 or EL1?
  2. Why does an interrupt handler need its own (banked) stack pointer?
  3. What two modes does a Cortex-M switch between?

FAQ

What are EL0–EL3?

AArch64 exception levels: EL0 apps, EL1 OS kernel, EL2 hypervisor, EL3 secure monitor. Higher = more privileged.

Privileged vs unprivileged?

Unprivileged (apps) can only touch their own resources; privileged (kernel/handlers) can configure the whole machine.

How is Cortex-M different?

It uses just Thread and Handler modes (plus privileged/unprivileged), not the classic AArch32 mode set.

Previous
← Day 4: Memory & endianness

← Back to the full course roadmap