Module 03 • COSC240

Virtual Memory & Paging Architectures

Examine the hardware and software architecture of virtual memory: address decomposition, Memory Management Unit (MMU) operation, Page Table Entry bitfields, and multi-level hierarchical paging structures.

1. Decoupling Virtual & Physical Memory

The fundamental limitation of Base and Limit dynamic relocation (Module 01) is that each process must still occupy a strictly contiguous block of physical memory. If an application requires 16 MB of RAM, and available memory is fragmented into four separate 4 MB holes, the program cannot run without expensive compaction.

Pioneered in 1962 on the University of Manchester Atlas computer, Virtual Memory via Paging completely breaks the contiguous allocation constraint:

To the executing CPU core, the process appears to inhabit a massive, unbroken, contiguous array of linear addresses ($0 \dots 2^{64}-1$). In reality, the physical frames backing those pages are scattered arbitrarily throughout physical RAM. External fragmentation is completely eliminated.

2. The Mathematical Virtual Address Split

When the CPU emits a virtual memory address $VA$, the hardware Memory Management Unit (MMU) automatically splits the binary address into two distinct components:

Virtual Address (VA) = [ Page Number (p) | Offset (d) ]

Let $S = 2^n$ be the page size in bytes. For an $m$-bit virtual address space:

Bitwise Address Translation Formulas:

$$ p = \lfloor VA / 2^n \rfloor = VA \gg n $$ $$ d = VA \bmod 2^n = VA \ \& \ (2^n - 1) $$ $$ \text{Physical Address (PA)} = (f \times 2^n) + d = (f \ll n) \mid d $$

Where $f = \text{PageTable}[p].\text{FrameNumber}$ is the physical frame retrieved from the Page Table.

Concrete 32-bit Architecture Example

Consider a 32-bit system with standard 4 KB ($2^{12}\text{ bytes}$) pages:

If the CPU references virtual address 0x0000840C:

Virtual Address:  0x0000840C
Binary:           0000 0000 0000 0000 1000 | 0100 0000 1100
                  \______________________/   \____________/
                   Page Number p = 8 (0x8)     Offset d = 0x40C (1036)

The MMU looks up index $8$ in the Page Table. If entry $8$ contains Frame Number $f = 2$ (0x00002), the Physical Address is formed by concatenating $f$ and $d$: $$ \text{PA} = (0\text{x}00002 \ll 12) \mid 0\text{x}40C = 0\text{x}0000240C $$

Interactive Walkthrough: Hardware MMU Paging Translation
Step through how the Memory Management Unit extracts $(p, d)$, queries the Page Table Entry, checks permission flags, and forms the physical memory address.
Step 1: Virtual Address Issued. CPU pipeline issues virtual address 0x000021A4 for an operand read instruction.
Phase: 1/4
VA: 0x000021A4
Page/Offset: p=2, d=0x1A4
Status: Valid (P=1)
PTE STATE:
Synchronized Visual Canvas — MMU Address Bus & Translation
p = 2 d = 1A4 VIRTUAL ADDRESS PAGE TABLE PTE 0: f=5 P=1 PTE 1: f=8 P=1 PTE 2: f=7 P=1 PTE 3: f=0 P=0 f = 7 1A4 PHYSICAL ADDR PAGE FAULT TRAP
MMU Translation: Ready to step
🔍 What Is Happening
CPU issues virtual address 0x000021A4. MMU extracts page number p=2 and offset d=0x1A4.
⚙ Why The System Does This
Address decomposition allows contiguous virtual bytes to map into non-contiguous physical RAM frames.

3. Anatomy of a Page Table Entry (PTE)

The Page Table is not merely an array of frame numbers; each Page Table Entry (PTE) contains critical hardware status and protection bitfields:

Page Frame Number (PFN)
Bits 31–12 (20 bits)
Flags / Unused
Bits 11–9
G
Global
D
Dirty
A
Access
U/S
Privilege
R/W
Read/Write
P
Present
Bit Field Name Hardware Function & Purpose
Present (P / Valid) Bit 0 1 if page is resident in physical RAM. 0 if page is unmapped or on disk; accessing triggers an immediate Page Fault.
Read/Write (R/W) Bit 1 0 = Read-Only (attempting to write triggers a protection fault). 1 = Read-Write. Used for code segment protection.
User/Supervisor (U/S) Bit 2 0 = Kernel mode only (Ring 0). 1 = User space accessible (Ring 3). Prevents user code from touching kernel memory.
Accessed (A / Ref) Bit 5 Set to 1 by the hardware MMU on any read or write. Inspected by page replacement algorithms (such as Clock or LRU aging).
Dirty (D / Modified) Bit 6 Set to 1 by the hardware MMU whenever a write occurs. When evicting the page, the OS knows it must write it back to disk.
Page Frame Number Bits 31–12 The upper physical address bits representing the physical RAM frame holding the page data.

