osdev-notes/Physical & Virtual Memory.md
2025-09-25 22:24:58 -04:00

4.5 KiB

Most processes are not permitted to directly access physical memory. Access is mediated transparently through the MMU (Memory Management Unit). Even the kernel's memory access is mediated through the MMU, so that it can account for all the allocated physical memory, and so that it doesn't overwrite its own address space.

Physical Memory

Physical memory on x86 is divided into "Page Frames":

  • Strictly physical.
  • Serves as the backing for a "Page", which is strictly virtual.
  • All of physical memory is separated into a number of page frames.
  • Can be either 4KiB, 2MiB, or 1GiB depending on the "level" of paging. This is a useful abstraction, because pages must be aligned at a multiple of their size - for example, a 2MiB page must be aligned on a 2MiB boundary. In the simplest setup involving 2MiB pages, all of physical memory would be divided into 2MiB page frames for accounting.

Virtual Memory & Pages

32-Bit Paging

32-Bit Paging involves two tables, or two "levels", that are traversed to determine the physical location of a logical address. The first table is the "Page Directory", and each entry in the page directory points to a "Page Table", which contains entries pointing to physical frames. In a sense, each entry in the page table is a page, in that it represents one physical page frame. Both the page directory, and each page table, contains 1024 4-byte (32-bit) entries. Overall, the page directory is 4096KiB, and so is each page table. In 32-bit paging mode, bits 12..=31 of the register CR3 indicate the address of the root page directory.

Each page directory entry looks like this:

31..=12 11..=8 7 6 5 4 3 2 1 0
Bits 31..=12 of address AVL PS=1 AVL A PCD PWT U/S R/W P
If the Page Size bit is set, the entry refers directly to a 4MiB page, instead of a page table.
31..=22 21 20..=13 12 11..=9 8 7 6 5 4 3 2 1 0
Bits 31..=22 of address RSVD Bits 39..=32 of address PAT AVL G PS=0 D A PCD PWT U/S R/W P
If the Page Size bit is set, the entry refers directly to a 4MiB page, instead of a page table.
Here are the keys and their meanings:
  • RSVD: Reserved - Must be set to 0, otherwise, will cause a page fault.
  • P: Present - If this bit is 1, the page is in memory. If this bit is 0, accessing the page will throw a Page Fault.
  • R/W: Read-Write - If this bit is 1, the page is writable. If this bit is 0, the page is read-only, and writing to it will Page Fault.
  • U/S: User/Supervisor - If this bit is 1, the page is accessible by unprivileged code. If this bit is 0, it is only accessible to the kernel or supervisor.
  • PWT: Page Write-Through - If this bit is 1, write-through caching is enabled, and changes to the cache are immediately written to physical memory. If this bit is 0, changes to the cache are only written when the cache is invalidated.
  • PCD: Page Cache Disable - If this bit is set, the page will not be cached.
  • A: Accessed - Set to 1 by the CPU if the Page Directory Entry was read by the CPU, as opposed to the address being obtained from the TLB.
  • D: Dirty - Set to 1 if a page is written to.
  • PS: Page Size - Set to 1 if the entry refers to a 4MiB page, instead of 1,024 4KiB pages stored in the referenced page table.
  • G: Global - If set to 1, the processor will not invalidate the relevant TLB entry if CR3 is modified.
  • AVL: Available - Unused by the CPU, and can be used by the OS. As far as I know, nothing popular uses these bits.

Pages

A page is a virtual, contiguous segment of memory, which is backed by exactly one page frame. A page is defined by its entry in a page table, or page directory, each of which may contain up to 4096 pages.

Address Translation Example

If a process wanted to access the virtual address 0xdeadbeef (a 32-bit virtual address), the MMU would separate the address into three parts. Address: 0xdeadbeef / 0b11011110101011011011111011101111 First 10 bits: 0b1101111010 / 890 - Page Directory Offset (Page Table) Next 10 bits: 0b1011011011 / 731 - Page Table Offset (Page Table Entry) Last 12 bits: 0b111011101111 / 3823 - Offset from start of page So the MMU would search for the 3,823rd byte, of the 731st page, of the 890th page table.