An interesting paper (via Muli Ben-Yehuda) that describes, in particular, VM organization of several platforms. A bit I didn't knew: ULTRIX uses two level page tables that are traversed bottom-up: leaf level of the tree lives in the virtual space and is contiguous in it. As a result, to handle TLB miss at the virtual address A it's enough to do:
ULTRIX page-fault handler. V0
phys_address = LEAF_TABLE[A >> PTABLE_SHIFT_LEAF];
Obviously it is somewhat more involved in reality, because appropriate portion of LEAF_TABLE[]
can be not in the TLB itself. In the latter case, root node of the tree is consulted:
ULTRIX page-fault handler. V1
if (tlb_miss(LEAF_TABLE + (A >> PTABLE_SHIFT_LEAF))
tlb_load(ROOT_NODE[A >> PTABLE_SHIFT_ROOT],
LEAF_TABLE + (A >> PTABLE_SHIFT_LEAF));
phys_address = LEAF_TABLE[A >> PTABLE_SHIFT_LEAF];
Root node is wired down into unmapped (physical) memory.
This design provides following advantages:
TLB miss handling requires one memory access in the best case, and two in the worst. In top-to-bottom page tables a la Intel, two (or three) accesses are necessary for every TLB refill;
This integrates nicely with virtually indexed processor caches;
This allows parts of page tables to be paged out easily.
Unfortunately Digital screwed this design by using slow software filled TLB.