HomeARM CourseDay 24
DAY 24 · SYSTEM & MEMORY

System Control — CP15 & Coprocessors

By EcrioniX · Updated Jun 6, 2026

We've turned on the MMU, configured caches, set up the MPU. But how do you actually flip those switches? The general-purpose registers r0–r15 can't do it. The control panel lives somewhere else entirely: the CP15 system control coprocessor. This is where the OS configures the machine itself.

1. The coprocessor concept

Classic ARM kept the core instruction set small and pushed extra functions into up to 16 coprocessors (CP0–CP15), accessed by dedicated instructions. The most important is CP15, the system control coprocessor — not for math, but the home of every register that configures the processor. (Other coprocessor numbers historically covered things like the floating-point/SIMD units, CP10/CP11, and debug, CP14.)

💡 The cockpit panel

If r0–r15 are the pilot's hands flying the plane, CP15 is the overhead switch panel: fuel pumps, hydraulics, pressurisation. You don't touch it every second, but nothing works until it's set correctly — and only the captain (privileged code) is allowed to.

2. Reading & writing CP15: MRC / MCR

You can't MOV into a coprocessor register. Instead two special instructions bridge the worlds:

InstructionDirectionMeaning
MRCCP15 → RdMove to Register from Coprocessor (read)
MCRRd → CP15Move to Coprocessor from Register (write)

Each access names the coprocessor and a set of opcodes/register IDs that select the exact system register (written c0, c1, …):

; Read the System Control Register (SCTLR) into r0 MRC p15, 0, r0, c1, c0, 0 ORR r0, r0, #1 ; set bit 0 = MMU enable MCR p15, 0, r0, c1, c0, 0 ; write it back → MMU now on

That three-instruction read-modify-write is literally how an OS turns on the MMU.

3. What CP15 controls

In short: if it configures the processor itself rather than computing a value, it's in CP15.

4. Privilege — and why it matters

CP15 is almost entirely privileged: user-mode code (Day 5) cannot touch it. That's deliberate — letting an app disable the MMU or rewrite the page-table base would destroy all isolation. Only the kernel, running privileged, configures the system. An unprivileged CP15 access faults straight to the OS.

5. AArch64: from coprocessors to named registers

The coprocessor encoding was powerful but cryptic — c1, c0, 0 tells you nothing. AArch64 (the 64-bit world, coming up next phase) dropped the coprocessor model and gave system registers real names, accessed with MRS (read) and MSR (write):

// AArch64 — same idea, self-documenting names + exception-level suffix MRS x0, SCTLR_EL1 // read System Control Register (EL1) ORR x0, x0, #1 // set MMU enable MSR SCTLR_EL1, x0 // write it back

The mechanism is the same as CP15 — special instructions reaching a separate control-register space — just far more readable, with an exception-level suffix (_EL1, _EL2…) instead of secure/mode juggling.

✅ The mental model

CP15 is the processor's control panel in 32-bit ARM — the registers that enable the MMU, caches and TLB and report identity. You reach them only with MRC (read) / MCR (write), only from privileged code. AArch64 keeps the concept but swaps the coprocessor encoding for named system registers via MRS/MSR.

🎯 Day 24 takeaways

Quick check

  1. Why can't you use MOV to enable the MMU?
  2. Which instruction reads a CP15 register, and which writes one?
  3. What's the AArch64 equivalent of MRC/MCR?

FAQ

What is CP15?

The system control coprocessor in 32-bit ARM, holding the registers that configure the MMU, caches, TLB and report processor identity.

MRC vs MCR?

MRC reads a coprocessor register into an ARM register; MCR writes an ARM register into a coprocessor register.

What changed in AArch64?

The coprocessor model was dropped for named system registers accessed with MRS/MSR (e.g. SCTLR_EL1).

Previous
← Day 23: TrustZone

← Back to the full course roadmap