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