Virtual Memory

• translation lookaside buffer (TLB)

• cache

• context switch

• discussion about where to go with the course

translation lookaside buffer (TLB)

• process of looking up virtual-to-physical address translation is called table walking

• table walking done by MMU hardware

• may take up to 4 memory reads (plus the actual access) for each virtual memory access

• locality makes caching worthwhile

• cache for virtual-to-physical translations is called translation lookaside buffer (TLB)

TLB implementation

• TLB is a table:

– entries are physical addresses of pages – indices are concatenation of context and

virtual page number

– associative memory takes index and returns entry (if any)

• page descriptors fetched by table walking are stored into TLB, displacing another entry (LRU?)

• TLB “hits” require a single memory access per virtual memory access

• TLB “misses” require 5 memory accesses per virtual memory access (with 4KB pages)

Memory Cache

• slow memory is cheaper than fast memory

• can you get the benefits of fast memory without paying much more than for slow memory?

• yes: have a large, slow main memory and a small, fast cache

• keep frequently-accessed instructions and data in the cache

• problem: frequently-accessed instructions and data change over time

Cache Behavior

• cache sits between CPU and memory

• on a read, if cache has virtual memory location, delivers contents

• on a write:

– if cache has location, store contents and write them back to memory:

∗ immediately (write-through cache)

∗ when the location is ejected from the

cache (write-back cache)

– if cache does not have virtual memory location:

∗ write goes directly to memory, or ∗ memory location is fetched, and new

value is written, then either write-through or write-back

Cache Organization

• data is cached by lines

• depending on system, line can be anywhere between 4(?) and 128 bytes

• bytes within a line belong to adjacent memory locations, and are loaded and ejected together

• bytes within a line are addressed by less significant bits of virtual address

• lines are identified by next more significant bits of virtual address

• each line has a tag, which includes:

– context number,

– the most significant bits of the virtual address

– access permission bits

Cache Access

• virtual address provided simultaneously to MMU and cache

• cache compares tag of matching line number

• if tag matches, data is returned (read) or accepted (write)

• if tag doesn’t match, we have a cache miss and MMU completes memory access:

– on read, cache ejects old line (writing back if modified and write-back cache) and stores new one when memory provides it

– on write, cache may or may not load new line, ejecting old (possibly writing back old line)

• all reads/writes to main memory are in for whole lines

context switch

• we may decide to switch contexts, i.e. stop executing code for one process/thread and start executing code for another

• must:

– save all thread-specific information on stack

– save the stack pointer so we can later restart the thread

– get stack pointer for the suspended thread – pop thread information from new stack

• in user mode: thread switch

• in supervisory mode: process switch (must change context register in MMU)

• assembly only (impossible in C)

context switch implementation

• save stack pointer

• save program counter (return address from call to this subroutine)

• save global floating point and flags registers • save all the register windows: save until all

register windows are on the stack

• do enough restore so window will underflow on next restore

• if switching processes, change MMU context (supervisory only)

• reload floating point, global registers, PC, SP • restore to load topmost register window • return to reloaded PC

homework

• due Friday, Nov 20th

• write a thread creation routine,

int create(void f(), char * stack):

create takes a function pointer and an area of memory to be used for the stack and returns a stack pointer for the new thread

• write a thread switch routine,

void ctswitch(int new)

• test using the following program

            main.c
#include <unistd.h>
extern int create(void f(), char * stack);
extern void ctswitch();
int t1, t2 = 0;
void f1 () {
  while (1) {
    printf ("thread 1\n"); sleep (1);
    ctswitch (t2); } }
void f2 () {
  while (1) {
    printf ("thread 2\n"); sleep (1);
    ctswitch (t1); } }
main () {
  char stack1 [10000], stack2 [10000];
  t1 = create (f1, stack1);
  t2 = create (f2, stack2);
  ctswitch (t1); }

Preview of the rest of the course

• at end of book

• what next?

• suggestion: compilers – parsing (lex, yacc)

– semantic analysis

– code generation

• other suggestions? (please come to class prepared)