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:
31 12 11 0
+-------------------+-----------+
| Page Number | Offset |
+-------------------+-----------+
Virtual Address
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
.
- Extracts and returns the page offset in virtual address
- Function:
uintptr_t pg_no (const void *va)
- Extracts and returns the page number in virtual address
va
.
- Extracts and returns the page number in virtual address
- Function: v
oid *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.
- Returns the start of the virtual page that
- Function:
void *pg_round_up (const void *va)
- Returns
va
rounded up to the nearest page boundary.
- Returns
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 of0x10000000
from0x80000000
to0xf0000000
. - 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.
- Returns true if
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 address0x1234
, 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.