4. Multi-Level Hierarchical Page Tables

While simple single-level paging successfully eliminates external memory fragmentation, it introduces a severe secondary challenge: the scaling crisis of page table memory overhead.

1. The Linear Page Table Scaling Crisis

In a flat (single-level) paging design, the operating system maintains a single monolithic array where every possible virtual page number corresponds to a contiguous slot in physical RAM.

The 32-Bit Linear Table Footprint:

On a 32-bit processor ($2^{32}\text{ bytes} = 4\text{ GB}$ address space) with 4 KB ($2^{12}\text{ bytes}$) pages: $$ \text{Total Virtual Pages} = \frac{2^{32}}{2^{12}} = 2^{20} = 1{,}048{,}576\text{ pages} $$ $$ \text{Page Table Size} = 2^{20}\text{ entries} \times 4\text{ bytes per PTE} = 4\text{ MB per process} $$

If a system runs $100$ concurrent processes, $400\text{ MB}$ of physical RAM is consumed solely by page table metadata. Crucially, each 4 MB table must be stored in strictly contiguous physical memory so the MMU can perform simple array index lookups ($Base + p \times 4$), re-introducing the contiguous allocation problem.

The 64-Bit Mathematical Impossibility:

On modern 64-bit architectures ($2^{64}\text{ bytes}$ address space) with 4 KB pages and 8-byte PTEs: $$ \text{Total Virtual Pages} = \frac{2^{64}}{2^{12}} = 2^{52} \approx 4.5 \times 10^{15}\text{ pages} $$ $$ \text{Page Table Size} = 2^{52}\text{ entries} \times 8\text{ bytes} = 2^{55}\text{ bytes} = 33{,}554{,}432\text{ GB} = 33{,}554\text{ TB} \approx 33\text{ Petabytes!} $$

Allocating a flat page table for a single 64-bit process would require millions of times more RAM than exists on entire enterprise servers.

2. The Principle of Address Space Sparsity

The reason flat linear page tables are so catastrophically wasteful is that real-world programs exhibit extreme address space sparsity.

A typical user application does not populate 4 GB or 16 Exabytes of memory continuously. Instead, its virtual layout consists of three small, isolated clusters:

The vast chasm between the top of the heap and the bottom of the stack—often spanning hundreds of gigabytes or terabytes—is completely empty and unmapped. A flat page table wastes over $99.9\%$ of its entries storing invalid PTEs ($P = 0$) for memory addresses the program never touches.

3. Two-Level Hierarchical Paging (32-Bit Systems)

To eliminate the storage overhead of unmapped address space, modern operating systems page the page table itself. In a two-level hierarchical paging scheme, the monolithic page table is broken into thousands of distinct 4 KB pages, coordinated by a top-level table called the Page Directory.

Address Bit Decomposition (10-10-12 Scheme)

A 32-bit virtual address is partitioned into three discrete fields:

Virtual Address (32b) = [ PDI (10 bits) | PTI (10 bits) | Offset d (12 bits) ]
How Hierarchical Paging Saves Memory

The architectural brilliance of multi-level paging lies in conditional allocation:

Conditional Sub-Tree Pruning:

If a $4\text{ MB}$ region of virtual memory contains no allocated pages, the corresponding Page Directory Entry is marked $\text{Present} = 0$. $$ \text{PDE.Present} = 0 \implies \text{Second-Level Page Table is NOT Allocated in RAM} $$

Consider a minimal 32-bit program requiring only $12\text{ KB}$ of memory (one 4 KB page for code, one for data, one for stack):

Total memory consumed for page tables: $4\text{ KB} + 4\text{ KB} + 4\text{ KB} = \mathbf{12\text{ KB}}$, compared to $4096\text{ KB}$ ($4\text{ MB}$) for a flat table—a $99.7\%$ memory savings!

4. x86-64 4-Level Paging Architecture (IA-32e / Long Mode)

On modern 64-bit x86-64 processors, the hierarchical paging model is extended to four discrete levels. While pointers in x86-64 are 64 bits wide, current processor hardware implements a 48-bit canonical virtual address space (capable of addressing 256 Terabytes).

