Paul Torrez, Tim Hallner, Kiran Mathrani
12 November 2006
modified by Anu Bhaskar
10 December 2006
Topics
Single Level Page Table
Calling the pmap function with a virtual page number as an argument will return the physical page number associated with it:
pmap(vpn) { return PTABLE[vpn]; }
2-Level Page Table
There is now a hierarchy of two different levels of tables, the first encountered being Level 1 and the second Level 0.
pmap(vpn) { uvpn = vpn / 2^10; lvpn = vpn % 2^10; l0pt = PTABLE[uvpn]; if (l0pt == FAULT) return FAULT; return l0pt[lvpn]; }
Level 1 Level 0
For example, if the virtual address = 0x00002003 = 0 * 2^22 + 2 * 2^12 + 3, then
offset = 3
uvpn = 0
lvpn = 2
Assuming we only have a small program running that only uses one physical page number (49):
To implement this scenario with a 2-level page table we would need only one Level 1 page table and one Level 0 page table. Because each table takes 4 KB to store, our entire page table takes only 8 KB to store versus 4 MB in the Single Level case. 2-Level page tables save space in a sparse address space. x86 machines use a 2-Level page table.
On a context switch, the kernel loads a new pmap function:
pmap(va)
can give different results depending on:Either return physical address or FAULT
<code> if (access_type == write) return fault; else return pa; </code> * Kernel-only mapping <code> if (cpl == user) //Remember Kernel must handle the context switch to preserve isolation return fault; else return pa; </code>
On a fault, the processor causes a trap, the kernel gets control, and the kernel runs the pfault function.
pfault(va, cpl, atype) { // page fault handler - either: install a mapping and restart process at faulting instruction - or: kill the process (segmentation fault) }
Problems solved by virtual memory
swapmap(proc, va) { - either: return disk address - or: return FAIL }
pfault(va, cpl, atype) { if (swapmap(current, va) != FAIL) { <process, va'> = removal_policy(); // process = process to steal page from, va' = which page to steal pa = process->pmap(va'); write page pa to disk @ swapmap(process, va'); set process->pmap(va') to FAULT; read disk @ swapmap(current, va) into page pa); set current->pmap(va) to pa; return; } else kill; }
Let's see how this process works.
If we didn't, than we would be infinitely creating more and more pages as more applications are run...
What would this result in?
Goal: Remove a page that won't be used and avoid "thrashing" - a high portion of accesses require a swap (because it's slow)
Note: If all memory accesses are uniformly random there is no good answer to the removal policy. We rely on Locality of Reference
FIFO | 1 | 2 | 3 | 4 | 1 | 2 | 5 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
P1 | 1 | 1 | 1 | 4 | 4 | 4 | 5 | 5 | 5 | 5 | 5 | 5 |
P2 | 2 | 2 | 2 | 1 | 1 | 1 | 1 | 1 | 3 | 3 | 3 | |
P3 | 3 | 3 | 3 | 2 | 2 | 2 | 2 | 2 | 4 | 4 |
Belady's | 1 | 2 | 3 | 4 | 1 | 2 | 5 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
P1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 3 | 3 | 3 |
P2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 4 | 4 | |
P3 | 3 | 4 | 4 | 4 | 5 | 5 | 5 | 5 | 5 | 5 |
LRU | 1 | 2 | 3 | 4 | 1 | 2 | 5 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
P1 | 1 | 1 | 1 | 4 | 4 | 4 | 5 | 5 | 5 | 3 | 3 | 3 |
P2 | 2 | 2 | 2 | 1 | 1 | 1 | 1 | 1 | 1 | 4 | 4 | |
P3 | 3 | 3 | 3 | 2 | 2 | 2 | 2 | 2 | 5 | 5 |
FIFO | 1 | 2 | 3 | 4 | 1 | 2 | 5 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
P1 | 1 | 1 | 1 | 1 | 1 | 1 | 5 | 5 | 5 | 5 | 4 | 4 |
P2 | 2 | 2 | 2 | 2 | 2 | 2 | 1 | 1 | 1 | 1 | 5 | |
P3 | 3 | 3 | 3 | 3 | 3 | 3 | 2 | 2 | 2 | 2 | ||
P4 | 4 | 4 | 4 | 4 | 4 | 4 | 3 | 3 | 3 |
LRU and Belady's Optimal don't suffer from Belady's Annomally Stack Algorithms never suffer from Belady's annomally
Optimizations Page hasn't changed so there is no need to swap and Demand Paging