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