mmu_if.m revision 179081
150276Speter#-
250276Speter# Copyright (c) 2005 Peter Grehan
350276Speter# All rights reserved.
450276Speter#
550276Speter# Redistribution and use in source and binary forms, with or without
650276Speter# modification, are permitted provided that the following conditions
750276Speter# are met:
850276Speter# 1. Redistributions of source code must retain the above copyright
950276Speter#    notice, this list of conditions and the following disclaimer.
1050276Speter# 2. Redistributions in binary form must reproduce the above copyright
1150276Speter#    notice, this list of conditions and the following disclaimer in the
1250276Speter#    documentation and/or other materials provided with the distribution.
1350276Speter#
1450276Speter# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1550276Speter# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1650276Speter# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1750276Speter# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1850276Speter# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1950276Speter# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2050276Speter# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2150276Speter# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2250276Speter# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2350276Speter# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2450276Speter# SUCH DAMAGE.
2550276Speter#
2650276Speter# $FreeBSD: head/sys/powerpc/powerpc/mmu_if.m 179081 2008-05-18 04:16:57Z alc $
2750276Speter#
2850276Speter
2950276Speter#include <sys/param.h>
3050276Speter#include <sys/lock.h>
3150276Speter#include <sys/mutex.h>
3250276Speter#include <sys/systm.h>
3350276Speter
3450276Speter#include <vm/vm.h>
3550276Speter#include <vm/vm_page.h>
3650276Speter
3750276Speter#include <machine/mmuvar.h>
3850276Speter
3950276Speter/**
4050276Speter * @defgroup MMU mmu - KObj methods for PowerPC MMU implementations
4150276Speter * @brief A set of methods required by all MMU implementations. These
4250276Speter * are basically direct call-thru's from the pmap machine-dependent
4350276Speter * code.
4450276Speter * Thanks to Bruce M Simpson's pmap man pages for routine descriptions.
4550276Speter *@{
4650276Speter */
4750276Speter
4850276SpeterINTERFACE mmu;
4950276Speter
5050276Speter#
5150276Speter# Default implementations of some methods
5250276Speter#
5350276SpeterCODE {
5450276Speter	static void mmu_null_copy(mmu_t mmu, pmap_t dst_pmap, pmap_t src_pmap,
5550276Speter	    vm_offset_t dst_addr, vm_size_t len, vm_offset_t src_addr)
5650276Speter	{
5750276Speter		return;
5850276Speter	}
5950276Speter
6050276Speter	static void mmu_null_growkernel(mmu_t mmu, vm_offset_t addr)
6150276Speter	{
6250276Speter		return;
6350276Speter	}
6450276Speter
6550276Speter	static void mmu_null_init(mmu_t mmu)
6650276Speter	{
6750276Speter		return;
6850276Speter	}
6950276Speter
7050276Speter	static boolean_t mmu_null_is_prefaultable(mmu_t mmu, pmap_t pmap,
7150276Speter	    vm_offset_t va)
7250276Speter	{
7350276Speter		return (FALSE);
7450276Speter	}
7550276Speter
7650276Speter	static void mmu_null_object_init_pt(mmu_t mmu, pmap_t pmap,
7750276Speter	    vm_offset_t addr, vm_object_t object, vm_pindex_t index,
7850276Speter	    vm_size_t size)
7950276Speter	{
8050276Speter		return;
8150276Speter	}
8250276Speter
8350276Speter	static void mmu_null_page_init(mmu_t mmu, vm_page_t m)
8450276Speter	{
8550276Speter		return;
8650276Speter	}
8750276Speter
8850276Speter	static void mmu_null_remove_pages(mmu_t mmu, pmap_t pmap)
8950276Speter	{
9050276Speter		return;
9150276Speter	}
9250276Speter
9350276Speter	static int mmu_null_mincore(mmu_t mmu, pmap_t pmap, vm_offset_t addr)
9450276Speter	{
9550276Speter		return (0);
9650276Speter	}
9750276Speter
9850276Speter	static void mmu_null_deactivate(struct thread *td)
9950276Speter	{
10050276Speter		return;
10150276Speter	}
10250276Speter
10350276Speter	static void mmu_null_align_superpage(mmu_t mmu, vm_object_t object,
10450276Speter	    vm_ooffset_t offset, vm_offset_t *addr, vm_size_t size)
10550276Speter	{
10650276Speter		return;
10750276Speter	}
10850276Speter};
10950276Speter
11050276Speter
11150276Speter/**
11250276Speter * @brief Change the wiring attribute for the page in the given physical
11350276Speter * map and virtual address.
11450276Speter *
11550276Speter * @param _pmap		physical map of page
11650276Speter * @param _va		page virtual address
11750276Speter * @param _wired	TRUE to increment wired count, FALSE to decrement
11850276Speter */
11950276SpeterMETHOD void change_wiring {
12050276Speter	mmu_t		_mmu;
12150276Speter	pmap_t		_pmap;
12250276Speter	vm_offset_t	_va;
12350276Speter	boolean_t	_wired;
12450276Speter};
12550276Speter
12650276Speter
12750276Speter/**
12850276Speter * @brief Clear the 'modified' bit on the given physical page
12950276Speter *
13050276Speter * @param _pg		physical page
13150276Speter */
13250276SpeterMETHOD void clear_modify {
13350276Speter	mmu_t		_mmu;
13450276Speter	vm_page_t	_pg;
13550276Speter};
13650276Speter
13750276Speter
13850276Speter/**
13950276Speter * @brief Clear the 'referenced' bit on the given physical page
14050276Speter *
14150276Speter * @param _pg		physical page
14250276Speter */
14350276SpeterMETHOD void clear_reference {
14450276Speter	mmu_t		_mmu;
14550276Speter	vm_page_t	_pg;
14650276Speter};
14750276Speter
14850276Speter
14950276Speter/**
15050276Speter * @brief Clear the write and modified bits in each of the given
15150276Speter * physical page's mappings
15250276Speter *
15350276Speter * @param _pg		physical page
15450276Speter */
15550276SpeterMETHOD void remove_write {
15650276Speter	mmu_t		_mmu;
15750276Speter	vm_page_t	_pg;
15850276Speter};
15950276Speter
16050276Speter
16150276Speter/**
16250276Speter * @brief Copy the address range given by the source physical map, virtual
16350276Speter * address and length to the destination physical map and virtual address.
16450276Speter * This routine is optional (xxx default null implementation ?)
16550276Speter *
16650276Speter * @param _dst_pmap	destination physical map
16750276Speter * @param _src_pmap	source physical map
16850276Speter * @param _dst_addr	destination virtual address
16950276Speter * @param _len		size of range
17050276Speter * @param _src_addr	source virtual address
17150276Speter */
17250276SpeterMETHOD void copy {
17350276Speter	mmu_t		_mmu;
17450276Speter	pmap_t		_dst_pmap;
17550276Speter	pmap_t		_src_pmap;
17650276Speter	vm_offset_t	_dst_addr;
17750276Speter	vm_size_t	_len;
17850276Speter	vm_offset_t	_src_addr;
17950276Speter} DEFAULT mmu_null_copy;
18050276Speter
18150276Speter
18250276Speter/**
18350276Speter * @brief Copy the source physical page to the destination physical page
18450276Speter *
18550276Speter * @param _src		source physical page
18650276Speter * @param _dst		destination physical page
18750276Speter */
18850276SpeterMETHOD void copy_page {
18950276Speter	mmu_t		_mmu;
19050276Speter	vm_page_t	_src;
19150276Speter	vm_page_t	_dst;
19250276Speter};
19350276Speter
19450276Speter
19550276Speter/**
19650276Speter * @brief Create a mapping between a virtual/physical address pair in the
19750276Speter * passed physical map with the specified protection and wiring
19850276Speter *
19950276Speter * @param _pmap		physical map
20050276Speter * @param _va		mapping virtual address
20150276Speter * @param _p		mapping physical page
20250276Speter * @param _prot		mapping page protection
20350276Speter * @param _wired	TRUE if page will be wired
20450276Speter */
20550276SpeterMETHOD void enter {
20650276Speter	mmu_t		_mmu;
20750276Speter	pmap_t		_pmap;
20850276Speter	vm_offset_t	_va;
20950276Speter	vm_page_t	_p;
21050276Speter	vm_prot_t	_prot;
21150276Speter	boolean_t	_wired;
21250276Speter};
21350276Speter
21450276Speter
21550276Speter/**
21650276Speter * @brief Maps a sequence of resident pages belonging to the same object.
21750276Speter *
21850276Speter * @param _pmap		physical map
21950276Speter * @param _start	virtual range start
22050276Speter * @param _end		virtual range end
22150276Speter * @param _m_start	physical page mapped at start
22250276Speter * @param _prot		mapping page protection
22350276Speter */
22450276SpeterMETHOD void enter_object {
22550276Speter	mmu_t		_mmu;
22650276Speter	pmap_t		_pmap;
22750276Speter	vm_offset_t	_start;
22850276Speter	vm_offset_t	_end;
22950276Speter	vm_page_t	_m_start;
23050276Speter	vm_prot_t	_prot;
23150276Speter};
23250276Speter
23350276Speter
23450276Speter/**
23550276Speter * @brief A faster entry point for page mapping where it is possible
23650276Speter * to short-circuit some of the tests in pmap_enter.
23750276Speter *
23850276Speter * @param _pmap		physical map (and also currently active pmap)
23950276Speter * @param _va		mapping virtual address
24050276Speter * @param _pg		mapping physical page
24150276Speter * @param _prot		new page protection - used to see if page is exec.
24250276Speter */
24350276SpeterMETHOD void enter_quick {
24450276Speter	mmu_t		_mmu;
24550276Speter	pmap_t		_pmap;
24650276Speter	vm_offset_t	_va;
24750276Speter	vm_page_t	_pg;
24850276Speter	vm_prot_t	_prot;
24950276Speter};
25050276Speter
25150276Speter
25250276Speter/**
25350276Speter * @brief Reverse map the given virtual address, returning the physical
25450276Speter * page associated with the address if a mapping exists.
25550276Speter *
25650276Speter * @param _pmap		physical map
25750276Speter * @param _va		mapping virtual address
25850276Speter *
25950276Speter * @retval 0		No mapping found
26050276Speter * @retval addr		The mapping physical address
26150276Speter */
26250276SpeterMETHOD vm_paddr_t extract {
26350276Speter	mmu_t		_mmu;
26450276Speter	pmap_t		_pmap;
26550276Speter	vm_offset_t	_va;
26650276Speter};
26750276Speter
26850276Speter
26950276Speter/**
27050276Speter * @brief Reverse map the given virtual address, returning the
27150276Speter * physical page if found. The page must be held (by calling
27250276Speter * vm_page_hold) if the page protection matches the given protection
27350276Speter *
27450276Speter * @param _pmap		physical map
27550276Speter * @param _va		mapping virtual address
27650276Speter * @param _prot		protection used to determine if physical page
27750276Speter *			should be locked
27850276Speter *
27950276Speter * @retval NULL		No mapping found
28050276Speter * @retval page		Pointer to physical page. Held if protections match
28150276Speter */
28250276SpeterMETHOD vm_page_t extract_and_hold {
28350276Speter	mmu_t		_mmu;
28450276Speter	pmap_t		_pmap;
28550276Speter	vm_offset_t	_va;
28650276Speter	vm_prot_t	_prot;
28750276Speter};
28850276Speter
28950276Speter
29050276Speter/**
29150276Speter * @brief Increase kernel virtual address space to the given virtual address.
29250276Speter * Not really required for PowerPC, so optional unless the MMU implementation
29350276Speter * can use it.
29450276Speter *
29550276Speter * @param _va		new upper limit for kernel virtual address space
29650276Speter */
29750276SpeterMETHOD void growkernel {
29850276Speter	mmu_t		_mmu;
29950276Speter	vm_offset_t	_va;
30050276Speter} DEFAULT mmu_null_growkernel;
30150276Speter
30250276Speter
30350276Speter/**
30450276Speter * @brief Called from vm_mem_init. Zone allocation is available at
30550276Speter * this stage so a convenient time to create zones. This routine is
30650276Speter * for MMU-implementation convenience and is optional.
30750276Speter */
30850276SpeterMETHOD void init {
30950276Speter	mmu_t		_mmu;
31050276Speter} DEFAULT mmu_null_init;
31150276Speter
31250276Speter
31350276Speter/**
31450276Speter * @brief Return if the page has been marked by MMU hardware to have been
31550276Speter * modified
31650276Speter *
31750276Speter * @param _pg		physical page to test
31850276Speter *
31950276Speter * @retval boolean	TRUE if page has been modified
32050276Speter */
32150276SpeterMETHOD boolean_t is_modified {
32250276Speter	mmu_t		_mmu;
32350276Speter	vm_page_t	_pg;
32450276Speter};
32550276Speter
32650276Speter
32750276Speter/**
32850276Speter * @brief Return whether the specified virtual address is a candidate to be
32950276Speter * prefaulted in. This routine is optional.
33050276Speter *
33150276Speter * @param _pmap		physical map
33250276Speter * @param _va		virtual address to test
33350276Speter *
33450276Speter * @retval boolean	TRUE if the address is a candidate.
33550276Speter */
33650276SpeterMETHOD boolean_t is_prefaultable {
33750276Speter	mmu_t		_mmu;
33850276Speter	pmap_t		_pmap;
33950276Speter	vm_offset_t	_va;
34050276Speter} DEFAULT mmu_null_is_prefaultable;
34150276Speter
34250276Speter
34350276Speter/**
34450276Speter * @brief Return a count of referenced bits for a page, clearing those bits.
34550276Speter * Not all referenced bits need to be cleared, but it is necessary that 0
34650276Speter * only be returned when there are none set.
34750276Speter *
34850276Speter * @params _m		physical page
34950276Speter *
35050276Speter * @retval int		count of referenced bits
35150276Speter */
35250276SpeterMETHOD boolean_t ts_referenced {
35350276Speter	mmu_t		_mmu;
35450276Speter	vm_page_t	_pg;
35550276Speter};
35650276Speter
35750276Speter
35850276Speter/**
35950276Speter * @brief Map the requested physical address range into kernel virtual
36050276Speter * address space. The value in _virt is taken as a hint. The virtual
36150276Speter * address of the range is returned, or NULL if the mapping could not
36250276Speter * be created. The range can be direct-mapped if that is supported.
36350276Speter *
36450276Speter * @param *_virt	Hint for start virtual address, and also return
36550276Speter *			value
36650276Speter * @param _start	physical address range start
36750276Speter * @param _end		physical address range end
36850276Speter * @param _prot		protection of range (currently ignored)
36950276Speter *
37050276Speter * @retval NULL		could not map the area
37150276Speter * @retval addr, *_virt	mapping start virtual address
37250276Speter */
37350276SpeterMETHOD vm_offset_t map {
37450276Speter	mmu_t		_mmu;
37550276Speter	vm_offset_t	*_virt;
37650276Speter	vm_paddr_t	_start;
37750276Speter	vm_paddr_t	_end;
37850276Speter	int		_prot;
37950276Speter};
38050276Speter
38150276Speter
38250276Speter/**
38350276Speter * @brief Used to create a contiguous set of read-only mappings for a
38450276Speter * given object to try and eliminate a cascade of on-demand faults as
38550276Speter * the object is accessed sequentially. This routine is optional.
38650276Speter *
38750276Speter * @param _pmap		physical map
38850276Speter * @param _addr		mapping start virtual address
38950276Speter * @param _object	device-backed V.M. object to be mapped
39050276Speter * @param _pindex	page-index within object of mapping start
39150276Speter * @param _size		size in bytes of mapping
39250276Speter */
39350276SpeterMETHOD void object_init_pt {
39450276Speter	mmu_t		_mmu;
39550276Speter	pmap_t		_pmap;
39650276Speter	vm_offset_t	_addr;
39750276Speter	vm_object_t	_object;
39850276Speter	vm_pindex_t	_pindex;
39950276Speter	vm_size_t	_size;
40050276Speter} DEFAULT mmu_null_object_init_pt;
40150276Speter
40250276Speter
40350276Speter/**
40450276Speter * @brief Used to determine if the specified page has a mapping for the
40550276Speter * given physical map, by scanning the list of reverse-mappings from the
40650276Speter * page. The list is scanned to a maximum of 16 entries.
40750276Speter *
40850276Speter * @param _pmap		physical map
40950276Speter * @param _pg		physical page
41050276Speter *
41150276Speter * @retval bool		TRUE if the physical map was found in the first 16
41250276Speter *			reverse-map list entries off the physical page.
41350276Speter */
41450276SpeterMETHOD boolean_t page_exists_quick {
41550276Speter	mmu_t		_mmu;
41650276Speter	pmap_t		_pmap;
41750276Speter	vm_page_t	_pg;
41850276Speter};
41950276Speter
42050276Speter
42150276Speter/**
42250276Speter * @brief Initialise the machine-dependent section of the physical page
42350276Speter * data structure. This routine is optional.
42450276Speter *
42550276Speter * @param _pg		physical page
42650276Speter */
42750276SpeterMETHOD void page_init {
42850276Speter	mmu_t		_mmu;
42950276Speter	vm_page_t	_pg;
43050276Speter} DEFAULT mmu_null_page_init;
43150276Speter
43250276Speter
43350276Speter/**
43450276Speter * @brief Count the number of managed mappings to the given physical
43550276Speter * page that are wired.
43650276Speter *
43750276Speter * @param _pg		physical page
43850276Speter *
43950276Speter * @retval int		the number of wired, managed mappings to the
44050276Speter *			given physical page
44150276Speter */
44250276SpeterMETHOD int page_wired_mappings {
44350276Speter	mmu_t		_mmu;
44450276Speter	vm_page_t	_pg;
44550276Speter};
44650276Speter
44750276Speter
44850276Speter/**
44950276Speter * @brief Initialise a physical map data structure
45050276Speter *
45150276Speter * @param _pmap		physical map
45250276Speter */
45350276SpeterMETHOD void pinit {
45450276Speter	mmu_t		_mmu;
45550276Speter	pmap_t		_pmap;
45650276Speter};
45750276Speter
45850276Speter
45950276Speter/**
46050276Speter * @brief Initialise the physical map for process 0, the initial process
46150276Speter * in the system.
46250276Speter * XXX default to pinit ?
46350276Speter *
46450276Speter * @param _pmap		physical map
46550276Speter */
46650276SpeterMETHOD void pinit0 {
46750276Speter	mmu_t		_mmu;
46850276Speter	pmap_t		_pmap;
46950276Speter};
47050276Speter
47150276Speter
47250276Speter/**
47350276Speter * @brief Set the protection for physical pages in the given virtual address
47450276Speter * range to the given value.
47550276Speter *
47650276Speter * @param _pmap		physical map
47750276Speter * @param _start	virtual range start
47850276Speter * @param _end		virtual range end
47950276Speter * @param _prot		new page protection
48050276Speter */
48150276SpeterMETHOD void protect {
48250276Speter	mmu_t		_mmu;
48350276Speter	pmap_t		_pmap;
48450276Speter	vm_offset_t	_start;
48550276Speter	vm_offset_t	_end;
48650276Speter	vm_prot_t	_prot;
48750276Speter};
48850276Speter
48950276Speter
49050276Speter/**
49150276Speter * @brief Create a mapping in kernel virtual address space for the given array
49250276Speter * of wired physical pages.
49350276Speter *
49450276Speter * @param _start	mapping virtual address start
49550276Speter * @param *_m		array of physical page pointers
49650276Speter * @param _count	array elements
49750276Speter */
49850276SpeterMETHOD void qenter {
49950276Speter	mmu_t		_mmu;
50050276Speter	vm_offset_t	_start;
50150276Speter	vm_page_t	*_pg;
50250276Speter	int		_count;
50350276Speter};
50450276Speter
50550276Speter
50650276Speter/**
50750276Speter * @brief Remove the temporary mappings created by qenter.
50850276Speter *
50950276Speter * @param _start	mapping virtual address start
51050276Speter * @param _count	number of pages in mapping
51150276Speter */
51250276SpeterMETHOD void qremove {
51350276Speter	mmu_t		_mmu;
51450276Speter	vm_offset_t	_start;
51550276Speter	int		_count;
51650276Speter};
51750276Speter
51850276Speter
51950276Speter/**
52050276Speter * @brief Release per-pmap resources, e.g. mutexes, allocated memory etc. There
52150276Speter * should be no existing mappings for the physical map at this point
52250276Speter *
52350276Speter * @param _pmap		physical map
52450276Speter */
52550276SpeterMETHOD void release {
52650276Speter	mmu_t		_mmu;
52750276Speter	pmap_t		_pmap;
52850276Speter};
52950276Speter
53050276Speter
53150276Speter/**
53250276Speter * @brief Remove all mappings in the given physical map for the start/end
53350276Speter * virtual address range. The range will be page-aligned.
53450276Speter *
53550276Speter * @param _pmap		physical map
53650276Speter * @param _start	mapping virtual address start
53750276Speter * @param _end		mapping virtual address end
53850276Speter */
53950276SpeterMETHOD void remove {
54050276Speter	mmu_t		_mmu;
54150276Speter	pmap_t		_pmap;
54250276Speter	vm_offset_t	_start;
54350276Speter	vm_offset_t	_end;
54450276Speter};
54550276Speter
54650276Speter
54750276Speter/**
54850276Speter * @brief Traverse the reverse-map list off the given physical page and
54950276Speter * remove all mappings. Clear the PG_WRITEABLE attribute from the page.
55050276Speter *
55150276Speter * @param _pg		physical page
55250276Speter */
55350276SpeterMETHOD void remove_all {
55450276Speter	mmu_t		_mmu;
55550276Speter	vm_page_t	_pg;
55650276Speter};
55750276Speter
55850276Speter
55950276Speter/**
56050276Speter * @brief Remove all mappings in the given start/end virtual address range
56150276Speter * for the given physical map. Similar to the remove method, but it used
56250276Speter * when tearing down all mappings in an address space. This method is
56350276Speter * optional, since pmap_remove will be called for each valid vm_map in
56450276Speter * the address space later.
56550276Speter *
56650276Speter * @param _pmap		physical map
56750276Speter * @param _start	mapping virtual address start
56850276Speter * @param _end		mapping virtual address end
56950276Speter */
57050276SpeterMETHOD void remove_pages {
57150276Speter	mmu_t		_mmu;
57250276Speter	pmap_t		_pmap;
57350276Speter} DEFAULT mmu_null_remove_pages;
57450276Speter
57550276Speter
57650276Speter/**
57750276Speter * @brief Zero a physical page. It is not assumed that the page is mapped,
57850276Speter * so a temporary (or direct) mapping may need to be used.
57950276Speter *
58050276Speter * @param _pg		physical page
58150276Speter */
58250276SpeterMETHOD void zero_page {
58350276Speter	mmu_t		_mmu;
58450276Speter	vm_page_t	_pg;
58550276Speter};
58650276Speter
58750276Speter
58850276Speter/**
58950276Speter * @brief Zero a portion of a physical page, starting at a given offset and
59050276Speter * for a given size (multiples of 512 bytes for 4k pages).
59150276Speter *
59250276Speter * @param _pg		physical page
59350276Speter * @param _off		byte offset from start of page
59450276Speter * @param _size		size of area to zero
59550276Speter */
59650276SpeterMETHOD void zero_page_area {
59750276Speter	mmu_t		_mmu;
59850276Speter	vm_page_t	_pg;
59950276Speter	int		_off;
60050276Speter	int		_size;
60150276Speter};
60250276Speter
60350276Speter
60450276Speter/**
60550276Speter * @brief Called from the idle loop to zero pages. XXX I think locking
60650276Speter * constraints might be different here compared to zero_page.
60750276Speter *
60850276Speter * @param _pg		physical page
60950276Speter */
61050276SpeterMETHOD void zero_page_idle {
61150276Speter	mmu_t		_mmu;
61250276Speter	vm_page_t	_pg;
61350276Speter};
61450276Speter
61550276Speter
61650276Speter/**
61750276Speter * @brief Extract mincore(2) information from a mapping. This routine is
61850276Speter * optional and is an optimisation: the mincore code will call is_modified
61950276Speter * and ts_referenced if no result is returned.
62050276Speter *
62150276Speter * @param _pmap		physical map
62250276Speter * @param _addr		page virtual address
62350276Speter *
62450276Speter * @retval 0		no result
62550276Speter * @retval non-zero	mincore(2) flag values
62650276Speter */
62750276SpeterMETHOD int mincore {
62850276Speter	mmu_t		_mmu;
62950276Speter	pmap_t		_pmap;
63050276Speter	vm_offset_t	_addr;
63150276Speter} DEFAULT mmu_null_mincore;
63250276Speter
63350276Speter
63450276Speter/**
63550276Speter * @brief Perform any operations required to allow a physical map to be used
63650276Speter * before it's address space is accessed.
63750276Speter *
63850276Speter * @param _td		thread associated with physical map
63950276Speter */
64050276SpeterMETHOD void activate {
64150276Speter	mmu_t		_mmu;
64250276Speter	struct thread	*_td;
64350276Speter};
64450276Speter
64550276Speter/**
64650276Speter * @brief Perform any operations required to deactivate a physical map,
64750276Speter * for instance as it is context-switched out.
64850276Speter *
64950276Speter * @param _td		thread associated with physical map
65050276Speter */
65150276SpeterMETHOD void deactivate {
65250276Speter	mmu_t		_mmu;
65350276Speter	struct thread	*_td;
65450276Speter} DEFAULT mmu_null_deactivate;
65550276Speter
65650276Speter/**
65750276Speter * @brief Return a hint for the best virtual address to map a tentative
65850276Speter * virtual address range in a given VM object. The default is to just
65950276Speter * return the given tentative start address.
66050276Speter *
66150276Speter * @param _obj		VM backing object
66250276Speter * @param _offset	starting offset with the VM object
66350276Speter * @param _addr		initial guess at virtual address
66450276Speter * @param _size		size of virtual address range
66550276Speter */
66650276SpeterMETHOD void align_superpage {
66750276Speter	mmu_t		_mmu;
66850276Speter	vm_object_t	_obj;
66950276Speter	vm_ooffset_t	_offset;
67050276Speter	vm_offset_t	*_addr;
67150276Speter	vm_size_t	_size;
67250276Speter} DEFAULT mmu_null_align_superpage;
67350276Speter
67450276Speter
67550276Speter
67650276Speter
67750276Speter/**
67850276Speter * INTERNAL INTERFACES
67950276Speter */
68050276Speter
68150276Speter/**
68250276Speter * @brief Bootstrap the VM system. At the completion of this routine, the
68350276Speter * kernel will be running in it's own address space with full control over
68450276Speter * paging.
68550276Speter *
68650276Speter * @param _start	start of reserved memory (obsolete ???)
68750276Speter * @param _end		end of reserved memory (obsolete ???)
68850276Speter *			XXX I think the intent of these was to allow
68950276Speter *			the memory used by kernel text+data+bss and
69050276Speter *			loader variables/load-time kld's to be carved out
69150276Speter *			of available physical mem.
69250276Speter *
69350276Speter */
69450276SpeterMETHOD void bootstrap {
69550276Speter	mmu_t		_mmu;
69650276Speter	vm_offset_t	_start;
69750276Speter	vm_offset_t	_end;
69850276Speter};
69950276Speter
70050276Speter
70150276Speter/**
70250276Speter * @brief Create a kernel mapping for a given physical address range.
70350276Speter * Called by bus code on behalf of device drivers. The mapping does not
70450276Speter * have to be a virtual address: it can be a direct-mapped physical address
70550276Speter * if that is supported by the MMU.
70650276Speter *
70750276Speter * @param _pa		start physical address
70850276Speter * @param _size		size in bytes of mapping
70950276Speter *
71050276Speter * @retval addr		address of mapping.
71150276Speter */
71250276SpeterMETHOD void * mapdev {
71350276Speter	mmu_t		_mmu;
71450276Speter	vm_offset_t	_pa;
71550276Speter	vm_size_t	_size;
71650276Speter};
71750276Speter
71850276Speter
71950276Speter/**
72050276Speter * @brief Remove the mapping created by mapdev. Called when a driver
72150276Speter * is unloaded.
72250276Speter *
72350276Speter * @param _va		Mapping address returned from mapdev
72450276Speter * @param _size		size in bytes of mapping
72550276Speter */
72650276SpeterMETHOD void unmapdev {
72750276Speter	mmu_t		_mmu;
72850276Speter	vm_offset_t	_va;
72950276Speter	vm_size_t	_size;
73050276Speter};
73150276Speter
73250276Speter
73350276Speter/**
73450276Speter * @brief Reverse-map a kernel virtual address
73550276Speter *
73650276Speter * @param _va		kernel virtual address to reverse-map
73750276Speter *
73850276Speter * @retval pa		physical address corresponding to mapping
73950276Speter */
74050276SpeterMETHOD vm_offset_t kextract {
74150276Speter	mmu_t		_mmu;
74250276Speter	vm_offset_t	_va;
74350276Speter};
74450276Speter
74550276Speter
74650276Speter/**
74750276Speter * @brief Map a wired page into kernel virtual address space
74850276Speter *
74950276Speter * @param _va		mapping virtual address
75050276Speter * @param _pa		mapping physical address
75150276Speter */
75250276SpeterMETHOD void kenter {
75350276Speter	mmu_t		_mmu;
75450276Speter	vm_offset_t	_va;
75550276Speter	vm_offset_t	_pa;
75650276Speter};
757
758
759/**
760 * @brief Determine if the given physical address range has been direct-mapped.
761 *
762 * @param _pa		physical address start
763 * @param _size		physical address range size
764 *
765 * @retval bool		TRUE if the range is direct-mapped.
766 */
767METHOD boolean_t dev_direct_mapped {
768	mmu_t		_mmu;
769	vm_offset_t	_pa;
770	vm_size_t	_size;
771};
772
773
774/**
775 * @brief Evaluate if a physical page has an executable mapping
776 *
777 * @param _pg		physical page
778 *
779 * @retval bool		TRUE if a physical mapping exists for the given page.
780 */
781METHOD boolean_t page_executable {
782	mmu_t		_mmu;
783	vm_page_t	_pg;
784};
785
786