]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ppc/pmap.c
xnu-344.21.74.tar.gz
[apple/xnu.git] / osfmk / ppc / pmap.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * @OSF_COPYRIGHT@
27 */
28 /*
29 * Mach Operating System
30 * Copyright (c) 1990,1991,1992 The University of Utah and
31 * the Center for Software Science (CSS).
32 * Copyright (c) 1991,1987 Carnegie Mellon University.
33 * All rights reserved.
34 *
35 * Permission to use, copy, modify and distribute this software and its
36 * documentation is hereby granted, provided that both the copyright
37 * notice and this permission notice appear in all copies of the
38 * software, derivative works or modified versions, and any portions
39 * thereof, and that both notices appear in supporting documentation,
40 * and that all advertising materials mentioning features or use of
41 * this software display the following acknowledgement: ``This product
42 * includes software developed by the Center for Software Science at
43 * the University of Utah.''
44 *
45 * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSS ALLOW FREE USE OF
46 * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
47 * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
48 * THIS SOFTWARE.
49 *
50 * CSS requests users of this software to return to css-dist@cs.utah.edu any
51 * improvements that they make and grant CSS redistribution rights.
52 *
53 * Carnegie Mellon requests users of this software to return to
54 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
55 * School of Computer Science
56 * Carnegie Mellon University
57 * Pittsburgh PA 15213-3890
58 * any improvements or extensions that they make and grant Carnegie Mellon
59 * the rights to redistribute these changes.
60 *
61 * Utah $Hdr: pmap.c 1.28 92/06/23$
62 * Author: Mike Hibler, Bob Wheeler, University of Utah CSS, 10/90
63 */
64
65 /*
66 * Manages physical address maps for powerpc.
67 *
68 * In addition to hardware address maps, this
69 * module is called upon to provide software-use-only
70 * maps which may or may not be stored in the same
71 * form as hardware maps. These pseudo-maps are
72 * used to store intermediate results from copy
73 * operations to and from address spaces.
74 *
75 * Since the information managed by this module is
76 * also stored by the logical address mapping module,
77 * this module may throw away valid virtual-to-physical
78 * mappings at almost any time. However, invalidations
79 * of virtual-to-physical mappings must be done as
80 * requested.
81 *
82 * In order to cope with hardware architectures which
83 * make virtual-to-physical map invalidates expensive,
84 * this module may delay invalidate or reduced protection
85 * operations until such time as they are actually
86 * necessary. This module is given full information to
87 * when physical maps must be made correct.
88 *
89 */
90
91 #include <zone_debug.h>
92 #include <cpus.h>
93 #include <debug.h>
94 #include <mach_kgdb.h>
95 #include <mach_vm_debug.h>
96 #include <db_machine_commands.h>
97
98 #include <kern/thread.h>
99 #include <kern/simple_lock.h>
100 #include <mach/vm_attributes.h>
101 #include <mach/vm_param.h>
102 #include <vm/vm_kern.h>
103 #include <kern/spl.h>
104
105 #include <kern/misc_protos.h>
106 #include <ppc/misc_protos.h>
107 #include <ppc/proc_reg.h>
108
109 #include <vm/pmap.h>
110 #include <vm/vm_map.h>
111 #include <vm/vm_page.h>
112
113 #include <ppc/pmap.h>
114 #include <ppc/mem.h>
115 #include <ppc/mappings.h>
116
117 #include <ppc/new_screen.h>
118 #include <ppc/Firmware.h>
119 #include <ppc/savearea.h>
120 #include <ppc/exception.h>
121 #include <ppc/low_trace.h>
122 #include <ddb/db_output.h>
123
124 extern unsigned int avail_remaining;
125 extern unsigned int mappingdeb0;
126 extern struct Saveanchor saveanchor; /* Aliged savearea anchor */
127 extern int real_ncpus; /* Number of actual CPUs */
128 unsigned int debugbackpocket; /* (TEST/DEBUG) */
129
130 vm_offset_t first_free_virt;
131 int current_free_region; /* Used in pmap_next_page */
132
133 pmapTransTab *pmapTrans; /* Point to the hash to pmap translations */
134 struct phys_entry *phys_table;
135
136 /* forward */
137 void pmap_activate(pmap_t pmap, thread_t th, int which_cpu);
138 void pmap_deactivate(pmap_t pmap, thread_t th, int which_cpu);
139 void copy_to_phys(vm_offset_t sva, vm_offset_t dpa, int bytecount);
140
141 #if MACH_VM_DEBUG
142 int pmap_list_resident_pages(pmap_t pmap, vm_offset_t *listp, int space);
143 #endif
144
145 /* NOTE: kernel_pmap_store must be in V=R storage and aligned!!!!!!!!!!!!!! */
146
147 extern struct pmap kernel_pmap_store;
148 pmap_t kernel_pmap; /* Pointer to kernel pmap and anchor for in-use pmaps */
149 addr64_t kernel_pmap_phys; /* Pointer to kernel pmap and anchor for in-use pmaps, physical address */
150 pmap_t cursor_pmap; /* Pointer to last pmap allocated or previous if removed from in-use list */
151 pmap_t sharedPmap; /* Pointer to common pmap for 64-bit address spaces */
152 struct zone *pmap_zone; /* zone of pmap structures */
153 boolean_t pmap_initialized = FALSE;
154
155 int ppc_max_pmaps; /* Maximum number of concurrent address spaces allowed. This is machine dependent */
156 addr64_t vm_max_address; /* Maximum effective address supported */
157 addr64_t vm_max_physical; /* Maximum physical address supported */
158
159 /*
160 * Physical-to-virtual translations are handled by inverted page table
161 * structures, phys_tables. Multiple mappings of a single page are handled
162 * by linking the affected mapping structures. We initialise one region
163 * for phys_tables of the physical memory we know about, but more may be
164 * added as it is discovered (eg. by drivers).
165 */
166
167 /*
168 * free pmap list. caches the first free_pmap_max pmaps that are freed up
169 */
170 int free_pmap_max = 32;
171 int free_pmap_count;
172 pmap_t free_pmap_list;
173 decl_simple_lock_data(,free_pmap_lock)
174
175 /*
176 * Function to get index into phys_table for a given physical address
177 */
178
179 struct phys_entry *pmap_find_physentry(ppnum_t pa)
180 {
181 int i;
182 unsigned int entry;
183
184 for (i = pmap_mem_regions_count - 1; i >= 0; i--) {
185 if (pa < pmap_mem_regions[i].mrStart) continue; /* See if we fit in this region */
186 if (pa > pmap_mem_regions[i].mrEnd) continue; /* Check the end too */
187
188 entry = (unsigned int)pmap_mem_regions[i].mrPhysTab + ((pa - pmap_mem_regions[i].mrStart) * sizeof(phys_entry));
189 return (struct phys_entry *)entry;
190 }
191 // kprintf("DEBUG - pmap_find_physentry: page 0x%08X not found\n", pa);
192 return 0;
193 }
194
195 /*
196 * kern_return_t
197 * pmap_add_physical_memory(vm_offset_t spa, vm_offset_t epa,
198 * boolean_t available, unsigned int attr)
199 *
200 * THIS IS NOT SUPPORTED
201 */
202 kern_return_t pmap_add_physical_memory(vm_offset_t spa, vm_offset_t epa,
203 boolean_t available, unsigned int attr)
204 {
205
206 panic("Forget it! You can't map no more memory, you greedy puke!\n");
207 return KERN_SUCCESS;
208 }
209
210 /*
211 * pmap_map(va, spa, epa, prot)
212 * is called during boot to map memory in the kernel's address map.
213 * A virtual address range starting at "va" is mapped to the physical
214 * address range "spa" to "epa" with machine independent protection
215 * "prot".
216 *
217 * "va", "spa", and "epa" are byte addresses and must be on machine
218 * independent page boundaries.
219 *
220 * Pages with a contiguous virtual address range, the same protection, and attributes.
221 * therefore, we map it with a single block.
222 *
223 * Note that this call will only map into 32-bit space
224 *
225 */
226
227 vm_offset_t
228 pmap_map(
229 vm_offset_t va,
230 vm_offset_t spa,
231 vm_offset_t epa,
232 vm_prot_t prot)
233 {
234
235 addr64_t colladr;
236
237 if (spa == epa) return(va);
238
239 assert(epa > spa);
240
241 colladr = mapping_make(kernel_pmap, (addr64_t)va, (ppnum_t)(spa >> 12), (mmFlgBlock | mmFlgPerm), (epa - spa) >> 12, prot & VM_PROT_ALL);
242
243 if(colladr) { /* Was something already mapped in the range? */
244 panic("pmap_map: attempt to map previously mapped range - va = %08X, pa = %08X, epa = %08X, collision = %016llX\n",
245 va, spa, epa, colladr);
246 }
247 return(va);
248 }
249
250 /*
251 * Bootstrap the system enough to run with virtual memory.
252 * Map the kernel's code and data, and allocate the system page table.
253 * Called with mapping done by BATs. Page_size must already be set.
254 *
255 * Parameters:
256 * msize: Total memory present
257 * first_avail: First virtual address available
258 * kmapsize: Size of kernel text and data
259 */
260 void
261 pmap_bootstrap(uint64_t msize, vm_offset_t *first_avail, unsigned int kmapsize)
262 {
263 register struct mapping *mp;
264 vm_offset_t addr;
265 vm_size_t size;
266 int i, num, j, rsize, mapsize, vmpagesz, vmmapsz, bank, nbits;
267 uint64_t tmemsize;
268 uint_t htslop;
269 vm_offset_t first_used_addr, PCAsize;
270 struct phys_entry *phys_table;
271
272 *first_avail = round_page_32(*first_avail); /* Make sure we start out on a page boundary */
273 vm_last_addr = VM_MAX_KERNEL_ADDRESS; /* Set the highest address know to VM */
274
275 /*
276 * Initialize kernel pmap
277 */
278 kernel_pmap = &kernel_pmap_store;
279 kernel_pmap_phys = (addr64_t)&kernel_pmap_store;
280 cursor_pmap = &kernel_pmap_store;
281
282 simple_lock_init(&kernel_pmap->lock, ETAP_VM_PMAP_KERNEL);
283
284 kernel_pmap->pmap_link.next = (queue_t)kernel_pmap; /* Set up anchor forward */
285 kernel_pmap->pmap_link.prev = (queue_t)kernel_pmap; /* Set up anchor reverse */
286 kernel_pmap->ref_count = 1;
287 kernel_pmap->pmapFlags = pmapKeyDef; /* Set the default keys */
288 kernel_pmap->pmapCCtl = pmapCCtlVal; /* Initialize cache control */
289 kernel_pmap->space = PPC_SID_KERNEL;
290 kernel_pmap->pmapvr = 0; /* Virtual = Real */
291
292 /*
293 * The hash table wants to have one pteg for every 2 physical pages.
294 * We will allocate this in physical RAM, outside of kernel virtual memory,
295 * at the top of the highest bank that will contain it.
296 * Note that "bank" doesn't refer to a physical memory slot here, it is a range of
297 * physically contiguous memory.
298 *
299 * The PCA will go there as well, immediately before the hash table.
300 */
301
302 nbits = cntlzw(((msize << 1) - 1) >> 32); /* Get first bit in upper half */
303 if(nbits == 32) nbits = nbits + cntlzw((uint_t)((msize << 1) - 1)); /* If upper half was empty, find bit in bottom half */
304 tmemsize = 0x8000000000000000ULL >> nbits; /* Get memory size rounded up to power of 2 */
305
306 if(tmemsize > 0x0000002000000000ULL) tmemsize = 0x0000002000000000ULL; /* Make sure we don't make an unsupported hash table size */
307
308 hash_table_size = (uint_t)(tmemsize >> 13) * per_proc_info[0].pf.pfPTEG; /* Get provisional hash_table_size */
309 if(hash_table_size < (256 * 1024)) hash_table_size = (256 * 1024); /* Make sure we are at least minimum size */
310
311 while(1) { /* Try to fit hash table in PCA into contiguous memory */
312
313 if(hash_table_size < (256 * 1024)) { /* Have we dropped too short? This should never, ever happen */
314 panic("pmap_bootstrap: Can't find space for hash table\n"); /* This will never print, system isn't up far enough... */
315 }
316
317 PCAsize = (hash_table_size / per_proc_info[0].pf.pfPTEG) * sizeof(PCA); /* Get total size of PCA table */
318 PCAsize = round_page_32(PCAsize); /* Make sure it is at least a page long */
319
320 for(bank = pmap_mem_regions_count - 1; bank >= 0; bank--) { /* Search backwards through banks */
321
322 hash_table_base = ((addr64_t)pmap_mem_regions[bank].mrEnd << 12) - hash_table_size + PAGE_SIZE; /* Get tenative address */
323
324 htslop = hash_table_base & (hash_table_size - 1); /* Get the extra that we will round down when we align */
325 hash_table_base = hash_table_base & -(addr64_t)hash_table_size; /* Round down to correct boundary */
326
327 if((hash_table_base - round_page_32(PCAsize)) >= ((addr64_t)pmap_mem_regions[bank].mrStart << 12)) break; /* Leave if we fit */
328 }
329
330 if(bank >= 0) break; /* We are done if we found a suitable bank */
331
332 hash_table_size = hash_table_size >> 1; /* Try the next size down */
333 }
334
335 if(htslop) { /* If there was slop (i.e., wasted pages for alignment) add a new region */
336 for(i = pmap_mem_regions_count - 1; i >= bank; i--) { /* Copy from end to our bank, including our bank */
337 pmap_mem_regions[i + 1].mrStart = pmap_mem_regions[i].mrStart; /* Set the start of the bank */
338 pmap_mem_regions[i + 1].mrAStart = pmap_mem_regions[i].mrAStart; /* Set the start of allocatable area */
339 pmap_mem_regions[i + 1].mrEnd = pmap_mem_regions[i].mrEnd; /* Set the end address of bank */
340 pmap_mem_regions[i + 1].mrAEnd = pmap_mem_regions[i].mrAEnd; /* Set the end address of allocatable area */
341 }
342
343 pmap_mem_regions[i + 1].mrStart = (hash_table_base + hash_table_size) >> 12; /* Set the start of the next bank to the start of the slop area */
344 pmap_mem_regions[i + 1].mrAStart = (hash_table_base + hash_table_size) >> 12; /* Set the start of allocatable area to the start of the slop area */
345 pmap_mem_regions[i].mrEnd = (hash_table_base + hash_table_size - 4096) >> 12; /* Set the end of our bank to the end of the hash table */
346
347 }
348
349 pmap_mem_regions[bank].mrAEnd = (hash_table_base - PCAsize - 4096) >> 12; /* Set the maximum allocatable in this bank */
350
351 hw_hash_init(); /* Initiaize the hash table and PCA */
352 hw_setup_trans(); /* Set up hardware registers needed for translation */
353
354 /*
355 * The hash table is now all initialized and so is the PCA. Go on to do the rest of it.
356 * This allocation is from the bottom up.
357 */
358
359 num = atop_64(msize); /* Get number of pages in all of memory */
360
361 /* Figure out how much we need to allocate */
362
363 size = (vm_size_t) (
364 (InitialSaveBloks * PAGE_SIZE) + /* Allow space for the initial context saveareas */
365 (BackPocketSaveBloks * PAGE_SIZE) + /* For backpocket saveareas */
366 trcWork.traceSize + /* Size of trace table */
367 ((((1 << maxAdrSpb) * sizeof(pmapTransTab)) + 4095) & -4096) + /* Size of pmap translate table */
368 (((num * sizeof(struct phys_entry)) + 4095) & -4096) /* For the physical entries */
369 );
370
371 mapsize = size = round_page_32(size); /* Get size of area to map that we just calculated */
372 mapsize = mapsize + kmapsize; /* Account for the kernel text size */
373
374 vmpagesz = round_page_32(num * sizeof(struct vm_page)); /* Allow for all vm_pages needed to map physical mem */
375 vmmapsz = round_page_32((num / 8) * sizeof(struct vm_map_entry)); /* Allow for vm_maps */
376
377 mapsize = mapsize + vmpagesz + vmmapsz; /* Add the VM system estimates into the grand total */
378
379 mapsize = mapsize + (4 * 1024 * 1024); /* Allow for 4 meg of extra mappings */
380 mapsize = ((mapsize / PAGE_SIZE) + MAPPERBLOK - 1) / MAPPERBLOK; /* Get number of blocks of mappings we need */
381 mapsize = mapsize + ((mapsize + MAPPERBLOK - 1) / MAPPERBLOK); /* Account for the mappings themselves */
382
383 size = size + (mapsize * PAGE_SIZE); /* Get the true size we need */
384
385 /* hash table must be aligned to its size */
386
387 addr = *first_avail; /* Set the address to start allocations */
388 first_used_addr = addr; /* Remember where we started */
389
390 bzero((char *)addr, size); /* Clear everything that we are allocating */
391
392 savearea_init(addr); /* Initialize the savearea chains and data */
393
394 addr = (vm_offset_t)((unsigned int)addr + ((InitialSaveBloks + BackPocketSaveBloks) * PAGE_SIZE)); /* Point past saveareas */
395
396 trcWork.traceCurr = (unsigned int)addr; /* Set first trace slot to use */
397 trcWork.traceStart = (unsigned int)addr; /* Set start of trace table */
398 trcWork.traceEnd = (unsigned int)addr + trcWork.traceSize; /* Set end of trace table */
399
400 addr = (vm_offset_t)trcWork.traceEnd; /* Set next allocatable location */
401
402 pmapTrans = (pmapTransTab *)addr; /* Point to the pmap to hash translation table */
403
404 pmapTrans[PPC_SID_KERNEL].pmapPAddr = (addr64_t)kernel_pmap; /* Initialize the kernel pmap in the translate table */
405 pmapTrans[PPC_SID_KERNEL].pmapVAddr = kernel_pmap; /* Initialize the kernel pmap in the translate table */
406
407 addr += ((((1 << maxAdrSpb) * sizeof(pmapTransTab)) + 4095) & -4096); /* Point past pmap translate table */
408
409 /* NOTE: the phys_table must be within the first 2GB of physical RAM. This makes sure we only need to do 32-bit arithmetic */
410
411 phys_table = (struct phys_entry *) addr; /* Get pointer to physical table */
412
413 for (bank = 0; bank < pmap_mem_regions_count; bank++) { /* Set pointer and initialize all banks of ram */
414
415 pmap_mem_regions[bank].mrPhysTab = phys_table; /* Set pointer to the physical table for this bank */
416
417 phys_table = phys_table + (pmap_mem_regions[bank].mrEnd - pmap_mem_regions[bank].mrStart + 1); /* Point to the next */
418 }
419
420 addr += (((num * sizeof(struct phys_entry)) + 4095) & -4096); /* Step on past the physical entries */
421
422 /*
423 * Remaining space is for mapping entries. Tell the initializer routine that
424 * the mapping system can't release this block because it's permanently assigned
425 */
426
427 mapping_init(); /* Initialize the mapping tables */
428
429 for(i = addr; i < first_used_addr + size; i += PAGE_SIZE) { /* Add initial mapping blocks */
430 mapping_free_init(i, 1, 0); /* Pass block address and say that this one is not releasable */
431 }
432 mapCtl.mapcmin = MAPPERBLOK; /* Make sure we only adjust one at a time */
433
434 /* Map V=R the page tables */
435 pmap_map(first_used_addr, first_used_addr,
436 round_page_32(first_used_addr + size), VM_PROT_READ | VM_PROT_WRITE);
437
438 *first_avail = round_page_32(first_used_addr + size); /* Set next available page */
439 first_free_virt = *first_avail; /* Ditto */
440
441 /* All the rest of memory is free - add it to the free
442 * regions so that it can be allocated by pmap_steal
443 */
444
445 pmap_mem_regions[0].mrAStart = (*first_avail >> 12); /* Set up the free area to start allocations (always in the first bank) */
446
447 current_free_region = 0; /* Set that we will start allocating in bank 0 */
448 avail_remaining = 0; /* Clear free page count */
449 for(bank = 0; bank < pmap_mem_regions_count; bank++) { /* Total up all of the pages in the system that are available */
450 avail_remaining += (pmap_mem_regions[bank].mrAEnd - pmap_mem_regions[bank].mrAStart) + 1; /* Add in allocatable pages in this bank */
451 }
452
453
454 }
455
456 /*
457 * pmap_init(spa, epa)
458 * finishes the initialization of the pmap module.
459 * This procedure is called from vm_mem_init() in vm/vm_init.c
460 * to initialize any remaining data structures that the pmap module
461 * needs to map virtual memory (VM is already ON).
462 *
463 * Note that the pmap needs to be sized and aligned to
464 * a power of two. This is because it is used both in virtual and
465 * real so it can't span a page boundary.
466 */
467
468 void
469 pmap_init(void)
470 {
471
472 addr64_t cva;
473
474 pmap_zone = zinit(pmapSize, 400 * pmapSize, 4096, "pmap");
475 #if ZONE_DEBUG
476 zone_debug_disable(pmap_zone); /* Can't debug this one 'cause it messes with size and alignment */
477 #endif /* ZONE_DEBUG */
478
479 pmap_initialized = TRUE;
480
481 /*
482 * Initialize list of freed up pmaps
483 */
484 free_pmap_list = 0; /* Set that there are no free pmaps */
485 free_pmap_count = 0;
486 simple_lock_init(&free_pmap_lock, ETAP_VM_PMAP_CACHE);
487
488 }
489
490 unsigned int pmap_free_pages(void)
491 {
492 return avail_remaining;
493 }
494
495 /*
496 * This function allocates physical pages.
497 */
498
499 /* Non-optimal, but only used for virtual memory startup.
500 * Allocate memory from a table of free physical addresses
501 * If there are no more free entries, too bad.
502 */
503
504 boolean_t pmap_next_page(ppnum_t *addrp)
505 {
506 int i;
507
508 if(current_free_region >= pmap_mem_regions_count) return FALSE; /* Return failure if we have used everything... */
509
510 for(i = current_free_region; i < pmap_mem_regions_count; i++) { /* Find the next bank with free pages */
511 if(pmap_mem_regions[i].mrAStart <= pmap_mem_regions[i].mrAEnd) break; /* Found one */
512 }
513
514 current_free_region = i; /* Set our current bank */
515 if(i >= pmap_mem_regions_count) return FALSE; /* Couldn't find a free page */
516
517 *addrp = pmap_mem_regions[i].mrAStart; /* Allocate the page */
518 pmap_mem_regions[i].mrAStart = pmap_mem_regions[i].mrAStart + 1; /* Set the next one to go */
519 avail_remaining--; /* Drop free count */
520
521 return TRUE;
522 }
523
524 void pmap_virtual_space(
525 vm_offset_t *startp,
526 vm_offset_t *endp)
527 {
528 *startp = round_page_32(first_free_virt);
529 *endp = vm_last_addr;
530 }
531
532 /*
533 * pmap_create
534 *
535 * Create and return a physical map.
536 *
537 * If the size specified for the map is zero, the map is an actual physical
538 * map, and may be referenced by the hardware.
539 *
540 * A pmap is either in the free list or in the in-use list. The only use
541 * of the in-use list (aside from debugging) is to handle the VSID wrap situation.
542 * Whenever a new pmap is allocated (i.e., not recovered from the free list). The
543 * in-use list is matched until a hole in the VSID sequence is found. (Note
544 * that the in-use pmaps are queued in VSID sequence order.) This is all done
545 * while free_pmap_lock is held.
546 *
547 * If the size specified is non-zero, the map will be used in software
548 * only, and is bounded by that size.
549 */
550 pmap_t
551 pmap_create(vm_size_t size)
552 {
553 pmap_t pmap, ckpmap, fore, aft;
554 int s, i;
555 unsigned int currSID, hspace;
556 addr64_t physpmap;
557
558 /*
559 * A software use-only map doesn't even need a pmap structure.
560 */
561 if (size)
562 return(PMAP_NULL);
563
564 /*
565 * If there is a pmap in the pmap free list, reuse it.
566 * Note that we use free_pmap_list for all chaining of pmaps, both to
567 * the free list and the in use chain (anchored from kernel_pmap).
568 */
569 s = splhigh();
570 simple_lock(&free_pmap_lock);
571
572 if(free_pmap_list) { /* Any free? */
573 pmap = free_pmap_list; /* Yes, allocate it */
574 free_pmap_list = (pmap_t)pmap->freepmap; /* Dequeue this one (we chain free ones through freepmap) */
575 free_pmap_count--;
576 }
577 else {
578 simple_unlock(&free_pmap_lock); /* Unlock just in case */
579 splx(s);
580
581 pmap = (pmap_t) zalloc(pmap_zone); /* Get one */
582 if (pmap == PMAP_NULL) return(PMAP_NULL); /* Handle out-of-memory condition */
583
584 bzero((char *)pmap, pmapSize); /* Clean up the pmap */
585
586 s = splhigh();
587 simple_lock(&free_pmap_lock); /* Lock it back up */
588
589 ckpmap = cursor_pmap; /* Get starting point for free ID search */
590 currSID = ckpmap->spaceNum; /* Get the actual space ID number */
591
592 while(1) { /* Keep trying until something happens */
593
594 currSID = (currSID + 1) & (maxAdrSp - 1); /* Get the next in the sequence */
595 if(((currSID * incrVSID) & (maxAdrSp - 1)) == invalSpace) continue; /* Skip the space we have reserved */
596 ckpmap = (pmap_t)ckpmap->pmap_link.next; /* On to the next in-use pmap */
597
598 if(ckpmap->spaceNum != currSID) break; /* If we are out of sequence, this is free */
599
600 if(ckpmap == cursor_pmap) { /* See if we have 2^20 already allocated */
601 panic("pmap_create: Maximum number (%d) active address spaces reached\n", maxAdrSp); /* Die pig dog */
602 }
603 }
604
605 pmap->space = (currSID * incrVSID) & (maxAdrSp - 1); /* Calculate the actual VSID */
606 pmap->spaceNum = currSID; /* Set the space ID number */
607 /*
608 * Now we link into the chain just before the out of sequence guy.
609 */
610
611 fore = (pmap_t)ckpmap->pmap_link.prev; /* Get the current's previous */
612 pmap->pmap_link.next = (queue_t)ckpmap; /* My next points to the current */
613 fore->pmap_link.next = (queue_t)pmap; /* Current's previous's next points to me */
614 pmap->pmap_link.prev = (queue_t)fore; /* My prev points to what the current pointed to */
615 ckpmap->pmap_link.prev = (queue_t)pmap; /* Current's prev points to me */
616
617 simple_lock_init(&pmap->lock, ETAP_VM_PMAP);
618
619 physpmap = ((addr64_t)pmap_find_phys(kernel_pmap, (addr64_t)pmap) << 12) | (addr64_t)((unsigned int)pmap & 0xFFF); /* Get the physical address of the pmap */
620
621 pmap->pmapvr = (addr64_t)((unsigned int)pmap) ^ physpmap; /* Make V to R translation mask */
622
623 pmapTrans[pmap->space].pmapPAddr = physpmap; /* Set translate table physical to point to us */
624 pmapTrans[pmap->space].pmapVAddr = pmap; /* Set translate table virtual to point to us */
625
626 }
627
628 pmap->pmapFlags = pmapKeyDef; /* Set default key */
629 pmap->pmapCCtl = pmapCCtlVal; /* Initialize cache control */
630 pmap->ref_count = 1;
631 pmap->stats.resident_count = 0;
632 pmap->stats.wired_count = 0;
633 pmap->pmapSCSubTag = 0x0000000000000000ULL; /* Make sure this is clean an tidy */
634 simple_unlock(&free_pmap_lock);
635
636 splx(s);
637 return(pmap);
638 }
639
640 /*
641 * pmap_destroy
642 *
643 * Gives up a reference to the specified pmap. When the reference count
644 * reaches zero the pmap structure is added to the pmap free list.
645 *
646 * Should only be called if the map contains no valid mappings.
647 */
648 void
649 pmap_destroy(pmap_t pmap)
650 {
651 int ref_count;
652 spl_t s;
653 pmap_t fore, aft;
654
655 if (pmap == PMAP_NULL)
656 return;
657
658 ref_count=hw_atomic_sub(&pmap->ref_count, 1); /* Back off the count */
659 if(ref_count>0) return; /* Still more users, leave now... */
660
661 if(ref_count < 0) /* Did we go too far? */
662 panic("pmap_destroy(): ref_count < 0");
663
664 #ifdef notdef
665 if(pmap->stats.resident_count != 0)
666 panic("PMAP_DESTROY: pmap not empty");
667 #else
668 if(pmap->stats.resident_count != 0) {
669 pmap_remove(pmap, 0, 0xFFFFFFFFFFFFF000ULL);
670 }
671 #endif
672
673 /*
674 * Add the pmap to the pmap free list.
675 */
676
677 s = splhigh();
678 /*
679 * Add the pmap to the pmap free list.
680 */
681 simple_lock(&free_pmap_lock);
682
683 if (free_pmap_count <= free_pmap_max) { /* Do we have enough spares? */
684
685 pmap->freepmap = (struct blokmap *)free_pmap_list; /* Queue in front */
686 free_pmap_list = pmap;
687 free_pmap_count++;
688 simple_unlock(&free_pmap_lock);
689
690 } else {
691 if(cursor_pmap == pmap) cursor_pmap = (pmap_t)pmap->pmap_link.prev; /* If we are releasing the cursor, back up */
692 fore = (pmap_t)pmap->pmap_link.prev;
693 aft = (pmap_t)pmap->pmap_link.next;
694 fore->pmap_link.next = pmap->pmap_link.next; /* My previous's next is my next */
695 aft->pmap_link.prev = pmap->pmap_link.prev; /* My next's previous is my previous */
696 simple_unlock(&free_pmap_lock);
697 pmapTrans[pmap->space].pmapPAddr = -1; /* Invalidate the translate table physical */
698 pmapTrans[pmap->space].pmapVAddr = -1; /* Invalidate the translate table virtual */
699 zfree(pmap_zone, (vm_offset_t) pmap);
700 }
701 splx(s);
702 }
703
704 /*
705 * pmap_reference(pmap)
706 * gains a reference to the specified pmap.
707 */
708 void
709 pmap_reference(pmap_t pmap)
710 {
711 spl_t s;
712
713 if (pmap != PMAP_NULL) hw_atomic_add(&pmap->ref_count, 1); /* Bump the count */
714 }
715
716 /*
717 * pmap_remove_some_phys
718 *
719 * Removes mappings of the associated page from the specified pmap
720 *
721 */
722 void pmap_remove_some_phys(
723 pmap_t pmap,
724 vm_offset_t pa)
725 {
726 register struct phys_entry *pp;
727 register struct mapping *mp;
728 unsigned int pindex;
729
730 if (pmap == PMAP_NULL) { /* This should never be called with a null pmap */
731 panic("pmap_remove_some_phys: null pmap\n");
732 }
733
734 pp = mapping_phys_lookup(pa, &pindex); /* Get physical entry */
735 if (pp == 0) return; /* Leave if not in physical RAM */
736
737 while(1) { /* Keep going until we toss all pages from this pmap */
738 if (pmap->pmapFlags & pmapVMhost) {
739 mp = hw_purge_phys(pp); /* Toss a map */
740 if(!mp ) return;
741 if((unsigned int)mp & mapRetCode) { /* Was there a failure? */
742 panic("pmap_remove_some_phys: hw_purge_phys failed - pp = %08X, pmap = %08X, code = %08X\n",
743 pp, pmap, mp);
744 }
745 } else {
746 mp = hw_purge_space(pp, pmap); /* Toss a map */
747 if(!mp ) return;
748 if((unsigned int)mp & mapRetCode) { /* Was there a failure? */
749 panic("pmap_remove_some_phys: hw_purge_pmap failed - pp = %08X, pmap = %08X, code = %08X\n",
750 pp, pmap, mp);
751 }
752 }
753 mapping_free(mp); /* Toss the mapping */
754 }
755
756 return; /* Leave... */
757 }
758
759 /*
760 * pmap_remove(pmap, s, e)
761 * unmaps all virtual addresses v in the virtual address
762 * range determined by [s, e) and pmap.
763 * s and e must be on machine independent page boundaries and
764 * s must be less than or equal to e.
765 *
766 * Note that pmap_remove does not remove any mappings in nested pmaps. We just
767 * skip those segments.
768 */
769 void
770 pmap_remove(
771 pmap_t pmap,
772 addr64_t sva,
773 addr64_t eva)
774 {
775 addr64_t va, endva;
776
777 if (pmap == PMAP_NULL) return; /* Leave if software pmap */
778
779
780 /* It is just possible that eva might have wrapped around to zero,
781 * and sometimes we get asked to liberate something of size zero
782 * even though it's dumb (eg. after zero length read_overwrites)
783 */
784 assert(eva >= sva);
785
786 /* If these are not page aligned the loop might not terminate */
787 assert((sva == trunc_page_64(sva)) && (eva == trunc_page_64(eva)));
788
789 va = sva & -4096LL; /* Round start down to a page */
790 endva = eva & -4096LL; /* Round end down to a page */
791
792 while(1) { /* Go until we finish the range */
793 va = mapping_remove(pmap, va); /* Remove the mapping and see what's next */
794 va = va & -4096LL; /* Make sure the "not found" indication is clear */
795 if((va == 0) || (va >= endva)) break; /* End loop if we finish range or run off the end */
796 }
797
798 }
799
800 /*
801 * Routine:
802 * pmap_page_protect
803 *
804 * Function:
805 * Lower the permission for all mappings to a given page.
806 */
807 void
808 pmap_page_protect(
809 ppnum_t pa,
810 vm_prot_t prot)
811 {
812 register struct phys_entry *pp;
813 boolean_t remove;
814 unsigned int pindex;
815 mapping *mp;
816
817
818 switch (prot) {
819 case VM_PROT_READ:
820 case VM_PROT_READ|VM_PROT_EXECUTE:
821 remove = FALSE;
822 break;
823 case VM_PROT_ALL:
824 return;
825 default:
826 remove = TRUE;
827 break;
828 }
829
830
831 pp = mapping_phys_lookup(pa, &pindex); /* Get physical entry */
832 if (pp == 0) return; /* Leave if not in physical RAM */
833
834 if (remove) { /* If the protection was set to none, we'll remove all mappings */
835
836 while(1) { /* Keep going until we toss all pages from this physical page */
837 mp = hw_purge_phys(pp); /* Toss a map */
838 if(!mp ) return;
839 if((unsigned int)mp & mapRetCode) { /* Was there a failure? */
840 panic("pmap_page_protect: hw_purge_phys failed - pp = %08X, code = %08X\n",
841 pp, mp);
842 }
843 mapping_free(mp); /* Toss the mapping */
844 }
845
846 return; /* Leave... */
847 }
848
849 /* When we get here, it means that we are to change the protection for a
850 * physical page.
851 */
852
853 mapping_protect_phys(pa, prot & VM_PROT_ALL); /* Change protection of all mappings to page. */
854
855 }
856
857 /*
858 * pmap_protect(pmap, s, e, prot)
859 * changes the protection on all virtual addresses v in the
860 * virtual address range determined by [s, e] and pmap to prot.
861 * s and e must be on machine independent page boundaries and
862 * s must be less than or equal to e.
863 *
864 * Note that any requests to change the protection of a nested pmap are
865 * ignored. Those changes MUST be done by calling this with the correct pmap.
866 */
867 void pmap_protect(
868 pmap_t pmap,
869 vm_offset_t sva,
870 vm_offset_t eva,
871 vm_prot_t prot)
872 {
873
874 addr64_t va, endva, nextva;
875
876 if (pmap == PMAP_NULL) return; /* Do nothing if no pmap */
877
878 if (prot == VM_PROT_NONE) { /* Should we kill the address range?? */
879 pmap_remove(pmap, (addr64_t)sva, (addr64_t)eva); /* Yeah, dump 'em */
880 return; /* Leave... */
881 }
882
883 va = sva & -4096LL; /* Round start down to a page */
884 endva = eva & -4096LL; /* Round end down to a page */
885
886 while(1) { /* Go until we finish the range */
887 (void)mapping_protect(pmap, va, prot & VM_PROT_ALL, &va); /* Change the protection and see what's next */
888 if((va == 0) || (va >= endva)) break; /* End loop if we finish range or run off the end */
889 }
890
891 }
892
893
894
895 /*
896 * pmap_enter
897 *
898 * Create a translation for the virtual address (virt) to the physical
899 * address (phys) in the pmap with the protection requested. If the
900 * translation is wired then we can not allow a full page fault, i.e.,
901 * the mapping control block is not eligible to be stolen in a low memory
902 * condition.
903 *
904 * NB: This is the only routine which MAY NOT lazy-evaluate
905 * or lose information. That is, this routine must actually
906 * insert this page into the given map NOW.
907 */
908 void
909 pmap_enter(pmap_t pmap, vm_offset_t va, ppnum_t pa, vm_prot_t prot,
910 unsigned int flags, boolean_t wired)
911 {
912 int memattr;
913 pmap_t opmap;
914 unsigned int mflags;
915 addr64_t colva;
916
917 if (pmap == PMAP_NULL) return; /* Leave if software pmap */
918
919 disable_preemption(); /* Don't change threads */
920
921 mflags = 0; /* Make sure this is initialized to nothing special */
922 if(!(flags & VM_WIMG_USE_DEFAULT)) { /* Are they supplying the attributes? */
923 mflags = mmFlgUseAttr | (flags & VM_MEM_GUARDED) | ((flags & VM_MEM_NOT_CACHEABLE) >> 1); /* Convert to our mapping_make flags */
924 }
925
926 /*
927 * It is possible to hang here if another processor is remapping any pages we collide with and are removing
928 */
929
930 while(1) { /* Keep trying the enter until it goes in */
931
932 colva = mapping_make(pmap, va, pa, mflags, 1, prot & VM_PROT_ALL); /* Enter the mapping into the pmap */
933
934 if(!colva) break; /* If there were no collisions, we are done... */
935
936 mapping_remove(pmap, colva); /* Remove the mapping that collided */
937 }
938
939 enable_preemption(); /* Thread change ok */
940
941 }
942
943 /*
944 * Enters translations for odd-sized V=F blocks.
945 *
946 * The higher level VM map should be locked to insure that we don't have a
947 * double diddle here.
948 *
949 * We panic if we get a block that overlaps with another. We do not merge adjacent
950 * blocks because removing any address within a block removes the entire block and if
951 * would really mess things up if we trashed too much.
952 *
953 * Once a block is mapped, it is unmutable, that is, protection, catch mode, etc. can
954 * not be changed. The block must be unmapped and then remapped with the new stuff.
955 * We also do not keep track of reference or change flags.
956 *
957 * Note that pmap_map_block_rc is the same but doesn't panic if collision.
958 *
959 */
960
961 void pmap_map_block(pmap_t pmap, addr64_t va, ppnum_t pa, vm_size_t size, vm_prot_t prot, int attr, unsigned int flags) { /* Map an autogenned block */
962
963 int memattr;
964 unsigned int mflags;
965 addr64_t colva;
966
967
968 if (pmap == PMAP_NULL) { /* Did they give us a pmap? */
969 panic("pmap_map_block: null pmap\n"); /* No, like that's dumb... */
970 }
971
972 // kprintf("pmap_map_block: (%08X) va = %016llX, pa = %08X, size = %08X, prot = %08X, attr = %08X, flags = %08X\n", /* (BRINGUP) */
973 // current_act(), va, pa, size, prot, attr, flags); /* (BRINGUP) */
974
975
976 mflags = mmFlgBlock | mmFlgUseAttr | (attr & VM_MEM_GUARDED) | ((attr & VM_MEM_NOT_CACHEABLE) >> 1); /* Convert to our mapping_make flags */
977 if(flags) mflags |= mmFlgPerm; /* Mark permanent if requested */
978
979 colva = mapping_make(pmap, va, pa, mflags, (size >> 12), prot); /* Enter the mapping into the pmap */
980
981 if(colva) { /* If there was a collision, panic */
982 panic("pmap_map_block: collision at %016llX, pmap = %08X\n", colva, pmap);
983 }
984
985 return; /* Return */
986 }
987
988 int pmap_map_block_rc(pmap_t pmap, addr64_t va, ppnum_t pa, vm_size_t size, vm_prot_t prot, int attr, unsigned int flags) { /* Map an autogenned block */
989
990 int memattr;
991 unsigned int mflags;
992 addr64_t colva;
993
994
995 if (pmap == PMAP_NULL) { /* Did they give us a pmap? */
996 panic("pmap_map_block_rc: null pmap\n"); /* No, like that's dumb... */
997 }
998
999 mflags = mmFlgBlock | mmFlgUseAttr | (attr & VM_MEM_GUARDED) | ((attr & VM_MEM_NOT_CACHEABLE) >> 1); /* Convert to our mapping_make flags */
1000 if(flags) mflags |= mmFlgPerm; /* Mark permanent if requested */
1001
1002 colva = mapping_make(pmap, va, pa, mflags, (size >> 12), prot); /* Enter the mapping into the pmap */
1003
1004 if(colva) return 0; /* If there was a collision, fail */
1005
1006 return 1; /* Return true of we worked */
1007 }
1008
1009 /*
1010 * pmap_extract(pmap, va)
1011 * returns the physical address corrsponding to the
1012 * virtual address specified by pmap and va if the
1013 * virtual address is mapped and 0 if it is not.
1014 * Note: we assume nothing is ever mapped to phys 0.
1015 *
1016 * NOTE: This call always will fail for physical addresses greater than 0xFFFFF000.
1017 */
1018 vm_offset_t pmap_extract(pmap_t pmap, vm_offset_t va) {
1019
1020 spl_t spl;
1021 register struct mapping *mp;
1022 register vm_offset_t pa;
1023 addr64_t nextva;
1024 ppnum_t ppoffset;
1025 unsigned int gva;
1026
1027 #ifdef BOGUSCOMPAT
1028 panic("pmap_extract: THIS CALL IS BOGUS. NEVER USE IT EVER. So there...\n"); /* Don't use this */
1029 #else
1030
1031 gva = (unsigned int)va; /* Make sure we don't have a sign */
1032
1033 spl = splhigh(); /* We can't allow any loss of control here */
1034
1035 mp = mapping_find(pmap, (addr64_t)gva, &nextva,1); /* Find the mapping for this address */
1036
1037 if(!mp) { /* Is the page mapped? */
1038 splx(spl); /* Enable interrupts */
1039 return 0; /* Pass back 0 if not found */
1040 }
1041
1042 ppoffset = (ppnum_t)(((gva & -4096LL) - (mp->mpVAddr & -4096LL)) >> 12); /* Get offset from va to base va */
1043
1044
1045 pa = mp->mpPAddr + ppoffset; /* Remember ppage because mapping may vanish after drop call */
1046
1047 mapping_drop_busy(mp); /* We have everything we need from the mapping */
1048 splx(spl); /* Restore 'rupts */
1049
1050 if(pa > maxPPage32) return 0; /* Force large addresses to fail */
1051
1052 pa = (pa << 12) | (va & 0xFFF); /* Convert physical page number to address */
1053
1054 #endif
1055 return pa; /* Return physical address or 0 */
1056 }
1057
1058 /*
1059 * ppnum_t pmap_find_phys(pmap, addr64_t va)
1060 * returns the physical page corrsponding to the
1061 * virtual address specified by pmap and va if the
1062 * virtual address is mapped and 0 if it is not.
1063 * Note: we assume nothing is ever mapped to phys 0.
1064 *
1065 */
1066 ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va) {
1067
1068 spl_t spl;
1069 register struct mapping *mp;
1070 ppnum_t pa, ppoffset;
1071 addr64_t nextva, curva;
1072
1073 spl = splhigh(); /* We can't allow any loss of control here */
1074
1075 mp = mapping_find(pmap, va, &nextva, 1); /* Find the mapping for this address */
1076
1077 if(!mp) { /* Is the page mapped? */
1078 splx(spl); /* Enable interrupts */
1079 return 0; /* Pass back 0 if not found */
1080 }
1081
1082
1083 ppoffset = (ppnum_t)(((va & -4096LL) - (mp->mpVAddr & -4096LL)) >> 12); /* Get offset from va to base va */
1084
1085 pa = mp->mpPAddr + ppoffset; /* Get the actual physical address */
1086
1087 mapping_drop_busy(mp); /* We have everything we need from the mapping */
1088
1089 splx(spl); /* Restore 'rupts */
1090 return pa; /* Return physical address or 0 */
1091 }
1092
1093
1094 /*
1095 * pmap_attributes:
1096 *
1097 * Set/Get special memory attributes; not implemented.
1098 *
1099 * Note: 'VAL_GET_INFO' is used to return info about a page.
1100 * If less than 1 page is specified, return the physical page
1101 * mapping and a count of the number of mappings to that page.
1102 * If more than one page is specified, return the number
1103 * of resident pages and the number of shared (more than
1104 * one mapping) pages in the range;
1105 *
1106 *
1107 */
1108 kern_return_t
1109 pmap_attribute(pmap, address, size, attribute, value)
1110 pmap_t pmap;
1111 vm_offset_t address;
1112 vm_size_t size;
1113 vm_machine_attribute_t attribute;
1114 vm_machine_attribute_val_t* value;
1115 {
1116
1117 return KERN_INVALID_ARGUMENT;
1118
1119 }
1120
1121 /*
1122 * pmap_attribute_cache_sync(vm_offset_t pa)
1123 *
1124 * Invalidates all of the instruction cache on a physical page and
1125 * pushes any dirty data from the data cache for the same physical page
1126 */
1127
1128 kern_return_t pmap_attribute_cache_sync(ppnum_t pp, vm_size_t size,
1129 vm_machine_attribute_t attribute,
1130 vm_machine_attribute_val_t* value) {
1131
1132 spl_t s;
1133 unsigned int i, npages;
1134
1135 npages = round_page_32(size) >> 12; /* Get the number of pages to do */
1136
1137 for(i = 0; i < npages; i++) { /* Do all requested pages */
1138 s = splhigh(); /* No interruptions here */
1139 sync_ppage(pp + i); /* Go flush data cache and invalidate icache */
1140 splx(s); /* Allow interruptions */
1141 }
1142
1143 return KERN_SUCCESS;
1144 }
1145
1146 /*
1147 * pmap_sync_caches_phys(ppnum_t pa)
1148 *
1149 * Invalidates all of the instruction cache on a physical page and
1150 * pushes any dirty data from the data cache for the same physical page
1151 */
1152
1153 void pmap_sync_caches_phys(ppnum_t pa) {
1154
1155 spl_t s;
1156
1157 s = splhigh(); /* No interruptions here */
1158 sync_ppage(pa); /* Sync up dem caches */
1159 splx(s); /* Allow interruptions */
1160 return;
1161 }
1162
1163 /*
1164 * pmap_collect
1165 *
1166 * Garbage collects the physical map system for pages that are no longer used.
1167 * It isn't implemented or needed or wanted.
1168 */
1169 void
1170 pmap_collect(pmap_t pmap)
1171 {
1172 return;
1173 }
1174
1175 /*
1176 * Routine: pmap_activate
1177 * Function:
1178 * Binds the given physical map to the given
1179 * processor, and returns a hardware map description.
1180 * It isn't implemented or needed or wanted.
1181 */
1182 void
1183 pmap_activate(
1184 pmap_t pmap,
1185 thread_t th,
1186 int which_cpu)
1187 {
1188 return;
1189 }
1190 /*
1191 * pmap_deactivate:
1192 * It isn't implemented or needed or wanted.
1193 */
1194 void
1195 pmap_deactivate(
1196 pmap_t pmap,
1197 thread_t th,
1198 int which_cpu)
1199 {
1200 return;
1201 }
1202
1203
1204 /*
1205 * pmap_pageable(pmap, s, e, pageable)
1206 * Make the specified pages (by pmap, offset)
1207 * pageable (or not) as requested.
1208 *
1209 * A page which is not pageable may not take
1210 * a fault; therefore, its page table entry
1211 * must remain valid for the duration.
1212 *
1213 * This routine is merely advisory; pmap_enter()
1214 * will specify that these pages are to be wired
1215 * down (or not) as appropriate.
1216 *
1217 * (called from vm/vm_fault.c).
1218 */
1219 void
1220 pmap_pageable(
1221 pmap_t pmap,
1222 vm_offset_t start,
1223 vm_offset_t end,
1224 boolean_t pageable)
1225 {
1226
1227 return; /* This is not used... */
1228
1229 }
1230 /*
1231 * Routine: pmap_change_wiring
1232 * NOT USED ANYMORE.
1233 */
1234 void
1235 pmap_change_wiring(
1236 register pmap_t pmap,
1237 vm_offset_t va,
1238 boolean_t wired)
1239 {
1240 return; /* This is not used... */
1241 }
1242
1243 /*
1244 * pmap_modify_pages(pmap, s, e)
1245 * sets the modified bit on all virtual addresses v in the
1246 * virtual address range determined by [s, e] and pmap,
1247 * s and e must be on machine independent page boundaries and
1248 * s must be less than or equal to e.
1249 *
1250 * Note that this function will not descend nested pmaps.
1251 */
1252 void
1253 pmap_modify_pages(
1254 pmap_t pmap,
1255 vm_offset_t sva,
1256 vm_offset_t eva)
1257 {
1258 spl_t spl;
1259 mapping *mp;
1260 ppnum_t pa;
1261 addr64_t va, endva, nextva;
1262 unsigned int saveflags;
1263
1264 if (pmap == PMAP_NULL) return; /* If no pmap, can't do it... */
1265
1266 va = sva & -4096; /* Round to page */
1267 endva = eva & -4096; /* Round to page */
1268
1269 while (va < endva) { /* Walk through all pages */
1270
1271 spl = splhigh(); /* We can't allow any loss of control here */
1272
1273 mp = mapping_find(pmap, (addr64_t)va, &va, 0); /* Find the mapping for this address */
1274
1275 if(!mp) { /* Is the page mapped? */
1276 splx(spl); /* Page not mapped, restore interruptions */
1277 if((va == 0) || (va >= endva)) break; /* We are done if there are no more or we hit the end... */
1278 continue; /* We are not done and there is more to check... */
1279 }
1280
1281 saveflags = mp->mpFlags; /* Remember the flags */
1282 pa = mp->mpPAddr; /* Remember ppage because mapping may vanish after drop call */
1283
1284 mapping_drop_busy(mp); /* We have everything we need from the mapping */
1285
1286 splx(spl); /* Restore 'rupts */
1287
1288 if(saveflags & (mpNest | mpBlock)) continue; /* Can't mess around with these guys... */
1289
1290 mapping_set_mod(pa); /* Set the modfied bit for this page */
1291
1292 if(va == 0) break; /* We hit the end of the pmap, might as well leave now... */
1293 }
1294 return; /* Leave... */
1295 }
1296
1297 /*
1298 * pmap_clear_modify(phys)
1299 * clears the hardware modified ("dirty") bit for one
1300 * machine independant page starting at the given
1301 * physical address. phys must be aligned on a machine
1302 * independant page boundary.
1303 */
1304 void
1305 pmap_clear_modify(vm_offset_t pa)
1306 {
1307
1308 mapping_clr_mod((ppnum_t)pa); /* Clear all change bits for physical page */
1309
1310 }
1311
1312 /*
1313 * pmap_is_modified(phys)
1314 * returns TRUE if the given physical page has been modified
1315 * since the last call to pmap_clear_modify().
1316 */
1317 boolean_t
1318 pmap_is_modified(register vm_offset_t pa)
1319 {
1320 return mapping_tst_mod((ppnum_t)pa); /* Check for modified */
1321
1322 }
1323
1324 /*
1325 * pmap_clear_reference(phys)
1326 * clears the hardware referenced bit in the given machine
1327 * independant physical page.
1328 *
1329 */
1330 void
1331 pmap_clear_reference(vm_offset_t pa)
1332 {
1333 mapping_clr_ref((ppnum_t)pa); /* Check for modified */
1334 }
1335
1336 /*
1337 * pmap_is_referenced(phys)
1338 * returns TRUE if the given physical page has been referenced
1339 * since the last call to pmap_clear_reference().
1340 */
1341 boolean_t
1342 pmap_is_referenced(vm_offset_t pa)
1343 {
1344 return mapping_tst_ref((ppnum_t)pa); /* Check for referenced */
1345 }
1346
1347 /*
1348 * pmap_canExecute(ppnum_t pa)
1349 * returns 1 if instructions can execute
1350 * returns 0 if know not (i.e. guarded and/or non-executable set)
1351 * returns -1 if we don't know (i.e., the page is no RAM)
1352 */
1353 int
1354 pmap_canExecute(ppnum_t pa)
1355 {
1356 phys_entry *physent;
1357 unsigned int pindex;
1358
1359 physent = mapping_phys_lookup(pa, &pindex); /* Get physical entry */
1360
1361 if(!physent) return -1; /* If there is no physical entry, we don't know... */
1362
1363 if((physent->ppLink & (ppN | ppG))) return 0; /* If we are marked non-executable or guarded, say we can not execute */
1364 return 1; /* Good to go... */
1365 }
1366
1367 #if MACH_VM_DEBUG
1368 int
1369 pmap_list_resident_pages(
1370 register pmap_t pmap,
1371 register vm_offset_t *listp,
1372 register int space)
1373 {
1374 return 0;
1375 }
1376 #endif /* MACH_VM_DEBUG */
1377
1378 /*
1379 * Locking:
1380 * spl: VM
1381 */
1382 void
1383 pmap_copy_part_page(
1384 vm_offset_t src,
1385 vm_offset_t src_offset,
1386 vm_offset_t dst,
1387 vm_offset_t dst_offset,
1388 vm_size_t len)
1389 {
1390 register struct phys_entry *pp_src, *pp_dst;
1391 spl_t s;
1392 addr64_t fsrc, fdst;
1393
1394 assert(((dst <<12) & PAGE_MASK+dst_offset+len) <= PAGE_SIZE);
1395 assert(((src <<12) & PAGE_MASK+src_offset+len) <= PAGE_SIZE);
1396
1397 fsrc = ((addr64_t)src << 12) + src_offset;
1398 fdst = ((addr64_t)dst << 12) + dst_offset;
1399
1400 phys_copy(fsrc, fdst, len); /* Copy the stuff physically */
1401 }
1402
1403 void
1404 pmap_zero_part_page(
1405 vm_offset_t p,
1406 vm_offset_t offset,
1407 vm_size_t len)
1408 {
1409 panic("pmap_zero_part_page");
1410 }
1411
1412 boolean_t pmap_verify_free(ppnum_t pa) {
1413
1414 struct phys_entry *pp;
1415 unsigned int pindex;
1416
1417 pp = mapping_phys_lookup(pa, &pindex); /* Get physical entry */
1418 if (pp == 0) return FALSE; /* If there isn't one, show no mapping... */
1419
1420 if(pp->ppLink & ~(ppLock | ppN | ppFlags)) return TRUE; /* We have at least one mapping */
1421 return FALSE; /* No mappings */
1422 }
1423
1424
1425 /* Determine if we need to switch space and set up for it if so */
1426
1427 void pmap_switch(pmap_t map)
1428 {
1429 unsigned int i;
1430
1431
1432 hw_blow_seg(copyIOaddr); /* Blow off the first segment */
1433 hw_blow_seg(copyIOaddr + 0x10000000ULL); /* Blow off the second segment */
1434
1435 /* when changing to kernel space, don't bother
1436 * doing anything, the kernel is mapped from here already.
1437 */
1438 if (map->space == PPC_SID_KERNEL) { /* Are we switching into kernel space? */
1439 return; /* If so, we don't do anything... */
1440 }
1441
1442 hw_set_user_space(map); /* Indicate if we need to load the SRs or not */
1443 return; /* Bye, bye, butterfly... */
1444 }
1445
1446 /*
1447 * kern_return_t pmap_nest(grand, subord, vstart, size)
1448 *
1449 * grand = the pmap that we will nest subord into
1450 * subord = the pmap that goes into the grand
1451 * vstart = start of range in pmap to be inserted
1452 * nstart = start of range in pmap nested pmap
1453 * size = Size of nest area (up to 16TB)
1454 *
1455 * Inserts a pmap into another. This is used to implement shared segments.
1456 * On the current PPC processors, this is limited to segment (256MB) aligned
1457 * segment sized ranges.
1458 *
1459 * We actually kinda allow recursive nests. The gating factor is that we do not allow
1460 * nesting on top of something that is already mapped, i.e., the range must be empty.
1461 *
1462 *
1463 *
1464 * Note that we depend upon higher level VM locks to insure that things don't change while
1465 * we are doing this. For example, VM should not be doing any pmap enters while it is nesting
1466 * or do 2 nests at once.
1467 */
1468
1469 kern_return_t pmap_nest(pmap_t grand, pmap_t subord, addr64_t vstart, addr64_t nstart, uint64_t size) {
1470
1471 addr64_t nextva, vend, colladdr;
1472 unsigned int msize;
1473 int i, nlists, asize;
1474 spl_t s;
1475 mapping *mp;
1476
1477
1478 if(size & 0x0FFFFFFFULL) return KERN_INVALID_VALUE; /* We can only do this for multiples of 256MB */
1479 if((size >> 28) > 65536) return KERN_INVALID_VALUE; /* Max size we can nest is 16TB */
1480 if(vstart & 0x0FFFFFFFULL) return KERN_INVALID_VALUE; /* We can only do this aligned to 256MB */
1481 if(nstart & 0x0FFFFFFFULL) return KERN_INVALID_VALUE; /* We can only do this aligned to 256MB */
1482
1483 if(size == 0) { /* Is the size valid? */
1484 panic("pmap_nest: size is invalid - %016llX\n", size);
1485 }
1486
1487 msize = (size >> 28) - 1; /* Change size to blocks of 256MB */
1488
1489 nlists = mapSetLists(grand); /* Set number of lists this will be on */
1490
1491 mp = mapping_alloc(nlists); /* Get a spare mapping block */
1492
1493 mp->mpFlags = 0x01000000 | mpNest | nlists; /* Set the flags. Make sure busy count is 1 */
1494 mp->mpSpace = subord->space; /* Set the address space/pmap lookup ID */
1495 mp->mpBSize = msize; /* Set the size */
1496 mp->mpPte = 0; /* Set the PTE invalid */
1497 mp->mpPAddr = 0; /* Set the physical page number */
1498 mp->mpVAddr = vstart; /* Set the address */
1499 mp->mpNestReloc = nstart - vstart; /* Set grand to nested vaddr relocation value */
1500
1501 colladdr = hw_add_map(grand, mp); /* Go add the mapping to the pmap */
1502
1503 if(colladdr) { /* Did it collide? */
1504 vend = vstart + size - 4096; /* Point to the last page we would cover in nest */
1505 panic("pmap_nest: attempt to nest into a non-empty range - pmap = %08X, start = %016llX, end = %016llX\n",
1506 grand, vstart, vend);
1507 }
1508
1509 return KERN_SUCCESS;
1510 }
1511
1512 /*
1513 * kern_return_t pmap_unnest(grand, vaddr)
1514 *
1515 * grand = the pmap that we will nest subord into
1516 * vaddr = start of range in pmap to be unnested
1517 *
1518 * Removes a pmap from another. This is used to implement shared segments.
1519 * On the current PPC processors, this is limited to segment (256MB) aligned
1520 * segment sized ranges.
1521 */
1522
1523 kern_return_t pmap_unnest(pmap_t grand, addr64_t vaddr) {
1524
1525 unsigned int oflags, seg, grandr, tstamp;
1526 int i, tcpu, mycpu;
1527 addr64_t nextva;
1528 spl_t s;
1529 mapping *mp;
1530
1531 s = splhigh(); /* Make sure interruptions are disabled */
1532
1533 mp = mapping_find(grand, vaddr, &nextva, 0); /* Find the nested map */
1534
1535 if(((unsigned int)mp & mapRetCode) != mapRtOK) { /* See if it was even nested */
1536 panic("pmap_unnest: Attempt to unnest an unnested segment - va = %016llX\n", vaddr);
1537 }
1538
1539 if(!(mp->mpFlags & mpNest)) { /* Did we find something other than a nest? */
1540 panic("pmap_unnest: Attempt to unnest something that is not a nest - va = %016llX\n", vaddr);
1541 }
1542
1543 if(mp->mpVAddr != vaddr) { /* Make sure the address is the same */
1544 panic("pmap_unnest: Attempt to unnest something that is not at start of nest - va = %016llX\n", vaddr);
1545 }
1546
1547 (void)hw_atomic_or(&mp->mpFlags, mpRemovable); /* Show that this mapping is now removable */
1548
1549 mapping_drop_busy(mp); /* Go ahead and relase the mapping now */
1550
1551 disable_preemption(); /* It's all for me! */
1552 splx(s); /* Restore 'rupts */
1553
1554 (void)mapping_remove(grand, vaddr); /* Toss the nested pmap mapping */
1555
1556 invalidateSegs(grand); /* Invalidate the pmap segment cache */
1557
1558 /*
1559 * Note that the following will force the segment registers to be reloaded
1560 * on all processors (if they are using the pmap we just changed) before returning.
1561 *
1562 * This is needed. The reason is that until the segment register is
1563 * reloaded, another thread in the same task on a different processor will
1564 * be able to access memory that it isn't allowed to anymore. That can happen
1565 * because access to the subordinate pmap is being removed, but the pmap is still
1566 * valid.
1567 *
1568 * Note that we only kick the other processor if we see that it was using the pmap while we
1569 * were changing it.
1570 */
1571
1572
1573 mycpu = cpu_number(); /* Who am I? Am I just a dream? */
1574 for(i=0; i < real_ncpus; i++) { /* Cycle through processors */
1575 if((unsigned int)grand == per_proc_info[i].ppUserPmapVirt) { /* Is this guy using the changed pmap? */
1576
1577 per_proc_info[i].ppInvSeg = 1; /* Show that we need to invalidate the segments */
1578
1579 if(i == mycpu) continue; /* Don't diddle ourselves */
1580
1581 tstamp = per_proc_info[i].ruptStamp[1]; /* Save the processor's last interrupt time stamp */
1582 if(cpu_signal(i, SIGPwake, 0, 0) != KERN_SUCCESS) { /* Make sure we see the pmap change */
1583 continue;
1584 }
1585
1586 if(!hw_cpu_wcng(&per_proc_info[i].ruptStamp[1], tstamp, LockTimeOut)) { /* Wait for the other processors to enter debug */
1587 panic("pmap_unnest: Other processor (%d) did not see interruption request\n", i);
1588 }
1589 }
1590 }
1591
1592 enable_preemption(); /* Others can run now */
1593 return KERN_SUCCESS; /* Bye, bye, butterfly... */
1594 }
1595
1596
1597 /*
1598 * void MapUserAddressSpaceInit(void)
1599 *
1600 * Initialized anything we need to in order to map user address space slices into
1601 * the kernel. Primarily used for copy in/out.
1602 *
1603 * Currently we only support one 512MB slot for this purpose. There are two special
1604 * mappings defined for the purpose: the special pmap nest, and linkage mapping.
1605 *
1606 * The special pmap nest (which is allocated in this function) is used as a place holder
1607 * in the kernel's pmap search list. It is 512MB long and covers the address range
1608 * starting at copyIOaddr. It points to no actual memory and when the fault handler
1609 * hits in it, it knows to look in the per_proc and start using the linkage
1610 * mapping contained therin.
1611 *
1612 * The linkage mapping is used to glue the user address space slice into the
1613 * kernel. It contains the relocation information used to transform the faulting
1614 * kernel address into the user address space. It also provides the link to the
1615 * user's pmap. This is pointed to by the per_proc and is switched in and out
1616 * whenever there is a context switch.
1617 *
1618 */
1619
1620 void MapUserAddressSpaceInit(void) {
1621
1622 addr64_t colladdr;
1623 int nlists, asize;
1624 mapping *mp;
1625
1626 nlists = mapSetLists(kernel_pmap); /* Set number of lists this will be on */
1627
1628 mp = mapping_alloc(nlists); /* Get a spare mapping block */
1629
1630 mp->mpFlags = 0x01000000 |mpNest | mpSpecial | nlists; /* Set the flags. Make sure busy count is 1 */
1631 mp->mpSpace = kernel_pmap->space; /* Set the address space/pmap lookup ID */
1632 mp->mpBSize = 1; /* Set the size to 2 segments */
1633 mp->mpPte = 0; /* Means nothing */
1634 mp->mpPAddr = 0; /* Means nothing */
1635 mp->mpVAddr = copyIOaddr; /* Set the address range we cover */
1636 mp->mpNestReloc = 0; /* Means nothing */
1637
1638 colladdr = hw_add_map(kernel_pmap, mp); /* Go add the mapping to the pmap */
1639
1640 if(colladdr) { /* Did it collide? */
1641 panic("MapUserAddressSpaceInit: MapUserAddressSpace range already mapped\n");
1642 }
1643
1644 return;
1645 }
1646
1647 /*
1648 * addr64_t MapUserAddressSpace(vm_map_t map, vm_offset_t va, size)
1649 *
1650 * map = the vm_map that we are mapping into the kernel
1651 * va = start of the address range we are mapping
1652 * size = size of the range. No greater than 256MB and not 0.
1653 * Note that we do not test validty, we chose to trust our fellows...
1654 *
1655 * Maps a slice of a user address space into a predefined kernel range
1656 * on a per-thread basis. In the future, the restriction of a predefined
1657 * range will be loosened.
1658 *
1659 * Builds the proper linkage map to map the user range
1660 * We will round this down to the previous segment boundary and calculate
1661 * the relocation to the kernel slot
1662 *
1663 * We always make a segment table entry here if we need to. This is mainly because of
1664 * copyin/out and if we don't, there will be multiple segment faults for
1665 * each system call. I have seen upwards of 30000 per second.
1666 *
1667 * We do check, however, to see if the slice is already mapped and if so,
1668 * we just exit. This is done for performance reasons. It was found that
1669 * there was a considerable boost in copyin/out performance if we did not
1670 * invalidate the segment at ReleaseUserAddressSpace time, so we dumped the
1671 * restriction that you had to bracket MapUserAddressSpace. Further, there
1672 * is a yet further boost if you didn't need to map it each time. The theory
1673 * behind this is that many times copies are to or from the same segment and
1674 * done multiple times within the same system call. To take advantage of that,
1675 * we check cioSpace and cioRelo to see if we've already got it.
1676 *
1677 * We also need to half-invalidate the slice when we context switch or go
1678 * back to user state. A half-invalidate does not clear the actual mapping,
1679 * but it does force the MapUserAddressSpace function to reload the segment
1680 * register/SLBE. If this is not done, we can end up some pretty severe
1681 * performance penalties. If we map a slice, and the cached space/relocation is
1682 * the same, we won't reload the segment registers. Howver, since we ran someone else,
1683 * our SR is cleared and we will take a fault. This is reasonable if we block
1684 * while copying (e.g., we took a page fault), but it is not reasonable when we
1685 * just start. For this reason, we half-invalidate to make sure that the SR is
1686 * explicitly reloaded.
1687 *
1688 * Note that we do not go to the trouble of making a pmap segment cache
1689 * entry for these guys because they are very short term -- 99.99% of the time
1690 * they will be unmapped before the next context switch.
1691 *
1692 */
1693
1694 addr64_t MapUserAddressSpace(vm_map_t map, addr64_t va, unsigned int size) {
1695
1696 addr64_t baddrs, reladd;
1697 thread_act_t act;
1698 mapping *mp;
1699 struct per_proc_info *perproc;
1700
1701 baddrs = va & 0xFFFFFFFFF0000000ULL; /* Isolate the segment */
1702 act = current_act(); /* Remember our activation */
1703
1704 reladd = baddrs - copyIOaddr; /* Get the relocation from user to kernel */
1705
1706 if((act->mact.cioSpace == map->pmap->space) && (act->mact.cioRelo == reladd)) { /* Already mapped? */
1707 return ((va & 0x0FFFFFFFULL) | copyIOaddr); /* Pass back the kernel address we are to use */
1708 }
1709
1710 disable_preemption(); /* Don't move... */
1711 perproc = getPerProc(); /* Get our per_proc_block */
1712
1713 mp = (mapping *)&perproc->ppCIOmp; /* Make up for C */
1714 act->mact.cioRelo = reladd; /* Relocation from user to kernel */
1715 mp->mpNestReloc = reladd; /* Relocation from user to kernel */
1716
1717 act->mact.cioSpace = map->pmap->space; /* Set the address space/pmap lookup ID */
1718 mp->mpSpace = map->pmap->space; /* Set the address space/pmap lookup ID */
1719
1720 /*
1721 * Here we make an assumption that we are going to be using the base pmap's address space.
1722 * If we are wrong, and that would be very, very, very rare, the fault handler will fix us up.
1723 */
1724
1725 hw_map_seg(map->pmap, copyIOaddr, baddrs); /* Make the entry for the first segment */
1726
1727 enable_preemption(); /* Let's move */
1728 return ((va & 0x0FFFFFFFULL) | copyIOaddr); /* Pass back the kernel address we are to use */
1729 }
1730
1731 /*
1732 * void ReleaseUserAddressMapping(addr64_t kva)
1733 *
1734 * kva = kernel address of the user copy in/out slice
1735 *
1736 */
1737
1738 void ReleaseUserAddressSpace(addr64_t kva) {
1739
1740 int i;
1741 addr64_t nextva, vend, kaddr, baddrs;
1742 unsigned int msize;
1743 thread_act_t act;
1744 mapping *mp;
1745
1746 if(kva == 0) return; /* Handle a 0 */
1747
1748 disable_preemption(); /* Don't move... */
1749
1750 act = current_act(); /* Remember our activation */
1751
1752 if(act->mact.cioSpace == invalSpace) { /* We only support one at a time */
1753 panic("ReleaseUserAddressMapping: attempt release undefined copy in/out user address space slice\n");
1754 }
1755
1756 act->mact.cioSpace = invalSpace; /* Invalidate space */
1757 mp = (mapping *)&per_proc_info[cpu_number()].ppCIOmp; /* Make up for C */
1758 mp->mpSpace = invalSpace; /* Trash it in the per_proc as well */
1759
1760 hw_blow_seg(copyIOaddr); /* Blow off the first segment */
1761 hw_blow_seg(copyIOaddr + 0x10000000ULL); /* Blow off the second segment */
1762
1763 enable_preemption(); /* Let's move */
1764
1765 return; /* Let's leave */
1766 }
1767
1768
1769
1770 /*
1771 * kern_return_t pmap_boot_map(size)
1772 *
1773 * size = size of virtual address range to be mapped
1774 *
1775 * This function is used to assign a range of virtual addresses before VM in
1776 * initialized. It starts at VM_MAX_KERNEL_ADDRESS and works downward.
1777 * The variable vm_last_addr contains the current highest possible VM
1778 * assignable address. It is a panic to attempt to call this after VM has
1779 * started up. The only problem is, is that we may not have the serial or
1780 * framebuffer mapped, so we'll never know we died.........
1781 */
1782
1783 vm_offset_t pmap_boot_map(vm_size_t size) {
1784
1785 if(kernel_map != VM_MAP_NULL) { /* Has VM already started? */
1786 panic("pmap_boot_map: VM started\n");
1787 }
1788
1789 size = round_page_32(size); /* Make sure this is in pages */
1790 vm_last_addr = vm_last_addr - size; /* Allocate the memory */
1791 return (vm_last_addr + 1); /* Return the vaddr we just allocated */
1792
1793 }
1794
1795
1796
1797 /* temporary workaround */
1798 boolean_t
1799 coredumpok(vm_map_t map, vm_offset_t va)
1800 {
1801 return TRUE;
1802 }