]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/powerpc/powerpc/mmu_if.m
Add a sv_copyout_auxargs() hook in sysentvec.
[FreeBSD/FreeBSD.git] / sys / powerpc / powerpc / mmu_if.m
1 #-
2 # Copyright (c) 2005 Peter Grehan
3 # All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
7 # are met:
8 # 1. Redistributions of source code must retain the above copyright
9 #    notice, this list of conditions and the following disclaimer.
10 # 2. Redistributions in binary form must reproduce the above copyright
11 #    notice, this list of conditions and the following disclaimer in the
12 #    documentation and/or other materials provided with the distribution.
13 #
14 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 # SUCH DAMAGE.
25 #
26 # $FreeBSD$
27 #
28
29 #include <sys/param.h>
30 #include <sys/lock.h>
31 #include <sys/mutex.h>
32 #include <sys/systm.h>
33
34 #include <vm/vm.h>
35 #include <vm/vm_page.h>
36
37 #include <machine/mmuvar.h>
38
39 /**
40  * @defgroup MMU mmu - KObj methods for PowerPC MMU implementations
41  * @brief A set of methods required by all MMU implementations. These
42  * are basically direct call-thru's from the pmap machine-dependent
43  * code.
44  * Thanks to Bruce M Simpson's pmap man pages for routine descriptions.
45  *@{
46  */
47
48 INTERFACE mmu;
49
50 #
51 # Default implementations of some methods
52 #
53 CODE {
54         static void mmu_null_copy(mmu_t mmu, pmap_t dst_pmap, pmap_t src_pmap,
55             vm_offset_t dst_addr, vm_size_t len, vm_offset_t src_addr)
56         {
57                 return;
58         }
59
60         static void mmu_null_growkernel(mmu_t mmu, vm_offset_t addr)
61         {
62                 return;
63         }
64
65         static void mmu_null_init(mmu_t mmu)
66         {
67                 return;
68         }
69
70         static boolean_t mmu_null_is_prefaultable(mmu_t mmu, pmap_t pmap,
71             vm_offset_t va)
72         {
73                 return (FALSE);
74         }
75
76         static void mmu_null_object_init_pt(mmu_t mmu, pmap_t pmap,
77             vm_offset_t addr, vm_object_t object, vm_pindex_t index,
78             vm_size_t size)
79         {
80                 return;
81         }
82
83         static void mmu_null_page_init(mmu_t mmu, vm_page_t m)
84         {
85                 return;
86         }
87
88         static void mmu_null_remove_pages(mmu_t mmu, pmap_t pmap)
89         {
90                 return;
91         }
92
93         static int mmu_null_mincore(mmu_t mmu, pmap_t pmap, vm_offset_t addr,
94             vm_paddr_t *pap)
95         {
96                 return (0);
97         }
98
99         static void mmu_null_deactivate(struct thread *td)
100         {
101                 return;
102         }
103
104         static void mmu_null_align_superpage(mmu_t mmu, vm_object_t object,
105             vm_ooffset_t offset, vm_offset_t *addr, vm_size_t size)
106         {
107                 return;
108         }
109
110         static void *mmu_null_mapdev_attr(mmu_t mmu, vm_paddr_t pa,
111             vm_size_t size, vm_memattr_t ma)
112         {
113                 return MMU_MAPDEV(mmu, pa, size);
114         }
115
116         static void mmu_null_kenter_attr(mmu_t mmu, vm_offset_t va,
117             vm_paddr_t pa, vm_memattr_t ma)
118         {
119                 MMU_KENTER(mmu, va, pa);
120         }
121
122         static void mmu_null_page_set_memattr(mmu_t mmu, vm_page_t m,
123             vm_memattr_t ma)
124         {
125                 return;
126         }
127
128         static int mmu_null_change_attr(mmu_t mmu, vm_offset_t va,
129             vm_size_t sz, vm_memattr_t mode)
130         {
131                 return (0);
132         }
133
134         static size_t mmu_null_scan_pmap(mmu_t mmu)
135         {
136                 return (0);
137         }
138
139         static void *mmu_null_dump_pmap_init(mmu_t mmu, unsigned blkpgs)
140         {
141                 return (NULL);
142         }
143
144         static void * mmu_null_dump_pmap(mmu_t mmu, void *ctx, void *buf,
145             u_long *nbytes)
146         {
147                 return (NULL);
148         }
149 };
150
151
152 /**
153  * @brief Apply the given advice to the specified range of addresses within
154  * the given pmap.  Depending on the advice, clear the referenced and/or
155  * modified flags in each mapping and set the mapped page's dirty field.
156  *
157  * @param _pmap         physical map
158  * @param _start        virtual range start
159  * @param _end          virtual range end
160  * @param _advice       advice to apply
161  */
162 METHOD void advise {
163         mmu_t           _mmu;
164         pmap_t          _pmap;
165         vm_offset_t     _start;
166         vm_offset_t     _end;
167         int             _advice;
168 };
169
170
171 /**
172  * @brief Clear the 'modified' bit on the given physical page
173  *
174  * @param _pg           physical page
175  */
176 METHOD void clear_modify {
177         mmu_t           _mmu;
178         vm_page_t       _pg;
179 };
180
181
182 /**
183  * @brief Clear the write and modified bits in each of the given
184  * physical page's mappings
185  *
186  * @param _pg           physical page
187  */
188 METHOD void remove_write {
189         mmu_t           _mmu;
190         vm_page_t       _pg;
191 };
192
193
194 /**
195  * @brief Copy the address range given by the source physical map, virtual
196  * address and length to the destination physical map and virtual address.
197  * This routine is optional (xxx default null implementation ?)
198  *
199  * @param _dst_pmap     destination physical map
200  * @param _src_pmap     source physical map
201  * @param _dst_addr     destination virtual address
202  * @param _len          size of range
203  * @param _src_addr     source virtual address
204  */
205 METHOD void copy {
206         mmu_t           _mmu;
207         pmap_t          _dst_pmap;
208         pmap_t          _src_pmap;
209         vm_offset_t     _dst_addr;
210         vm_size_t       _len;
211         vm_offset_t     _src_addr;
212 } DEFAULT mmu_null_copy;
213
214
215 /**
216  * @brief Copy the source physical page to the destination physical page
217  *
218  * @param _src          source physical page
219  * @param _dst          destination physical page
220  */
221 METHOD void copy_page {
222         mmu_t           _mmu;
223         vm_page_t       _src;
224         vm_page_t       _dst;
225 };
226
227 METHOD void copy_pages {
228         mmu_t           _mmu;
229         vm_page_t       *_ma;
230         vm_offset_t     _a_offset;
231         vm_page_t       *_mb;
232         vm_offset_t     _b_offset;
233         int             _xfersize;
234 };
235
236 /**
237  * @brief Create a mapping between a virtual/physical address pair in the
238  * passed physical map with the specified protection and wiring
239  *
240  * @param _pmap         physical map
241  * @param _va           mapping virtual address
242  * @param _p            mapping physical page
243  * @param _prot         mapping page protection
244  * @param _flags        pmap_enter flags
245  * @param _psind        superpage size index
246  */
247 METHOD int enter {
248         mmu_t           _mmu;
249         pmap_t          _pmap;
250         vm_offset_t     _va;
251         vm_page_t       _p;
252         vm_prot_t       _prot;
253         u_int           _flags;
254         int8_t          _psind;
255 };
256
257
258 /**
259  * @brief Maps a sequence of resident pages belonging to the same object.
260  *
261  * @param _pmap         physical map
262  * @param _start        virtual range start
263  * @param _end          virtual range end
264  * @param _m_start      physical page mapped at start
265  * @param _prot         mapping page protection
266  */
267 METHOD void enter_object {
268         mmu_t           _mmu;
269         pmap_t          _pmap;
270         vm_offset_t     _start;
271         vm_offset_t     _end;
272         vm_page_t       _m_start;
273         vm_prot_t       _prot;
274 };
275
276
277 /**
278  * @brief A faster entry point for page mapping where it is possible
279  * to short-circuit some of the tests in pmap_enter.
280  *
281  * @param _pmap         physical map (and also currently active pmap)
282  * @param _va           mapping virtual address
283  * @param _pg           mapping physical page
284  * @param _prot         new page protection - used to see if page is exec.
285  */
286 METHOD void enter_quick {
287         mmu_t           _mmu;
288         pmap_t          _pmap;
289         vm_offset_t     _va;
290         vm_page_t       _pg;
291         vm_prot_t       _prot;
292 };
293
294
295 /**
296  * @brief Reverse map the given virtual address, returning the physical
297  * page associated with the address if a mapping exists.
298  *
299  * @param _pmap         physical map
300  * @param _va           mapping virtual address
301  *
302  * @retval 0            No mapping found
303  * @retval addr         The mapping physical address
304  */
305 METHOD vm_paddr_t extract {
306         mmu_t           _mmu;
307         pmap_t          _pmap;
308         vm_offset_t     _va;
309 };
310
311
312 /**
313  * @brief Reverse map the given virtual address, returning the
314  * physical page if found. The page must be held (by calling
315  * vm_page_hold) if the page protection matches the given protection
316  *
317  * @param _pmap         physical map
318  * @param _va           mapping virtual address
319  * @param _prot         protection used to determine if physical page
320  *                      should be locked
321  *
322  * @retval NULL         No mapping found
323  * @retval page         Pointer to physical page. Held if protections match
324  */
325 METHOD vm_page_t extract_and_hold {
326         mmu_t           _mmu;
327         pmap_t          _pmap;
328         vm_offset_t     _va;
329         vm_prot_t       _prot;
330 };
331
332
333 /**
334  * @brief Increase kernel virtual address space to the given virtual address.
335  * Not really required for PowerPC, so optional unless the MMU implementation
336  * can use it.
337  *
338  * @param _va           new upper limit for kernel virtual address space
339  */
340 METHOD void growkernel {
341         mmu_t           _mmu;
342         vm_offset_t     _va;
343 } DEFAULT mmu_null_growkernel;
344
345
346 /**
347  * @brief Called from vm_mem_init. Zone allocation is available at
348  * this stage so a convenient time to create zones. This routine is
349  * for MMU-implementation convenience and is optional.
350  */
351 METHOD void init {
352         mmu_t           _mmu;
353 } DEFAULT mmu_null_init;
354
355
356 /**
357  * @brief Return if the page has been marked by MMU hardware to have been
358  * modified
359  *
360  * @param _pg           physical page to test
361  *
362  * @retval boolean      TRUE if page has been modified
363  */
364 METHOD boolean_t is_modified {
365         mmu_t           _mmu;
366         vm_page_t       _pg;
367 };
368
369
370 /**
371  * @brief Return whether the specified virtual address is a candidate to be
372  * prefaulted in. This routine is optional.
373  *
374  * @param _pmap         physical map
375  * @param _va           virtual address to test
376  *
377  * @retval boolean      TRUE if the address is a candidate.
378  */
379 METHOD boolean_t is_prefaultable {
380         mmu_t           _mmu;
381         pmap_t          _pmap;
382         vm_offset_t     _va;
383 } DEFAULT mmu_null_is_prefaultable;
384
385
386 /**
387  * @brief Return whether or not the specified physical page was referenced
388  * in any physical maps.
389  *
390  * @params _pg          physical page
391  *
392  * @retval boolean      TRUE if page has been referenced
393  */
394 METHOD boolean_t is_referenced {
395         mmu_t           _mmu;
396         vm_page_t       _pg;
397 };
398
399
400 /**
401  * @brief Return a count of referenced bits for a page, clearing those bits.
402  * Not all referenced bits need to be cleared, but it is necessary that 0
403  * only be returned when there are none set.
404  *
405  * @params _m           physical page
406  *
407  * @retval int          count of referenced bits
408  */
409 METHOD int ts_referenced {
410         mmu_t           _mmu;
411         vm_page_t       _pg;
412 };
413
414
415 /**
416  * @brief Map the requested physical address range into kernel virtual
417  * address space. The value in _virt is taken as a hint. The virtual
418  * address of the range is returned, or NULL if the mapping could not
419  * be created. The range can be direct-mapped if that is supported.
420  *
421  * @param *_virt        Hint for start virtual address, and also return
422  *                      value
423  * @param _start        physical address range start
424  * @param _end          physical address range end
425  * @param _prot         protection of range (currently ignored)
426  *
427  * @retval NULL         could not map the area
428  * @retval addr, *_virt mapping start virtual address
429  */
430 METHOD vm_offset_t map {
431         mmu_t           _mmu;
432         vm_offset_t     *_virt;
433         vm_paddr_t      _start;
434         vm_paddr_t      _end;
435         int             _prot;
436 };
437
438
439 /**
440  * @brief Used to create a contiguous set of read-only mappings for a
441  * given object to try and eliminate a cascade of on-demand faults as
442  * the object is accessed sequentially. This routine is optional.
443  *
444  * @param _pmap         physical map
445  * @param _addr         mapping start virtual address
446  * @param _object       device-backed V.M. object to be mapped
447  * @param _pindex       page-index within object of mapping start
448  * @param _size         size in bytes of mapping
449  */
450 METHOD void object_init_pt {
451         mmu_t           _mmu;
452         pmap_t          _pmap;
453         vm_offset_t     _addr;
454         vm_object_t     _object;
455         vm_pindex_t     _pindex;
456         vm_size_t       _size;
457 } DEFAULT mmu_null_object_init_pt;
458
459
460 /**
461  * @brief Used to determine if the specified page has a mapping for the
462  * given physical map, by scanning the list of reverse-mappings from the
463  * page. The list is scanned to a maximum of 16 entries.
464  *
465  * @param _pmap         physical map
466  * @param _pg           physical page
467  *
468  * @retval bool         TRUE if the physical map was found in the first 16
469  *                      reverse-map list entries off the physical page.
470  */
471 METHOD boolean_t page_exists_quick {
472         mmu_t           _mmu;
473         pmap_t          _pmap;
474         vm_page_t       _pg;
475 };
476
477
478 /**
479  * @brief Initialise the machine-dependent section of the physical page
480  * data structure. This routine is optional.
481  *
482  * @param _pg           physical page
483  */
484 METHOD void page_init {
485         mmu_t           _mmu;
486         vm_page_t       _pg;
487 } DEFAULT mmu_null_page_init;
488
489
490 /**
491  * @brief Count the number of managed mappings to the given physical
492  * page that are wired.
493  *
494  * @param _pg           physical page
495  *
496  * @retval int          the number of wired, managed mappings to the
497  *                      given physical page
498  */
499 METHOD int page_wired_mappings {
500         mmu_t           _mmu;
501         vm_page_t       _pg;
502 };
503
504
505 /**
506  * @brief Initialise a physical map data structure
507  *
508  * @param _pmap         physical map
509  */
510 METHOD void pinit {
511         mmu_t           _mmu;
512         pmap_t          _pmap;
513 };
514
515
516 /**
517  * @brief Initialise the physical map for process 0, the initial process
518  * in the system.
519  * XXX default to pinit ?
520  *
521  * @param _pmap         physical map
522  */
523 METHOD void pinit0 {
524         mmu_t           _mmu;
525         pmap_t          _pmap;
526 };
527
528
529 /**
530  * @brief Set the protection for physical pages in the given virtual address
531  * range to the given value.
532  *
533  * @param _pmap         physical map
534  * @param _start        virtual range start
535  * @param _end          virtual range end
536  * @param _prot         new page protection
537  */
538 METHOD void protect {
539         mmu_t           _mmu;
540         pmap_t          _pmap;
541         vm_offset_t     _start;
542         vm_offset_t     _end;
543         vm_prot_t       _prot;
544 };
545
546
547 /**
548  * @brief Create a mapping in kernel virtual address space for the given array
549  * of wired physical pages.
550  *
551  * @param _start        mapping virtual address start
552  * @param *_m           array of physical page pointers
553  * @param _count        array elements
554  */
555 METHOD void qenter {
556         mmu_t           _mmu;
557         vm_offset_t     _start;
558         vm_page_t       *_pg;
559         int             _count;
560 };
561
562
563 /**
564  * @brief Remove the temporary mappings created by qenter.
565  *
566  * @param _start        mapping virtual address start
567  * @param _count        number of pages in mapping
568  */
569 METHOD void qremove {
570         mmu_t           _mmu;
571         vm_offset_t     _start;
572         int             _count;
573 };
574
575
576 /**
577  * @brief Release per-pmap resources, e.g. mutexes, allocated memory etc. There
578  * should be no existing mappings for the physical map at this point
579  *
580  * @param _pmap         physical map
581  */
582 METHOD void release {
583         mmu_t           _mmu;
584         pmap_t          _pmap;
585 };
586
587
588 /**
589  * @brief Remove all mappings in the given physical map for the start/end
590  * virtual address range. The range will be page-aligned.
591  *
592  * @param _pmap         physical map
593  * @param _start        mapping virtual address start
594  * @param _end          mapping virtual address end
595  */
596 METHOD void remove {
597         mmu_t           _mmu;
598         pmap_t          _pmap;
599         vm_offset_t     _start;
600         vm_offset_t     _end;
601 };
602
603
604 /**
605  * @brief Traverse the reverse-map list off the given physical page and
606  * remove all mappings. Clear the PGA_WRITEABLE attribute from the page.
607  *
608  * @param _pg           physical page
609  */
610 METHOD void remove_all {
611         mmu_t           _mmu;
612         vm_page_t       _pg;
613 };
614
615
616 /**
617  * @brief Remove all mappings in the given start/end virtual address range
618  * for the given physical map. Similar to the remove method, but it used
619  * when tearing down all mappings in an address space. This method is
620  * optional, since pmap_remove will be called for each valid vm_map in
621  * the address space later.
622  *
623  * @param _pmap         physical map
624  * @param _start        mapping virtual address start
625  * @param _end          mapping virtual address end
626  */
627 METHOD void remove_pages {
628         mmu_t           _mmu;
629         pmap_t          _pmap;
630 } DEFAULT mmu_null_remove_pages;
631
632
633 /**
634  * @brief Clear the wired attribute from the mappings for the specified range
635  * of addresses in the given pmap.
636  *
637  * @param _pmap         physical map
638  * @param _start        virtual range start
639  * @param _end          virtual range end
640  */
641 METHOD void unwire {
642         mmu_t           _mmu;
643         pmap_t          _pmap;
644         vm_offset_t     _start;
645         vm_offset_t     _end;
646 };
647
648
649 /**
650  * @brief Zero a physical page. It is not assumed that the page is mapped,
651  * so a temporary (or direct) mapping may need to be used.
652  *
653  * @param _pg           physical page
654  */
655 METHOD void zero_page {
656         mmu_t           _mmu;
657         vm_page_t       _pg;
658 };
659
660
661 /**
662  * @brief Zero a portion of a physical page, starting at a given offset and
663  * for a given size (multiples of 512 bytes for 4k pages).
664  *
665  * @param _pg           physical page
666  * @param _off          byte offset from start of page
667  * @param _size         size of area to zero
668  */
669 METHOD void zero_page_area {
670         mmu_t           _mmu;
671         vm_page_t       _pg;
672         int             _off;
673         int             _size;
674 };
675
676
677 /**
678  * @brief Extract mincore(2) information from a mapping.
679  *
680  * @param _pmap         physical map
681  * @param _addr         page virtual address
682  * @param _pa           page physical address
683  *
684  * @retval 0            no result
685  * @retval non-zero     mincore(2) flag values
686  */
687 METHOD int mincore {
688         mmu_t           _mmu;
689         pmap_t          _pmap;
690         vm_offset_t     _addr;
691         vm_paddr_t      *_pap;
692 } DEFAULT mmu_null_mincore;
693
694
695 /**
696  * @brief Perform any operations required to allow a physical map to be used
697  * before it's address space is accessed.
698  *
699  * @param _td           thread associated with physical map
700  */
701 METHOD void activate {
702         mmu_t           _mmu;
703         struct thread   *_td;
704 };
705
706 /**
707  * @brief Perform any operations required to deactivate a physical map,
708  * for instance as it is context-switched out.
709  *
710  * @param _td           thread associated with physical map
711  */
712 METHOD void deactivate {
713         mmu_t           _mmu;
714         struct thread   *_td;
715 } DEFAULT mmu_null_deactivate;
716
717 /**
718  * @brief Return a hint for the best virtual address to map a tentative
719  * virtual address range in a given VM object. The default is to just
720  * return the given tentative start address.
721  *
722  * @param _obj          VM backing object
723  * @param _offset       starting offset with the VM object
724  * @param _addr         initial guess at virtual address
725  * @param _size         size of virtual address range
726  */
727 METHOD void align_superpage {
728         mmu_t           _mmu;
729         vm_object_t     _obj;
730         vm_ooffset_t    _offset;
731         vm_offset_t     *_addr;
732         vm_size_t       _size;
733 } DEFAULT mmu_null_align_superpage;
734
735
736
737
738 /**
739  * INTERNAL INTERFACES
740  */
741
742 /**
743  * @brief Bootstrap the VM system. At the completion of this routine, the
744  * kernel will be running in its own address space with full control over
745  * paging.
746  *
747  * @param _start        start of reserved memory (obsolete ???)
748  * @param _end          end of reserved memory (obsolete ???)
749  *                      XXX I think the intent of these was to allow
750  *                      the memory used by kernel text+data+bss and
751  *                      loader variables/load-time kld's to be carved out
752  *                      of available physical mem.
753  *
754  */
755 METHOD void bootstrap {
756         mmu_t           _mmu;
757         vm_offset_t     _start;
758         vm_offset_t     _end;
759 };
760
761 /**
762  * @brief Set up the MMU on the current CPU. Only called by the PMAP layer
763  * for alternate CPUs on SMP systems.
764  *
765  * @param _ap           Set to 1 if the CPU being set up is an AP
766  *
767  */
768 METHOD void cpu_bootstrap {
769         mmu_t           _mmu;
770         int             _ap;
771 };
772
773
774 /**
775  * @brief Create a kernel mapping for a given physical address range.
776  * Called by bus code on behalf of device drivers. The mapping does not
777  * have to be a virtual address: it can be a direct-mapped physical address
778  * if that is supported by the MMU.
779  *
780  * @param _pa           start physical address
781  * @param _size         size in bytes of mapping
782  *
783  * @retval addr         address of mapping.
784  */
785 METHOD void * mapdev {
786         mmu_t           _mmu;
787         vm_paddr_t      _pa;
788         vm_size_t       _size;
789 };
790
791 /**
792  * @brief Create a kernel mapping for a given physical address range.
793  * Called by bus code on behalf of device drivers. The mapping does not
794  * have to be a virtual address: it can be a direct-mapped physical address
795  * if that is supported by the MMU.
796  *
797  * @param _pa           start physical address
798  * @param _size         size in bytes of mapping
799  * @param _attr         cache attributes
800  *
801  * @retval addr         address of mapping.
802  */
803 METHOD void * mapdev_attr {
804         mmu_t           _mmu;
805         vm_paddr_t      _pa;
806         vm_size_t       _size;
807         vm_memattr_t    _attr;
808 } DEFAULT mmu_null_mapdev_attr;
809
810 /**
811  * @brief Change cache control attributes for a page. Should modify all
812  * mappings for that page.
813  *
814  * @param _m            page to modify
815  * @param _ma           new cache control attributes
816  */
817 METHOD void page_set_memattr {
818         mmu_t           _mmu;
819         vm_page_t       _pg;
820         vm_memattr_t    _ma;
821 } DEFAULT mmu_null_page_set_memattr;
822
823 /**
824  * @brief Remove the mapping created by mapdev. Called when a driver
825  * is unloaded.
826  *
827  * @param _va           Mapping address returned from mapdev
828  * @param _size         size in bytes of mapping
829  */
830 METHOD void unmapdev {
831         mmu_t           _mmu;
832         vm_offset_t     _va;
833         vm_size_t       _size;
834 };
835
836 /**
837  * @brief Provide a kernel-space pointer that can be used to access the
838  * given userland address. The kernel accessible length returned in klen
839  * may be less than the requested length of the userland buffer (ulen). If
840  * so, retry with a higher address to get access to the later parts of the
841  * buffer. Returns EFAULT if no mapping can be made, else zero.
842  *
843  * @param _pm           PMAP for the user pointer.
844  * @param _uaddr        Userland address to map.
845  * @param _kaddr        Corresponding kernel address.
846  * @param _ulen         Length of user buffer.
847  * @param _klen         Available subset of ulen with _kaddr.
848  */
849 METHOD int map_user_ptr {
850         mmu_t           _mmu;
851         pmap_t          _pm;
852         volatile const void *_uaddr;
853         void            **_kaddr;
854         size_t          _ulen;
855         size_t          *_klen;
856 };
857
858 /**
859  * @brief Decode a kernel pointer, as visible to the current thread,
860  * by setting whether it corresponds to a user or kernel address and
861  * the address in the respective memory maps to which the address as
862  * seen in the kernel corresponds. This is essentially the inverse of
863  * MMU_MAP_USER_PTR() above and is used in kernel-space fault handling.
864  * Returns 0 on success or EFAULT if the address could not be mapped. 
865  */
866 METHOD int decode_kernel_ptr {
867         mmu_t           _mmu;
868         vm_offset_t     addr;
869         int             *is_user;
870         vm_offset_t     *decoded_addr;
871 };
872
873 /**
874  * @brief Reverse-map a kernel virtual address
875  *
876  * @param _va           kernel virtual address to reverse-map
877  *
878  * @retval pa           physical address corresponding to mapping
879  */
880 METHOD vm_paddr_t kextract {
881         mmu_t           _mmu;
882         vm_offset_t     _va;
883 };
884
885
886 /**
887  * @brief Map a wired page into kernel virtual address space
888  *
889  * @param _va           mapping virtual address
890  * @param _pa           mapping physical address
891  */
892 METHOD void kenter {
893         mmu_t           _mmu;
894         vm_offset_t     _va;
895         vm_paddr_t      _pa;
896 };
897
898 /**
899  * @brief Map a wired page into kernel virtual address space
900  *
901  * @param _va           mapping virtual address
902  * @param _pa           mapping physical address
903  * @param _ma           mapping cache control attributes
904  */
905 METHOD void kenter_attr {
906         mmu_t           _mmu;
907         vm_offset_t     _va;
908         vm_paddr_t      _pa;
909         vm_memattr_t    _ma;
910 } DEFAULT mmu_null_kenter_attr;
911
912 /**
913  * @brief Unmap a wired page from kernel virtual address space
914  *
915  * @param _va           mapped virtual address
916  */
917 METHOD void kremove {
918         mmu_t           _mmu;
919         vm_offset_t     _va;
920 };
921
922 /**
923  * @brief Determine if the given physical address range has been direct-mapped.
924  *
925  * @param _pa           physical address start
926  * @param _size         physical address range size
927  *
928  * @retval bool         TRUE if the range is direct-mapped.
929  */
930 METHOD boolean_t dev_direct_mapped {
931         mmu_t           _mmu;
932         vm_paddr_t      _pa;
933         vm_size_t       _size;
934 };
935
936
937 /**
938  * @brief Enforce instruction cache coherency. Typically called after a
939  * region of memory has been modified and before execution of or within
940  * that region is attempted. Setting breakpoints in a process through
941  * ptrace(2) is one example of when the instruction cache needs to be
942  * made coherent.
943  *
944  * @param _pm           the physical map of the virtual address
945  * @param _va           the virtual address of the modified region
946  * @param _sz           the size of the modified region
947  */
948 METHOD void sync_icache {
949         mmu_t           _mmu;
950         pmap_t          _pm;
951         vm_offset_t     _va;
952         vm_size_t       _sz;
953 };
954
955
956 /**
957  * @brief Create temporary memory mapping for use by dumpsys().
958  *
959  * @param _pa           The physical page to map.
960  * @param _sz           The requested size of the mapping.
961  * @param _va           The virtual address of the mapping.
962  */
963 METHOD void dumpsys_map {
964         mmu_t           _mmu;
965         vm_paddr_t      _pa;
966         size_t          _sz;
967         void            **_va;
968 };
969
970
971 /**
972  * @brief Remove temporary dumpsys() mapping.
973  *
974  * @param _pa           The physical page to map.
975  * @param _sz           The requested size of the mapping.
976  * @param _va           The virtual address of the mapping.
977  */
978 METHOD void dumpsys_unmap {
979         mmu_t           _mmu;
980         vm_paddr_t      _pa;
981         size_t          _sz;
982         void            *_va;
983 };
984
985
986 /**
987  * @brief Initialize memory chunks for dumpsys.
988  */
989 METHOD void scan_init {
990         mmu_t           _mmu;
991 };
992
993 /**
994  * @brief Scan kernel PMAP, adding mapped physical pages to dump.
995  *
996  * @retval pmap_size    Number of bytes used by all PTE entries.
997  */
998 METHOD size_t scan_pmap {
999         mmu_t           _mmu;
1000 } DEFAULT mmu_null_scan_pmap;
1001
1002 /**
1003  * @brief Initialize a PMAP dump.
1004  *
1005  * @param _blkpgs       Size of a dump block, in pages.
1006  *
1007  * @retval ctx          Dump context, used by dump_pmap.
1008  */
1009 METHOD void * dump_pmap_init {
1010         mmu_t           _mmu;
1011         unsigned        _blkpgs;
1012 } DEFAULT mmu_null_dump_pmap_init;
1013
1014 /**
1015  * @brief Dump a block of PTEs.
1016  * The size of the dump block is specified in dump_pmap_init and
1017  * the 'buf' argument must be big enough to hold a full block.
1018  * If the page table resides in regular memory, then the 'buf'
1019  * argument is ignored and a pointer to the specified dump block
1020  * is returned instead, avoiding memory copy. Else, the buffer is
1021  * filled with PTEs and the own buffer pointer is returned.
1022  * In the end, the cursor in 'ctx' is adjusted to point to the next block.
1023  *
1024  * @param _ctx          Dump context, retrieved from dump_pmap_init.
1025  * @param _buf          Buffer to hold the dump block contents.
1026  * @param _nbytes       Number of bytes dumped.
1027  *
1028  * @retval NULL         No more blocks to dump.
1029  * @retval buf          Pointer to dumped data (may be different than _buf).
1030  */
1031 METHOD void * dump_pmap {
1032         mmu_t           _mmu;
1033         void            *_ctx;
1034         void            *_buf;
1035         u_long          *_nbytes;
1036 } DEFAULT mmu_null_dump_pmap;
1037
1038 /**
1039  * @brief Create a temporary thread-local KVA mapping of a single page.
1040  *
1041  * @param _pg           The physical page to map
1042  *
1043  * @retval addr         The temporary KVA
1044  */
1045 METHOD vm_offset_t quick_enter_page {
1046         mmu_t           _mmu;
1047         vm_page_t       _pg;
1048 };
1049
1050 /**
1051  * @brief Undo a mapping created by quick_enter_page
1052  *
1053  * @param _va           The mapped KVA
1054  */
1055 METHOD void quick_remove_page {
1056         mmu_t           _mmu;
1057         vm_offset_t     _va;
1058 };
1059
1060 /**
1061  * @brief Change the specified virtual address range's memory type.
1062  *
1063  * @param _va           The virtual base address to change
1064  *
1065  * @param _sz           Size of the region to change
1066  *
1067  * @param _mode         New mode to set on the VA range
1068  *
1069  * @retval error        0 on success, EINVAL or ENOMEM on error.
1070  */
1071 METHOD int change_attr {
1072         mmu_t           _mmu;
1073         vm_offset_t     _va;
1074         vm_size_t       _sz;
1075         vm_memattr_t    _mode;
1076 } DEFAULT mmu_null_change_attr;
1077