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.
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.)
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.
You can't MOV into a coprocessor register. Instead two special instructions bridge the worlds:
| Instruction | Direction | Meaning |
|---|---|---|
| MRC | CP15 → Rd | Move to Register from Coprocessor (read) |
| MCR | Rd → CP15 | Move 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, …):
That three-instruction read-modify-write is literally how an OS turns on the MMU.
In short: if it configures the processor itself rather than computing a value, it's in CP15.
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.
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):
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.
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.
The system control coprocessor in 32-bit ARM, holding the registers that configure the MMU, caches, TLB and report processor identity.
MRC reads a coprocessor register into an ARM register; MCR writes an ARM register into a coprocessor register.
The coprocessor model was dropped for named system registers accessed with MRS/MSR (e.g. SCTLR_EL1).