OSTEP Chapter 19
Remember that the
Problem with virtual address translatation: extra memory references are needed to access translation tables, and these memory references can slow programs down by a factor of two or three. There are too many entries in typical page tables to keep them all loaded registers so they need to reside im memory (RAM).
We will introduce the fundamental concept of locality: at any given time a process is only using a few pages or segments.
Solution: Translation Lookaside Buffer (TLB). A translation buffer is used to store a few of the translation table entries. It is very fast, but only remembers a small number of entries. On each memory reference:
TLB Organization: Show picture of black box. Virtual page number goes in, physical page location comes out. Similar to a cache, usually direct mapped.
TLB is just a memory with some comparators. Typical size of memory: 128 entries. Each entry holds a virtual page number and the corresponding physical page number. How can memory be organized to find an entry quickly?
Disadvantage of TLB scheme: if two pages use the same entry of the memory, only one of them can be remembered at once. If process is referencing both pages at same time, TLB does not work very well.
Example: TLB with 64 (100 octal) slots. Suppose the following virtual pages are referenced (octal): 621, 2145, 621, 2145, ... 321, 2145, 321, 621.
TLBs are a lot like hash tables except simpler (must be to be implemented in hardware). Some hash functions are better than others.
Another approach: let any given virtual page use either of two slots in the TLB. Make memory wider, use two comparators to check both slots at once.
Must be careful to flush TLB during each context swap. Why?
In practice, TLB's have been extremely successful with 95% or great hit rates for relatively small sizes.
A solution (used on the IBM Power, Sun SPARC, and others) to this problem has two parts:
With an inverted page table, most address translations are handled by the TLB. When there is a miss in the TLB, the operating is notified (via an interrupt) and TLB miss-handler is invoked.
The general is a technique that is sometimes called a shadow table. The idea of a shadow is simple (and familiar to Fortran programmers!):
For example, consider the hardware defined page table to be an array of structures:
struct Page_Entry { unsigned PageFrame_hi : 10; // 42-bit page frame number unsigned PageFrame_mid : 16; unsigned PageFrame_low : 16; unsigned UserRead : 1; unsigned UserWrite : 1; unsigned KernelRead : 1; unsigned KernelWrite : 1; unsigned Reference : 1; unsigned Dirty : 1; unsigned Valid : 1; } struct Page_Entry pageTable[TABLESIZE];If you wanted to added a couple of data members, you cannot simply change it to the following:
struct Page_Entry { unsigned PageFrame_hi : 10; unsigned PageFrame_mid : 16; unsigned PageFrame_low : 16; unsigned UserRead : 1; unsigned UserWrite : 1; unsigned KernelRead : 1; unsigned KernelWrite : 1; unsigned Reference : 1; unsigned Dirty : 1; unsigned Valid : 1; Time_t lastRefTime; PageList *shared; }Instead, you would define a a second array based on this type:
struct Page_Entry { struct PE_Shadow { unsigned PageFrame_hi : 10; Time_t lastRefTime; unsigned PageFrame_mid : 16; PageList *shared; unsigned PageFrame_low : 16; } unsigned UserRead : 1; unsigned UserWrite : 1; unsigned KernelRead : 1; unsigned KernelWrite : 1; unsigned Reference : 1; unsigned Dirty : 1; unsigned Valid : 1; } struct Page_Entry pageTable[TABLESIZE]; struct PE_Shadow pageShadow[TABLESIZE];