1/* 2 * Copyright (c) 2000-2012 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * @OSF_COPYRIGHT@ 30 */ 31/* 32 * Mach Operating System 33 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University 34 * All Rights Reserved. 35 * 36 * Permission to use, copy, modify and distribute this software and its 37 * documentation is hereby granted, provided that both the copyright 38 * notice and this permission notice appear in all copies of the 39 * software, derivative works or modified versions, and any portions 40 * thereof, and that both notices appear in supporting documentation. 41 * 42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 45 * 46 * Carnegie Mellon requests users of this software to return to 47 * 48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 49 * School of Computer Science 50 * Carnegie Mellon University 51 * Pittsburgh PA 15213-3890 52 * 53 * any improvements or extensions that they make and grant Carnegie Mellon 54 * the rights to redistribute these changes. 55 */ 56/* 57 */ 58/* 59 * File: vm/pmap.h 60 * Author: Avadis Tevanian, Jr. 61 * Date: 1985 62 * 63 * Machine address mapping definitions -- machine-independent 64 * section. [For machine-dependent section, see "machine/pmap.h".] 65 */ 66 67#ifndef _VM_PMAP_H_ 68#define _VM_PMAP_H_ 69 70#include <mach/kern_return.h> 71#include <mach/vm_param.h> 72#include <mach/vm_types.h> 73#include <mach/vm_attributes.h> 74#include <mach/boolean.h> 75#include <mach/vm_prot.h> 76 77#ifdef KERNEL_PRIVATE 78 79/* 80 * The following is a description of the interface to the 81 * machine-dependent "physical map" data structure. The module 82 * must provide a "pmap_t" data type that represents the 83 * set of valid virtual-to-physical addresses for one user 84 * address space. [The kernel address space is represented 85 * by a distinguished "pmap_t".] The routines described manage 86 * this type, install and update virtual-to-physical mappings, 87 * and perform operations on physical addresses common to 88 * many address spaces. 89 */ 90 91/* Copy between a physical page and a virtual address */ 92/* LP64todo - switch to vm_map_offset_t when it grows */ 93extern kern_return_t copypv( 94 addr64_t source, 95 addr64_t sink, 96 unsigned int size, 97 int which); 98#define cppvPsnk 1 99#define cppvPsnkb 31 100#define cppvPsrc 2 101#define cppvPsrcb 30 102#define cppvFsnk 4 103#define cppvFsnkb 29 104#define cppvFsrc 8 105#define cppvFsrcb 28 106#define cppvNoModSnk 16 107#define cppvNoModSnkb 27 108#define cppvNoRefSrc 32 109#define cppvNoRefSrcb 26 110#define cppvKmap 64 /* Use the kernel's vm_map */ 111#define cppvKmapb 25 112 113#ifdef MACH_KERNEL_PRIVATE 114 115#include <machine/pmap.h> 116 117/* 118 * Routines used for initialization. 119 * There is traditionally also a pmap_bootstrap, 120 * used very early by machine-dependent code, 121 * but it is not part of the interface. 122 * 123 * LP64todo - 124 * These interfaces are tied to the size of the 125 * kernel pmap - and therefore use the "local" 126 * vm_offset_t, etc... types. 127 */ 128 129extern void *pmap_steal_memory(vm_size_t size); 130 /* During VM initialization, 131 * steal a chunk of memory. 132 */ 133extern unsigned int pmap_free_pages(void); /* During VM initialization, 134 * report remaining unused 135 * physical pages. 136 */ 137extern void pmap_startup( 138 vm_offset_t *startp, 139 vm_offset_t *endp); 140 /* During VM initialization, 141 * use remaining physical pages 142 * to allocate page frames. 143 */ 144extern void pmap_init(void); 145 /* Initialization, 146 * after kernel runs 147 * in virtual memory. 148 */ 149 150extern void mapping_adjust(void); /* Adjust free mapping count */ 151 152extern void mapping_free_prime(void); /* Primes the mapping block release list */ 153 154#ifndef MACHINE_PAGES 155/* 156 * If machine/pmap.h defines MACHINE_PAGES, it must implement 157 * the above functions. The pmap module has complete control. 158 * Otherwise, it must implement 159 * pmap_free_pages 160 * pmap_virtual_space 161 * pmap_next_page 162 * pmap_init 163 * and vm/vm_resident.c implements pmap_steal_memory and pmap_startup 164 * using pmap_free_pages, pmap_next_page, pmap_virtual_space, 165 * and pmap_enter. pmap_free_pages may over-estimate the number 166 * of unused physical pages, and pmap_next_page may return FALSE 167 * to indicate that there are no more unused pages to return. 168 * However, for best performance pmap_free_pages should be accurate. 169 */ 170 171extern boolean_t pmap_next_page(ppnum_t *pnum); 172extern boolean_t pmap_next_page_hi(ppnum_t *pnum); 173 /* During VM initialization, 174 * return the next unused 175 * physical page. 176 */ 177extern void pmap_virtual_space( 178 vm_offset_t *virtual_start, 179 vm_offset_t *virtual_end); 180 /* During VM initialization, 181 * report virtual space 182 * available for the kernel. 183 */ 184#endif /* MACHINE_PAGES */ 185 186/* 187 * Routines to manage the physical map data structure. 188 */ 189extern pmap_t pmap_create( /* Create a pmap_t. */ 190 ledger_t ledger, 191 vm_map_size_t size, 192 __unused boolean_t is_64bit); 193extern pmap_t (pmap_kernel)(void); /* Return the kernel's pmap */ 194extern void pmap_reference(pmap_t pmap); /* Gain a reference. */ 195extern void pmap_destroy(pmap_t pmap); /* Release a reference. */ 196extern void pmap_switch(pmap_t); 197 198 199extern void pmap_enter( /* Enter a mapping */ 200 pmap_t pmap, 201 vm_map_offset_t v, 202 ppnum_t pn, 203 vm_prot_t prot, 204 vm_prot_t fault_type, 205 unsigned int flags, 206 boolean_t wired); 207 208extern kern_return_t pmap_enter_options( 209 pmap_t pmap, 210 vm_map_offset_t v, 211 ppnum_t pn, 212 vm_prot_t prot, 213 vm_prot_t fault_type, 214 unsigned int flags, 215 boolean_t wired, 216 unsigned int options, 217 void *arg); 218 219extern void pmap_remove_some_phys( 220 pmap_t pmap, 221 ppnum_t pn); 222 223 224/* 225 * Routines that operate on physical addresses. 226 */ 227 228extern void pmap_page_protect( /* Restrict access to page. */ 229 ppnum_t phys, 230 vm_prot_t prot); 231 232extern void pmap_page_protect_options( /* Restrict access to page. */ 233 ppnum_t phys, 234 vm_prot_t prot, 235 unsigned int options, 236 void *arg); 237 238extern void (pmap_zero_page)( 239 ppnum_t pn); 240 241extern void (pmap_zero_part_page)( 242 ppnum_t pn, 243 vm_offset_t offset, 244 vm_size_t len); 245 246extern void (pmap_copy_page)( 247 ppnum_t src, 248 ppnum_t dest); 249 250extern void (pmap_copy_part_page)( 251 ppnum_t src, 252 vm_offset_t src_offset, 253 ppnum_t dst, 254 vm_offset_t dst_offset, 255 vm_size_t len); 256 257extern void (pmap_copy_part_lpage)( 258 vm_offset_t src, 259 ppnum_t dst, 260 vm_offset_t dst_offset, 261 vm_size_t len); 262 263extern void (pmap_copy_part_rpage)( 264 ppnum_t src, 265 vm_offset_t src_offset, 266 vm_offset_t dst, 267 vm_size_t len); 268 269extern unsigned int (pmap_disconnect)( /* disconnect mappings and return reference and change */ 270 ppnum_t phys); 271 272extern unsigned int (pmap_disconnect_options)( /* disconnect mappings and return reference and change */ 273 ppnum_t phys, 274 unsigned int options, 275 void *arg); 276 277extern kern_return_t (pmap_attribute_cache_sync)( /* Flush appropriate 278 * cache based on 279 * page number sent */ 280 ppnum_t pn, 281 vm_size_t size, 282 vm_machine_attribute_t attribute, 283 vm_machine_attribute_val_t* value); 284 285extern unsigned int (pmap_cache_attributes)( 286 ppnum_t pn); 287 288/* 289 * Set (override) cache attributes for the specified physical page 290 */ 291extern void pmap_set_cache_attributes( 292 ppnum_t, 293 unsigned int); 294extern void pmap_sync_page_data_phys(ppnum_t pa); 295extern void pmap_sync_page_attributes_phys(ppnum_t pa); 296 297/* 298 * debug/assertions. pmap_verify_free returns true iff 299 * the given physical page is mapped into no pmap. 300 */ 301extern boolean_t pmap_verify_free(ppnum_t pn); 302 303/* 304 * Statistics routines 305 */ 306extern int (pmap_resident_count)(pmap_t pmap); 307extern int (pmap_resident_max)(pmap_t pmap); 308 309/* 310 * Sundry required (internal) routines 311 */ 312#ifdef CURRENTLY_UNUSED_AND_UNTESTED 313extern void pmap_collect(pmap_t pmap);/* Perform garbage 314 * collection, if any */ 315#endif 316/* 317 * Optional routines 318 */ 319extern void (pmap_copy)( /* Copy range of mappings, 320 * if desired. */ 321 pmap_t dest, 322 pmap_t source, 323 vm_map_offset_t dest_va, 324 vm_map_size_t size, 325 vm_map_offset_t source_va); 326 327extern kern_return_t (pmap_attribute)( /* Get/Set special memory 328 * attributes */ 329 pmap_t pmap, 330 vm_map_offset_t va, 331 vm_map_size_t size, 332 vm_machine_attribute_t attribute, 333 vm_machine_attribute_val_t* value); 334 335/* 336 * Routines defined as macros. 337 */ 338#ifndef PMAP_ACTIVATE_USER 339#ifndef PMAP_ACTIVATE 340#define PMAP_ACTIVATE_USER(thr, cpu) 341#else /* PMAP_ACTIVATE */ 342#define PMAP_ACTIVATE_USER(thr, cpu) { \ 343 pmap_t pmap; \ 344 \ 345 pmap = (thr)->map->pmap; \ 346 if (pmap != pmap_kernel()) \ 347 PMAP_ACTIVATE(pmap, (thr), (cpu)); \ 348} 349#endif /* PMAP_ACTIVATE */ 350#endif /* PMAP_ACTIVATE_USER */ 351 352#ifndef PMAP_DEACTIVATE_USER 353#ifndef PMAP_DEACTIVATE 354#define PMAP_DEACTIVATE_USER(thr, cpu) 355#else /* PMAP_DEACTIVATE */ 356#define PMAP_DEACTIVATE_USER(thr, cpu) { \ 357 pmap_t pmap; \ 358 \ 359 pmap = (thr)->map->pmap; \ 360 if ((pmap) != pmap_kernel()) \ 361 PMAP_DEACTIVATE(pmap, (thr), (cpu)); \ 362} 363#endif /* PMAP_DEACTIVATE */ 364#endif /* PMAP_DEACTIVATE_USER */ 365 366#ifndef PMAP_ACTIVATE_KERNEL 367#ifndef PMAP_ACTIVATE 368#define PMAP_ACTIVATE_KERNEL(cpu) 369#else /* PMAP_ACTIVATE */ 370#define PMAP_ACTIVATE_KERNEL(cpu) \ 371 PMAP_ACTIVATE(pmap_kernel(), THREAD_NULL, cpu) 372#endif /* PMAP_ACTIVATE */ 373#endif /* PMAP_ACTIVATE_KERNEL */ 374 375#ifndef PMAP_DEACTIVATE_KERNEL 376#ifndef PMAP_DEACTIVATE 377#define PMAP_DEACTIVATE_KERNEL(cpu) 378#else /* PMAP_DEACTIVATE */ 379#define PMAP_DEACTIVATE_KERNEL(cpu) \ 380 PMAP_DEACTIVATE(pmap_kernel(), THREAD_NULL, cpu) 381#endif /* PMAP_DEACTIVATE */ 382#endif /* PMAP_DEACTIVATE_KERNEL */ 383 384#ifndef PMAP_ENTER 385/* 386 * Macro to be used in place of pmap_enter() 387 */ 388#define PMAP_ENTER(pmap, virtual_address, page, protection, fault_type, flags, wired) \ 389 MACRO_BEGIN \ 390 pmap_t __pmap = (pmap); \ 391 vm_page_t __page = (page); \ 392 int __options = 0; \ 393 \ 394 PMAP_ENTER_CHECK(__pmap, __page) \ 395 if (__page->object->internal) { \ 396 __options |= PMAP_OPTIONS_INTERNAL; \ 397 } \ 398 if (__page->reusable || __page->object->all_reusable) { \ 399 __options |= PMAP_OPTIONS_REUSABLE; \ 400 } \ 401 (void) pmap_enter_options(__pmap, \ 402 (virtual_address), \ 403 __page->phys_page, \ 404 (protection), \ 405 (fault_type), \ 406 (flags), \ 407 (wired), \ 408 __options, \ 409 NULL); \ 410 MACRO_END 411#endif /* !PMAP_ENTER */ 412 413#ifndef PMAP_ENTER_OPTIONS 414#define PMAP_ENTER_OPTIONS(pmap, virtual_address, page, protection, \ 415 fault_type, flags, wired, options, result) \ 416 MACRO_BEGIN \ 417 pmap_t __pmap = (pmap); \ 418 vm_page_t __page = (page); \ 419 int __extra_options = 0; \ 420 \ 421 PMAP_ENTER_CHECK(__pmap, __page) \ 422 if (__page->object->internal) { \ 423 __extra_options |= PMAP_OPTIONS_INTERNAL; \ 424 } \ 425 if (__page->reusable || __page->object->all_reusable) { \ 426 __extra_options |= PMAP_OPTIONS_REUSABLE; \ 427 } \ 428 result = pmap_enter_options(__pmap, \ 429 (virtual_address), \ 430 __page->phys_page, \ 431 (protection), \ 432 (fault_type), \ 433 (flags), \ 434 (wired), \ 435 (options) | __extra_options, \ 436 NULL); \ 437 MACRO_END 438#endif /* !PMAP_ENTER_OPTIONS */ 439 440#ifndef PMAP_SET_CACHE_ATTR 441#define PMAP_SET_CACHE_ATTR(mem, object, cache_attr, batch_pmap_op) \ 442 MACRO_BEGIN \ 443 if (!batch_pmap_op) { \ 444 pmap_set_cache_attributes(mem->phys_page, cache_attr); \ 445 object->set_cache_attr = TRUE; \ 446 } \ 447 MACRO_END 448#endif /* PMAP_SET_CACHE_ATTR */ 449 450#ifndef PMAP_BATCH_SET_CACHE_ATTR 451#define PMAP_BATCH_SET_CACHE_ATTR(object, user_page_list, \ 452 cache_attr, num_pages, batch_pmap_op) \ 453 MACRO_BEGIN \ 454 if ((batch_pmap_op)) { \ 455 unsigned int __page_idx=0; \ 456 while (__page_idx < (num_pages)) { \ 457 pmap_set_cache_attributes( \ 458 user_page_list[__page_idx].phys_addr, \ 459 (cache_attr)); \ 460 __page_idx++; \ 461 } \ 462 (object)->set_cache_attr = TRUE; \ 463 } \ 464 MACRO_END 465#endif /* PMAP_BATCH_SET_CACHE_ATTR */ 466 467#define PMAP_ENTER_CHECK(pmap, page) \ 468{ \ 469 if ((pmap) != kernel_pmap) { \ 470 ASSERT_PAGE_DECRYPTED(page); \ 471 } \ 472 if ((page)->error) { \ 473 panic("VM page %p should not have an error\n", \ 474 (page)); \ 475 } \ 476} 477 478/* 479 * Routines to manage reference/modify bits based on 480 * physical addresses, simulating them if not provided 481 * by the hardware. 482 */ 483struct pfc { 484 long pfc_cpus; 485 long pfc_invalid_global; 486}; 487 488typedef struct pfc pmap_flush_context; 489 490 /* Clear reference bit */ 491extern void pmap_clear_reference(ppnum_t pn); 492 /* Return reference bit */ 493extern boolean_t (pmap_is_referenced)(ppnum_t pn); 494 /* Set modify bit */ 495extern void pmap_set_modify(ppnum_t pn); 496 /* Clear modify bit */ 497extern void pmap_clear_modify(ppnum_t pn); 498 /* Return modify bit */ 499extern boolean_t pmap_is_modified(ppnum_t pn); 500 /* Return modified and referenced bits */ 501extern unsigned int pmap_get_refmod(ppnum_t pn); 502 /* Clear modified and referenced bits */ 503extern void pmap_clear_refmod(ppnum_t pn, unsigned int mask); 504#define VM_MEM_MODIFIED 0x01 /* Modified bit */ 505#define VM_MEM_REFERENCED 0x02 /* Referenced bit */ 506extern void pmap_clear_refmod_options(ppnum_t pn, unsigned int mask, unsigned int options, void *); 507 508 509extern void pmap_flush_context_init(pmap_flush_context *); 510extern void pmap_flush(pmap_flush_context *); 511 512/* 513 * Routines that operate on ranges of virtual addresses. 514 */ 515extern void pmap_protect( /* Change protections. */ 516 pmap_t map, 517 vm_map_offset_t s, 518 vm_map_offset_t e, 519 vm_prot_t prot); 520 521extern void pmap_protect_options( /* Change protections. */ 522 pmap_t map, 523 vm_map_offset_t s, 524 vm_map_offset_t e, 525 vm_prot_t prot, 526 unsigned int options, 527 void *arg); 528 529extern void (pmap_pageable)( 530 pmap_t pmap, 531 vm_map_offset_t start, 532 vm_map_offset_t end, 533 boolean_t pageable); 534 535 536extern uint64_t pmap_nesting_size_min; 537extern uint64_t pmap_nesting_size_max; 538 539extern kern_return_t pmap_nest(pmap_t, 540 pmap_t, 541 addr64_t, 542 addr64_t, 543 uint64_t); 544extern kern_return_t pmap_unnest(pmap_t, 545 addr64_t, 546 uint64_t); 547extern boolean_t pmap_adjust_unnest_parameters(pmap_t, vm_map_offset_t *, vm_map_offset_t *); 548#endif /* MACH_KERNEL_PRIVATE */ 549 550extern boolean_t pmap_is_noencrypt(ppnum_t); 551extern void pmap_set_noencrypt(ppnum_t pn); 552extern void pmap_clear_noencrypt(ppnum_t pn); 553 554/* 555 * JMM - This portion is exported to other kernel components right now, 556 * but will be pulled back in the future when the needed functionality 557 * is provided in a cleaner manner. 558 */ 559 560extern pmap_t kernel_pmap; /* The kernel's map */ 561#define pmap_kernel() (kernel_pmap) 562 563/* machine independent WIMG bits */ 564 565#define VM_MEM_GUARDED 0x1 /* (G) Guarded Storage */ 566#define VM_MEM_COHERENT 0x2 /* (M) Memory Coherency */ 567#define VM_MEM_NOT_CACHEABLE 0x4 /* (I) Cache Inhibit */ 568#define VM_MEM_WRITE_THROUGH 0x8 /* (W) Write-Through */ 569 570#define VM_WIMG_USE_DEFAULT 0x80 571#define VM_WIMG_MASK 0xFF 572 573#define VM_MEM_SUPERPAGE 0x100 /* map a superpage instead of a base page */ 574#define VM_MEM_STACK 0x200 575 576#define PMAP_OPTIONS_NOWAIT 0x1 /* don't block, return 577 * KERN_RESOURCE_SHORTAGE 578 * instead */ 579#define PMAP_OPTIONS_NOENTER 0x2 /* expand pmap if needed 580 * but don't enter mapping 581 */ 582#define PMAP_OPTIONS_COMPRESSOR 0x4 /* credit the compressor for 583 * this operation */ 584#define PMAP_OPTIONS_INTERNAL 0x8 /* page from internal object */ 585#define PMAP_OPTIONS_REUSABLE 0x10 /* page is "reusable" */ 586#define PMAP_OPTIONS_NOFLUSH 0x20 /* delay flushing of pmap */ 587#define PMAP_OPTIONS_NOREFMOD 0x40 /* don't need ref/mod on disconnect */ 588#define PMAP_OPTIONS_REMOVE 0x100 /* removing a mapping */ 589 590#if !defined(__LP64__) 591extern vm_offset_t pmap_extract(pmap_t pmap, 592 vm_map_offset_t va); 593#endif 594extern void pmap_change_wiring( /* Specify pageability */ 595 pmap_t pmap, 596 vm_map_offset_t va, 597 boolean_t wired); 598 599/* LP64todo - switch to vm_map_offset_t when it grows */ 600extern void pmap_remove( /* Remove mappings. */ 601 pmap_t map, 602 vm_map_offset_t s, 603 vm_map_offset_t e); 604 605extern void pmap_remove_options( /* Remove mappings. */ 606 pmap_t map, 607 vm_map_offset_t s, 608 vm_map_offset_t e, 609 int options); 610 611extern void pmap_reusable( 612 pmap_t map, 613 vm_map_offset_t s, 614 vm_map_offset_t e, 615 boolean_t reusable); 616 617extern void fillPage(ppnum_t pa, unsigned int fill); 618 619extern void pmap_map_sharedpage(task_t task, pmap_t pmap); 620extern void pmap_unmap_sharedpage(pmap_t pmap); 621 622#if defined(__LP64__) 623void pmap_pre_expand(pmap_t pmap, vm_map_offset_t vaddr); 624#endif 625 626unsigned int pmap_query_resident(pmap_t pmap, 627 vm_map_offset_t s, 628 vm_map_offset_t e); 629 630#endif /* KERNEL_PRIVATE */ 631 632#endif /* _VM_PMAP_H_ */ 633