NAME
pmap
—
machine dependent interface to the
MMU
SYNOPSIS
#include
<machine/pmap.h>
DESCRIPTION
The architecture-dependent pmap
module
describes how the physical mapping is done between the user-processes and
kernel virtual addresses and the physical addresses of the main memory,
providing machine-dependent translation and access tables that are used
directly or indirectly by the memory-management hardware. The
pmap
layer can be viewed as a big array of mapping
entries that are indexed by virtual address to produce a physical address
and flags. These flags describe the page's protection, whether the page has
been referenced or modified and other characteristics.
The pmap
interface is consistent across
all platforms and hides the way page mappings are stored.
INITIALIZATION
void
pmap_init
(void);
The
pmap_init
()
function is called from the machine-independent
uvm(9) initialization code, when the MMU is enabled.
PAGE MANAGEMENT
Modified/referenced information is only tracked for pages managed
by uvm(9) (pages for which a vm_page structure exists). Only managed
mappings of those pages have modified/referenced tracking. The use of
unmanaged mappings should be limited to code which may execute in interrupt
context (such as
malloc(9)) or to enter mappings for physical addresses which are not
managed by uvm(9). This allows pmap
modules to avoid
blocking interrupts when manipulating data structures or holding locks.
Unmanaged mappings may only be entered into the kernel's virtual address
space. The modified/referenced bits must be tracked on a per-page basis, as
they are not attributes of a mapping, but attributes of a page. Therefore,
even after all mappings for a given page have been removed, the
modified/referenced bits for that page must be preserved. The only time the
modified/referenced bits may be cleared is when
uvm(9) explicitly calls the
pmap_clear_modify
()
and
pmap_clear_reference
()
functions. These functions must also change any internal state necessary to
detect the page being modified or referenced again after the
modified/referenced state is cleared.
Mappings entered by
pmap_enter
()
are managed, mappings entered by pmap_kenter_pa
()
are not.
MAPPING ALLOCATION
int
pmap_enter
(pmap_t
pmap, vaddr_t va,
paddr_t pa,
vm_prot_t prot,
int flags);
void
pmap_kenter_pa
(vaddr_t
va, paddr_t pa,
vm_prot_t prot);
void
pmap_remove
(pmap_t
pmap, vaddr_t sva,
vaddr_t eva);
void
pmap_kremove
(vaddr_t
va, vsize_t
size);
The
pmap_enter
()
function creates a managed mapping for physical page
pa at the specified virtual address
va in the target physical map
pmap with protection specified by
prot:
- PROT_READ
- The mapping must allow reading.
- PROT_WRITE
- The mapping must allow writing.
- PROT_EXEC
- The page mapped contains instructions that will be executed by the processor.
The flags argument contains protection bits (the same bits used in the prot argument) indicating the type of access that caused the mapping to be created. This information may be used to seed modified/referenced information for the page being mapped, possibly avoiding redundant faults on platforms that track modified/referenced information in software. Other information provided by flags:
- PMAP_WIRED
- The mapping being created is a wired mapping.
- PMAP_CANFAIL
- The call to
pmap_enter
() is allowed to fail. If this flag is not set, and thepmap_enter
() call is unable to create the mapping, perhaps due to insufficient resources, thepmap
module must panic.
The access type provided in the flags argument will never exceed the protection specified by prot.
The
pmap_enter
()
function is called by the fault routine to establish a mapping for the page
being faulted in. If pmap_enter
() is called to enter
a mapping at a virtual address for which a mapping already exists, the
previous mapping must be invalidated. pmap_enter
()
is sometimes called to change the protection for a pre-existing mapping, or
to change the “wired” attribute for a pre-existing
mapping.
The
pmap_kenter_pa
()
function creates an unmanaged mapping of physical address
pa at the specified virtual address
va with the protection specified by
prot.
The
pmap_remove
()
function removes the range of virtual addresses sva to
eva from pmap, assuming proper
alignment. pmap_remove
() is called during an unmap
operation to remove low-level machine dependent mappings.
The
pmap_kremove
()
function removes an unmanaged mapping at virtual address
va of size size.
A call to
pmap_update
()
must be made after pmap_kenter_pa
() or
pmap_kremove
() to notify the
pmap
layer that the mappings need to be made
correct.
ACCESS PROTECTION
void
pmap_unwire
(pmap_t
pmap, vaddr_t
va);
void
pmap_protect
(pmap_t
pmap, vaddr_t sva,
vaddr_t eva,
vm_prot_t prot);
void
pmap_page_protect
(struct
vm_page *pg, vm_prot_t
prot);
The
pmap_unwire
()
function clears the wired attribute for a map/virtual-address pair. The
mapping must already exist in pmap.
The
pmap_protect
()
function sets the physical protection on range sva to
eva, in pmap.
The
pmap_protect
()
function is called during a copy-on-write operation to write protect
copy-on-write memory, and when paging out a page to remove all mappings of a
page. The
pmap_page_protect
()
function sets the permission for all mapping to page
pg. The pmap_page_protect
()
function is called before a pageout operation to ensure that all pmap
references to a page are removed.
PHYSICAL PAGE-USAGE INFORMATION
boolean_t
pmap_is_modified
(struct
vm_page *pg);
boolean_t
pmap_clear_modify
(struct
vm_page *pg);
boolean_t
pmap_is_referenced
(struct
vm_page *pg);
boolean_t
pmap_clear_reference
(struct
vm_page *pg);
The
pmap_is_modified
()
and
pmap_clear_modify
()
functions read/set the modify bits on the specified physical page
pg. The pmap_is_referenced
()
and pmap_clear_reference
() functions read/set the
reference bits on the specified physical page pg.
The
pmap_is_referenced
()
and pmap_is_modified
() functions are called by the
pagedaemon when looking for pages to free. The
pmap_clear_referenced
()
and pmap_clear_modify
() functions are called by the
pagedaemon to help identification of pages that are no longer in demand.
PHYSICAL PAGE INITIALIZATION
void
pmap_copy_page
(struct
vm_page *src, struct
vm_page *dst);
void
pmap_zero_page
(struct
vm_page *page);
The
pmap_copy_page
()
function copies the content of the physical page src
to physical page dst.
The
pmap_zero_page
()
function fills page with zeroes.
INTERNAL DATA STRUCTURE MANAGEMENT
pmap_t
pmap_create
(void);
void
pmap_reference
(pmap_t
pmap);
void
pmap_destroy
(pmap_t
pmap);
The
pmap_create
()
function creates an instance of the pmap structure.
The
pmap_reference
()
function increments the reference count on pmap.
The
pmap_destroy
()
function decrements the reference count on physical map
pmap and retires it from service if the count drops to
zero, assuming it contains no valid mappings.
OPTIONAL FUNCTIONS
vaddr_t
pmap_steal_memory
(vsize_t
size, vaddr_t
*vstartp, vaddr_t
*vendp);
vaddr_t
pmap_growkernel
(vaddr_t
maxkvaddr);
void
pmap_update
(pmap_t
pmap);
void
pmap_collect
(pmap_t
pmap);
void
pmap_virtual_space
(vaddr_t
*vstartp, vaddr_t
*vendp);
void
pmap_copy
(pmap_t
dst_pmap, pmap_t
src_pmap, vaddr_t
dst_addr, vsize_t
len, vaddr_t
src_addr);
Wired memory allocation before the virtual
memory system is bootstrapped is accomplished by the
pmap_steal_memory
()
function. After that point, the kernel memory allocation routines should be
used.
The
pmap_growkernel
()
function can preallocate kernel page tables to a specified virtual
address.
The
pmap_update
()
function notifies the pmap
module to force
processing of all delayed actions for all pmaps.
The
pmap_collect
()
function informs the pmap
module that the given
pmap is not expected to be used for some time, giving the
pmap
module a chance to prioritize. The initial
bounds of the kernel virtual address space are returned by
pmap_virtual_space
().
The
pmap_copy
()
function copies the range specified by src_addr and
src_len from src_pmap to the
range described by dst_addr and
dst_len in dst_map.
pmap_copy
() is called during a
fork(2) operation to give the child process an initial set of
low-level mappings.
SEE ALSO
HISTORY
The 4.4BSD pmap
module is based on Mach 3.0. The introduction of
uvm(9) left the pmap
interface unchanged for
the most part.
BUGS
Ifdefs must be documented.
pmap_update
() should be mandatory.