|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * Mach Operating System ! 27: * Copyright (c) 1990,1991,1992 The University of Utah and ! 28: * the Center for Software Science (CSS). ! 29: * Copyright (c) 1991,1987 Carnegie Mellon University. ! 30: * All rights reserved. ! 31: * ! 32: * Permission to use, copy, modify and distribute this software and its ! 33: * documentation is hereby granted, provided that both the copyright ! 34: * notice and this permission notice appear in all copies of the ! 35: * software, derivative works or modified versions, and any portions ! 36: * thereof, and that both notices appear in supporting documentation, ! 37: * and that all advertising materials mentioning features or use of ! 38: * this software display the following acknowledgement: ``This product ! 39: * includes software developed by the Center for Software Science at ! 40: * the University of Utah.'' ! 41: * ! 42: * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSS ALLOW FREE USE OF ! 43: * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY ! 44: * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF ! 45: * THIS SOFTWARE. ! 46: * ! 47: * CSS requests users of this software to return to [email protected] any ! 48: * improvements that they make and grant CSS redistribution rights. ! 49: * ! 50: * Carnegie Mellon requests users of this software to return to ! 51: * Software Distribution Coordinator or [email protected] ! 52: * School of Computer Science ! 53: * Carnegie Mellon University ! 54: * Pittsburgh PA 15213-3890 ! 55: * any improvements or extensions that they make and grant Carnegie Mellon ! 56: * the rights to redistribute these changes. ! 57: * ! 58: * Utah $Hdr: pmap.c 1.28 92/06/23$ ! 59: * Author: Mike Hibler, Bob Wheeler, University of Utah CSS, 10/90 ! 60: */ ! 61: ! 62: /* ! 63: * Manages physical address maps for powerpc. ! 64: * ! 65: * In addition to hardware address maps, this ! 66: * module is called upon to provide software-use-only ! 67: * maps which may or may not be stored in the same ! 68: * form as hardware maps. These pseudo-maps are ! 69: * used to store intermediate results from copy ! 70: * operations to and from address spaces. ! 71: * ! 72: * Since the information managed by this module is ! 73: * also stored by the logical address mapping module, ! 74: * this module may throw away valid virtual-to-physical ! 75: * mappings at almost any time. However, invalidations ! 76: * of virtual-to-physical mappings must be done as ! 77: * requested. ! 78: * ! 79: * In order to cope with hardware architectures which ! 80: * make virtual-to-physical map invalidates expensive, ! 81: * this module may delay invalidate or reduced protection ! 82: * operations until such time as they are actually ! 83: * necessary. This module is given full information to ! 84: * when physical maps must be made correct. ! 85: * ! 86: */ ! 87: ! 88: #include <cpus.h> ! 89: #include <debug.h> ! 90: #include <mach_kgdb.h> ! 91: #include <mach_vm_debug.h> ! 92: #include <db_machine_commands.h> ! 93: ! 94: #include <kern/thread.h> ! 95: #include <mach/vm_attributes.h> ! 96: #include <mach/vm_param.h> ! 97: #include <kern/spl.h> ! 98: ! 99: #include <kern/misc_protos.h> ! 100: #include <ppc/misc_protos.h> ! 101: #include <ppc/proc_reg.h> ! 102: ! 103: #include <vm/pmap.h> ! 104: #include <vm/vm_map.h> ! 105: #include <vm/vm_page.h> ! 106: ! 107: #include <ppc/pmap.h> ! 108: #include <ppc/pmap_internals.h> ! 109: #include <ppc/mem.h> ! 110: #include <ppc/mappings.h> ! 111: ! 112: #include <ppc/new_screen.h> ! 113: #include <ppc/Firmware.h> ! 114: #include <ppc/savearea.h> ! 115: #include <ddb/db_output.h> ! 116: ! 117: #if DB_MACHINE_COMMANDS ! 118: /* optionally enable traces of pmap operations in post-mortem trace table */ ! 119: /* #define PMAP_LOWTRACE 1 */ ! 120: #define PMAP_LOWTRACE 0 ! 121: #else /* DB_MACHINE_COMMANDS */ ! 122: /* Can not trace even if we wanted to */ ! 123: #define PMAP_LOWTRACE 0 ! 124: #endif /* DB_MACHINE_COMMANDS */ ! 125: ! 126: #define PERFTIMES 0 ! 127: ! 128: #if PERFTIMES && DEBUG ! 129: #define debugLog2(a, b, c) dbgLog2(a, b, c) ! 130: #else ! 131: #define debugLog2(a, b, c) ! 132: #endif ! 133: ! 134: extern unsigned int avail_remaining; ! 135: extern unsigned int mappingdeb0; ! 136: extern struct Saveanchor saveanchor; /* Aliged savearea anchor */ ! 137: unsigned int debugbackpocket; /* (TEST/DEBUG) */ ! 138: ! 139: vm_offset_t avail_next; ! 140: vm_offset_t first_free_virt; ! 141: int current_free_region; /* Used in pmap_next_page */ ! 142: ! 143: /* forward */ ! 144: void pmap_activate(pmap_t pmap, thread_t th, int which_cpu); ! 145: void pmap_deactivate(pmap_t pmap, thread_t th, int which_cpu); ! 146: void copy_to_phys(vm_offset_t sva, vm_offset_t dpa, int bytecount); ! 147: ! 148: #if MACH_VM_DEBUG ! 149: int pmap_list_resident_pages(pmap_t pmap, vm_offset_t *listp, int space); ! 150: #endif ! 151: ! 152: #if DEBUG ! 153: #define PDB_USER 0x01 /* exported functions */ ! 154: #define PDB_MAPPING 0x02 /* low-level mapping routines */ ! 155: #define PDB_ENTER 0x04 /* pmap_enter specifics */ ! 156: #define PDB_COPY 0x08 /* copy page debugging */ ! 157: #define PDB_ZERO 0x10 /* zero page debugging */ ! 158: #define PDB_WIRED 0x20 /* things concerning wired entries */ ! 159: #define PDB_PTEG 0x40 /* PTEG overflows */ ! 160: #define PDB_LOCK 0x100 /* locks */ ! 161: #define PDB_IO 0x200 /* Improper use of WIMG_IO checks - PCI machines */ ! 162: ! 163: int pmdebug=0; ! 164: ! 165: #define PCI_BASE 0x80000000 ! 166: #endif ! 167: ! 168: struct pmap kernel_pmap_store; ! 169: pmap_t kernel_pmap; ! 170: struct zone *pmap_zone; /* zone of pmap structures */ ! 171: boolean_t pmap_initialized = FALSE; ! 172: ! 173: /* ! 174: * Physical-to-virtual translations are handled by inverted page table ! 175: * structures, phys_tables. Multiple mappings of a single page are handled ! 176: * by linking the affected mapping structures. We initialise one region ! 177: * for phys_tables of the physical memory we know about, but more may be ! 178: * added as it is discovered (eg. by drivers). ! 179: */ ! 180: struct phys_entry *phys_table; /* For debugging */ ! 181: ! 182: lock_t pmap_system_lock; ! 183: ! 184: decl_simple_lock_data(,tlb_system_lock) ! 185: ! 186: /* ! 187: * free pmap list. caches the first free_pmap_max pmaps that are freed up ! 188: */ ! 189: int free_pmap_max = 32; ! 190: int free_pmap_count; ! 191: queue_head_t free_pmap_list; ! 192: decl_simple_lock_data(,free_pmap_lock) ! 193: ! 194: /* ! 195: * Function to get index into phys_table for a given physical address ! 196: */ ! 197: ! 198: struct phys_entry *pmap_find_physentry(vm_offset_t pa) ! 199: { ! 200: int i; ! 201: struct phys_entry *entry; ! 202: ! 203: for (i = pmap_mem_regions_count-1; i >= 0; i--) { ! 204: if (pa < pmap_mem_regions[i].start) ! 205: continue; ! 206: if (pa >= pmap_mem_regions[i].end) ! 207: return PHYS_NULL; ! 208: ! 209: entry = &pmap_mem_regions[i].phys_table[(pa - pmap_mem_regions[i].start) >> PPC_PGSHIFT]; ! 210: __asm__ volatile("dcbt 0,%0" : : "r" (entry)); /* We will use this in a little bit */ ! 211: return entry; ! 212: } ! 213: kprintf("DEBUG : pmap_find_physentry 0x%08x out of range\n",pa); ! 214: return PHYS_NULL; ! 215: } ! 216: ! 217: /* ! 218: * kern_return_t ! 219: * pmap_add_physical_memory(vm_offset_t spa, vm_offset_t epa, ! 220: * boolean_t available, unsigned int attr) ! 221: * Allocate some extra physentries for the physical addresses given, ! 222: * specifying some default attribute that on the powerpc specifies ! 223: * the default cachability for any mappings using these addresses ! 224: * If the memory is marked as available, it is added to the general ! 225: * VM pool, otherwise it is not (it is reserved for card IO etc). ! 226: */ ! 227: kern_return_t pmap_add_physical_memory(vm_offset_t spa, vm_offset_t epa, ! 228: boolean_t available, unsigned int attr) ! 229: { ! 230: int i,j; ! 231: spl_t s; ! 232: ! 233: /* Only map whole pages */ ! 234: ! 235: panic("Forget it! You can't map no more memory, you greedy puke!\n"); ! 236: ! 237: spa = trunc_page(spa); ! 238: epa = round_page(epa); ! 239: ! 240: /* First check that the region doesn't already exist */ ! 241: ! 242: assert (epa >= spa); ! 243: for (i = 0; i < pmap_mem_regions_count; i++) { ! 244: /* If we're below the next region, then no conflict */ ! 245: if (epa < pmap_mem_regions[i].start) ! 246: break; ! 247: if (spa < pmap_mem_regions[i].end) { ! 248: #if DEBUG ! 249: kprintf("pmap_add_physical_memory(0x%08x,0x%08x,0x%08x) - memory already present\n",spa,epa,attr); ! 250: #endif /* DEBUG */ ! 251: return KERN_NO_SPACE; ! 252: } ! 253: } ! 254: ! 255: #if DEBUG ! 256: kprintf("pmap_add_physical_memory; region insert spot: %d out of %d\n", i, pmap_mem_regions_count); /* (TEST/DEBUG) */ ! 257: #endif ! 258: ! 259: /* Check that we've got enough space for another region */ ! 260: if (pmap_mem_regions_count == PMAP_MEM_REGION_MAX) ! 261: return KERN_RESOURCE_SHORTAGE; ! 262: ! 263: /* Once here, i points to the mem_region above ours in physical mem */ ! 264: ! 265: /* allocate a new phys_table for this new region */ ! 266: #if DEBUG ! 267: kprintf("pmap_add_physical_memory; kalloc\n"); /* (TEST/DEBUG) */ ! 268: #endif ! 269: ! 270: phys_table = (struct phys_entry *) ! 271: kalloc(sizeof(struct phys_entry) * atop(epa-spa)); ! 272: #if DEBUG ! 273: kprintf("pmap_add_physical_memory; new phys_table: %08X\n", phys_table); /* (TEST/DEBUG) */ ! 274: #endif ! 275: ! 276: /* Initialise the new phys_table entries */ ! 277: for (j = 0; j < atop(epa-spa); j++) { ! 278: ! 279: phys_table[j].phys_link = MAPPING_NULL; ! 280: ! 281: mapping_phys_init(&phys_table[j], spa+(j*PAGE_SIZE), attr); /* Initialize the hardware specific portions */ ! 282: ! 283: } ! 284: s = splhigh(); ! 285: ! 286: /* Move all the phys_table entries up some to make room in ! 287: * the ordered list. ! 288: */ ! 289: for (j = pmap_mem_regions_count; j > i ; j--) ! 290: pmap_mem_regions[j] = pmap_mem_regions[j-1]; ! 291: ! 292: /* Insert a new entry with some memory to back it */ ! 293: ! 294: pmap_mem_regions[i].start = spa; ! 295: pmap_mem_regions[i].end = epa; ! 296: pmap_mem_regions[i].phys_table = phys_table; ! 297: ! 298: pmap_mem_regions_count++; ! 299: splx(s); ! 300: ! 301: #if DEBUG ! 302: for(i=0; i<pmap_mem_regions_count; i++) { /* (TEST/DEBUG) */ ! 303: kprintf("region %d: %08X %08X %08X\n", i, pmap_mem_regions[i].start, ! 304: pmap_mem_regions[i].end, pmap_mem_regions[i].phys_table); /* (TEST/DEBUG) */ ! 305: } ! 306: #endif ! 307: ! 308: if (available) { ! 309: kprintf("warning : pmap_add_physical_mem() " ! 310: "available not yet supported\n"); ! 311: } ! 312: ! 313: return KERN_SUCCESS; ! 314: } ! 315: ! 316: /* ! 317: * pmap_map(va, spa, epa, prot) ! 318: * is called during boot to map memory in the kernel's address map. ! 319: * A virtual address range starting at "va" is mapped to the physical ! 320: * address range "spa" to "epa" with machine independent protection ! 321: * "prot". ! 322: * ! 323: * "va", "spa", and "epa" are byte addresses and must be on machine ! 324: * independent page boundaries. ! 325: * ! 326: * If we can allocate an autogen area, we will. Autogenned area are contiguous physical ! 327: * pages with a contiguous virtual address range, the same protection, and attributes. ! 328: * The autogen_map routine tells us if it could do it or not. ! 329: */ ! 330: vm_offset_t ! 331: pmap_map( ! 332: vm_offset_t va, ! 333: vm_offset_t spa, ! 334: vm_offset_t epa, ! 335: vm_prot_t prot) ! 336: { ! 337: ! 338: ! 339: if (spa == epa) ! 340: return(va); ! 341: ! 342: assert(epa > spa); ! 343: ! 344: if(autogen_map(kernel_pmap->space, va, spa, epa, prot, PTE_WIMG_DEFAULT)) return(va); /* Allocate an autogen area if we can */ ! 345: ! 346: ! 347: debugLog2(40, va, spa); /* Log pmap_map call */ ! 348: ! 349: while (spa < epa) { ! 350: pmap_enter(kernel_pmap, va, spa, prot, TRUE); ! 351: ! 352: va += PAGE_SIZE; ! 353: spa += PAGE_SIZE; ! 354: } ! 355: ! 356: debugLog2(41, epa, prot); /* Log pmap_map call */ ! 357: ! 358: return(va); ! 359: } ! 360: ! 361: /* ! 362: * pmap_map_bd(va, spa, epa, prot) ! 363: * Back-door routine for mapping kernel VM at initialisation. ! 364: * Used for mapping memory outside the known physical memory ! 365: * space, with caching disabled. Designed for use by device probes. ! 366: * ! 367: * A virtual address range starting at "va" is mapped to the physical ! 368: * address range "spa" to "epa" with machine independent protection ! 369: * "prot". ! 370: * ! 371: * "va", "spa", and "epa" are byte addresses and must be on machine ! 372: * independent page boundaries. ! 373: * ! 374: * WARNING: The current version of memcpy() can use the dcbz instruction ! 375: * on the destination addresses. This will cause an alignment exception ! 376: * and consequent overhead if the destination is caching-disabled. So ! 377: * avoid memcpy()ing into the memory mapped by this function. ! 378: * ! 379: * also, many other pmap_ routines will misbehave if you try and change ! 380: * protections or remove these mappings, they are designed to be permanent. ! 381: * ! 382: * These areas will be added to the autogen list, if possible. Existing translations ! 383: * are overridden and their mapping stuctures are released. This takes place in ! 384: * the autogen_map function. ! 385: * ! 386: * Locking: ! 387: * this routine is called only during system initialization when only ! 388: * one processor is active, so no need to take locks... ! 389: */ ! 390: vm_offset_t ! 391: pmap_map_bd( ! 392: vm_offset_t va, ! 393: vm_offset_t spa, ! 394: vm_offset_t epa, ! 395: vm_prot_t prot) ! 396: { ! 397: spl_t spl; ! 398: register struct mapping *mp; ! 399: register struct phys_entry *pp; ! 400: ! 401: ! 402: if (spa == epa) ! 403: return(va); ! 404: ! 405: assert(epa > spa); ! 406: ! 407: debugLog2(42, va, epa); /* Log pmap_map call */ ! 408: ! 409: spl = splhigh(); ! 410: ! 411: if(autogen_map(PPC_SID_KERNEL, va, spa, epa, prot, PTE_WIMG_IO)) { /* Allocate an autogen area if we can */ ! 412: splx(spl); /* Ok, we allocated one, set back the spl */ ! 413: ! 414: debugLog2(43, epa, prot); /* Log pmap_map call */ ! 415: ! 416: return(va); /* Return... */ ! 417: } ! 418: ! 419: while (spa < epa) { ! 420: ! 421: ! 422: mapping_remove(PPC_SID_KERNEL, va); /* Remove any active mapping for this VADDR */ ! 423: ! 424: pp = pmap_find_physentry(spa); /* Get the physent, note, it's ok to fail, ! 425: we don't care about a physical page here */ ! 426: mapping_make(kernel_pmap, PPC_SID_KERNEL, pp, va, spa, prot, PTE_WIMG_IO); /* Make the address mapping*/ ! 427: ! 428: va += PAGE_SIZE; ! 429: spa += PAGE_SIZE; ! 430: } ! 431: ! 432: splx(spl); ! 433: ! 434: debugLog2(43, epa, prot); /* Log pmap_map call */ ! 435: ! 436: return(va); ! 437: } ! 438: ! 439: /* ! 440: * Bootstrap the system enough to run with virtual memory. ! 441: * Map the kernel's code and data, and allocate the system page table. ! 442: * Called with mapping done by BATs. Page_size must already be set. ! 443: * ! 444: * Parameters: ! 445: * mem_size: Total memory present ! 446: * first_avail: First virtual address available ! 447: * first_phys_avail: First physical address available ! 448: */ ! 449: void ! 450: pmap_bootstrap(unsigned int mem_size, vm_offset_t *first_avail, vm_offset_t *first_phys_avail, unsigned int kmapsize) ! 451: { ! 452: register struct mapping *mp; ! 453: vm_offset_t addr; ! 454: vm_size_t size; ! 455: int i, num, j, rsize, mapsize, vmpagesz, vmmapsz; ! 456: unsigned int mask; ! 457: vm_offset_t first_used_addr; ! 458: PCA *pcaptr; ! 459: savectl *savec, *savec2; ! 460: vm_offset_t save, save2; ! 461: ! 462: *first_avail = round_page(*first_avail); ! 463: ! 464: #if DEBUG ! 465: kprintf("first_avail=%08X; first_phys_avail=%08X; avail_remaining=%d\n", ! 466: *first_avail, *first_phys_avail, avail_remaining); ! 467: #endif ! 468: ! 469: assert(PAGE_SIZE == PPC_PGBYTES); ! 470: ! 471: /* ! 472: * Initialize kernel pmap ! 473: */ ! 474: kernel_pmap = &kernel_pmap_store; ! 475: ! 476: lock_init(&pmap_system_lock, ! 477: FALSE, /* NOT a sleep lock */ ! 478: ETAP_VM_PMAP_SYS, ! 479: ETAP_VM_PMAP_SYS_I); ! 480: ! 481: simple_lock_init(&kernel_pmap->lock, ETAP_VM_PMAP_KERNEL); ! 482: ! 483: kernel_pmap->ref_count = 1; ! 484: kernel_pmap->space = PPC_SID_KERNEL; ! 485: ! 486: /* ! 487: * Allocate: (from first_avail up) ! 488: * Aligned to its own size: ! 489: * hash table (for mem size 2**x, allocate 2**(x-10) entries) ! 490: * mapping table (same size and immediatly following hash table) ! 491: */ ! 492: /* hash_table_size must be a power of 2, recommended sizes are ! 493: * taken from PPC601 User Manual, table 6-19. We take the next ! 494: * highest size if mem_size is not a power of two. ! 495: * TODO NMGS make this configurable at boot time. ! 496: */ ! 497: ! 498: num = sizeof(pte_t) * (mem_size >> 10); ! 499: ! 500: for (hash_table_size = 64 * 1024; /* minimum size = 64Kbytes */ ! 501: hash_table_size < num; ! 502: hash_table_size *= 2) ! 503: continue; ! 504: ! 505: /* Scale to within any physical memory layout constraints */ ! 506: do { ! 507: num = atop(mem_size); /* num now holds mem_size in pages */ ! 508: ! 509: /* size of all structures that we're going to allocate */ ! 510: ! 511: size = (vm_size_t) ( ! 512: (InitialSaveBloks * PAGE_SIZE) + /* Allow space for the initial context saveareas */ ! 513: (8 * PAGE_SIZE) + /* For backpocket saveareas */ ! 514: hash_table_size + /* For hash table */ ! 515: hash_table_size + /* For PTEG allocation table */ ! 516: (num * sizeof(struct phys_entry)) /* For the physical entries */ ! 517: ); ! 518: ! 519: mapsize = size = round_page(size); /* Get size of area to map that we just calculated */ ! 520: mapsize = mapsize + kmapsize; /* Account for the kernel text size */ ! 521: ! 522: vmpagesz = round_page(num * sizeof(struct vm_page)); /* Allow for all vm_pages needed to map physical mem */ ! 523: vmmapsz = round_page((num / 2) * sizeof(struct vm_map_entry)); /* Allow for vm_maps */ ! 524: ! 525: mapsize = mapsize + vmpagesz + vmmapsz; /* Add the VM system estimates into the grand total */ ! 526: ! 527: mapsize = mapsize + (4 * 1024 * 1024); /* Allow for 4 meg of extra mappings */ ! 528: mapsize = ((mapsize / PAGE_SIZE) + MAPPERBLOK - 1) / MAPPERBLOK; /* Get number of blocks of mappings we need */ ! 529: mapsize = mapsize + ((mapsize + MAPPERBLOK - 1) / MAPPERBLOK); /* Account for the mappings themselves */ ! 530: ! 531: #if DEBUG ! 532: kprintf("pmap_bootstrap: initial vm_pages = %08X\n", vmpagesz); ! 533: kprintf("pmap_bootstrap: initial vm_maps = %08X\n", vmmapsz); ! 534: kprintf("pmap_bootstrap: size before mappings = %08X\n", size); ! 535: kprintf("pmap_bootstrap: kernel map size = %08X\n", kmapsize); ! 536: kprintf("pmap_bootstrap: mapping blocks rqrd = %08X\n", mapsize); ! 537: #endif ! 538: ! 539: size = size + (mapsize * PAGE_SIZE); /* Get the true size we need */ ! 540: ! 541: /* hash table must be aligned to its size */ ! 542: ! 543: addr = (*first_avail + ! 544: (hash_table_size-1)) & ~(hash_table_size-1); ! 545: ! 546: if (addr + size > pmap_mem_regions[0].end) { ! 547: hash_table_size /= 2; ! 548: } else { ! 549: break; ! 550: } ! 551: /* If we have had to shrink hash table to too small, panic */ ! 552: if (hash_table_size == 32 * 1024) ! 553: panic("cannot lay out pmap memory map correctly"); ! 554: } while (1); ! 555: ! 556: #if DEBUG ! 557: kprintf("hash table size=%08X, total size of area=%08X, addr=%08X\n", ! 558: hash_table_size, size, addr); ! 559: #endif ! 560: if (round_page(*first_phys_avail) < trunc_page(addr)) { ! 561: /* We are stepping over at least one page here, so ! 562: * add this region to the free regions so that it can ! 563: * be allocated by pmap_steal ! 564: */ ! 565: free_regions[free_regions_count].start = round_page(*first_phys_avail); ! 566: free_regions[free_regions_count].end = trunc_page(addr); ! 567: ! 568: avail_remaining += (free_regions[free_regions_count].end - ! 569: free_regions[free_regions_count].start) / ! 570: PPC_PGBYTES; ! 571: #if DEBUG ! 572: kprintf("ADDED FREE REGION from 0x%08x to 0x%08x, avail_remaining = %d\n", ! 573: free_regions[free_regions_count].start,free_regions[free_regions_count].end, ! 574: avail_remaining); ! 575: #endif /* DEBUG */ ! 576: free_regions_count++; ! 577: } ! 578: ! 579: /* Zero everything - this also invalidates the hash table entries */ ! 580: bzero((char *)addr, size); ! 581: ! 582: /* Set up some pointers to our new structures */ ! 583: ! 584: /* from here, addr points to the next free address */ ! 585: ! 586: first_used_addr = addr; /* remember where we started */ ! 587: ! 588: /* Set up hash table address and dma buffer address, keeping ! 589: * alignment. These mappings are all 1-1, so dma_r == dma_v ! 590: * ! 591: * If hash_table_size == dma_buffer_alignment, then put hash_table ! 592: * first, since dma_buffer_size may be smaller than alignment, but ! 593: * hash table alignment==hash_table_size. ! 594: */ ! 595: hash_table_base = addr; ! 596: ! 597: addr += hash_table_size; ! 598: addr += hash_table_size; /* Add another for the PTEG Control Area */ ! 599: assert((hash_table_base & (hash_table_size-1)) == 0); ! 600: ! 601: pcaptr = (PCA *)(hash_table_base+hash_table_size); /* Point to the PCA table */ ! 602: ! 603: for(i=0; i < (hash_table_size/64) ; i++) { /* For all of PTEG control areas: */ ! 604: pcaptr[i].flgs.PCAalflgs.PCAfree=0xFF; /* Mark all slots free */ ! 605: pcaptr[i].flgs.PCAalflgs.PCAsteal=0x01; /* Initialize steal position */ ! 606: } ! 607: ! 608: /* ! 609: * Allocate our initial context save areas. As soon as we do this, ! 610: * we can take an interrupt. We do the saveareas here, 'cause they're guaranteed ! 611: * to be at least page aligned. ! 612: */ ! 613: save2 = addr; /* Remember first page */ ! 614: save = addr; /* Point to the whole block of blocks */ ! 615: savec2 = (savectl *)(addr + PAGE_SIZE - sizeof(savectl)); /* Point to the first's control area */ ! 616: ! 617: for(i=0; i < InitialSaveBloks; i++) { /* Initialize the saveareas */ ! 618: ! 619: savec = (savectl *)(save + PAGE_SIZE - sizeof(savectl)); /* Get the control area for this one */ ! 620: ! 621: savec->sac_alloc = sac_empty; /* Mark both free */ ! 622: savec->sac_vrswap = 0; /* V=R, so the translation factor is 0 */ ! 623: savec->sac_flags = sac_perm; /* Mark it permanent */ ! 624: ! 625: savec->sac_flags |= 0x0000EE00; /* (TEST/DEBUG) */ ! 626: ! 627: save += PAGE_SIZE; /* Jump up to the next one now */ ! 628: ! 629: savec->sac_next = (unsigned int *)save; /* Link these two */ ! 630: ! 631: } ! 632: ! 633: savec->sac_next = (unsigned int *)0; /* Clear the forward pointer for the last */ ! 634: savec2->sac_alloc &= 0x7FFFFFFF; /* Mark the first one in use */ ! 635: ! 636: saveanchor.savefree = (unsigned int)save2; /* Point to the first one */ ! 637: saveanchor.savecount = InitialSaveBloks * sac_cnt; /* The total number of save areas allocated */ ! 638: saveanchor.saveinuse = 1; /* Number of areas in use */ ! 639: saveanchor.savemin = InitialSaveMin; /* We abend if lower than this */ ! 640: saveanchor.saveneghyst = InitialNegHysteresis; /* The minimum number to keep free (must be a multiple of sac_cnt) */ ! 641: saveanchor.savetarget = InitialSaveTarget; /* The target point for free save areas (must be a multiple of sac_cnt) */ ! 642: saveanchor.saveposhyst = InitialPosHysteresis; /* The high water mark for free save areas (must be a multiple of sac_cnt) */ ! 643: __asm__ volatile ("mtsprg 1, %0" : : "r" (save2)); /* Tell the exception handler about it */ ! 644: ! 645: addr += InitialSaveBloks * PAGE_SIZE; /* Move up the next free address */ ! 646: ! 647: save2 = addr; ! 648: save = addr; ! 649: savec2 = (savectl *)(addr + PAGE_SIZE - sizeof(savectl)); ! 650: ! 651: for(i=0; i < 8; i++) { /* Allocate backpocket saveareas */ ! 652: ! 653: savec = (savectl *)(save + PAGE_SIZE - sizeof(savectl)); ! 654: ! 655: savec->sac_alloc = sac_empty; ! 656: savec->sac_vrswap = 0; ! 657: savec->sac_flags = sac_perm; ! 658: savec->sac_flags |= 0x0000EE00; ! 659: ! 660: save += PAGE_SIZE; ! 661: ! 662: savec->sac_next = (unsigned int *)save; ! 663: ! 664: } ! 665: ! 666: savec->sac_next = (unsigned int *)0; ! 667: savec2->sac_alloc &= 0x7FFFFFFF; ! 668: debugbackpocket = save2; ! 669: addr += 8 * PAGE_SIZE; ! 670: ! 671: /* phys_table is static to help debugging, ! 672: * this variable is no longer actually used ! 673: * outside of this scope ! 674: */ ! 675: ! 676: phys_table = (struct phys_entry *) addr; ! 677: ! 678: #if DEBUG ! 679: kprintf("hash_table_base =%08X\n", hash_table_base); ! 680: kprintf("phys_table =%08X\n", phys_table); ! 681: kprintf("pmap_mem_regions_count =%08X\n", pmap_mem_regions_count); ! 682: #endif ! 683: ! 684: for (i = 0; i < pmap_mem_regions_count; i++) { ! 685: ! 686: pmap_mem_regions[i].phys_table = phys_table; ! 687: rsize = (pmap_mem_regions[i].end - (unsigned int)pmap_mem_regions[i].start)/PAGE_SIZE; ! 688: ! 689: #if DEBUG ! 690: kprintf("Initializing physical table for region %d\n", i); ! 691: kprintf(" table=%08X, size=%08X, start=%08X, end=%08X\n", ! 692: phys_table, rsize, pmap_mem_regions[i].start, ! 693: (unsigned int)pmap_mem_regions[i].end); ! 694: #endif ! 695: ! 696: for (j = 0; j < rsize; j++) { ! 697: phys_table[j].phys_link = MAPPING_NULL; ! 698: mapping_phys_init(&phys_table[j], (unsigned int)pmap_mem_regions[i].start+(j*PAGE_SIZE), ! 699: PTE_WIMG_DEFAULT); /* Initializes hw specific storage attributes */ ! 700: } ! 701: phys_table = phys_table + ! 702: atop(pmap_mem_regions[i].end - pmap_mem_regions[i].start); ! 703: } ! 704: ! 705: /* restore phys_table for debug */ ! 706: phys_table = (struct phys_entry *) addr; ! 707: ! 708: addr += sizeof(struct phys_entry) * num; ! 709: ! 710: simple_lock_init(&tlb_system_lock, ETAP_VM_PMAP_TLB); ! 711: ! 712: /* Initialise the registers necessary for supporting the hashtable */ ! 713: #if DEBUG ! 714: kprintf("*** hash_table_init: base=%08X, size=%08X\n", hash_table_base, hash_table_size); ! 715: #endif ! 716: ! 717: hash_table_init(hash_table_base, hash_table_size); ! 718: ! 719: /* ! 720: * Remaining space is for mapping entries. Tell the initializer routine that ! 721: * the mapping system can't release this block because it's permanently assigned ! 722: */ ! 723: ! 724: mapping_init(); /* Initialize the mapping tables */ ! 725: ! 726: for(i = addr; i < first_used_addr + size; i += PAGE_SIZE) { /* Add initial mapping blocks */ ! 727: mapping_free_init(i, 1, 0); /* Pass block address and say that this one is not releasable */ ! 728: } ! 729: mapCtl.mapcmin = MAPPERBLOK; /* Make sure we only adjust one at a time */ ! 730: ! 731: #if DEBUG ! 732: ! 733: kprintf("mapping kernel memory from 0x%08x to 0x%08x, to address 0x%08x\n", ! 734: first_used_addr, round_page(first_used_addr+size), ! 735: first_used_addr); ! 736: #endif /* DEBUG */ ! 737: ! 738: /* Map V=R the page tables */ ! 739: pmap_map(first_used_addr, first_used_addr, ! 740: round_page(first_used_addr+size), VM_PROT_READ | VM_PROT_WRITE); ! 741: ! 742: #if DEBUG ! 743: ! 744: for(i=first_used_addr; i < round_page(first_used_addr+size); i+=PAGE_SIZE) { /* Step through all these mappings */ ! 745: if(i != (j = kvtophys(i))) { /* Verify that the mapping was made V=R */ ! 746: kprintf("*** V=R mapping failed to verify: V=%08X; R=%08X\n", i, j); ! 747: } ! 748: } ! 749: #endif ! 750: ! 751: *first_avail = round_page(first_used_addr + size); ! 752: first_free_virt = round_page(first_used_addr + size); ! 753: ! 754: /* All the rest of memory is free - add it to the free ! 755: * regions so that it can be allocated by pmap_steal ! 756: */ ! 757: free_regions[free_regions_count].start = *first_avail; ! 758: free_regions[free_regions_count].end = pmap_mem_regions[0].end; ! 759: ! 760: avail_remaining += (free_regions[free_regions_count].end - ! 761: free_regions[free_regions_count].start) / ! 762: PPC_PGBYTES; ! 763: ! 764: #if DEBUG ! 765: kprintf("ADDED FREE REGION from 0x%08x to 0x%08x, avail_remaining = %d\n", ! 766: free_regions[free_regions_count].start,free_regions[free_regions_count].end, ! 767: avail_remaining); ! 768: #endif /* DEBUG */ ! 769: ! 770: free_regions_count++; ! 771: ! 772: current_free_region = 0; ! 773: ! 774: avail_next = free_regions[current_free_region].start; ! 775: ! 776: #if DEBUG ! 777: kprintf("Number of free regions=%d\n",free_regions_count); /* (TEST/DEBUG) */ ! 778: kprintf("Current free region=%d\n",current_free_region); /* (TEST/DEBUG) */ ! 779: for(i=0;i<free_regions_count; i++) { /* (TEST/DEBUG) */ ! 780: kprintf("Free region %3d - from %08X to %08X\n", i, free_regions[i].start, ! 781: free_regions[i].end); /* (TEST/DEBUG) */ ! 782: } ! 783: for (i = 0; i < pmap_mem_regions_count; i++) { /* (TEST/DEBUG) */ ! 784: kprintf("PMAP region %3d - from %08X to %08X; phys=%08X\n", i, /* (TEST/DEBUG) */ ! 785: pmap_mem_regions[i].start, /* (TEST/DEBUG) */ ! 786: pmap_mem_regions[i].end, /* (TEST/DEBUG) */ ! 787: pmap_mem_regions[i].phys_table); /* (TEST/DEBUG) */ ! 788: } ! 789: #endif ! 790: ! 791: } ! 792: ! 793: /* ! 794: * pmap_init(spa, epa) ! 795: * finishes the initialization of the pmap module. ! 796: * This procedure is called from vm_mem_init() in vm/vm_init.c ! 797: * to initialize any remaining data structures that the pmap module ! 798: * needs to map virtual memory (VM is already ON). ! 799: */ ! 800: ! 801: void ! 802: pmap_init(void) ! 803: { ! 804: vm_size_t s; ! 805: ! 806: s = sizeof(struct pmap); ! 807: pmap_zone = zinit(s, 400*s, 4096, "pmap"); ! 808: ! 809: pmap_initialized = TRUE; ! 810: ! 811: /* ! 812: * Initialize list of freed up pmaps ! 813: */ ! 814: queue_init(&free_pmap_list); ! 815: free_pmap_count = 0; ! 816: simple_lock_init(&free_pmap_lock, ETAP_VM_PMAP_CACHE); ! 817: } ! 818: ! 819: unsigned int pmap_free_pages(void) ! 820: { ! 821: return avail_remaining; ! 822: } ! 823: ! 824: boolean_t pmap_next_page(vm_offset_t *addrp) ! 825: { ! 826: /* Non optimal, but only used for virtual memory startup. ! 827: * Allocate memory from a table of free physical addresses ! 828: * If there are no more free entries, too bad. We have two ! 829: * tables to look through, free_regions[] which holds free ! 830: * regions from inside pmap_mem_regions[0], and the others... ! 831: * pmap_mem_regions[1..] ! 832: */ ! 833: ! 834: /* current_free_region indicates the next free entry, ! 835: * if it's less than free_regions_count, then we're still ! 836: * in free_regions, otherwise we're in pmap_mem_regions ! 837: */ ! 838: ! 839: if (current_free_region >= free_regions_count) { ! 840: /* We're into the pmap_mem_regions, handle this ! 841: * separately to free_regions ! 842: */ ! 843: ! 844: int current_pmap_mem_region = current_free_region - ! 845: free_regions_count + 1; ! 846: if (current_pmap_mem_region > pmap_mem_regions_count) ! 847: return FALSE; ! 848: *addrp = avail_next; ! 849: avail_next += PAGE_SIZE; ! 850: avail_remaining--; ! 851: if (avail_next >= pmap_mem_regions[current_pmap_mem_region].end) { ! 852: current_free_region++; ! 853: current_pmap_mem_region++; ! 854: avail_next = pmap_mem_regions[current_pmap_mem_region].start; ! 855: #if DEBUG ! 856: kprintf("pmap_next_page : next region start=0x%08x\n",avail_next); ! 857: #endif /* DEBUG */ ! 858: } ! 859: return TRUE; ! 860: } ! 861: ! 862: /* We're in the free_regions, allocate next page and increment ! 863: * counters ! 864: */ ! 865: *addrp = avail_next; ! 866: ! 867: avail_next += PAGE_SIZE; ! 868: avail_remaining--; ! 869: ! 870: if (avail_next >= free_regions[current_free_region].end) { ! 871: current_free_region++; ! 872: if (current_free_region < free_regions_count) ! 873: avail_next = free_regions[current_free_region].start; ! 874: else ! 875: avail_next = pmap_mem_regions[current_free_region - ! 876: free_regions_count + 1].start; ! 877: #if DEBUG ! 878: kprintf("pmap_next_page : next region start=0x%08x\n",avail_next); ! 879: #endif ! 880: } ! 881: return TRUE; ! 882: } ! 883: ! 884: void pmap_virtual_space( ! 885: vm_offset_t *startp, ! 886: vm_offset_t *endp) ! 887: { ! 888: *startp = round_page(first_free_virt); ! 889: *endp = VM_MAX_KERNEL_ADDRESS; ! 890: } ! 891: ! 892: /* ! 893: * pmap_create ! 894: * ! 895: * Create and return a physical map. ! 896: * ! 897: * If the size specified for the map is zero, the map is an actual physical ! 898: * map, and may be referenced by the hardware. ! 899: * ! 900: * If the size specified is non-zero, the map will be used in software ! 901: * only, and is bounded by that size. ! 902: */ ! 903: pmap_t ! 904: pmap_create(vm_size_t size) ! 905: { ! 906: pmap_t pmap; ! 907: int s; ! 908: space_t sid; ! 909: ! 910: #if PMAP_LOWTRACE ! 911: dbgTrace(0xF1D00001, size, 0); /* (TEST/DEBUG) */ ! 912: #endif ! 913: ! 914: #if DEBUG ! 915: if (pmdebug & PDB_USER) ! 916: kprintf("pmap_create(size=%x)%c", size, size ? '\n' : ' '); ! 917: #endif ! 918: ! 919: /* ! 920: * A software use-only map doesn't even need a pmap structure. ! 921: */ ! 922: if (size) ! 923: return(PMAP_NULL); ! 924: ! 925: /* ! 926: * If there is a pmap in the pmap free list, reuse it. ! 927: */ ! 928: s = splhigh(); ! 929: simple_lock(&free_pmap_lock); ! 930: if (!queue_empty(&free_pmap_list)) { ! 931: queue_remove_first(&free_pmap_list, ! 932: pmap, ! 933: pmap_t, ! 934: pmap_link); ! 935: free_pmap_count--; ! 936: } else { ! 937: pmap = PMAP_NULL; ! 938: } ! 939: simple_unlock(&free_pmap_lock); ! 940: splx(s); ! 941: ! 942: /* ! 943: * Couldn't find a pmap on the free list, try to allocate a new one. ! 944: */ ! 945: if (pmap == PMAP_NULL) { ! 946: pmap = (pmap_t) zalloc(pmap_zone); ! 947: if (pmap == PMAP_NULL) ! 948: return(PMAP_NULL); ! 949: ! 950: /* ! 951: * Allocate space IDs for the pmap. ! 952: * If all are allocated, there is nothing we can do. ! 953: */ ! 954: pmap->space = mapping_space(); ! 955: ! 956: simple_lock_init(&pmap->lock, ETAP_VM_PMAP); ! 957: } ! 958: pmap->ref_count = 1; ! 959: pmap->stats.resident_count = 0; ! 960: pmap->stats.wired_count = 0; ! 961: ! 962: #if PMAP_LOWTRACE ! 963: dbgTrace(0xF1D00002, (unsigned int)pmap, (unsigned int)pmap->space); /* (TEST/DEBUG) */ ! 964: #endif ! 965: ! 966: #if DEBUG ! 967: if (pmdebug & PDB_USER) ! 968: kprintf("-> %x, space id = %d\n", pmap, pmap->space); ! 969: #endif ! 970: return(pmap); ! 971: } ! 972: ! 973: /* ! 974: * pmap_destroy ! 975: * ! 976: * Gives up a reference to the specified pmap. When the reference count ! 977: * reaches zero the pmap structure is added to the pmap free list. ! 978: * ! 979: * Should only be called if the map contains no valid mappings. ! 980: */ ! 981: void ! 982: pmap_destroy(pmap_t pmap) ! 983: { ! 984: int ref_count; ! 985: spl_t s; ! 986: ! 987: #if PMAP_LOWTRACE ! 988: dbgTrace(0xF1D00003, (unsigned int)pmap, 0); /* (TEST/DEBUG) */ ! 989: #endif ! 990: ! 991: #if DEBUG ! 992: if (pmdebug & PDB_USER) ! 993: kprintf("pmap_destroy(pmap=%x)\n", pmap); ! 994: #endif ! 995: ! 996: if (pmap == PMAP_NULL) ! 997: return; ! 998: ! 999: ref_count=hw_atomic_sub(&pmap->ref_count, 1); /* Back off the count */ ! 1000: if(ref_count>0) return; /* Still more users, leave now... */ ! 1001: ! 1002: if(ref_count < 0) /* Did we go too far? */ ! 1003: panic("pmap_destroy(): ref_count < 0"); ! 1004: ! 1005: ! 1006: assert(pmap->stats.resident_count == 0); ! 1007: ! 1008: /* ! 1009: * Add the pmap to the pmap free list. ! 1010: */ ! 1011: ! 1012: s = splhigh(); ! 1013: /* ! 1014: * Add the pmap to the pmap free list. ! 1015: */ ! 1016: simple_lock(&free_pmap_lock); ! 1017: if (free_pmap_count <= free_pmap_max) { ! 1018: ! 1019: queue_enter_first(&free_pmap_list, pmap, pmap_t, pmap_link); ! 1020: free_pmap_count++; ! 1021: simple_unlock(&free_pmap_lock); ! 1022: } else { ! 1023: simple_unlock(&free_pmap_lock); ! 1024: zfree(pmap_zone, (vm_offset_t) pmap); ! 1025: } ! 1026: splx(s); ! 1027: } ! 1028: ! 1029: /* ! 1030: * pmap_reference(pmap) ! 1031: * gains a reference to the specified pmap. ! 1032: */ ! 1033: void ! 1034: pmap_reference(pmap_t pmap) ! 1035: { ! 1036: spl_t s; ! 1037: ! 1038: #if PMAP_LOWTRACE ! 1039: dbgTrace(0xF1D00004, (unsigned int)pmap, 0); /* (TEST/DEBUG) */ ! 1040: #endif ! 1041: ! 1042: #if DEBUG ! 1043: if (pmdebug & PDB_USER) ! 1044: kprintf("pmap_reference(pmap=%x)\n", pmap); ! 1045: #endif ! 1046: ! 1047: if (pmap != PMAP_NULL) hw_atomic_add(&pmap->ref_count, 1); /* Bump the count */ ! 1048: } ! 1049: ! 1050: /* ! 1051: * pmap_remove(pmap, s, e) ! 1052: * unmaps all virtual addresses v in the virtual address ! 1053: * range determined by [s, e) and pmap. ! 1054: * s and e must be on machine independent page boundaries and ! 1055: * s must be less than or equal to e. ! 1056: */ ! 1057: void ! 1058: pmap_remove( ! 1059: pmap_t pmap, ! 1060: vm_offset_t sva, ! 1061: vm_offset_t eva) ! 1062: { ! 1063: spl_t spl; ! 1064: struct mapping *mp; ! 1065: ! 1066: #if PMAP_LOWTRACE ! 1067: dbgTrace(0xF1D00005, (unsigned int)pmap, sva|((eva-sva)>>12)); /* (TEST/DEBUG) */ ! 1068: #endif ! 1069: ! 1070: #if DEBUG ! 1071: if (pmdebug & PDB_USER) ! 1072: kprintf("pmap_remove(pmap=%x, sva=%x, eva=%x)\n", ! 1073: pmap, sva, eva); ! 1074: #endif ! 1075: ! 1076: if (pmap == PMAP_NULL) ! 1077: return; ! 1078: ! 1079: /* It is just possible that eva might have wrapped around to zero, ! 1080: * and sometimes we get asked to liberate something of size zero ! 1081: * even though it's dumb (eg. after zero length read_overwrites) ! 1082: */ ! 1083: assert(eva >= sva); ! 1084: ! 1085: /* If these are not page aligned the loop might not terminate */ ! 1086: assert((sva == trunc_page(sva)) && (eva == trunc_page(eva))); ! 1087: ! 1088: /* We liberate addresses from high to low, since the stack grows ! 1089: * down. This means that we won't need to test addresses below ! 1090: * the limit of stack growth ! 1091: */ ! 1092: ! 1093: debugLog2(44, sva, eva); /* Log pmap_map call */ ! 1094: ! 1095: while (pmap->stats.resident_count && (eva > sva)) { ! 1096: ! 1097: eva -= PAGE_SIZE; /* Back up a page */ ! 1098: mapping_remove(pmap->space, eva); /* Remove the mapping for this address */ ! 1099: } ! 1100: ! 1101: debugLog2(45, 0, 0); /* Log pmap_map call */ ! 1102: } ! 1103: ! 1104: /* ! 1105: * Routine: ! 1106: * pmap_page_protect ! 1107: * ! 1108: * Function: ! 1109: * Lower the permission for all mappings to a given page. ! 1110: */ ! 1111: void ! 1112: pmap_page_protect( ! 1113: vm_offset_t pa, ! 1114: vm_prot_t prot) ! 1115: { ! 1116: spl_t spl; ! 1117: register struct phys_entry *pp; ! 1118: boolean_t remove; ! 1119: ! 1120: ! 1121: #if PMAP_LOWTRACE ! 1122: dbgTrace(0xF1D00006, (unsigned int)pa, (unsigned int)prot); /* (TEST/DEBUG) */ ! 1123: #endif ! 1124: ! 1125: #if DEBUG ! 1126: if (pmdebug & PDB_USER) ! 1127: kprintf("pmap_page_protect(pa=%x, prot=%x)\n", pa, prot); ! 1128: #endif ! 1129: ! 1130: debugLog2(46, pa, prot); /* Log pmap_page_protect call */ ! 1131: ! 1132: switch (prot) { ! 1133: case VM_PROT_READ: ! 1134: case VM_PROT_READ|VM_PROT_EXECUTE: ! 1135: remove = FALSE; ! 1136: break; ! 1137: case VM_PROT_ALL: ! 1138: return; ! 1139: default: ! 1140: remove = TRUE; ! 1141: break; ! 1142: } ! 1143: ! 1144: pp = pmap_find_physentry(pa); /* Get the physent for this page */ ! 1145: if (pp == PHYS_NULL) return; /* Leave if not in physical RAM */ ! 1146: ! 1147: if (remove) { /* If the protection was set to none, we'll remove all mappings */ ! 1148: mapping_purge(pp); /* Get rid of them all */ ! 1149: ! 1150: debugLog2(47, 0, 0); /* Log pmap_map call */ ! 1151: return; /* Leave... */ ! 1152: } ! 1153: ! 1154: /* When we get here, it means that we are to change the protection for a ! 1155: * physical page. ! 1156: */ ! 1157: ! 1158: spl=splhigh(); /* No interruptions during this */ ! 1159: mapping_protect(pp, prot, 0); /* Change protection of all mappings to page. ! 1160: Say that the physent is not locked yet */ ! 1161: splx(spl); /* Restore interrupt state */ ! 1162: ! 1163: debugLog2(47, 1, 0); /* Log pmap_map call */ ! 1164: } ! 1165: ! 1166: /* ! 1167: * pmap_protect(pmap, s, e, prot) ! 1168: * changes the protection on all virtual addresses v in the ! 1169: * virtual address range determined by [s, e] and pmap to prot. ! 1170: * s and e must be on machine independent page boundaries and ! 1171: * s must be less than or equal to e. ! 1172: */ ! 1173: void pmap_protect( ! 1174: pmap_t pmap, ! 1175: vm_offset_t sva, ! 1176: vm_offset_t eva, ! 1177: vm_prot_t prot) ! 1178: { ! 1179: spl_t spl; ! 1180: register struct phys_entry *pp; ! 1181: register struct mapping *mp, *mpv; ! 1182: ! 1183: #if PMAP_LOWTRACE ! 1184: dbgTrace(0xF1D00008, (unsigned int)pmap, (unsigned int)(sva|((eva-sva)>>12))); /* (TEST/DEBUG) */ ! 1185: #endif ! 1186: ! 1187: #if DEBUG ! 1188: if (pmdebug & PDB_USER) ! 1189: kprintf("pmap_protect(pmap=%x, sva=%x, eva=%x, prot=%x)\n", pmap, sva, eva, prot); ! 1190: ! 1191: assert(sva < eva); ! 1192: #endif ! 1193: ! 1194: if (pmap == PMAP_NULL) ! 1195: return; ! 1196: ! 1197: debugLog2(48, sva, eva); /* Log pmap_map call */ ! 1198: ! 1199: if (prot == VM_PROT_NONE) { /* Should we kill the address range?? */ ! 1200: pmap_remove(pmap, sva, eva); /* Yeah, dump 'em */ ! 1201: ! 1202: debugLog2(49, prot, 0); /* Log pmap_map call */ ! 1203: ! 1204: return; /* Leave... */ ! 1205: } ! 1206: ! 1207: sva = trunc_page(sva); /* Start up a page boundary */ ! 1208: ! 1209: for ( ; sva < eva; sva += PAGE_SIZE) { /* Step it a page at a time */ ! 1210: ! 1211: spl=splhigh(); /* Don't interrupt me, I'm busy */ ! 1212: ! 1213: mp = hw_lock_phys_vir(pmap->space, sva); /* Lock the physical entry for this mapping */ ! 1214: if(mp) { /* Only do this if it is mapped */ ! 1215: if((unsigned int)mp&1) { /* Did the lock on the phys entry time out? */ ! 1216: panic("pmap_protect: timeout obtaining lock on physical entry\n"); /* Scream bloody murder! */ ! 1217: splx(spl); /* I'm not busy no more */ ! 1218: return; ! 1219: } ! 1220: ! 1221: mpv = hw_cpv(mp); /* Get virtual address of mapping */ ! 1222: if(mpv->physent) { /* If there is a physical page, */ ! 1223: mapping_protect(mpv->physent, prot, 1); /* Change the protection in every translation for ! 1224: this physical page and say the physent's locked already */ ! 1225: hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK); /* Unlock the physical entry */ ! 1226: } ! 1227: } ! 1228: splx(spl); /* I'm not busy no more */ ! 1229: } ! 1230: ! 1231: debugLog2(49, prot, 1); /* Log pmap_map call */ ! 1232: return; /* Leave... */ ! 1233: } ! 1234: ! 1235: /* ! 1236: * pmap_enter ! 1237: * ! 1238: * Create a translation for the virtual address (virt) to the physical ! 1239: * address (phys) in the pmap with the protection requested. If the ! 1240: * translation is wired then we can not allow a full page fault, i.e., ! 1241: * the mapping control block is not eligible to be stolen in a low memory ! 1242: * condition. ! 1243: * ! 1244: * NB: This is the only routine which MAY NOT lazy-evaluate ! 1245: * or lose information. That is, this routine must actually ! 1246: * insert this page into the given map NOW. ! 1247: */ ! 1248: void ! 1249: pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot, ! 1250: boolean_t wired) ! 1251: { ! 1252: spl_t spl; ! 1253: struct mapping *mp; ! 1254: struct phys_entry *pp; ! 1255: int memattr; ! 1256: ! 1257: #if PMAP_LOWTRACE ! 1258: dbgTrace(0xF1D00009, (unsigned int)pmap, (unsigned int)va); /* (TEST/DEBUG) */ ! 1259: dbgTrace(0xF1D04009, (unsigned int)pa, (unsigned int)prot); /* (TEST/DEBUG) */ ! 1260: #endif ! 1261: ! 1262: if (pmap == PMAP_NULL) return; /* If they gave us no pmap, just leave... */ ! 1263: ! 1264: debugLog2(50, va, pa); /* Log pmap_map call */ ! 1265: ! 1266: pp = pmap_find_physentry(pa); /* Get the physent for this physical page */ ! 1267: ! 1268: spl=splhigh(); /* Have to disallow interrupts between the ! 1269: time we possibly clear a mapping and the time ! 1270: we get it remapped again. An I/O SLIH could ! 1271: try to drive an IOR using the page before ! 1272: we get it mapped (Dude! This was a tough ! 1273: bug!!!!) */ ! 1274: ! 1275: mapping_remove(pmap->space, va); /* Remove any other mapping at this address */ ! 1276: memattr = PTE_WIMG_IO; /* Assume I/O mapping for a moment */ ! 1277: if(pp) { /* Is there a physical mapping? */ ! 1278: mapping_phys_attr(pp, prot, pp->pte1&0x00000078); /* Set the physical protect default */ ! 1279: memattr = ((pp->pte1&0x00000078) >> 3); /* Set the mapping properly */ ! 1280: } ! 1281: mp=mapping_make(pmap, pmap->space, pp, va, pa, prot, memattr); /* Make the address mapping */ ! 1282: ! 1283: splx(spl); /* I'm not busy no more - come what may */ ! 1284: ! 1285: debugLog2(51, prot, 0); /* Log pmap_map call */ ! 1286: ! 1287: #if DEBUG ! 1288: if (pmdebug & (PDB_USER|PDB_ENTER)) ! 1289: kprintf("leaving pmap_enter\n"); ! 1290: #endif ! 1291: ! 1292: } ! 1293: ! 1294: /* ! 1295: * pmap_extract(pmap, va) ! 1296: * returns the physical address corrsponding to the ! 1297: * virtual address specified by pmap and va if the ! 1298: * virtual address is mapped and 0 if it is not. ! 1299: */ ! 1300: vm_offset_t pmap_extract(pmap_t pmap, vm_offset_t va) { ! 1301: ! 1302: spl_t spl; ! 1303: register struct mapping *mp, *mpv; ! 1304: register vm_offset_t pa; ! 1305: ! 1306: ! 1307: #if PMAP_LOWTRACE ! 1308: dbgTrace(0xF1D0000B, (unsigned int)pmap, (unsigned int)va); /* (TEST/DEBUG) */ ! 1309: #endif ! 1310: #if DEBUG ! 1311: if (pmdebug & PDB_USER) ! 1312: kprintf("pmap_extract(pmap=%x, va=%x)\n", pmap, va); ! 1313: #endif ! 1314: ! 1315: pa = (vm_offset_t) 0; /* Clear this to 0 */ ! 1316: ! 1317: debugLog2(52, pmap->space, va); /* Log pmap_map call */ ! 1318: ! 1319: spl = splhigh(); /* We can't allow any loss of control here */ ! 1320: ! 1321: if(mp=hw_lock_phys_vir(pmap->space, va)) { /* Find the mapping for this vaddr and lock physent */ ! 1322: if((unsigned int)mp&1) { /* Did the lock on the phys entry time out? */ ! 1323: panic("pmap_extract: timeout obtaining lock on physical entry\n"); /* Scream bloody murder! */ ! 1324: splx(spl); /* Interruptions are cool now */ ! 1325: return 0; ! 1326: } ! 1327: mpv = hw_cpv(mp); /* Get virtual address of mapping */ ! 1328: pa = (vm_offset_t)((mpv->PTEr & -PAGE_SIZE) | ((unsigned int)va & (PAGE_SIZE-1))); /* Build the physical address */ ! 1329: if(mpv->physent) hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK); /* Unlock the physical entry */ ! 1330: splx(spl); /* Interruptions are cool now */ ! 1331: ! 1332: debugLog2(53, pa, 0); /* Log pmap_map call */ ! 1333: ! 1334: return pa; /* Return the physical address... */ ! 1335: } ! 1336: ! 1337: splx(spl); /* Interruptions are cool now */ ! 1338: ! 1339: debugLog2(53, pa, 0); /* Log pmap_map call */ ! 1340: ! 1341: return pa; /* Send back a 0 'cause there's no translation... */ ! 1342: } ! 1343: ! 1344: /* ! 1345: * pmap_attributes: ! 1346: * ! 1347: * Set/Get special memory attributes; Set is not implemented. ! 1348: * ! 1349: * Note: 'VAL_GET_INFO' is used to return info about a page. ! 1350: * If less than 1 page is specified, return the physical page ! 1351: * mapping and a count of the number of mappings to that page. ! 1352: * If more than one page is specified, return the number ! 1353: * of resident pages and the number of shared (more than ! 1354: * one mapping) pages in the range; ! 1355: * ! 1356: */ ! 1357: kern_return_t ! 1358: pmap_attribute(pmap, address, size, attribute, value) ! 1359: pmap_t pmap; ! 1360: vm_offset_t address; ! 1361: vm_size_t size; ! 1362: vm_machine_attribute_t attribute; ! 1363: vm_machine_attribute_val_t* value; ! 1364: { ! 1365: spl_t s; ! 1366: vm_offset_t sva, eva; ! 1367: vm_offset_t pa; ! 1368: kern_return_t ret; ! 1369: register struct mapping *mp, *mpv; ! 1370: register struct phys_entry *pp; ! 1371: int total; ! 1372: ! 1373: if (attribute != MATTR_CACHE) ! 1374: return KERN_INVALID_ARGUMENT; ! 1375: ! 1376: /* We can't get the caching attribute for more than one page ! 1377: * at a time ! 1378: */ ! 1379: if ((*value == MATTR_VAL_GET) && ! 1380: (trunc_page(address) != trunc_page(address+size-1))) ! 1381: return KERN_INVALID_ARGUMENT; ! 1382: ! 1383: if (pmap == PMAP_NULL) ! 1384: return KERN_SUCCESS; ! 1385: ! 1386: sva = trunc_page(address); ! 1387: eva = round_page(address + size); ! 1388: ret = KERN_SUCCESS; ! 1389: ! 1390: debugLog2(54, address, attribute); /* Log pmap_map call */ ! 1391: ! 1392: switch (*value) { ! 1393: case MATTR_VAL_CACHE_SYNC: /* sync I+D caches */ ! 1394: if (PROCESSOR_VERSION == PROCESSOR_VERSION_601) { /* Don't need this for 601s... */ ! 1395: break; ! 1396: } ! 1397: case MATTR_VAL_CACHE_FLUSH: /* flush from all caches */ ! 1398: case MATTR_VAL_DCACHE_FLUSH: /* flush from data cache(s) */ ! 1399: case MATTR_VAL_ICACHE_FLUSH: /* flush from instr cache(s) */ ! 1400: sva = trunc_page(sva); ! 1401: s = splhigh(); ! 1402: for (; sva < eva; sva += PAGE_SIZE) { ! 1403: ! 1404: if(!(mp = hw_lock_phys_vir(pmap->space, sva))) /* Find the mapping for this vaddr and lock physent */ ! 1405: continue; /* Skip if the page is not mapped... */ ! 1406: ! 1407: if((unsigned int)mp&1) { /* Did the lock on the phys entry time out? */ ! 1408: panic("pmap_attribute: timeout obtaining lock on physical entry\n"); /* Scream bloody murder! */ ! 1409: continue; ! 1410: } ! 1411: ! 1412: mpv = hw_cpv(mp); /* Get virtual address of mapping */ ! 1413: if((unsigned int)mpv->physent) { /* Is there a physical entry? */ ! 1414: pa = (vm_offset_t)mpv->physent->pte1 & -PAGE_SIZE; /* Yes, get the physical address from there */ ! 1415: } ! 1416: else { ! 1417: pa = (vm_offset_t)(mpv->PTEr & PAGE_SIZE); /* Otherwise from the mapping */ ! 1418: } ! 1419: ! 1420: switch (*value) { /* What type was that again? */ ! 1421: case MATTR_VAL_CACHE_SYNC: /* It is sync I+D caches */ ! 1422: sync_cache(pa, PAGE_SIZE); /* Sync up dem caches */ ! 1423: break; /* Done with this one here... */ ! 1424: ! 1425: case MATTR_VAL_CACHE_FLUSH: /* It is flush from all caches */ ! 1426: flush_dcache(pa, PAGE_SIZE, TRUE); /* Flush out the data cache */ ! 1427: invalidate_icache(pa, PAGE_SIZE, TRUE); /* Flush out the instruction cache */ ! 1428: break; /* Done with this one here... */ ! 1429: ! 1430: case MATTR_VAL_DCACHE_FLUSH: /* It is flush from data cache(s) */ ! 1431: flush_dcache(pa, PAGE_SIZE, TRUE); /* Flush out the data cache */ ! 1432: break; /* Done with this one here... */ ! 1433: ! 1434: case MATTR_VAL_ICACHE_FLUSH: /* It is flush from instr cache(s) */ ! 1435: invalidate_icache(pa, PAGE_SIZE, TRUE); /* Flush out the instruction cache */ ! 1436: break; /* Done with this one here... */ ! 1437: } ! 1438: if(mpv->physent) hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK); /* Unlock the physical entry if it exists*/ ! 1439: ! 1440: } ! 1441: splx(s); ! 1442: break; ! 1443: ! 1444: case MATTR_VAL_GET_INFO: /* Get info */ ! 1445: total = 0; ! 1446: s = splhigh(); /* Lock 'em out */ ! 1447: if (size <= PAGE_SIZE) { /* Do they want just one page */ ! 1448: if(!(mp = hw_lock_phys_vir(pmap->space, sva))) { /* Find the mapping for this vaddr and lock physent */ ! 1449: *value = 0; /* Return nothing if no mapping */ ! 1450: } ! 1451: else { ! 1452: if((unsigned int)mp&1) { /* Did the lock on the phys entry time out? */ ! 1453: panic("pmap_attribute: timeout obtaining lock on physical entry\n"); /* Scream bloody murder! */ ! 1454: } ! 1455: mpv = hw_cpv(mp); /* Get virtual address of mapping */ ! 1456: if(pp = mpv->physent) { /* Check for a physical entry */ ! 1457: total = 0; /* Clear the count */ ! 1458: for (mpv = (mapping *)hw_cpv((mapping *)((unsigned int)pp->phys_link & ~PHYS_FLAGS)); mpv != NULL; mpv = hw_cpv(mp->next)) total++; /* Count the mapping */ ! 1459: *value = (vm_machine_attribute_val_t) ((pp->pte1 & -PAGE_SIZE) | total); /* Pass back the physical address and the count of mappings */ ! 1460: hw_unlock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK); /* Clear the physical entry lock */ ! 1461: } ! 1462: else { /* This is the case for an I/O mapped area */ ! 1463: *value = (vm_machine_attribute_val_t) ((mpv->PTEr & -PAGE_SIZE) | 1); /* Pass back the physical address and the count of mappings */ ! 1464: } ! 1465: } ! 1466: } ! 1467: else { ! 1468: total = 0; ! 1469: while (sva < eva) { ! 1470: if(mp = hw_lock_phys_vir(pmap->space, sva)) { /* Find the mapping for this vaddr and lock physent */ ! 1471: if((unsigned int)mp&1) { /* Did the lock on the phys entry time out? */ ! 1472: panic("pmap_attribute: timeout obtaining lock on physical entry\n"); /* Scream bloody murder! */ ! 1473: continue; ! 1474: } ! 1475: mpv = hw_cpv(mp); /* Get virtual address of mapping */ ! 1476: total += 65536 + (mpv->physent && ((mapping *)((unsigned int)mpv->physent->phys_link & -32))->next); /* Count the "resident" and shared pages */ ! 1477: hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK); /* Clear the physical entry lock */ ! 1478: } ! 1479: sva += PAGE_SIZE; ! 1480: } ! 1481: *value = total; ! 1482: } ! 1483: splx(s); ! 1484: break; ! 1485: ! 1486: case MATTR_VAL_GET: /* return current value */ ! 1487: case MATTR_VAL_OFF: /* turn attribute off */ ! 1488: case MATTR_VAL_ON: /* turn attribute on */ ! 1489: default: ! 1490: ret = KERN_INVALID_ARGUMENT; ! 1491: break; ! 1492: } ! 1493: ! 1494: debugLog2(55, 0, 0); /* Log pmap_map call */ ! 1495: ! 1496: return ret; ! 1497: } ! 1498: ! 1499: /* ! 1500: * pmap_collect ! 1501: * ! 1502: * Garbage collects the physical map system for pages that are no longer used. ! 1503: * It isn't implemented or needed or wanted. ! 1504: */ ! 1505: void ! 1506: pmap_collect(pmap_t pmap) ! 1507: { ! 1508: return; ! 1509: } ! 1510: ! 1511: /* ! 1512: * Routine: pmap_activate ! 1513: * Function: ! 1514: * Binds the given physical map to the given ! 1515: * processor, and returns a hardware map description. ! 1516: * It isn't implemented or needed or wanted. ! 1517: */ ! 1518: void ! 1519: pmap_activate( ! 1520: pmap_t pmap, ! 1521: thread_t th, ! 1522: int which_cpu) ! 1523: { ! 1524: return; ! 1525: } ! 1526: /* ! 1527: * pmap_deactivate: ! 1528: * It isn't implemented or needed or wanted. ! 1529: */ ! 1530: void ! 1531: pmap_deactivate( ! 1532: pmap_t pmap, ! 1533: thread_t th, ! 1534: int which_cpu) ! 1535: { ! 1536: return; ! 1537: } ! 1538: ! 1539: #if DEBUG ! 1540: ! 1541: /* ! 1542: * pmap_zero_page ! 1543: * pmap_copy page ! 1544: * ! 1545: * are implemented in movc.s, these ! 1546: * are just wrappers to help debugging ! 1547: */ ! 1548: ! 1549: extern void pmap_zero_page_assembler(vm_offset_t p); ! 1550: extern void pmap_copy_page_assembler(vm_offset_t src, vm_offset_t dst); ! 1551: ! 1552: /* ! 1553: * pmap_zero_page(pa) ! 1554: * ! 1555: * pmap_zero_page zeros the specified (machine independent) page pa. ! 1556: */ ! 1557: void ! 1558: pmap_zero_page( ! 1559: vm_offset_t p) ! 1560: { ! 1561: register struct mapping *mp; ! 1562: register struct phys_entry *pp; ! 1563: ! 1564: if (pmdebug & (PDB_USER|PDB_ZERO)) ! 1565: kprintf("pmap_zero_page(pa=%x)\n", p); ! 1566: ! 1567: /* ! 1568: * XXX can these happen? ! 1569: */ ! 1570: if (pmap_find_physentry(p) == PHYS_NULL) ! 1571: panic("zero_page: physaddr out of range"); ! 1572: ! 1573: pmap_zero_page_assembler(p); ! 1574: } ! 1575: ! 1576: /* ! 1577: * pmap_copy_page(src, dst) ! 1578: * ! 1579: * pmap_copy_page copies the specified (machine independent) ! 1580: * page from physical address src to physical address dst. ! 1581: * ! 1582: * We need to invalidate the cache for address dst before ! 1583: * we do the copy. Apparently there won't be any mappings ! 1584: * to the dst address normally. ! 1585: */ ! 1586: void ! 1587: pmap_copy_page( ! 1588: vm_offset_t src, ! 1589: vm_offset_t dst) ! 1590: { ! 1591: register struct phys_entry *pp; ! 1592: ! 1593: if (pmdebug & (PDB_USER|PDB_COPY)) ! 1594: kprintf("pmap_copy_page(spa=%x, dpa=%x)\n", src, dst); ! 1595: if (pmdebug & PDB_COPY) ! 1596: kprintf("pmap_copy_page: phys_copy(%x, %x, %x)\n", ! 1597: src, dst, PAGE_SIZE); ! 1598: ! 1599: pmap_copy_page_assembler(src, dst); ! 1600: } ! 1601: #endif /* DEBUG */ ! 1602: ! 1603: /* ! 1604: * pmap_pageable(pmap, s, e, pageable) ! 1605: * Make the specified pages (by pmap, offset) ! 1606: * pageable (or not) as requested. ! 1607: * ! 1608: * A page which is not pageable may not take ! 1609: * a fault; therefore, its page table entry ! 1610: * must remain valid for the duration. ! 1611: * ! 1612: * This routine is merely advisory; pmap_enter() ! 1613: * will specify that these pages are to be wired ! 1614: * down (or not) as appropriate. ! 1615: * ! 1616: * (called from vm/vm_fault.c). ! 1617: */ ! 1618: void ! 1619: pmap_pageable( ! 1620: pmap_t pmap, ! 1621: vm_offset_t start, ! 1622: vm_offset_t end, ! 1623: boolean_t pageable) ! 1624: { ! 1625: ! 1626: return; /* This is not used... */ ! 1627: ! 1628: } ! 1629: /* ! 1630: * Routine: pmap_change_wiring ! 1631: * NOTE USED ANYMORE. ! 1632: */ ! 1633: void ! 1634: pmap_change_wiring( ! 1635: register pmap_t pmap, ! 1636: vm_offset_t va, ! 1637: boolean_t wired) ! 1638: { ! 1639: return; /* This is not used... */ ! 1640: } ! 1641: ! 1642: /* ! 1643: * pmap_modify_pages(pmap, s, e) ! 1644: * sets the modified bit on all virtual addresses v in the ! 1645: * virtual address range determined by [s, e] and pmap, ! 1646: * s and e must be on machine independent page boundaries and ! 1647: * s must be less than or equal to e. ! 1648: */ ! 1649: void ! 1650: pmap_modify_pages( ! 1651: pmap_t pmap, ! 1652: vm_offset_t sva, ! 1653: vm_offset_t eva) ! 1654: { ! 1655: spl_t spl; ! 1656: mapping *mp; ! 1657: ! 1658: #if PMAP_LOWTRACE ! 1659: dbgTrace(0xF1D00010, (unsigned int)pmap, (unsigned int)(sva|((eva-sva)>>12))); /* (TEST/DEBUG) */ ! 1660: #endif ! 1661: ! 1662: #if DEBUG ! 1663: if (pmdebug & PDB_USER) kprintf("pmap_modify_pages(pmap=%x, sva=%x, eva=%x)\n", pmap, sva, eva); ! 1664: #endif ! 1665: ! 1666: if (pmap == PMAP_NULL) return; /* If no pmap, can't do it... */ ! 1667: ! 1668: debugLog2(56, sva, eva); /* Log pmap_map call */ ! 1669: ! 1670: spl=splhigh(); /* Don't bother me */ ! 1671: ! 1672: for ( ; sva < eva; sva += PAGE_SIZE) { /* Cycle through the whole range */ ! 1673: mp = hw_lock_phys_vir(pmap->space, sva); /* Lock the physical entry for this mapping */ ! 1674: if(mp) { /* Did we find one? */ ! 1675: if((unsigned int)mp&1) { /* Did the lock on the phys entry time out? */ ! 1676: panic("pmap_modify_pages: timeout obtaining lock on physical entry\n"); /* Scream bloody murder! */ ! 1677: continue; ! 1678: } ! 1679: mp = hw_cpv(mp); /* Convert to virtual addressing */ ! 1680: if(!mp->physent) continue; /* No physical entry means an I/O page, we can't set attributes */ ! 1681: mapping_set_mod(mp->physent); /* Set the modfied bit for this page */ ! 1682: hw_unlock_bit((unsigned int *)&mp->physent->phys_link, PHYS_LOCK); /* Unlock the physical entry */ ! 1683: } ! 1684: } ! 1685: splx(spl); /* Restore the interrupt level */ ! 1686: ! 1687: debugLog2(57, 0, 0); /* Log pmap_map call */ ! 1688: return; /* Leave... */ ! 1689: } ! 1690: ! 1691: /* ! 1692: * pmap_clear_modify(phys) ! 1693: * clears the hardware modified ("dirty") bit for one ! 1694: * machine independant page starting at the given ! 1695: * physical address. phys must be aligned on a machine ! 1696: * independant page boundary. ! 1697: */ ! 1698: void ! 1699: pmap_clear_modify(vm_offset_t pa) ! 1700: { ! 1701: register struct phys_entry *pp; ! 1702: spl_t spl; ! 1703: ! 1704: #if PMAP_LOWTRACE ! 1705: dbgTrace(0xF1D00011, (unsigned int)pa, 0); /* (TEST/DEBUG) */ ! 1706: #endif ! 1707: #if DEBUG ! 1708: if (pmdebug & PDB_USER) ! 1709: kprintf("pmap_clear_modify(pa=%x)\n", pa); ! 1710: #endif ! 1711: ! 1712: pp = pmap_find_physentry(pa); /* Find the physent for this page */ ! 1713: if (pp == PHYS_NULL) return; /* If there isn't one, just leave... */ ! 1714: ! 1715: debugLog2(58, pa, 0); /* Log pmap_map call */ ! 1716: ! 1717: spl=splhigh(); /* Don't bother me */ ! 1718: ! 1719: if(!hw_lock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK, LockTimeOut)) { /* Try to get the lock on the physical entry */ ! 1720: panic("pmap_clear_modify: Timeout getting lock on physent at %08X\n", pp); /* Arrrgghhhh! */ ! 1721: splx(spl); /* Restore 'rupts */ ! 1722: return; /* Should die before here */ ! 1723: } ! 1724: ! 1725: mapping_clr_mod(pp); /* Clear all change bits for physical page */ ! 1726: ! 1727: hw_unlock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK); /* Unlock the physical entry */ ! 1728: splx(spl); /* Restore the interrupt level */ ! 1729: ! 1730: debugLog2(59, 0, 0); /* Log pmap_map call */ ! 1731: } ! 1732: ! 1733: /* ! 1734: * pmap_is_modified(phys) ! 1735: * returns TRUE if the given physical page has been modified ! 1736: * since the last call to pmap_clear_modify(). ! 1737: */ ! 1738: boolean_t ! 1739: pmap_is_modified(register vm_offset_t pa) ! 1740: { ! 1741: register struct phys_entry *pp; ! 1742: spl_t spl; ! 1743: boolean_t ret; ! 1744: ! 1745: ! 1746: #if PMAP_LOWTRACE ! 1747: dbgTrace(0xF1D00012, (unsigned int)pa, 0); /* (TEST/DEBUG) */ ! 1748: #endif ! 1749: #if DEBUG ! 1750: if (pmdebug & PDB_USER) ! 1751: kprintf("pmap_is_modified(pa=%x)\n", pa); ! 1752: #endif ! 1753: ! 1754: pp = pmap_find_physentry(pa); /* Find the physent for this page */ ! 1755: if (pp == PHYS_NULL) return(FALSE); /* Just indicate not set... */ ! 1756: ! 1757: debugLog2(60, pa, 0); /* Log pmap_map call */ ! 1758: ! 1759: spl=splhigh(); /* Don't bother me */ ! 1760: ! 1761: if(!hw_lock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK, LockTimeOut)) { /* Try to get the lock on the physical entry */ ! 1762: panic("pmap_is_modified: Timeout getting lock on physent at %08X\n", pp); /* Arrrgghhhh! */ ! 1763: splx(spl); /* Restore 'rupts */ ! 1764: return 0; /* Should die before here */ ! 1765: } ! 1766: ! 1767: ret = mapping_tst_mod(pp); /* Check for modified */ ! 1768: ! 1769: hw_unlock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK); /* Unlock the physical entry */ ! 1770: splx(spl); /* Restore the interrupt level */ ! 1771: ! 1772: debugLog2(61, ret, 0); /* Log pmap_map call */ ! 1773: ! 1774: return ret; ! 1775: } ! 1776: ! 1777: /* ! 1778: * pmap_clear_reference(phys) ! 1779: * clears the hardware referenced bit in the given machine ! 1780: * independant physical page. ! 1781: * ! 1782: */ ! 1783: void ! 1784: pmap_clear_reference(vm_offset_t pa) ! 1785: { ! 1786: register struct phys_entry *pp; ! 1787: spl_t spl; ! 1788: ! 1789: ! 1790: #if PMAP_LOWTRACE ! 1791: dbgTrace(0xF1D00013, (unsigned int)pa, 0); /* (TEST/DEBUG) */ ! 1792: #endif ! 1793: #if DEBUG ! 1794: if (pmdebug & PDB_USER) ! 1795: kprintf("pmap_clear_reference(pa=%x)\n", pa); ! 1796: #endif ! 1797: ! 1798: pp = pmap_find_physentry(pa); /* Find the physent for this page */ ! 1799: if (pp == PHYS_NULL) return; /* If there isn't one, just leave... */ ! 1800: ! 1801: debugLog2(62, pa, 0); /* Log pmap_map call */ ! 1802: ! 1803: spl=splhigh(); /* Don't bother me */ ! 1804: mapping_clr_ref(pp); /* Clear all reference bits for physical page */ ! 1805: splx(spl); /* Restore the interrupt level */ ! 1806: ! 1807: debugLog2(63, 0, 0); /* Log pmap_map call */ ! 1808: ! 1809: } ! 1810: ! 1811: /* ! 1812: * pmap_is_referenced(phys) ! 1813: * returns TRUE if the given physical page has been referenced ! 1814: * since the last call to pmap_clear_reference(). ! 1815: */ ! 1816: boolean_t ! 1817: pmap_is_referenced(vm_offset_t pa) ! 1818: { ! 1819: register struct phys_entry *pp; ! 1820: spl_t spl; ! 1821: boolean_t ret; ! 1822: ! 1823: ! 1824: #if PMAP_LOWTRACE ! 1825: dbgTrace(0xF1D00014, (unsigned int)pa, 0); /* (TEST/DEBUG) */ ! 1826: #endif ! 1827: #if DEBUG ! 1828: if (pmdebug & PDB_USER) ! 1829: kprintf("pmap_is_referenced(pa=%x)\n", pa); ! 1830: #endif ! 1831: ! 1832: pp = pmap_find_physentry(pa); /* Find the physent for this page */ ! 1833: if (pp == PHYS_NULL) return(FALSE); /* Just indicate not set... */ ! 1834: ! 1835: debugLog2(64, pa, 0); /* Log pmap_map call */ ! 1836: ! 1837: spl=splhigh(); /* Don't bother me */ ! 1838: ! 1839: if(!hw_lock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK, LockTimeOut)) { /* Try to get the lock on the physical entry */ ! 1840: panic("pmap_is_referenced: Timeout getting lock on physent at %08X\n", pp); /* Arrrgghhhh! */ ! 1841: splx(spl); /* Restore 'rupts */ ! 1842: return 0; /* Should die before here */ ! 1843: } ! 1844: ! 1845: ret = mapping_tst_ref(pp); /* Check for referenced */ ! 1846: ! 1847: hw_unlock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK); /* Unlock the physical entry */ ! 1848: splx(spl); /* Restore the interrupt level */ ! 1849: ! 1850: debugLog2(65, ret, 0); /* Log pmap_map call */ ! 1851: ! 1852: return ret; ! 1853: } ! 1854: ! 1855: #if MACH_VM_DEBUG ! 1856: int ! 1857: pmap_list_resident_pages( ! 1858: register pmap_t pmap, ! 1859: register vm_offset_t *listp, ! 1860: register int space) ! 1861: { ! 1862: return 0; ! 1863: } ! 1864: #endif /* MACH_VM_DEBUG */ ! 1865: ! 1866: /* ! 1867: * Locking: ! 1868: * spl: VM ! 1869: */ ! 1870: void ! 1871: pmap_copy_part_page( ! 1872: vm_offset_t src, ! 1873: vm_offset_t src_offset, ! 1874: vm_offset_t dst, ! 1875: vm_offset_t dst_offset, ! 1876: vm_size_t len) ! 1877: { ! 1878: register struct phys_entry *pp_src, *pp_dst; ! 1879: spl_t s; ! 1880: ! 1881: ! 1882: #if PMAP_LOWTRACE ! 1883: dbgTrace(0xF1D00019, (unsigned int)src+src_offset, (unsigned int)dst+dst_offset); /* (TEST/DEBUG) */ ! 1884: dbgTrace(0xF1D04019, (unsigned int)len, 0); /* (TEST/DEBUG) */ ! 1885: #endif ! 1886: s = splhigh(); ! 1887: ! 1888: assert(((dst & PAGE_MASK)+dst_offset+len) <= PAGE_SIZE); ! 1889: assert(((src & PAGE_MASK)+src_offset+len) <= PAGE_SIZE); ! 1890: ! 1891: /* ! 1892: * Since the source and destination are physical addresses, ! 1893: * turn off data translation to perform a bcopy() in bcopy_phys(). ! 1894: */ ! 1895: phys_copy((vm_offset_t) src+src_offset, ! 1896: (vm_offset_t) dst+dst_offset, len); ! 1897: ! 1898: splx(s); ! 1899: } ! 1900: ! 1901: void ! 1902: pmap_zero_part_page( ! 1903: vm_offset_t p, ! 1904: vm_offset_t offset, ! 1905: vm_size_t len) ! 1906: { ! 1907: panic("pmap_zero_part_page"); ! 1908: } ! 1909: ! 1910: boolean_t pmap_verify_free(vm_offset_t pa) { ! 1911: ! 1912: struct phys_entry *pp; ! 1913: ! 1914: #if PMAP_LOWTRACE ! 1915: dbgTrace(0xF1D00007, (unsigned int)pa, 0); /* (TEST/DEBUG) */ ! 1916: #endif ! 1917: ! 1918: #if DEBUG ! 1919: if (pmdebug & PDB_USER) ! 1920: kprintf("pmap_verify_free(pa=%x)\n", pa); ! 1921: #endif ! 1922: ! 1923: if (!pmap_initialized) return(TRUE); ! 1924: ! 1925: pp = pmap_find_physentry(pa); /* Look up the physical entry */ ! 1926: if (pp == PHYS_NULL) return FALSE; /* If there isn't one, show no mapping... */ ! 1927: return ((mapping *)((unsigned int)pp->phys_link & ~PHYS_FLAGS) == MAPPING_NULL); /* Otherwise, return TRUE if mapping exists... */ ! 1928: } ! 1929: ! 1930: ! 1931: /* Determine if we need to switch space and set up for it if so */ ! 1932: ! 1933: void pmap_switch(pmap_t map) ! 1934: { ! 1935: unsigned int i; ! 1936: ! 1937: #if DEBUG ! 1938: if (watchacts & WA_PCB) { ! 1939: kprintf("Switching to map at 0x%08x, space=%d\n", ! 1940: map,map->space); ! 1941: } ! 1942: #endif /* DEBUG */ ! 1943: ! 1944: ! 1945: /* when changing to kernel space (collocated servers), don't bother ! 1946: * doing anything, the kernel is mapped from here already. ! 1947: */ ! 1948: if (map->space == PPC_SID_KERNEL) { /* Are we switching into kernel space? */ ! 1949: return; /* If so, we don't do anything... */ ! 1950: } ! 1951: ! 1952: hw_set_user_space(map->space); /* Indicate if we need to load the SRs or not */ ! 1953: return; /* Bye, bye, butterfly... */ ! 1954: } ! 1955: ! 1956: #ifdef MACH_BSD ! 1957: /* ! 1958: * pmap_move_page - Move pages from one kernel vaddr to another. ! 1959: * ! 1960: * Parameters: ! 1961: * from - Original kernel va (Mach. indep. page boundary) ! 1962: * to - New kernel va (Mach. indep. page boundary) ! 1963: * size - Bytes to move. (Mach. indep. pages) ! 1964: * ! 1965: * Returns: ! 1966: * Nothing. ! 1967: */ ! 1968: void pmap_move_page(unsigned long from, unsigned long to, vm_size_t size) { ! 1969: ! 1970: mapping *mp; ! 1971: vm_offset_t pa; ! 1972: vm_size_t cs; ! 1973: ! 1974: ! 1975: if ((size & page_mask) != 0) { ! 1976: panic("pmap_move_page: partial mach indep page"); ! 1977: } ! 1978: ! 1979: debugLog2(66, from, to); /* Log pmap_map call */ ! 1980: ! 1981: for(cs = 0; cs < size; cs += PAGE_SIZE) { /* Do the whole range */ ! 1982: ! 1983: if(!mapping_remap(kernel_pmap->space, from, to)) { /* Remap the vaddr */ ! 1984: panic("pmap_move_page: from address not mapped (from=%08X; to=%08X; size=%08X", from, to, size); /* Didn't work, squeal like a piggy... */ ! 1985: return; /* Didn't find any, return... */ ! 1986: } ! 1987: ! 1988: from += PAGE_SIZE; /* Get the next "from" address */ ! 1989: to += PAGE_SIZE; /* Get the next "to" address */ ! 1990: } ! 1991: ! 1992: debugLog2(67, from, to); /* Log pmap_map call */ ! 1993: ! 1994: return; /* Bye... */ ! 1995: } ! 1996: ! 1997: /* ! 1998: * Move pages from one kernel virtual address to another. ! 1999: * Both addresses are assumed to reside in the Sysmap, ! 2000: * and size must be a multiple of the page size. ! 2001: */ ! 2002: void ! 2003: pagemove( ! 2004: register caddr_t from, ! 2005: register caddr_t to, ! 2006: int size) ! 2007: { ! 2008: pmap_move_page((unsigned long)from, (unsigned long)to, (vm_size_t)size); ! 2009: } ! 2010: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.