1152179Sgrehan#-
2152179Sgrehan# Copyright (c) 2005 Peter Grehan
3152179Sgrehan# All rights reserved.
4152179Sgrehan#
5152179Sgrehan# Redistribution and use in source and binary forms, with or without
6152179Sgrehan# modification, are permitted provided that the following conditions
7152179Sgrehan# are met:
8152179Sgrehan# 1. Redistributions of source code must retain the above copyright
9152179Sgrehan#    notice, this list of conditions and the following disclaimer.
10152179Sgrehan# 2. Redistributions in binary form must reproduce the above copyright
11152179Sgrehan#    notice, this list of conditions and the following disclaimer in the
12152179Sgrehan#    documentation and/or other materials provided with the distribution.
13152179Sgrehan#
14152179Sgrehan# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15152179Sgrehan# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16152179Sgrehan# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17152179Sgrehan# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18152179Sgrehan# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19152179Sgrehan# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20152179Sgrehan# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21152179Sgrehan# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22152179Sgrehan# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23152179Sgrehan# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24152179Sgrehan# SUCH DAMAGE.
25152179Sgrehan#
26152179Sgrehan# $FreeBSD$
27152179Sgrehan#
28152179Sgrehan
29152179Sgrehan#include <sys/param.h>
30152179Sgrehan#include <sys/lock.h>
31152179Sgrehan#include <sys/mutex.h>
32152179Sgrehan#include <sys/systm.h>
33152179Sgrehan
34152179Sgrehan#include <vm/vm.h>
35152179Sgrehan#include <vm/vm_page.h>
36152179Sgrehan
37152179Sgrehan#include <machine/mmuvar.h>
38152179Sgrehan
39152179Sgrehan/**
40152179Sgrehan * @defgroup MMU mmu - KObj methods for PowerPC MMU implementations
41152179Sgrehan * @brief A set of methods required by all MMU implementations. These
42152179Sgrehan * are basically direct call-thru's from the pmap machine-dependent
43152179Sgrehan * code.
44152179Sgrehan * Thanks to Bruce M Simpson's pmap man pages for routine descriptions.
45152179Sgrehan *@{
46152179Sgrehan */
47152179Sgrehan
48152179SgrehanINTERFACE mmu;
49152179Sgrehan
50152179Sgrehan#
51152179Sgrehan# Default implementations of some methods
52152179Sgrehan#
53152179SgrehanCODE {
54152179Sgrehan	static void mmu_null_copy(mmu_t mmu, pmap_t dst_pmap, pmap_t src_pmap,
55152179Sgrehan	    vm_offset_t dst_addr, vm_size_t len, vm_offset_t src_addr)
56152179Sgrehan	{
57152179Sgrehan		return;
58152179Sgrehan	}
59152179Sgrehan
60152179Sgrehan	static void mmu_null_growkernel(mmu_t mmu, vm_offset_t addr)
61152179Sgrehan	{
62152179Sgrehan		return;
63152179Sgrehan	}
64152179Sgrehan
65152179Sgrehan	static void mmu_null_init(mmu_t mmu)
66152179Sgrehan	{
67152179Sgrehan		return;
68152179Sgrehan	}
69152179Sgrehan
70152179Sgrehan	static boolean_t mmu_null_is_prefaultable(mmu_t mmu, pmap_t pmap,
71152179Sgrehan	    vm_offset_t va)
72152179Sgrehan	{
73152179Sgrehan		return (FALSE);
74152179Sgrehan	}
75152179Sgrehan
76152179Sgrehan	static void mmu_null_object_init_pt(mmu_t mmu, pmap_t pmap,
77152179Sgrehan	    vm_offset_t addr, vm_object_t object, vm_pindex_t index,
78152179Sgrehan	    vm_size_t size)
79152179Sgrehan	{
80152179Sgrehan		return;
81152179Sgrehan	}
82152179Sgrehan
83152179Sgrehan	static void mmu_null_page_init(mmu_t mmu, vm_page_t m)
84152179Sgrehan	{
85152179Sgrehan		return;
86152179Sgrehan	}
87152179Sgrehan
88157443Speter	static void mmu_null_remove_pages(mmu_t mmu, pmap_t pmap)
89152179Sgrehan	{
90152179Sgrehan		return;
91152179Sgrehan	}
92152179Sgrehan
93208504Salc	static int mmu_null_mincore(mmu_t mmu, pmap_t pmap, vm_offset_t addr,
94208504Salc	    vm_paddr_t *locked_pa)
95152179Sgrehan	{
96152179Sgrehan		return (0);
97152179Sgrehan	}
98152179Sgrehan
99152179Sgrehan	static void mmu_null_deactivate(struct thread *td)
100152179Sgrehan	{
101152179Sgrehan		return;
102152179Sgrehan	}
103152179Sgrehan
104179081Salc	static void mmu_null_align_superpage(mmu_t mmu, vm_object_t object,
105179081Salc	    vm_ooffset_t offset, vm_offset_t *addr, vm_size_t size)
106152179Sgrehan	{
107179081Salc		return;
108152179Sgrehan	}
109190684Smarcel
110190684Smarcel	static struct pmap_md *mmu_null_scan_md(mmu_t mmu, struct pmap_md *p)
111190684Smarcel	{
112190684Smarcel		return (NULL);
113190684Smarcel	}
114213307Snwhitehorn
115213307Snwhitehorn	static void *mmu_null_mapdev_attr(mmu_t mmu, vm_offset_t pa,
116213307Snwhitehorn	    vm_size_t size, vm_memattr_t ma)
117213307Snwhitehorn	{
118213307Snwhitehorn		return MMU_MAPDEV(mmu, pa, size);
119213307Snwhitehorn	}
120213307Snwhitehorn
121213307Snwhitehorn	static void mmu_null_kenter_attr(mmu_t mmu, vm_offset_t va,
122213307Snwhitehorn	    vm_offset_t pa, vm_memattr_t ma)
123213307Snwhitehorn	{
124213307Snwhitehorn		MMU_KENTER(mmu, va, pa);
125213307Snwhitehorn	}
126213307Snwhitehorn
127213307Snwhitehorn	static void mmu_null_page_set_memattr(mmu_t mmu, vm_page_t m,
128213307Snwhitehorn	    vm_memattr_t ma)
129213307Snwhitehorn	{
130213307Snwhitehorn		return;
131213307Snwhitehorn	}
132152179Sgrehan};
133152179Sgrehan
134152179Sgrehan
135152179Sgrehan/**
136255028Salc * @brief Apply the given advice to the specified range of addresses within
137255028Salc * the given pmap.  Depending on the advice, clear the referenced and/or
138255028Salc * modified flags in each mapping and set the mapped page's dirty field.
139255028Salc *
140255028Salc * @param _pmap		physical map
141255028Salc * @param _start	virtual range start
142255028Salc * @param _end		virtual range end
143255028Salc * @param _advice	advice to apply
144255028Salc */
145255028SalcMETHOD void advise {
146255028Salc	mmu_t		_mmu;
147255028Salc	pmap_t		_pmap;
148255028Salc	vm_offset_t	_start;
149255028Salc	vm_offset_t	_end;
150255028Salc	int		_advice;
151255028Salc};
152255028Salc
153255028Salc
154255028Salc/**
155152179Sgrehan * @brief Clear the 'modified' bit on the given physical page
156152179Sgrehan *
157152179Sgrehan * @param _pg		physical page
158152179Sgrehan */
159152179SgrehanMETHOD void clear_modify {
160152179Sgrehan	mmu_t		_mmu;
161152179Sgrehan	vm_page_t	_pg;
162152179Sgrehan};
163152179Sgrehan
164152179Sgrehan
165152179Sgrehan/**
166160889Salc * @brief Clear the write and modified bits in each of the given
167160889Salc * physical page's mappings
168160889Salc *
169160889Salc * @param _pg		physical page
170160889Salc */
171160889SalcMETHOD void remove_write {
172160889Salc	mmu_t		_mmu;
173160889Salc	vm_page_t	_pg;
174160889Salc};
175160889Salc
176160889Salc
177160889Salc/**
178152179Sgrehan * @brief Copy the address range given by the source physical map, virtual
179152179Sgrehan * address and length to the destination physical map and virtual address.
180152179Sgrehan * This routine is optional (xxx default null implementation ?)
181152179Sgrehan *
182152179Sgrehan * @param _dst_pmap	destination physical map
183152179Sgrehan * @param _src_pmap	source physical map
184152179Sgrehan * @param _dst_addr	destination virtual address
185152179Sgrehan * @param _len		size of range
186152179Sgrehan * @param _src_addr	source virtual address
187152179Sgrehan */
188152179SgrehanMETHOD void copy {
189152179Sgrehan	mmu_t		_mmu;
190152179Sgrehan	pmap_t		_dst_pmap;
191152179Sgrehan	pmap_t		_src_pmap;
192152179Sgrehan	vm_offset_t	_dst_addr;
193152179Sgrehan	vm_size_t	_len;
194152179Sgrehan	vm_offset_t	_src_addr;
195152179Sgrehan} DEFAULT mmu_null_copy;
196152179Sgrehan
197152179Sgrehan
198152179Sgrehan/**
199152179Sgrehan * @brief Copy the source physical page to the destination physical page
200152179Sgrehan *
201152179Sgrehan * @param _src		source physical page
202152179Sgrehan * @param _dst		destination physical page
203152179Sgrehan */
204152179SgrehanMETHOD void copy_page {
205152179Sgrehan	mmu_t		_mmu;
206152179Sgrehan	vm_page_t	_src;
207152179Sgrehan	vm_page_t	_dst;
208152179Sgrehan};
209152179Sgrehan
210248280SkibMETHOD void copy_pages {
211248280Skib	mmu_t		_mmu;
212248280Skib	vm_page_t	*_ma;
213248280Skib	vm_offset_t	_a_offset;
214248280Skib	vm_page_t	*_mb;
215248280Skib	vm_offset_t	_b_offset;
216248280Skib	int		_xfersize;
217248280Skib};
218152179Sgrehan
219152179Sgrehan/**
220152179Sgrehan * @brief Create a mapping between a virtual/physical address pair in the
221152179Sgrehan * passed physical map with the specified protection and wiring
222152179Sgrehan *
223152179Sgrehan * @param _pmap		physical map
224152179Sgrehan * @param _va		mapping virtual address
225152179Sgrehan * @param _p		mapping physical page
226152179Sgrehan * @param _prot		mapping page protection
227270439Skib * @param _flags	pmap_enter flags
228270439Skib * @param _psind	superpage size index
229152179Sgrehan */
230270439SkibMETHOD int enter {
231152179Sgrehan	mmu_t		_mmu;
232152179Sgrehan	pmap_t		_pmap;
233152179Sgrehan	vm_offset_t	_va;
234152179Sgrehan	vm_page_t	_p;
235152179Sgrehan	vm_prot_t	_prot;
236270439Skib	u_int		_flags;
237270439Skib	int8_t		_psind;
238152179Sgrehan};
239152179Sgrehan
240152179Sgrehan
241152179Sgrehan/**
242159303Salc * @brief Maps a sequence of resident pages belonging to the same object.
243159303Salc *
244159303Salc * @param _pmap		physical map
245159303Salc * @param _start	virtual range start
246159303Salc * @param _end		virtual range end
247159303Salc * @param _m_start	physical page mapped at start
248159303Salc * @param _prot		mapping page protection
249159303Salc */
250159303SalcMETHOD void enter_object {
251159303Salc	mmu_t		_mmu;
252159303Salc	pmap_t		_pmap;
253159303Salc	vm_offset_t	_start;
254159303Salc	vm_offset_t	_end;
255159303Salc	vm_page_t	_m_start;
256159303Salc	vm_prot_t	_prot;
257159303Salc};
258159303Salc
259159303Salc
260159303Salc/**
261152179Sgrehan * @brief A faster entry point for page mapping where it is possible
262152179Sgrehan * to short-circuit some of the tests in pmap_enter.
263152179Sgrehan *
264152179Sgrehan * @param _pmap		physical map (and also currently active pmap)
265152179Sgrehan * @param _va		mapping virtual address
266152179Sgrehan * @param _pg		mapping physical page
267152179Sgrehan * @param _prot		new page protection - used to see if page is exec.
268152179Sgrehan */
269159627SupsMETHOD void enter_quick {
270152179Sgrehan	mmu_t		_mmu;
271152179Sgrehan	pmap_t		_pmap;
272152179Sgrehan	vm_offset_t	_va;
273152179Sgrehan	vm_page_t	_pg;
274152179Sgrehan	vm_prot_t	_prot;
275152179Sgrehan};
276152179Sgrehan
277152179Sgrehan
278152179Sgrehan/**
279152179Sgrehan * @brief Reverse map the given virtual address, returning the physical
280152179Sgrehan * page associated with the address if a mapping exists.
281152179Sgrehan *
282152179Sgrehan * @param _pmap		physical map
283152179Sgrehan * @param _va		mapping virtual address
284152179Sgrehan *
285152179Sgrehan * @retval 0		No mapping found
286152179Sgrehan * @retval addr		The mapping physical address
287152179Sgrehan */
288152179SgrehanMETHOD vm_paddr_t extract {
289152179Sgrehan	mmu_t		_mmu;
290152179Sgrehan	pmap_t		_pmap;
291152179Sgrehan	vm_offset_t	_va;
292152179Sgrehan};
293152179Sgrehan
294152179Sgrehan
295152179Sgrehan/**
296152179Sgrehan * @brief Reverse map the given virtual address, returning the
297152179Sgrehan * physical page if found. The page must be held (by calling
298152179Sgrehan * vm_page_hold) if the page protection matches the given protection
299152179Sgrehan *
300152179Sgrehan * @param _pmap		physical map
301152179Sgrehan * @param _va		mapping virtual address
302152179Sgrehan * @param _prot		protection used to determine if physical page
303152179Sgrehan *			should be locked
304152179Sgrehan *
305152179Sgrehan * @retval NULL		No mapping found
306152179Sgrehan * @retval page		Pointer to physical page. Held if protections match
307152179Sgrehan */
308152179SgrehanMETHOD vm_page_t extract_and_hold {
309152179Sgrehan	mmu_t		_mmu;
310152179Sgrehan	pmap_t		_pmap;
311152179Sgrehan	vm_offset_t	_va;
312152179Sgrehan	vm_prot_t	_prot;
313152179Sgrehan};
314152179Sgrehan
315152179Sgrehan
316152179Sgrehan/**
317152179Sgrehan * @brief Increase kernel virtual address space to the given virtual address.
318152179Sgrehan * Not really required for PowerPC, so optional unless the MMU implementation
319152179Sgrehan * can use it.
320152179Sgrehan *
321152179Sgrehan * @param _va		new upper limit for kernel virtual address space
322152179Sgrehan */
323152179SgrehanMETHOD void growkernel {
324152179Sgrehan	mmu_t		_mmu;
325152179Sgrehan	vm_offset_t	_va;
326152179Sgrehan} DEFAULT mmu_null_growkernel;
327152179Sgrehan
328152179Sgrehan
329152179Sgrehan/**
330152179Sgrehan * @brief Called from vm_mem_init. Zone allocation is available at
331152179Sgrehan * this stage so a convenient time to create zones. This routine is
332152179Sgrehan * for MMU-implementation convenience and is optional.
333152179Sgrehan */
334152179SgrehanMETHOD void init {
335152179Sgrehan	mmu_t		_mmu;
336152179Sgrehan} DEFAULT mmu_null_init;
337152179Sgrehan
338152179Sgrehan
339152179Sgrehan/**
340152179Sgrehan * @brief Return if the page has been marked by MMU hardware to have been
341152179Sgrehan * modified
342152179Sgrehan *
343152179Sgrehan * @param _pg		physical page to test
344152179Sgrehan *
345152179Sgrehan * @retval boolean	TRUE if page has been modified
346152179Sgrehan */
347152179SgrehanMETHOD boolean_t is_modified {
348152179Sgrehan	mmu_t		_mmu;
349152179Sgrehan	vm_page_t	_pg;
350152179Sgrehan};
351152179Sgrehan
352152179Sgrehan
353152179Sgrehan/**
354152179Sgrehan * @brief Return whether the specified virtual address is a candidate to be
355152179Sgrehan * prefaulted in. This routine is optional.
356152179Sgrehan *
357152179Sgrehan * @param _pmap		physical map
358152179Sgrehan * @param _va		virtual address to test
359152179Sgrehan *
360152179Sgrehan * @retval boolean	TRUE if the address is a candidate.
361152179Sgrehan */
362152179SgrehanMETHOD boolean_t is_prefaultable {
363152179Sgrehan	mmu_t		_mmu;
364152179Sgrehan	pmap_t		_pmap;
365152179Sgrehan	vm_offset_t	_va;
366152179Sgrehan} DEFAULT mmu_null_is_prefaultable;
367152179Sgrehan
368152179Sgrehan
369152179Sgrehan/**
370207155Salc * @brief Return whether or not the specified physical page was referenced
371207155Salc * in any physical maps.
372207155Salc *
373207155Salc * @params _pg		physical page
374207155Salc *
375207155Salc * @retval boolean	TRUE if page has been referenced
376207155Salc */
377207155SalcMETHOD boolean_t is_referenced {
378207155Salc	mmu_t		_mmu;
379207155Salc	vm_page_t	_pg;
380207155Salc};
381207155Salc
382207155Salc
383207155Salc/**
384152179Sgrehan * @brief Return a count of referenced bits for a page, clearing those bits.
385152179Sgrehan * Not all referenced bits need to be cleared, but it is necessary that 0
386152179Sgrehan * only be returned when there are none set.
387152179Sgrehan *
388152179Sgrehan * @params _m		physical page
389152179Sgrehan *
390152179Sgrehan * @retval int		count of referenced bits
391152179Sgrehan */
392238357SalcMETHOD int ts_referenced {
393152179Sgrehan	mmu_t		_mmu;
394152179Sgrehan	vm_page_t	_pg;
395152179Sgrehan};
396152179Sgrehan
397152179Sgrehan
398152179Sgrehan/**
399152179Sgrehan * @brief Map the requested physical address range into kernel virtual
400152179Sgrehan * address space. The value in _virt is taken as a hint. The virtual
401152179Sgrehan * address of the range is returned, or NULL if the mapping could not
402152179Sgrehan * be created. The range can be direct-mapped if that is supported.
403152179Sgrehan *
404152179Sgrehan * @param *_virt	Hint for start virtual address, and also return
405152179Sgrehan *			value
406152179Sgrehan * @param _start	physical address range start
407152179Sgrehan * @param _end		physical address range end
408152179Sgrehan * @param _prot		protection of range (currently ignored)
409152179Sgrehan *
410152179Sgrehan * @retval NULL		could not map the area
411152179Sgrehan * @retval addr, *_virt	mapping start virtual address
412152179Sgrehan */
413152179SgrehanMETHOD vm_offset_t map {
414152179Sgrehan	mmu_t		_mmu;
415152179Sgrehan	vm_offset_t	*_virt;
416152179Sgrehan	vm_paddr_t	_start;
417152179Sgrehan	vm_paddr_t	_end;
418152179Sgrehan	int		_prot;
419152179Sgrehan};
420152179Sgrehan
421152179Sgrehan
422152179Sgrehan/**
423152179Sgrehan * @brief Used to create a contiguous set of read-only mappings for a
424152179Sgrehan * given object to try and eliminate a cascade of on-demand faults as
425152179Sgrehan * the object is accessed sequentially. This routine is optional.
426152179Sgrehan *
427152179Sgrehan * @param _pmap		physical map
428152179Sgrehan * @param _addr		mapping start virtual address
429152179Sgrehan * @param _object	device-backed V.M. object to be mapped
430152179Sgrehan * @param _pindex	page-index within object of mapping start
431152179Sgrehan * @param _size		size in bytes of mapping
432152179Sgrehan */
433152179SgrehanMETHOD void object_init_pt {
434152179Sgrehan	mmu_t		_mmu;
435152179Sgrehan	pmap_t		_pmap;
436152179Sgrehan	vm_offset_t	_addr;
437152179Sgrehan	vm_object_t	_object;
438152179Sgrehan	vm_pindex_t	_pindex;
439152179Sgrehan	vm_size_t	_size;
440152179Sgrehan} DEFAULT mmu_null_object_init_pt;
441152179Sgrehan
442152179Sgrehan
443152179Sgrehan/**
444152179Sgrehan * @brief Used to determine if the specified page has a mapping for the
445152179Sgrehan * given physical map, by scanning the list of reverse-mappings from the
446152179Sgrehan * page. The list is scanned to a maximum of 16 entries.
447152179Sgrehan *
448152179Sgrehan * @param _pmap		physical map
449152179Sgrehan * @param _pg		physical page
450152179Sgrehan *
451152179Sgrehan * @retval bool		TRUE if the physical map was found in the first 16
452152179Sgrehan *			reverse-map list entries off the physical page.
453152179Sgrehan */
454152179SgrehanMETHOD boolean_t page_exists_quick {
455152179Sgrehan	mmu_t		_mmu;
456152179Sgrehan	pmap_t		_pmap;
457152179Sgrehan	vm_page_t	_pg;
458152179Sgrehan};
459152179Sgrehan
460152179Sgrehan
461152179Sgrehan/**
462152179Sgrehan * @brief Initialise the machine-dependent section of the physical page
463152179Sgrehan * data structure. This routine is optional.
464152179Sgrehan *
465152179Sgrehan * @param _pg		physical page
466152179Sgrehan */
467152179SgrehanMETHOD void page_init {
468152179Sgrehan	mmu_t		_mmu;
469152179Sgrehan	vm_page_t	_pg;
470152179Sgrehan} DEFAULT mmu_null_page_init;
471152179Sgrehan
472152179Sgrehan
473152179Sgrehan/**
474173708Salc * @brief Count the number of managed mappings to the given physical
475173708Salc * page that are wired.
476173708Salc *
477173708Salc * @param _pg		physical page
478173708Salc *
479173708Salc * @retval int		the number of wired, managed mappings to the
480173708Salc *			given physical page
481173708Salc */
482173708SalcMETHOD int page_wired_mappings {
483173708Salc	mmu_t		_mmu;
484173708Salc	vm_page_t	_pg;
485173708Salc};
486173708Salc
487173708Salc
488173708Salc/**
489152179Sgrehan * @brief Initialise a physical map data structure
490152179Sgrehan *
491152179Sgrehan * @param _pmap		physical map
492152179Sgrehan */
493152179SgrehanMETHOD void pinit {
494152179Sgrehan	mmu_t		_mmu;
495152179Sgrehan	pmap_t		_pmap;
496152179Sgrehan};
497152179Sgrehan
498152179Sgrehan
499152179Sgrehan/**
500152179Sgrehan * @brief Initialise the physical map for process 0, the initial process
501152179Sgrehan * in the system.
502152179Sgrehan * XXX default to pinit ?
503152179Sgrehan *
504152179Sgrehan * @param _pmap		physical map
505152179Sgrehan */
506152179SgrehanMETHOD void pinit0 {
507152179Sgrehan	mmu_t		_mmu;
508152179Sgrehan	pmap_t		_pmap;
509152179Sgrehan};
510152179Sgrehan
511152179Sgrehan
512152179Sgrehan/**
513152179Sgrehan * @brief Set the protection for physical pages in the given virtual address
514152179Sgrehan * range to the given value.
515152179Sgrehan *
516152179Sgrehan * @param _pmap		physical map
517152179Sgrehan * @param _start	virtual range start
518152179Sgrehan * @param _end		virtual range end
519152179Sgrehan * @param _prot		new page protection
520152179Sgrehan */
521152179SgrehanMETHOD void protect {
522152179Sgrehan	mmu_t		_mmu;
523152179Sgrehan	pmap_t		_pmap;
524152179Sgrehan	vm_offset_t	_start;
525152179Sgrehan	vm_offset_t	_end;
526152179Sgrehan	vm_prot_t	_prot;
527152179Sgrehan};
528152179Sgrehan
529152179Sgrehan
530152179Sgrehan/**
531152179Sgrehan * @brief Create a mapping in kernel virtual address space for the given array
532152179Sgrehan * of wired physical pages.
533152179Sgrehan *
534152179Sgrehan * @param _start	mapping virtual address start
535152179Sgrehan * @param *_m		array of physical page pointers
536152179Sgrehan * @param _count	array elements
537152179Sgrehan */
538152179SgrehanMETHOD void qenter {
539152179Sgrehan	mmu_t		_mmu;
540152179Sgrehan	vm_offset_t	_start;
541152179Sgrehan	vm_page_t	*_pg;
542152179Sgrehan	int		_count;
543152179Sgrehan};
544152179Sgrehan
545152179Sgrehan
546152179Sgrehan/**
547152179Sgrehan * @brief Remove the temporary mappings created by qenter.
548152179Sgrehan *
549152179Sgrehan * @param _start	mapping virtual address start
550152179Sgrehan * @param _count	number of pages in mapping
551152179Sgrehan */
552152179SgrehanMETHOD void qremove {
553152179Sgrehan	mmu_t		_mmu;
554152179Sgrehan	vm_offset_t	_start;
555152179Sgrehan	int		_count;
556152179Sgrehan};
557152179Sgrehan
558152179Sgrehan
559152179Sgrehan/**
560152179Sgrehan * @brief Release per-pmap resources, e.g. mutexes, allocated memory etc. There
561152179Sgrehan * should be no existing mappings for the physical map at this point
562152179Sgrehan *
563152179Sgrehan * @param _pmap		physical map
564152179Sgrehan */
565152179SgrehanMETHOD void release {
566152179Sgrehan	mmu_t		_mmu;
567152179Sgrehan	pmap_t		_pmap;
568152179Sgrehan};
569152179Sgrehan
570152179Sgrehan
571152179Sgrehan/**
572152179Sgrehan * @brief Remove all mappings in the given physical map for the start/end
573152179Sgrehan * virtual address range. The range will be page-aligned.
574152179Sgrehan *
575152179Sgrehan * @param _pmap		physical map
576152179Sgrehan * @param _start	mapping virtual address start
577152179Sgrehan * @param _end		mapping virtual address end
578152179Sgrehan */
579152179SgrehanMETHOD void remove {
580152179Sgrehan	mmu_t		_mmu;
581152179Sgrehan	pmap_t		_pmap;
582152179Sgrehan	vm_offset_t	_start;
583152179Sgrehan	vm_offset_t	_end;
584152179Sgrehan};
585152179Sgrehan
586152179Sgrehan
587152179Sgrehan/**
588152179Sgrehan * @brief Traverse the reverse-map list off the given physical page and
589225418Skib * remove all mappings. Clear the PGA_WRITEABLE attribute from the page.
590152179Sgrehan *
591152179Sgrehan * @param _pg		physical page
592152179Sgrehan */
593152179SgrehanMETHOD void remove_all {
594152179Sgrehan	mmu_t		_mmu;
595152179Sgrehan	vm_page_t	_pg;
596152179Sgrehan};
597152179Sgrehan
598152179Sgrehan
599152179Sgrehan/**
600152179Sgrehan * @brief Remove all mappings in the given start/end virtual address range
601152179Sgrehan * for the given physical map. Similar to the remove method, but it used
602152179Sgrehan * when tearing down all mappings in an address space. This method is
603152179Sgrehan * optional, since pmap_remove will be called for each valid vm_map in
604152179Sgrehan * the address space later.
605152179Sgrehan *
606152179Sgrehan * @param _pmap		physical map
607152179Sgrehan * @param _start	mapping virtual address start
608152179Sgrehan * @param _end		mapping virtual address end
609152179Sgrehan */
610152179SgrehanMETHOD void remove_pages {
611152179Sgrehan	mmu_t		_mmu;
612152179Sgrehan	pmap_t		_pmap;
613152179Sgrehan} DEFAULT mmu_null_remove_pages;
614152179Sgrehan
615152179Sgrehan
616152179Sgrehan/**
617270920Skib * @brief Clear the wired attribute from the mappings for the specified range
618270920Skib * of addresses in the given pmap.
619270920Skib *
620270920Skib * @param _pmap		physical map
621270920Skib * @param _start	virtual range start
622270920Skib * @param _end		virtual range end
623270920Skib */
624270920SkibMETHOD void unwire {
625270920Skib	mmu_t		_mmu;
626270920Skib	pmap_t		_pmap;
627270920Skib	vm_offset_t	_start;
628270920Skib	vm_offset_t	_end;
629270920Skib};
630270920Skib
631270920Skib
632270920Skib/**
633152179Sgrehan * @brief Zero a physical page. It is not assumed that the page is mapped,
634152179Sgrehan * so a temporary (or direct) mapping may need to be used.
635152179Sgrehan *
636152179Sgrehan * @param _pg		physical page
637152179Sgrehan */
638152179SgrehanMETHOD void zero_page {
639152179Sgrehan	mmu_t		_mmu;
640152179Sgrehan	vm_page_t	_pg;
641152179Sgrehan};
642152179Sgrehan
643152179Sgrehan
644152179Sgrehan/**
645152179Sgrehan * @brief Zero a portion of a physical page, starting at a given offset and
646152179Sgrehan * for a given size (multiples of 512 bytes for 4k pages).
647152179Sgrehan *
648152179Sgrehan * @param _pg		physical page
649152179Sgrehan * @param _off		byte offset from start of page
650152179Sgrehan * @param _size		size of area to zero
651152179Sgrehan */
652152179SgrehanMETHOD void zero_page_area {
653152179Sgrehan	mmu_t		_mmu;
654152179Sgrehan	vm_page_t	_pg;
655152179Sgrehan	int		_off;
656152179Sgrehan	int		_size;
657152179Sgrehan};
658152179Sgrehan
659152179Sgrehan
660152179Sgrehan/**
661152179Sgrehan * @brief Called from the idle loop to zero pages. XXX I think locking
662152179Sgrehan * constraints might be different here compared to zero_page.
663152179Sgrehan *
664152179Sgrehan * @param _pg		physical page
665152179Sgrehan */
666152179SgrehanMETHOD void zero_page_idle {
667152179Sgrehan	mmu_t		_mmu;
668152179Sgrehan	vm_page_t	_pg;
669152179Sgrehan};
670152179Sgrehan
671152179Sgrehan
672152179Sgrehan/**
673208504Salc * @brief Extract mincore(2) information from a mapping.
674152179Sgrehan *
675152179Sgrehan * @param _pmap		physical map
676152179Sgrehan * @param _addr		page virtual address
677208504Salc * @param _locked_pa	page physical address
678152179Sgrehan *
679152179Sgrehan * @retval 0		no result
680152179Sgrehan * @retval non-zero	mincore(2) flag values
681152179Sgrehan */
682152179SgrehanMETHOD int mincore {
683152179Sgrehan	mmu_t		_mmu;
684152179Sgrehan	pmap_t		_pmap;
685152179Sgrehan	vm_offset_t	_addr;
686208504Salc	vm_paddr_t	*_locked_pa;
687152179Sgrehan} DEFAULT mmu_null_mincore;
688152179Sgrehan
689152179Sgrehan
690152179Sgrehan/**
691152179Sgrehan * @brief Perform any operations required to allow a physical map to be used
692152179Sgrehan * before it's address space is accessed.
693152179Sgrehan *
694152179Sgrehan * @param _td		thread associated with physical map
695152179Sgrehan */
696152179SgrehanMETHOD void activate {
697152179Sgrehan	mmu_t		_mmu;
698152179Sgrehan	struct thread	*_td;
699152179Sgrehan};
700152179Sgrehan
701152179Sgrehan/**
702152179Sgrehan * @brief Perform any operations required to deactivate a physical map,
703152179Sgrehan * for instance as it is context-switched out.
704152179Sgrehan *
705152179Sgrehan * @param _td		thread associated with physical map
706152179Sgrehan */
707152179SgrehanMETHOD void deactivate {
708152179Sgrehan	mmu_t		_mmu;
709152179Sgrehan	struct thread	*_td;
710152179Sgrehan} DEFAULT mmu_null_deactivate;
711152179Sgrehan
712152179Sgrehan/**
713152179Sgrehan * @brief Return a hint for the best virtual address to map a tentative
714152179Sgrehan * virtual address range in a given VM object. The default is to just
715152179Sgrehan * return the given tentative start address.
716152179Sgrehan *
717152179Sgrehan * @param _obj		VM backing object
718179081Salc * @param _offset	starting offset with the VM object
719152179Sgrehan * @param _addr		initial guess at virtual address
720152179Sgrehan * @param _size		size of virtual address range
721152179Sgrehan */
722179081SalcMETHOD void align_superpage {
723152179Sgrehan	mmu_t		_mmu;
724152179Sgrehan	vm_object_t	_obj;
725179081Salc	vm_ooffset_t	_offset;
726179081Salc	vm_offset_t	*_addr;
727152179Sgrehan	vm_size_t	_size;
728179081Salc} DEFAULT mmu_null_align_superpage;
729152179Sgrehan
730152179Sgrehan
731152179Sgrehan
732152179Sgrehan
733152179Sgrehan/**
734152179Sgrehan * INTERNAL INTERFACES
735152179Sgrehan */
736152179Sgrehan
737152179Sgrehan/**
738152179Sgrehan * @brief Bootstrap the VM system. At the completion of this routine, the
739152179Sgrehan * kernel will be running in it's own address space with full control over
740152179Sgrehan * paging.
741152179Sgrehan *
742152179Sgrehan * @param _start	start of reserved memory (obsolete ???)
743152179Sgrehan * @param _end		end of reserved memory (obsolete ???)
744152179Sgrehan *			XXX I think the intent of these was to allow
745152179Sgrehan *			the memory used by kernel text+data+bss and
746152179Sgrehan *			loader variables/load-time kld's to be carved out
747152179Sgrehan *			of available physical mem.
748152179Sgrehan *
749152179Sgrehan */
750152179SgrehanMETHOD void bootstrap {
751152179Sgrehan	mmu_t		_mmu;
752152179Sgrehan	vm_offset_t	_start;
753152179Sgrehan	vm_offset_t	_end;
754152179Sgrehan};
755152179Sgrehan
756190681Snwhitehorn/**
757190681Snwhitehorn * @brief Set up the MMU on the current CPU. Only called by the PMAP layer
758190681Snwhitehorn * for alternate CPUs on SMP systems.
759190681Snwhitehorn *
760190681Snwhitehorn * @param _ap		Set to 1 if the CPU being set up is an AP
761190681Snwhitehorn *
762190681Snwhitehorn */
763190681SnwhitehornMETHOD void cpu_bootstrap {
764190681Snwhitehorn	mmu_t		_mmu;
765190681Snwhitehorn	int		_ap;
766190681Snwhitehorn};
767152179Sgrehan
768190681Snwhitehorn
769152179Sgrehan/**
770152179Sgrehan * @brief Create a kernel mapping for a given physical address range.
771152179Sgrehan * Called by bus code on behalf of device drivers. The mapping does not
772152179Sgrehan * have to be a virtual address: it can be a direct-mapped physical address
773152179Sgrehan * if that is supported by the MMU.
774152179Sgrehan *
775152179Sgrehan * @param _pa		start physical address
776152179Sgrehan * @param _size		size in bytes of mapping
777152179Sgrehan *
778152179Sgrehan * @retval addr		address of mapping.
779152179Sgrehan */
780152179SgrehanMETHOD void * mapdev {
781152179Sgrehan	mmu_t		_mmu;
782236000Sraj	vm_paddr_t	_pa;
783152179Sgrehan	vm_size_t	_size;
784152179Sgrehan};
785152179Sgrehan
786213307Snwhitehorn/**
787213307Snwhitehorn * @brief Create a kernel mapping for a given physical address range.
788213307Snwhitehorn * Called by bus code on behalf of device drivers. The mapping does not
789213307Snwhitehorn * have to be a virtual address: it can be a direct-mapped physical address
790213307Snwhitehorn * if that is supported by the MMU.
791213307Snwhitehorn *
792213307Snwhitehorn * @param _pa		start physical address
793213307Snwhitehorn * @param _size		size in bytes of mapping
794213307Snwhitehorn * @param _attr		cache attributes
795213307Snwhitehorn *
796213307Snwhitehorn * @retval addr		address of mapping.
797213307Snwhitehorn */
798213307SnwhitehornMETHOD void * mapdev_attr {
799213307Snwhitehorn	mmu_t		_mmu;
800213307Snwhitehorn	vm_offset_t	_pa;
801213307Snwhitehorn	vm_size_t	_size;
802213307Snwhitehorn	vm_memattr_t	_attr;
803213307Snwhitehorn} DEFAULT mmu_null_mapdev_attr;
804152179Sgrehan
805152179Sgrehan/**
806213307Snwhitehorn * @brief Change cache control attributes for a page. Should modify all
807213307Snwhitehorn * mappings for that page.
808213307Snwhitehorn *
809213307Snwhitehorn * @param _m		page to modify
810213307Snwhitehorn * @param _ma		new cache control attributes
811213307Snwhitehorn */
812213307SnwhitehornMETHOD void page_set_memattr {
813213307Snwhitehorn	mmu_t		_mmu;
814213307Snwhitehorn	vm_page_t	_pg;
815213307Snwhitehorn	vm_memattr_t	_ma;
816213307Snwhitehorn} DEFAULT mmu_null_page_set_memattr;
817213307Snwhitehorn
818213307Snwhitehorn/**
819152179Sgrehan * @brief Remove the mapping created by mapdev. Called when a driver
820152179Sgrehan * is unloaded.
821152179Sgrehan *
822152179Sgrehan * @param _va		Mapping address returned from mapdev
823152179Sgrehan * @param _size		size in bytes of mapping
824152179Sgrehan */
825152179SgrehanMETHOD void unmapdev {
826152179Sgrehan	mmu_t		_mmu;
827152179Sgrehan	vm_offset_t	_va;
828152179Sgrehan	vm_size_t	_size;
829152179Sgrehan};
830152179Sgrehan
831152179Sgrehan
832152179Sgrehan/**
833152179Sgrehan * @brief Reverse-map a kernel virtual address
834152179Sgrehan *
835152179Sgrehan * @param _va		kernel virtual address to reverse-map
836152179Sgrehan *
837152179Sgrehan * @retval pa		physical address corresponding to mapping
838152179Sgrehan */
839236000SrajMETHOD vm_paddr_t kextract {
840152179Sgrehan	mmu_t		_mmu;
841152179Sgrehan	vm_offset_t	_va;
842152179Sgrehan};
843152179Sgrehan
844152179Sgrehan
845152179Sgrehan/**
846152179Sgrehan * @brief Map a wired page into kernel virtual address space
847152179Sgrehan *
848152179Sgrehan * @param _va		mapping virtual address
849152179Sgrehan * @param _pa		mapping physical address
850152179Sgrehan */
851152179SgrehanMETHOD void kenter {
852152179Sgrehan	mmu_t		_mmu;
853152179Sgrehan	vm_offset_t	_va;
854236000Sraj	vm_paddr_t	_pa;
855152179Sgrehan};
856152179Sgrehan
857213307Snwhitehorn/**
858213307Snwhitehorn * @brief Map a wired page into kernel virtual address space
859213307Snwhitehorn *
860213307Snwhitehorn * @param _va		mapping virtual address
861213307Snwhitehorn * @param _pa		mapping physical address
862213307Snwhitehorn * @param _ma		mapping cache control attributes
863213307Snwhitehorn */
864213307SnwhitehornMETHOD void kenter_attr {
865213307Snwhitehorn	mmu_t		_mmu;
866213307Snwhitehorn	vm_offset_t	_va;
867213307Snwhitehorn	vm_offset_t	_pa;
868213307Snwhitehorn	vm_memattr_t	_ma;
869213307Snwhitehorn} DEFAULT mmu_null_kenter_attr;
870152179Sgrehan
871152179Sgrehan/**
872152179Sgrehan * @brief Determine if the given physical address range has been direct-mapped.
873152179Sgrehan *
874152179Sgrehan * @param _pa		physical address start
875152179Sgrehan * @param _size		physical address range size
876152179Sgrehan *
877152179Sgrehan * @retval bool		TRUE if the range is direct-mapped.
878152179Sgrehan */
879152179SgrehanMETHOD boolean_t dev_direct_mapped {
880152179Sgrehan	mmu_t		_mmu;
881236000Sraj	vm_paddr_t	_pa;
882152179Sgrehan	vm_size_t	_size;
883152179Sgrehan};
884164895Sgrehan
885164895Sgrehan
886164895Sgrehan/**
887198341Smarcel * @brief Enforce instruction cache coherency. Typically called after a
888198341Smarcel * region of memory has been modified and before execution of or within
889198341Smarcel * that region is attempted. Setting breakpoints in a process through
890198341Smarcel * ptrace(2) is one example of when the instruction cache needs to be
891198341Smarcel * made coherent.
892164895Sgrehan *
893198341Smarcel * @param _pm		the physical map of the virtual address
894198341Smarcel * @param _va		the virtual address of the modified region
895198341Smarcel * @param _sz		the size of the modified region
896164895Sgrehan */
897198341SmarcelMETHOD void sync_icache {
898164895Sgrehan	mmu_t		_mmu;
899198341Smarcel	pmap_t		_pm;
900198341Smarcel	vm_offset_t	_va;
901198341Smarcel	vm_size_t	_sz;
902164895Sgrehan};
903164895Sgrehan
904190684Smarcel
905190684Smarcel/**
906190684Smarcel * @brief Create temporary memory mapping for use by dumpsys().
907190684Smarcel *
908190684Smarcel * @param _md		The memory chunk in which the mapping lies.
909190684Smarcel * @param _ofs		The offset within the chunk of the mapping.
910190684Smarcel * @param _sz		The requested size of the mapping.
911190684Smarcel *
912190684Smarcel * @retval vm_offset_t	The virtual address of the mapping.
913190684Smarcel *			
914190684Smarcel * The sz argument is modified to reflect the actual size of the
915190684Smarcel * mapping.
916190684Smarcel */
917190684SmarcelMETHOD vm_offset_t dumpsys_map {
918190684Smarcel	mmu_t		_mmu;
919190684Smarcel	struct pmap_md	*_md;
920190684Smarcel	vm_size_t	_ofs;
921190684Smarcel	vm_size_t	*_sz;
922190684Smarcel};
923190684Smarcel
924190684Smarcel
925190684Smarcel/**
926190684Smarcel * @brief Remove temporary dumpsys() mapping.
927190684Smarcel *
928190684Smarcel * @param _md		The memory chunk in which the mapping lies.
929190684Smarcel * @param _ofs		The offset within the chunk of the mapping.
930190684Smarcel * @param _va		The virtual address of the mapping.
931190684Smarcel */
932190684SmarcelMETHOD void dumpsys_unmap {
933190684Smarcel	mmu_t		_mmu;
934190684Smarcel	struct pmap_md	*_md;
935190684Smarcel	vm_size_t	_ofs;
936190684Smarcel	vm_offset_t	_va;
937190684Smarcel};
938190684Smarcel
939190684Smarcel
940190684Smarcel/**
941190684Smarcel * @brief Scan/iterate memory chunks.
942190684Smarcel *
943190684Smarcel * @param _prev		The previously returned chunk or NULL.
944190684Smarcel *
945190684Smarcel * @retval		The next (or first when _prev is NULL) chunk.
946190684Smarcel */
947190684SmarcelMETHOD struct pmap_md * scan_md {
948190684Smarcel	mmu_t		_mmu;
949190684Smarcel	struct pmap_md	*_prev;
950190684Smarcel} DEFAULT mmu_null_scan_md;
951