Virtual Addresses
A 32-bit virtual address can be divided into a 20-bit page number and a 12-bit page offset (or just offset), like this:
Macros and Functions
Work with Virtual Addresses
Header threads/vaddr.h
defines these functions and macros for working with virtual addresses:
Macro: PGSHIFT
Macro: PGBITS
The bit index (0) and number of bits (12) of the offset part of a virtual address, respectively.
Macro: PGMASK
A bit mask with the bits in the page offset set to 1, the rest set to 0 (0xfff).
Macro: PGSIZE
The page size in bytes (4,096).
Function: unsigned pg_ofs (const void *va)
Extracts and returns the page offset in virtual address va.
Function: uintptr_t pg_no (const void *va)
Extracts and returns the page number in virtual address va.
Function: void *pg_round_down (const void *va)
Returns the start of the virtual page that va points within, that is, va with the page offset set to 0.
Function: void *pg_round_up (const void *va)
Returns va rounded up to the nearest page boundary.
Work with User/Kernel Virtual Memory Boundary
Virtual memory in Pintos is divided into two regions: user virtual memory and kernel virtual memory. The boundary between them is PHYS_BASE
:
Macro: PHYS_BASE
Base address of kernel virtual memory.
It defaults to 0xc0000000 (3 GB), but it may be changed to any multiple of 0x10000000 from 0x80000000 to 0xf0000000.
User virtual memory ranges from virtual address 0 up to
PHYS_BASE
. Kernel virtual memory occupies the rest of the virtual address space, fromPHYS_BASE
up to 4 GB.
Function: bool is_user_vaddr (const void *va)
Function: bool is_kernel_vaddr (const void *va)
Returns true if va is a user or kernel virtual address, respectively, false otherwise.
Work with Mapping Kernel VM One-to-One to PM
The 80x86 doesn't provide any way to directly access memory given a physical address. This ability is often necessary in an operating system kernel, so Pintos works around it by mapping kernel virtual memory one-to-one to physical memory.
That is, virtual address
PHYS_BASE
accesses physical address 0, virtual addressPHYS_BASE
+ 0x1234 accesses physical address 0x1234, and so on up to the size of the machine's physical memory.Thus, adding
PHYS_BASE
to a physical address obtains a kernel virtual address that accesses that address; conversely, subtractingPHYS_BASE
from a kernel virtual address obtains the corresponding physical address.
Header threads/vaddr.h
provides a pair of functions to do these translations:
Function: void *ptov (uintptr_t pa)
Returns the kernel virtual address corresponding to physical address pa, which should be between 0 and the number of bytes of physical memory.
Function: uintptr_t vtop (void *va)
Returns the physical address corresponding to va, which must be a kernel virtual address.
Last updated