Computer Architecture Cheatsheet
Virtual Memory
Use this Computer Architecture reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Purpose of Virtual Memory
Virtual memory provides each process with its own private, contiguous address space, independent of physical DRAM layout. It enables:
- Protection — processes cannot read/write each other's memory
- Isolation — a crash in one process doesn't corrupt others
- Abstraction — programs can be larger than physical RAM (demand paging)
- Sharing — pages can be mapped read-only into multiple processes (shared libraries)
- Simplified linking — programs can assume fixed load addresses
Address Translation
Every memory access uses a virtual address (VA). The MMU translates it to a physical address (PA):
Virtual Address Page Table Physical Address
[ VPN | page offset ] ──────────────► [ PPN | page offset ]
(MMU)- VPN = Virtual Page Number
- PPN (or PFN) = Physical Page Number / Frame Number
- Page offset = unchanged; same in VA and PA
- Page size = 2^(offset bits). Common: 4 KB (12-bit offset), 2 MB, 1 GB (huge pages)
Address Space Example (x86-64, 4 KB pages)
64-bit VA: [ 16 sign-ext | 9 PML4 | 9 PDP | 9 PD | 9 PT | 12 offset ]
- 4-level page table on x86-64 (PML4 → PDPT → PD → PT → page) → 48-bit VA
- Bits 63:48 must equal bit 47 (canonical addresses — sign-extended); non-canonical access faults (#GP)
- 5-level paging (LA57): adds a PML5 level → 57-bit VA (128 PiB); shipping on Ice Lake+ servers, enabled per boot
- Each table has 2⁹ = 512 entries × 8 bytes = 4 KB per table
- ARM uses a similar structure (PGD → PUD → PMD → PTE)
Page Table Entry (PTE) Fields (x86-64)
| Bit(s) | Field | Meaning |
|---|---|---|
| 0 | Present (P) | 1 = page in physical memory |
| 1 | R/W | 0 = read-only, 1 = read/write |
| 2 | U/S | 0 = supervisor only, 1 = user accessible |
| 3 | Write-through | Cache write policy |
| 4 | Cache disable | Bypass cache (MMIO) |
| 5 | Accessed (A) | Set by hardware on any access |
| 6 | Dirty (D) | Set by hardware on write |
| 7 | PAT / Page size | If set at PD level → 2 MB huge page |
| 11:8 | Available | OS use |
| 51:12 | PPN | Physical page frame number |
| 62:59 | Protection key | 4-bit key (PKU/PKS), permission checked against PKRU |
| 63 | NX / XD | No-execute (prevents code execution) |
Page Fault Types
| Type | Cause | OS action |
|---|---|---|
| Demand page fault | Page not loaded yet (P=0) | Load page from disk, update PTE |
| Protection fault | Write to read-only page, or user access to kernel | SIGSEGV / segmentation fault |
| Copy-on-Write (CoW) | Write to shared read-only copy after fork() | Duplicate page, mark both writable |
| Minor fault | Page not mapped, but in page cache | Map the existing physical page |
| Major fault | Page must be read from disk | I/O required; high latency |
TLB (Translation Lookaside Buffer)
The page table walk is expensive (3–5 memory accesses for a 4-level table). The TLB is a small cache of recent VA→PA translations — L1 TLBs are fully or highly associative; larger L2 TLBs are set-associative (4–8-way) on modern cores.
TLB hit: ~1 cycle extra latency (parallel with cache lookup) TLB miss: ~20–50+ cycles (hardware page-table walk, PTW)
Typical TLB Parameters
| Level | Entries | Hit latency | Notes |
|---|---|---|---|
| L1 ITLB | 64–128 | 0–1 cycles | Instruction-only |
| L1 DTLB | 32–64 | 0–1 cycles | Data-only |
| L2 Unified TLB | 512–2048 | 5–10 cycles | Combined |
| Page-Walk Cache | — | — | Caches intermediate page-table entries |
TLB Shootdown
When the OS modifies a PTE (e.g., unmaps a page), it must invalidate any TLB entry holding that VA across all cores using that address space:
- OS modifies PTE
- OS sends IPI (Inter-Processor Interrupt) to other cores
- Each core executes
INVLPG <va>(x86) orTLBI(ARM) - Originating core waits for acknowledgements
- Flushing continues
TLB shootdowns are expensive — minimize mappings changes (mmap/munmap) in hot paths.
Page Replacement Policies
When a page fault occurs and physical memory is full, the OS must evict a page:
| Algorithm | Description | Optimal? | Notes |
|---|---|---|---|
| Optimal (OPT) | Evict the page not needed for longest future time | Yes | Theoretical; not implementable |
| LRU | Evict least recently used | Near-optimal | Expensive to implement exactly |
| Clock (second chance) | Circular list; evict first page with A=0 | — | Classic UNIX/Mach; PostgreSQL's buffer pool (clock-sweep) |
| LRU-K | Use Kth most recent access | — | More scan-resistant; LRU-2 used in SQL Server's buffer manager |
| NRU (Not Recently Used) | Combine A and D bits into 4 classes | — | Cheap; approximate LRU |
Linux does not use classic clock — it approximates LRU with two lists (active/inactive) per memory cgroup, promoting/demoting pages between them (multi-gen LRU since 6.1).
NRU Classes
| Class | Accessed | Dirty | Preference to evict |
|---|---|---|---|
| 0 | 0 | 0 | First (best) |
| 1 | 0 | 1 | Second |
| 2 | 1 | 0 | Third |
| 3 | 1 | 1 | Last (worst) |
Huge Pages
| Size | x86-64 | ARM | Benefit |
|---|---|---|---|
| 4 KB | Standard | Standard | Fine-grained control |
| 2 MB | Large page (PD entry) | 2 MB block | Fewer TLB entries for same range |
| 1 GB | Huge page (PDP entry) | 1 GB block | Minimal TLB pressure |
Linux: Transparent Huge Pages (THP) automatically promotes 4 KB pages to 2 MB when contiguous. hugetlbfs for explicit huge-page allocation.
Memory Protection
| Mechanism | Description |
|---|---|
| Read/Write/Execute bits | Per-page permissions in PTE |
| Supervisor bit | Kernel vs user access control |
| NX bit (no-execute) | Prevents executing data pages (defeats shellcode) |
| SMEP / SMAP | Supervisor cannot execute/access user pages (x86) |
| ASLR | Randomize base addresses of stack, heap, libraries |
| PIE (Position Independent Executable) | Text relocatable; ASLR can randomize code |
Segmentation (legacy)
x86 originally used segments (base + limit per logical address region) before paging. Modern x86-64 uses flat segmentation (all segments base=0, limit=2⁶⁴) — paging is the real protection mechanism. Segments still exist for fs and gs as thread-local storage pointers.
Copy-on-Write (CoW) in fork()
Parent calls fork(): - Child gets a copy of parent's page table - All pages marked read-only in both parent and child - Physical pages are shared First write by either process: - Protection fault - OS allocates new page, copies content - Updates faulting process's PTE to new page, marks R/W - Other process still references original (now also R/W)
CoW makes fork() + exec() extremely cheap — only modified pages are actually copied.