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