10. Virtual Memory (MMU) - Enabling Caching and Protection¶
The Memory Management Unit (MMU) is a critical component of modern processors. It translates Virtual Addresses (VA) to Physical Addresses (PA) and controls memory attributes like caching and access permissions.
Why use the MMU?¶
- Caching: Without MMU, all memory access is treated as "Device Memory" (uncached) by default on ARMv8, which is extremely slow. Enabling MMU allows us to mark RAM as "Normal Memory" (Cacheable).
- Protection: We can prevent user programs from accessing kernel memory.
- Virtualization: Each process can have its own isolated address space.
Translation Tables (Page Tables)¶
ARMv8 uses a multi-level table structure. For a 4KB granule, we typically use 3 or 4 levels. We'll use 3 levels to map the first 1GB of memory.
- Level 0 (PGD): Points to Level 1.
- Level 1 (PUD): Each entry covers 1GB.
- Level 2 (PMD): Each entry covers 2MB (Block Descriptor).
- Level 3 (PTE): Each entry covers 4KB (Page Descriptor) - We won't use this yet.
Identity Mapping¶
To keep things simple, we will use Identity Mapping, meaning Virtual Address = Physical Address.
0x00000000-0x3F000000: Normal Memory (RAM) - Cacheable0x3F000000-0x40000000: Device Memory (Peripherals) - Uncached
Implementation¶
1. Descriptors (include/mmu.h)¶
We define the bits for the table descriptors.
2. Table Setup (kernel/mmu.c)¶
We populate the tables in C.
3. Enabling MMU (boot/mmu.S)¶
We need to write to system registers: - TTBR0_EL1: Point to our PGD table. - TCR_EL1: Configure address size (T0SZ) and granule (4KB). - MAIR_EL1: Define memory attributes (0=Device, 1=Normal). - SCTLR_EL1: Turn on the MMU (M bit) and Caches (C and I bits).
Building and Testing¶
1. Build¶
2. Deploy¶
Copy mmu_demo.img to SD card (rename to kernel8.img).
3. Expected Output¶
You should see a significant speedup in memory operations if you compare cached vs uncached (though this demo just confirms it works).
Troubleshooting¶
- System Hangs: If the MMU config is wrong (e.g., mapping UART as Cacheable, or invalid table pointers), the CPU will crash immediately.
- Triple Fault: If the exception handlers themselves cause an exception (e.g., they are unmapped), the CPU resets.
What's Next?¶
With the MMU active, we have a high-performance foundation. The next major step is Multitasking (Context Switching), where we will use the MMU to isolate processes.