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