1057 lines
31 KiB
Groff
1057 lines
31 KiB
Groff
.\" $NetBSD: pmap.9,v 1.12 2002/02/13 08:18:48 ross Exp $
|
|
.\"
|
|
.\" Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
|
|
.\" All rights reserved.
|
|
.\"
|
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
|
.\" by Jason R. Thorpe.
|
|
.\"
|
|
.\" Redistribution and use in source and binary forms, with or without
|
|
.\" modification, are permitted provided that the following conditions
|
|
.\" are met:
|
|
.\" 1. Redistributions of source code must retain the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer.
|
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer in the
|
|
.\" documentation and/or other materials provided with the distribution.
|
|
.\" 3. All advertising materials mentioning features or use of this software
|
|
.\" must display the following acknowledgement:
|
|
.\" This product includes software developed by the NetBSD
|
|
.\" Foundation, Inc. and its contributors.
|
|
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
|
.\" contributors may be used to endorse or promote products derived
|
|
.\" from this software without specific prior written permission.
|
|
.\"
|
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
|
.\"
|
|
.Dd April 16, 2001
|
|
.Dt PMAP 9
|
|
.Os
|
|
.Sh NAME
|
|
.Nm pmap
|
|
.Nd machine-dependent portion of the virtual memory system
|
|
.Sh SYNOPSIS
|
|
.Fd #include \*[Lt]sys/param.h\*[Gt]
|
|
.Fd #include \*[Lt]uvm/uvm_extern.h\*[Gt]
|
|
.Ft void
|
|
.Fn "pmap_init" "void"
|
|
.Ft void
|
|
.Fn "pmap_virtual_space" "vaddr_t *vstartp" "vaddr_t *vendp"
|
|
.Ft vaddr_t
|
|
.Fn "pmap_steal_memory" "vsize_t size" "vaddr_t *vstartp" "vaddr_t *vendp"
|
|
.Ft pmap_t
|
|
.Fn "pmap_kernel" "void"
|
|
.Ft pmap_t
|
|
.Fn "pmap_create" "void"
|
|
.Ft void
|
|
.Fn "pmap_destroy" "pmap_t pmap"
|
|
.Ft void
|
|
.Fn "pmap_reference" "pmap_t pmap"
|
|
.Ft void
|
|
.Fn "pmap_fork" "pmap_t src_map" "pmap_t dst_map"
|
|
.Ft long
|
|
.Fn "pmap_resident_count" "pmap_t pmap"
|
|
.Ft long
|
|
.Fn "pmap_wired_count" "pmap_t pmap"
|
|
.Ft vaddr_t
|
|
.Fn "pmap_growkernel" "vaddr_t maxkvaddr"
|
|
.Ft int
|
|
.Fn "pmap_enter" "pmap_t pmap" "vaddr_t va" "paddr_t pa" "vm_prot_t prot" \
|
|
"int flags"
|
|
.Ft void
|
|
.Fn "pmap_remove" "pmap_t pmap" "vaddr_t sva" "vaddr_t eva"
|
|
.Ft void
|
|
.Fn "pmap_protect" "pmap_t pmap" "vaddr_t sva" "vaddr_t eva" "vm_prot_t prot"
|
|
.Ft void
|
|
.Fn "pmap_unwire" "pmap_t pmap" "vaddr_t va"
|
|
.Ft boolean_t
|
|
.Fn "pmap_extract" "pmap_t pmap" "vaddr_t va" "paddr_t *pap"
|
|
.Ft void
|
|
.Fn "pmap_kenter_pa" "vaddr_t va" "paddr_t pa" "vm_prot_t prot"
|
|
.Ft void
|
|
.Fn "pmap_kremove" "vaddr_t va" "vsize_t size"
|
|
.Ft void
|
|
.Fn "pmap_copy" "pmap_t dst_map" "pmap_t src_map" "vaddr_t dst_addr" \
|
|
"vsize_t len" "vaddr_t src_addr"
|
|
.Ft void
|
|
.Fn "pmap_collect" "pmap_t pmap"
|
|
.Ft void
|
|
.Fn "pmap_update" "pmap_t pmap"
|
|
.Ft void
|
|
.Fn "pmap_activate" "struct proc *p"
|
|
.Ft void
|
|
.Fn "pmap_deactivate" "struct proc *p"
|
|
.Ft void
|
|
.Fn "pmap_zero_page" "paddr_t pa"
|
|
.Ft void
|
|
.Fn "pmap_copy_page" "paddr_t src" "paddr_t dst"
|
|
.Ft void
|
|
.Fn "pmap_page_protect" "struct vm_page *pg" "vm_prot_t prot"
|
|
.Ft boolean_t
|
|
.Fn "pmap_clear_modify" "struct vm_page *pg"
|
|
.Ft boolean_t
|
|
.Fn "pmap_clear_reference" "struct vm_page *pg"
|
|
.Ft boolean_t
|
|
.Fn "pmap_is_modified" "struct vm_page *pg"
|
|
.Ft boolean_t
|
|
.Fn "pmap_is_referenced" "struct vm_page *pg"
|
|
.Ft paddr_t
|
|
.Fn "pmap_phys_address" "int cookie"
|
|
.Ft vaddr_t
|
|
.Fn "PMAP_MAP_POOLPAGE" "paddr_t pa"
|
|
.Ft paddr_t
|
|
.Fn "PMAP_UNMAP_POOLPAGE" "vaddr_t va"
|
|
.Sh DESCRIPTION
|
|
The
|
|
.Nm
|
|
module is the machine-dependent portion of the
|
|
.Nx
|
|
virtual memory system
|
|
.Xr uvm 9 .
|
|
The purpose of the
|
|
.Nm
|
|
module is to manage physical address maps, to program the
|
|
memory management hardware on the system, and perform any
|
|
cache operations necessary to ensure correct operation of
|
|
the virtual memory system. The
|
|
.Nm
|
|
module is also responsible for maintaining certain information
|
|
required by
|
|
.Xr uvm 9 .
|
|
.Pp
|
|
In order to cope with hardware architectures that make the
|
|
invalidation of virtual address mappings expensive (e.g.
|
|
TLB invalidations, TLB shootdown operations for multiple
|
|
processors), the
|
|
.Nm
|
|
module is allowed to delay mapping invalidation or protection
|
|
operations until such time as they are actually necessary. The
|
|
functions that are allowed to delay such actions are
|
|
.Fn pmap_enter ,
|
|
.Fn pmap_remove ,
|
|
.Fn pmap_protect ,
|
|
.Fn pmap_kenter_pa ,
|
|
and
|
|
.Fn pmap_kremove .
|
|
Callers of these functions must use the
|
|
.Fn pmap_update
|
|
function to notify the
|
|
.Nm
|
|
module that the mappings need to be made correct. Since the
|
|
.Nm
|
|
module is provided with information as to which processors are
|
|
using a given physical map, the
|
|
.Nm
|
|
module may use whatever optimizations it has available to reduce
|
|
the expense of virtual-to-physical mapping synchronization.
|
|
.Ss HEADER FILES AND DATA STRUCTURES
|
|
Machine-dependent code must provide the header file
|
|
.Pa \*[Lt]machine/pmap.h\*[Gt] .
|
|
This file contains the definition of the
|
|
.Dv pmap
|
|
structure:
|
|
.Bd -literal -offset indent
|
|
struct pmap {
|
|
/* Contents defined by pmap implementation. */
|
|
};
|
|
typedef struct pmap *pmap_t;
|
|
.Ed
|
|
.Pp
|
|
This header file may also define other data structures that the
|
|
.Nm
|
|
implementation uses.
|
|
.Pp
|
|
Note that all prototypes for
|
|
.Nm
|
|
interface functions are provided by the header file
|
|
.Pa \*[Lt]uvm/uvm_pmap.h\*[Gt] .
|
|
It is possible to override this behavior by defining the
|
|
C pre-processor macro
|
|
.Dq PMAP_EXCLUDE_DECLS .
|
|
This may be used to add a layer of indirection to
|
|
.Nm
|
|
API calls, for handling different MMU types in a single
|
|
.Nm
|
|
module, for example. If the
|
|
.Dq PMAP_EXCLUDE_DECLS
|
|
macro is defined,
|
|
.Pa \*[Lt]machine/pmap.h\*[Gt]
|
|
.Em must
|
|
provide function prototypes in a block like so:
|
|
.Bd -literal -offset indent
|
|
#ifdef _KERNEL /* not exposed to user namespace */
|
|
__BEGIN_DECLS /* make safe for C++ */
|
|
/* Prototypes go here. */
|
|
__END_DECLS
|
|
#endif /* _KERNEL */
|
|
.Ed
|
|
.Pp
|
|
The header file
|
|
.Pa \*[Lt]uvm/uvm_pmap.h\*[Gt]
|
|
defines a structure for tracking
|
|
.Nm
|
|
statistics (see below). This structure is defined as:
|
|
.Bd -literal -offset indent
|
|
struct pmap_statistics {
|
|
long resident_count; /* number of mapped pages */
|
|
long wired_count; /* number of wired pages */
|
|
};
|
|
.Ed
|
|
.Ss WIRED MAPPINGS
|
|
The
|
|
.Nm
|
|
module is based on the premise that all information contained
|
|
in the physical maps it manages is redundant. That is, physical
|
|
map information may be
|
|
.Dq forgotten
|
|
by the
|
|
.Nm
|
|
module in the event that it is necessary to do so; it can be rebuilt
|
|
by
|
|
.Xr uvm 9
|
|
by taking a page fault. There is one exception to this rule: so-called
|
|
.Dq wired
|
|
mappings may not be forgotten. Wired mappings are those for which either
|
|
no high-level information exists with which to rebuild the mapping, or
|
|
mappings which are needed by critical sections of code where taking a
|
|
page fault is unacceptable. Information about which mappings are wired
|
|
is provided to the
|
|
.Nm
|
|
module when a mapping is established.
|
|
.Ss MODIFIED/REFERENCED INFORMATION
|
|
The
|
|
.Nm
|
|
module is required to keep track of whether or not a page managed
|
|
by the virtual memory system has been referenced or modified. This
|
|
information is used by
|
|
.Xr uvm 9
|
|
to determine what happens to the page when scanned by the
|
|
pagedaemon.
|
|
.Pp
|
|
Many CPUs provide hardware support for tracking
|
|
modified/referenced information. However, many CPUs, particularly
|
|
modern RISC CPUs, do not. On CPUs which lack hardware support
|
|
for modified/referenced tracking, the
|
|
.Nm
|
|
module must emulate it in software. There are several strategies
|
|
for doing this, and the best strategy depends on the CPU.
|
|
.Pp
|
|
The
|
|
.Dq referenced
|
|
attribute is used by the pagedaemon to determine if a page is
|
|
.Dq active .
|
|
Active pages are not candidates for re-use in the page replacement
|
|
algorithm. Accurate referenced information is not required for
|
|
correct operation; if supplying referenced information for a page
|
|
is not feasible, then the
|
|
.Nm
|
|
implementation should always consider the
|
|
.Dq referenced
|
|
attribute to be FALSE.
|
|
.Pp
|
|
The
|
|
.Dq modified
|
|
attribute is used by the pagedaemon to determine if a page needs
|
|
to be cleaned (written to backing store; swap space, a regular file, etc.).
|
|
Accurate modified information
|
|
.Em must
|
|
be provided by the
|
|
.Nm
|
|
module for correct operation of the virtual memory system.
|
|
.Pp
|
|
Note that modified/referenced information is only tracked for
|
|
pages managed by the virtual memory system (i.e. pages for
|
|
which a vm_page structure exists). In addition, only
|
|
.Dq managed
|
|
mappings of those pages have modified/referenced tracking. Mappings
|
|
entered with the
|
|
.Fn pmap_enter
|
|
function are
|
|
.Dq managed
|
|
mappings. It is possible for
|
|
.Dq unmanaged
|
|
mappings of a page to be created, using the
|
|
.Fn pmap_kenter_pa
|
|
function. The use of
|
|
.Dq unmanaged
|
|
mappings should be limited to code which may execute in interrupt context
|
|
(for example, the kernel memory allocator), or to enter mappings for
|
|
physical addresses which are not managed by the virtual memory system.
|
|
.Dq Unmanaged
|
|
mappings may only be entered into the kernel's virtual address space.
|
|
This constraint is placed on the callers of the
|
|
.Fn pmap_kenter_pa
|
|
and
|
|
.Fn pmap_kremove
|
|
functions so that the
|
|
.Nm
|
|
implementation need not block interrupts when manipulating data
|
|
structures or holding locks.
|
|
.Pp
|
|
Also note that the modified/referenced information must be tracked
|
|
on a per-page basis; 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 information for that page
|
|
.Em must
|
|
be preserved. The only time the modified/referenced attributes may
|
|
be cleared is when the virtual memory system explicitly calls the
|
|
.Fn pmap_clear_modify
|
|
and
|
|
.Fn pmap_clear_reference
|
|
functions.
|
|
.Ss STATISTICS
|
|
The
|
|
.Nm
|
|
is required to keep statistics as to the number of
|
|
.Dq resident
|
|
pages and the number of
|
|
.Dq wired
|
|
pages.
|
|
.Pp
|
|
A
|
|
.Dq resident
|
|
page is one for which a mapping exists. This statistic is used to
|
|
compute the resident size of a process and enforce resource limits.
|
|
Only pages (whether managed by the virtual memory system or not)
|
|
which are mapped into a physical map should be counted in the resident
|
|
count.
|
|
.Pp
|
|
A
|
|
.Dq wired
|
|
page is one for which a wired mapping exists. This statistic is used to
|
|
enforce resource limits.
|
|
.Pp
|
|
Note that it is recommended (though not required) that the
|
|
.Nm
|
|
implementation utilize the
|
|
.Dv pmap_statistics
|
|
structure in the tracking of
|
|
.Nm
|
|
statistics by placing it inside the
|
|
.Dv pmap
|
|
structure and adjusting the counts when mappings are established, changed,
|
|
or removed. This avoids potentially expensive data structure traversals
|
|
when the statistics are queried.
|
|
.Ss REQUIRED FUNCTIONS
|
|
This section describes functions that a
|
|
.Nm
|
|
module must provide to the virtual memory system.
|
|
.Bl -tag -width indent -offset indent
|
|
.It void Fn "pmap_init" "void"
|
|
This function initializes the
|
|
.Nm
|
|
module. It is called by
|
|
.Fn uvm_init
|
|
to initialize any data structures that the module needs to
|
|
manage physical maps.
|
|
.It pmap_t Fn "pmap_kernel" "void"
|
|
Return a pointer to the
|
|
.Dv pmap
|
|
structure that maps the kernel virtual address space.
|
|
.Pp
|
|
Note that this function may be provided as a C pre-processor macro.
|
|
.It void Fn "pmap_virtual_space" "vaddr_t *vstartp" "vaddr_t *vendp"
|
|
The
|
|
.Fn pmap_virtual_space
|
|
function is called to determine the initial kernel virtual address
|
|
space beginning and end. These values are used to create the kernel's
|
|
virtual memory map. The function must set
|
|
.Fa *vstartp
|
|
to the first kernel virtual address that will be managed by
|
|
.Xr uvm 9 ,
|
|
and must set
|
|
.Fa *vendp
|
|
to the last kernel virtual address that will be managed by
|
|
.Xr uvm 9 .
|
|
.Pp
|
|
If the
|
|
.Fn pmap_growkernel
|
|
feature is used by a
|
|
.Nm
|
|
implementation, then
|
|
.Fa *vendp
|
|
should be set to the maximum kernel virtual address allowed by the
|
|
implementation. If
|
|
.Fn pmap_growkernel
|
|
is not used, then
|
|
.Fa *vendp
|
|
.Em must
|
|
be set to the maximum kernel virtual address that can be mapped with
|
|
the resources currently allocated to map the kernel virtual address
|
|
space.
|
|
.It pmap_t Fn "pmap_create" "void"
|
|
Create a physical map and return it to the caller. The reference
|
|
count on the new map is 1.
|
|
.It void Fn "pmap_destroy" "pmap_t pmap"
|
|
Drop the reference count on the specified physical map. If the
|
|
reference count drops to 0, all resources associated with the
|
|
physical map are released and the physical map destroyed. In the
|
|
case of a drop-to-0, no mappings will exist in the map. The
|
|
.Nm
|
|
implementation may assert this.
|
|
.It void Fn "pmap_reference" "pmap_t pmap"
|
|
Increment the reference count on the specified physical map.
|
|
.It long Fn "pmap_resident_count" "pmap_t pmap"
|
|
Query the
|
|
.Dq resident pages
|
|
statistic for
|
|
.Fa pmap .
|
|
.Pp
|
|
Note that this function may be provided as a C pre-processor macro.
|
|
.It long Fn "pmap_wired_count" "pmap_t pmap"
|
|
Query the
|
|
.Dq wired pages"
|
|
statistic for
|
|
.Fa pmap .
|
|
.Pp
|
|
Note that this function may be provided as a C pre-processor macro.
|
|
.It int Fn "pmap_enter" "pmap_t pmap" "vaddr_t va" "paddr_t pa" \
|
|
"vm_prot_t prot" "int flags"
|
|
Create a mapping in physical map
|
|
.Fa pmap
|
|
for the physical address
|
|
.Fa pa
|
|
at the virtual address
|
|
.Fa va
|
|
with protection specified by bits in
|
|
.Fa prot :
|
|
.Bl -tag -width "VM_PROT_EXECUTE " -offset indent
|
|
.It VM_PROT_READ
|
|
The mapping must allow reading.
|
|
.It VM_PROT_WRITE
|
|
The mapping must allow writing.
|
|
.It VM_PROT_EXECUTE
|
|
The page mapped contains instructions that will be executed by the
|
|
processor.
|
|
.El
|
|
.Pp
|
|
The
|
|
.Fa flags
|
|
argument contains protection bits (the same bits as used in the
|
|
.Fa 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
|
|
.Fa flags :
|
|
.Bl -tag -width "PMAP_CANFAIL " -offset indent
|
|
.It PMAP_WIRED
|
|
The mapping being created is a wired mapping.
|
|
.It PMAP_CANFAIL
|
|
The call to
|
|
.Fn pmap_enter
|
|
is allowed to fail. If this flag is
|
|
.Em not
|
|
set, and the
|
|
.Fn pmap_enter
|
|
call is unable to create the mapping, perhaps due to insufficient
|
|
resources, the
|
|
.Nm
|
|
module must panic.
|
|
.El
|
|
.Pp
|
|
The access type provided in the
|
|
.Fa flags
|
|
argument will never exceed the protection specified by
|
|
.Fa prot .
|
|
The
|
|
.Nm
|
|
implementation may assert this.
|
|
Note that on systems that do not provide hardware support for
|
|
tracking modified/referenced information, modified/referenced
|
|
information for the page
|
|
.Em must
|
|
be seeded with the access type provided in
|
|
.Fa flags
|
|
if the PMAP_WIRED flag is set. This is to prevent a fault
|
|
for the purpose of tracking modified/referenced information
|
|
from occurring while the system is in a critical section where
|
|
a fault would be unacceptable.
|
|
.Pp
|
|
Note that
|
|
.Fn pmap_enter
|
|
is sometimes called to enter a mapping at a virtual address
|
|
for which a mapping already exists. In this situation, the
|
|
implementation must take whatever action is necessary to
|
|
invalidate the previous mapping before entering the new one.
|
|
.Pp
|
|
Also note that
|
|
.Fn pmap_enter
|
|
is sometimes called to change the protection for a pre-existing
|
|
mapping, or to change the
|
|
.Dq wired
|
|
attribute for a pre-existing mapping.
|
|
.Pp
|
|
The
|
|
.Fn pmap_enter
|
|
function returns 0 on success or an error code indicating the mode
|
|
of failure.
|
|
.It void Fn "pmap_remove" "pmap_t pmap" "vaddr_t sva" "vaddr_t eva"
|
|
Remove mappings from the virtual address range
|
|
.Fa sva
|
|
to
|
|
.Fa eva
|
|
from the specified physical map.
|
|
.It void Fn "pmap_protect" "pmap_t pmap" "vaddr_t sva" "vaddr_t eva" \
|
|
"vm_prot_t prot"
|
|
Set the protection of the mappings in the virtual address range
|
|
.Fa sva
|
|
to
|
|
.Fa eva
|
|
in the specified physical map.
|
|
.It void Fn "pmap_unwire" "pmap_t pmap" "vaddr_t va"
|
|
Clear the
|
|
.Dq wired
|
|
attribute on the mapping for virtual address
|
|
.Fa va .
|
|
.It boolean_t Fn "pmap_extract" "pmap_t pmap" "vaddr_t va" "paddr_t *pap"
|
|
This function extracts a mapping from the specified physical map. It
|
|
serves two purposes: to determine if a mapping exists for the specified
|
|
virtual address, and to determine what physical address is mapped at the
|
|
specified virtual address.
|
|
.Pp
|
|
The
|
|
.Fn pmap_extract
|
|
function returns FALSE if a mapping for
|
|
.Fa va
|
|
does not exist. Otherwise, it returns TRUE and places the
|
|
physical address mapped at
|
|
.Fa va
|
|
into
|
|
.Fa *pap
|
|
if the
|
|
.Fa pap
|
|
argument is non-NULL.
|
|
.It void Fn "pmap_kenter_pa" "vaddr_t va" "paddr_t pa" "vm_prot_t prot"
|
|
Enter an
|
|
.Dq unmanaged
|
|
mapping for physical address
|
|
.Fa pa
|
|
at virtual address
|
|
.Fa va
|
|
with protection
|
|
.Fa prot
|
|
into the kernel physical map. Mappings of this type are always
|
|
.Dq wired ,
|
|
and are unaffected by routines that alter the protection of pages
|
|
(such as
|
|
.Fn pmap_page_protect ) Ns .
|
|
Such mappings are also not included in the gathering of modified/referenced
|
|
information about a page. Mappings created with
|
|
.Fn pmap_kenter_pa
|
|
may be removed only with a call to
|
|
.Fn pmap_kremove .
|
|
.Pp
|
|
Note that
|
|
.Fn pmap_kenter_pa
|
|
must be safe for use in interrupt context.
|
|
.Fn splvm
|
|
blocks interrupts that might cause
|
|
.Fn pmap_kenter_pa
|
|
to be called.
|
|
.It void Fn "pmap_kremove" "vaddr_t va" "vsize_t size"
|
|
Remove all mappings starting at virtual address
|
|
.Fa va
|
|
for
|
|
.Fa size
|
|
bytes from the kernel physical map. All mappings that are
|
|
removed must be the
|
|
.Dq unmanaged
|
|
type created with
|
|
.Fn pmap_kenter_pa .
|
|
The implementation may assert this.
|
|
.It void Fn "pmap_copy" "pmap_t dst_map" "pmap_t src_map" "vaddr_t dst_addr" \
|
|
"vsize_t len" "vaddr_t src_addr"
|
|
This function copies the mappings starting at
|
|
.Fa src_addr
|
|
in
|
|
.Fa src_map
|
|
for
|
|
.Fa len
|
|
bytes into
|
|
.Fa dst_map
|
|
starting at
|
|
.Fa dst_addr .
|
|
.Pp
|
|
Note that while this function is required to be provided by a
|
|
.Nm
|
|
implementation, it is not actually required to do anything.
|
|
.Fn pmap_copy
|
|
is merely advisory (it is used in the
|
|
.Xr fork 2
|
|
path to
|
|
.Dq pre-fault
|
|
the child's address space).
|
|
.It void Fn "pmap_collect" "pmap_t pmap"
|
|
This function is called just before a process is swapped out to
|
|
allow the
|
|
.Nm
|
|
module to release resources used to map the process's address space.
|
|
The implementation may choose to remove physical mappings in order
|
|
to free e.g. page tables back to the system. Note, however, that
|
|
wired mappings must
|
|
.Em not
|
|
be removed when
|
|
.Fn pmap_collect
|
|
is called.
|
|
.Pp
|
|
Note that while this function is required to be provided by a
|
|
.Nm
|
|
implementation, it is not actually required to do anything.
|
|
.Fn pmap_collect
|
|
is merely advisory. It is recommended, however, that
|
|
.Fn pmap_collect
|
|
be fully implemented by a
|
|
.Nm
|
|
implementation.
|
|
.It void Fn "pmap_update" "pmap_t pmap"
|
|
This function is used to inform the
|
|
.Nm
|
|
module that all physical mappings, for the specified pmap, must now be
|
|
correct. That is, all delayed virtual-to-physical mappings updates
|
|
(such as TLB invalidation or address space identifier updates) must
|
|
be completed. This routine must be used after calls to
|
|
.Fn pmap_enter ,
|
|
.Fn pmap_remove ,
|
|
.Fn pmap_protect ,
|
|
.Fn pmap_kenter_pa ,
|
|
and
|
|
.Fn pmap_kremove
|
|
in order to ensure correct operation of the virtual memory system.
|
|
.Pp
|
|
If a
|
|
.Nm
|
|
implementation does not delay virtual-to-physical mapping updates,
|
|
.Fn pmap_update
|
|
has no operation. In this case, the call may be deleted using
|
|
a C pre-processor macro in
|
|
.Pa \*[Lt]machine/pmap.h\*[Gt] .
|
|
.It void Fn "pmap_activate" "struct proc *p"
|
|
Activate the physical map used by process
|
|
.Fa p .
|
|
This is called by the virtual memory system when the the
|
|
virtual memory context for a process is changed, and is also
|
|
often used by machine-dependent context switch code to program
|
|
the memory management hardware with the process's page table
|
|
base, etc. Note that
|
|
.Fn pmap_activate
|
|
may not always be called when
|
|
.Fa p
|
|
is the current process.
|
|
.Fn pmap_activate
|
|
must be able to handle this scenario.
|
|
.It void Fn "pmap_deactivate" "struct proc *p"
|
|
Deactivate the physical map used by process
|
|
.Fa p .
|
|
It is generally used in conjunction with
|
|
.Fn pmap_activate .
|
|
Like
|
|
.Fn pmap_activate ,
|
|
.Fn pmap_deactivate
|
|
may not always be called when
|
|
.Fa p
|
|
is the current process.
|
|
.It void Fn "pmap_zero_page" "paddr_t pa"
|
|
Zero the PAGE_SIZE sized region starting at physical address
|
|
.Fa pa .
|
|
The
|
|
.Nm
|
|
implementation must take whatever steps are necessary to map the
|
|
page to a kernel-accessible address and zero the page. It is
|
|
suggested that implementations use an optimized zeroing algorithm,
|
|
as the performance of this function directly impacts page fault
|
|
performance. The implementation may assume that the region is
|
|
PAGE_SIZE aligned and exactly PAGE_SIZE bytes in length.
|
|
.Pp
|
|
Note that the cache configuration of the platform should also be
|
|
considered in the implementation of
|
|
.Fn pmap_zero_page .
|
|
For example, on systems with a physically-addressed cache, the cache
|
|
load caused by zeroing the page will not be wasted, as the zeroing is
|
|
usually done on-demand. However, on systems with a virtually-addressed
|
|
cached, the cache load caused by zeroing the page
|
|
.Em will
|
|
be wasted, as the page will be mapped at a virtual address which is
|
|
different from that used to zero the page. In the virtually-addressed
|
|
cache case, care should also be taken to avoid cache alias problems.
|
|
.It void Fn "pmap_copy_page" "paddr_t src" "paddr_t dst"
|
|
Copy the PAGE_SIZE sized region starting at physical address
|
|
.Fa src
|
|
to the same sized region starting at physical address
|
|
.Fa dst .
|
|
The
|
|
.Nm
|
|
implementation must take whatever steps are necessary to map the
|
|
source and destination pages to a kernel-accessible address and
|
|
perform the copy. It is suggested that implementations use an
|
|
optimized copy algorithm, as the performance of this function
|
|
directly impacts page fault performance. The implementation may
|
|
assume that both regions are PAGE_SIZE aligned and exactly PAGE_SIZE
|
|
bytes in length.
|
|
.Pp
|
|
The same cache considerations that apply to
|
|
.Fn pmap_zero_page
|
|
apply to
|
|
.Fn pmap_copy_page .
|
|
.It void Fn "pmap_page_protect" "struct vm_page *pg" "vm_prot_t prot"
|
|
Lower the permissions for all mappings of the page
|
|
.Fa pg
|
|
to
|
|
.Fa prot .
|
|
This function is used by the virtual memory system to implement
|
|
copy-on-write (called with VM_PROT_READ set in
|
|
.Fa prot )
|
|
and to revoke all mappings when cleaning a page (called with
|
|
no bits set in
|
|
.Fa prot ) Ns .
|
|
Access permissions must never be added to a page as a result of
|
|
this call.
|
|
.It boolean_t Fn "pmap_clear_modify" "struct vm_page *pg"
|
|
Clear the
|
|
.Dq modified
|
|
attribute on the page
|
|
.Fa pg .
|
|
.Pp
|
|
The
|
|
.Fn pmap_clear_modify
|
|
function returns TRUE or FALSE indicating whether or not the
|
|
.Dq modified
|
|
attribute was set on the page before it was cleared.
|
|
.Pp
|
|
Note that this function may be provided as a C pre-processor macro.
|
|
.It boolean_t Fn "pmap_clear_reference" "struct vm_page *pg"
|
|
Clear the
|
|
.Dq referenced
|
|
attribute on the page
|
|
.Fa pg .
|
|
.Pp
|
|
The
|
|
.Fn pmap_clear_reference
|
|
function returns TRUE or FALSE indicating whether or not the
|
|
.Dq referenced
|
|
attribute was set on the page before it was cleared.
|
|
.Pp
|
|
Note that this function may be provided as a C pre-processor macro.
|
|
.It boolean_t Fn "pmap_is_modified" "struct vm_page *pg"
|
|
Test whether or not the
|
|
.Dq modified
|
|
attribute is set on page
|
|
.Fa pg .
|
|
.Pp
|
|
Note that this function may be provided as a C pre-processor macro.
|
|
.It boolean_t Fn "pmap_is_referenced" "struct vm_page *pg"
|
|
Test whether or not the
|
|
.Dq referenced
|
|
attribute is set on page
|
|
.Fa pg .
|
|
.Pp
|
|
Note that this function may be provided as a C pre-processor macro.
|
|
.It paddr_t Fn "pmap_phys_address" "int cookie"
|
|
Convert a cookie returned by a device
|
|
.Fn mmap
|
|
function into a physical address. This function is provided to
|
|
accommodate systems which have physical address spaces larger than
|
|
can be directly addressed by the platform's
|
|
.Fa paddr_t
|
|
type. The existence of this function is highly dubious, and it is
|
|
expected that this function will be removed from the
|
|
.Nm pmap
|
|
API in a future release of
|
|
.Nx .
|
|
.Pp
|
|
Note that this function may be provided as a C pre-processor macro.
|
|
.El
|
|
.Ss OPTIONAL FUNCTIONS
|
|
This section describes several optional functions in the
|
|
.Nm
|
|
API.
|
|
.Bl -tag -width indent -offset indent
|
|
.It vaddr_t Fn "pmap_steal_memory" "vsize_t size" "vaddr_t *vstartp" \
|
|
"vaddr_t *vendp"
|
|
This function is a bootstrap memory allocator, which may be provided
|
|
as an alternative to the bootstrap memory allocator used within
|
|
.Xr uvm 9
|
|
itself. It is particularly useful on systems which provide e.g.
|
|
a direct-mapped memory segment. This function works by stealing
|
|
pages from the (to be) managed memory pool, which has already been
|
|
provided to
|
|
.Xr uvm 9
|
|
in the vm_physmem[] array. The pages are then mapped, or otherwise
|
|
made accessible to the kernel, in a machine-dependent way. The
|
|
memory must be zeroed by
|
|
.Fn pmap_steal_memory .
|
|
Note that memory allocated with
|
|
.Fn pmap_steal_memory
|
|
will never be freed, and mappings made by
|
|
.Fn pmap_steal_memory
|
|
must never be
|
|
.Dq forgotten .
|
|
.Pp
|
|
Note that
|
|
.Fn pmap_steal_memory
|
|
should not be used as a general-purpose early-startup memory
|
|
allocation routine. It is intended to be used only by the
|
|
.Fn uvm_pageboot_alloc
|
|
routine and its supporting routines. If you need to allocate
|
|
memory before the virtual memory system is initialized, use
|
|
.Fn uvm_pageboot_alloc .
|
|
See
|
|
.Xr uvm 9
|
|
for more information.
|
|
.Pp
|
|
The
|
|
.Fn pmap_steal_memory
|
|
function returns the kernel-accessible address of the allocated memory.
|
|
If no memory can be allocated, or if allocated memory cannot be mapped,
|
|
the function must panic.
|
|
.Pp
|
|
If the
|
|
.Fn pmap_steal_memory
|
|
function uses address space from the range provided to
|
|
.Xr uvm 9
|
|
by the
|
|
.Fn pmap_virtual_space
|
|
call, then
|
|
.Fn pmap_steal_memory
|
|
must adjust
|
|
.Fa *vstartp
|
|
and
|
|
.Fa *vendp
|
|
upon return.
|
|
.Pp
|
|
The
|
|
.Fn pmap_steal_memory
|
|
function is enabled by defining the C pre-processor macro
|
|
.Dq PMAP_STEAL_MEMORY
|
|
in
|
|
.Pa \*[Lt]machine/pmap.h\*[Gt] .
|
|
.It vaddr_t Fn "pmap_growkernel" "vaddr_t maxkvaddr"
|
|
Management of the kernel virtual address space is complicated by the
|
|
fact that it is not always safe to wait for resources with which to
|
|
map a kernel virtual address. However, it is not always desirable to
|
|
pre-allocate all resources necessary to map the entire kernel virtual
|
|
address space.
|
|
.Pp
|
|
The
|
|
.Fn pmap_growkernel
|
|
interface is designed to help alleviate this problem. The virtual
|
|
memory startup code may choose to allocate an initial set of mapping
|
|
resources (e.g. page tables) and set an internal variable indicating
|
|
how much kernel virtual address space can be mapped using those initial
|
|
resources. Then, when the virtual memory system wishes to map something
|
|
at an address beyond that initial limit, it calls
|
|
.Fn pmap_growkernel
|
|
to pre-allocate more sources with which to create the mapping. Note that
|
|
once additional kernel virtual address space mapping resources have been
|
|
allocated, they should not be freed; it is likely they will be needed
|
|
again.
|
|
.Pp
|
|
The
|
|
.Fn pmap_growkernel
|
|
function returns the new maximum kernel virtual address that can be mapped
|
|
with the resources it has available. If new resources cannot be allocated,
|
|
.Fn pmap_growkernel
|
|
must panic.
|
|
.Pp
|
|
The
|
|
.Fn pmap_growkernel
|
|
function is enabled by defining the C pre-processor macro
|
|
.Dq PMAP_GROWKERNEL
|
|
in
|
|
.Pa \*[Lt]machine/pmap.h\*[Gt] .
|
|
.It void Fn "pmap_fork" "pmap_t src_map" "pmap_t dst_map"
|
|
Some
|
|
.Nm
|
|
implementations may need to keep track of other information not
|
|
directly related to the virtual address space. For example, on
|
|
the i386 port, the Local Descriptor Table state of a process is
|
|
associated with the pmap (this is due to the fact that applications
|
|
manipulate the Local Descriptor Table directly expect it to be
|
|
logically associated with the virtual memory state of the process).
|
|
.Pp
|
|
The
|
|
.Fn pmap_fork
|
|
function is provided as a way to associate information from
|
|
.Fa src_map
|
|
with
|
|
.Fa dst_map
|
|
when a
|
|
.Dv vmspace
|
|
is forked.
|
|
.Fn pmap_fork
|
|
is called from
|
|
.Fn uvmspace_fork .
|
|
.Pp
|
|
The
|
|
.Fn pmap_fork
|
|
function is enabled by defining the C pre-processor macro
|
|
.Dq PMAP_FORK
|
|
in
|
|
.Pa \*[Lt]machine/pmap.h\*[Gt] .
|
|
.It vaddr_t Fn "PMAP_MAP_POOLPAGE" "paddr_t pa"
|
|
This function is used by the
|
|
.Xr pool 9
|
|
memory pool manager. Pools allocate backing pages one at a time. This
|
|
is provided as a means to use hardware features such as a direct-mapped
|
|
memory segment to map the pages used by the
|
|
.Xr pool 9
|
|
allocator. This can lead to better performance by e.g. reducing
|
|
TLB contention.
|
|
.Pp
|
|
.Fn PMAP_MAP_POOLPAGE
|
|
returns the kernel-accessible address of the page being mapped. It must
|
|
always succeed.
|
|
.Pp
|
|
The use of
|
|
.Fn PMAP_MAP_POOLPAGE
|
|
is enabled by defining it as a C pre-processor macro in
|
|
.Fa \*[Lt]machine/pmap.h\*[Gt] .
|
|
If
|
|
.Fn PMAP_MAP_POOLPAGE
|
|
is defined,
|
|
.Fn PMAP_UNMAP_POOLPAGE
|
|
must also be defined.
|
|
.Pp
|
|
The following is an example of how to define
|
|
.Fn PMAP_MAP_POOLPAGE :
|
|
.Bd -literal -offset indent
|
|
#define PMAP_MAP_POOLPAGE(pa) MIPS_PHYS_TO_KSEG0((pa))
|
|
.Ed
|
|
.Pp
|
|
This takes the physical address of a page and returns the KSEG0
|
|
address of that page on a MIPS processor.
|
|
.It paddr_t Fn "PMAP_UNMAP_POOLPAGE" "vaddr_t va"
|
|
This function is the inverse of
|
|
.Fn PMAP_MAP_POOLPAGE .
|
|
.Pp
|
|
.Fn PMAP_UNMAP_POOLPAGE
|
|
returns the physical address of the page corresponding to the
|
|
provided kernel-accessible address.
|
|
.Pp
|
|
The use of
|
|
.Fn PMAP_UNMAP_POOLPAGE
|
|
is enabled by defining it as a C pre-processor macro in
|
|
.Fa \*[Lt]machine/pmap.h\*[Gt] .
|
|
If
|
|
.Fn PMAP_UNMAP_POOLPAGE
|
|
is defined,
|
|
.Fn PMAP_MAP_POOLPAGE
|
|
must also be defined.
|
|
.Pp
|
|
The following is an example of how to define
|
|
.Fn PMAP_UNMAP_POOLPAGE :
|
|
.Bd -literal -offset indent
|
|
#define PMAP_UNMAP_POOLPAGE(pa) MIPS_KSEG0_TO_PHYS((va))
|
|
.Ed
|
|
.Pp
|
|
This takes the KSEG0 address of a previously-mapped pool page
|
|
and returns the physical address of that page on a MIPS processor.
|
|
.El
|
|
.Sh SEE ALSO
|
|
.Xr uvm 9
|
|
.Sh HISTORY
|
|
The
|
|
.Nm
|
|
module was originally part of the design of the virtual memory system
|
|
in the Mach Operating System. The goal was to provide a clean separation
|
|
between the machine-independent and the machine-dependent portions of
|
|
the virtual memory system, in stark contrast to the original
|
|
.Bx 3
|
|
virtual memory system, which was specific to the VAX.
|
|
.Pp
|
|
Between
|
|
.Bx 4.3
|
|
and
|
|
.Bx 4.4 ,
|
|
the Mach virtual memory system, including the
|
|
.Nm
|
|
API, was ported to
|
|
.Bx
|
|
and included in the
|
|
.Bx 4.4
|
|
release.
|
|
.Pp
|
|
.Nx
|
|
inherited the
|
|
.Bx
|
|
version of the Mach virtual memory system.
|
|
.Nx 1.4
|
|
was the first
|
|
.Nx
|
|
release with the new
|
|
.Xr uvm 9
|
|
virtual memory system, which included several changes to the
|
|
.Nm
|
|
API. Since the introduction of
|
|
.Xr uvm 9 ,
|
|
the
|
|
.Nm
|
|
API has evolved further.
|
|
.Sh AUTHORS
|
|
The original Mach VAX
|
|
.Nm
|
|
module was written by
|
|
.An Avadis Tevanian, Jr.
|
|
and
|
|
.An Michael Wayne Young .
|
|
.Pp
|
|
.An Mike Hibler
|
|
did the integration of the Mach virtual memory system into
|
|
.Bx 4.4
|
|
and implemented a
|
|
.Nm
|
|
module for the Motorola 68020+68851/68030/68040.
|
|
.Pp
|
|
The
|
|
.Nm
|
|
API as it exists in
|
|
.Nx
|
|
is derived from
|
|
.Bx 4.4 ,
|
|
and has been modified by
|
|
.An Chuck Cranor ,
|
|
.An Charles M. Hannum ,
|
|
.An Chuck Silvers ,
|
|
.An Wolfgang Solfrank ,
|
|
.An Bill Sommerfeld ,
|
|
and
|
|
.An Jason R. Thorpe .
|
|
.Pp
|
|
The author of this document is
|
|
.An Jason R. Thorpe
|
|
.Aq thorpej@netbsd.org .
|
|
.Sh BUGS
|
|
The use and definition of
|
|
.Fn pmap_activate
|
|
and
|
|
.Fn pmap_deactivate
|
|
needs to be reexamined.
|
|
.Pp
|
|
The use of
|
|
.Fn pmap_copy
|
|
needs to be reexamined. Empirical evidence suggests that performance
|
|
of the system suffers when
|
|
.Fn pmap_copy
|
|
actually performs its defined function. This is largely due to the
|
|
fact that the copy of the virtual-to-physical mappings is wasted if
|
|
the process calls
|
|
.Xr execve 2
|
|
after
|
|
.Xr fork 2 .
|
|
For this reason, it is recommended that
|
|
.Nm
|
|
implementations leave the body of the
|
|
.Fn pmap_copy
|
|
function empty for now.
|