Now, we're officially done with caches. As a review, the storage hierarchy looks like this:
We're going to introduce virtual memory which makes it seem like DRAM is bigger than it is.
DRAM is too expensive, but disk is cheap... we want our program to work even if it requires more DRAM than we bought. We also don't want a program that works on a machine with 2048 MB of DRAM to stop working if we try to run it on a machine with only 512MB of main memory.
Also, many programs run on the same machine. Each of them may require GBs of storage - unrelated programs should not have access to each other's storage.
Finally, it would be nice to be able to enforce different policies on different portions of memory (read-only), etc. It would be nice to have an ability for an application to not access another application's memory.
One early solution is to leave the problem to the programmer. This assumes that the programmer knows the exact configuration of the machine, and the programmer must either make sure that the program fits in memory, or break the program up into pieces that do fit and load each other off the disk when necessary.
This sounds crazy to us, but there are real-world applications that actually use this. The best example is a Playstation 2. You as the programmer know that:
This solution gives a little automation to help the programmer. This builds the application in overlays, and two pieces of code and data may be overlayed if:
In C++, the keyword to control this is union
.
Managing overlays is performed by the compiler - good compilers may determine overlay regions. The compiler adds code to read the required overlay memory off the disk when necessary.
The hardware is simple. However, can we use hardware to have a superior solution?
With virtual memory, you build new hardware and software that automatically translates each memory reference from a virtual address (address in a virtual array of bytes) into a physical address (which the hardware uses to identify where the storage actually resides).
Any time you see the word virtual in computer science and architecture, it means "using a level of indirection".
Virtual memory lets the programmer address a memory array larger than the DRAM available on a particular computer system. Virtual memory enables multiple programs to share the same physical memory with:
This is managed by hardware logic and operating system software. The hardware is there for speed, and software for flexibility and because disk storage is controlled by the operating system. The hardware must be designed to support VM.
First, you treat the main memory like a cache. Misses go to the disk. This takes a long time. How do we minimize this?
The address translation from virtual address to physical address is handled by the Page Table, a new data structure accessed by the OS and HW stored in memory.
Input: virtual address, with virtual page number, and page offset. The page table register points to the first entry in the page table. In virtual memory, you're going to put the physical table in memory itself. Each process will get a separate page table register.
When you index at the virtual page number, this gets translated to a physical address and then you add the page offset to get a physical address.
Now, remember, if you try to access something and it doens't have a valid memory in DRAM, you get a disk address and this tells you where it lives in the hard drive. This drives a page fault, which tells the OS to:
This is not a hardware problem! Take EECS 482 :)
Most operating systems have a hidden partition to support the disk portion of virtual memory.