Canonical Address Sign Extension

In a 48-bit virtual address, bits 47 through 0 define the address space, while bits 63 through 48 must be an identical copy of bit 47 (sign-extension rule):

The 9-9-9-9-12 Bit Decomposition

Because each Page Table Entry in 64-bit mode is 8 bytes wide, a single 4 KB page frame holds exactly $4096 / 8 = 512 = 2^9$ entries. Consequently, every level of the hierarchy indexes exactly 9 bits:

PML4
Bits 47–39 (9b)
512 entries (512 GB each)
PDPT
Bits 38–30 (9b)
512 entries (1 GB each)
PD
Bits 29–21 (9b)
512 entries (2 MB each)
PT
Bits 20–12 (9b)
512 entries (4 KB each)
Offset
Bits 11–0 (12b)
4096 bytes
The Hardware Table Walk Sequence

The CPU control register CR3 stores the physical base address of the active process's root PML4 table. When translating address $VA$, the hardware MMU executes the following sequential steps:

  1. PML4 Lookup: Load entry at physical address $\text{CR3} + (\text{PML4\_Index} \times 8)$. If $P = 0$, raise Page Fault. Extract base address of PDPT.
  2. PDPT Lookup: Load entry at physical address $\text{PDPT\_Base} + (\text{PDPT\_Index} \times 8)$. If $P = 0$, raise Page Fault. Extract base address of PD.
  3. PD Lookup: Load entry at physical address $\text{PD\_Base} + (\text{PD\_Index} \times 8)$. If $P = 0$, raise Page Fault. Extract base address of PT.
  4. PT Lookup: Load entry at physical address $\text{PT\_Base} + (\text{PT\_Index} \times 8)$. If $P = 0$, raise Page Fault. Extract Physical Frame Number ($f$).
  5. Physical Address Assembly: Compute final physical address $\text{PA} = (f \ll 12) \mid \text{Offset}$.

5. Large Pages & Huge Pages (Page Size Extensions)

Traversing four levels of page tables adds significant overhead. For database engines, virtual machine hypervisors (KVM), and scientific simulations with massive memory footprints, standard 4 KB pages cause severe TLB cache thrashing.

Modern processors allow the MMU to terminate the tree walk early by setting the Page Size (PS) bit (bit 7) in intermediate table entries:

2 MB Huge Pages (x86-64)

By setting the PS bit in a Page Directory (PD) entry, the PD entry points directly to a contiguous 2 MB physical frame, completely bypassing the fourth-level Page Table (PT).

Offset expands from 12 bits to 21 bits ($2^{21} = 2\text{ MB}$).
Virtual Address: 9b PML4 + 9b PDPT + 9b PD + 21b Offset.

A single TLB entry now maps 2 MB instead of 4 KB ($512\times$ greater cache coverage).

1 GB Giant Pages (x86-64)

By setting the PS bit in a Page Directory Pointer Table (PDPT) entry, the entry points directly to a contiguous 1 GB physical frame, bypassing both the PD and PT levels.

Offset expands from 12 bits to 30 bits ($2^{30} = 1\text{ GB}$).
Virtual Address: 9b PML4 + 9b PDPT + 30b Offset.

Enables hypervisors to map hundreds of gigabytes of guest physical memory with negligible TLB misses.

6. Modern Scaling: 5-Level Paging (Paging57)

With high-performance cloud servers deploying hundreds of terabytes of physical memory, the 48-bit canonical limit (256 TB virtual space) has become an architectural bottleneck.

Modern processors (Intel Ice Lake and newer, AMD Zen 4) introduce 5-Level Paging (Paging57):

7. The Memory Amplification Penalty & The TLB Imperative

Hierarchical paging brilliantly solves the memory storage scaling crisis, but it introduces a severe hardware performance bottleneck:

The Memory Amplification Penalty:

In a 4-level paging system, fetching a single 8-byte variable from RAM requires: $$ 4 \text{ (Page Table Traversal Reads)} + 1 \text{ (Actual Data Read)} = \mathbf{5 \text{ Memory Access Cycles}} $$

If a physical RAM access takes 50 nanoseconds, a simple memory read would take $250\text{ ns}$—a catastrophic $400\%$ hardware slowdown on every memory instruction.

Without specialized hardware caching, modern multi-level virtual memory would be unacceptably slow. In Module 04, we examine the critical hardware component that restores near-zero-latency translation: the Translation Lookaside Buffer (TLB).