|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
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: /*
89: * CAVAETS:
90: *
91: * Needs more work for MP support
92: */
93:
94: #include <debug.h>
95: #include <mach_vm_debug.h>
96:
97: #include <kern/thread.h>
98: #include <mach/vm_attributes.h>
99: #include <mach/vm_param.h>
100: #include <kernserv/machine/spl.h>
101:
102: #include <machdep/ppc/proc_reg.h>
103: #include <machdep/ppc/mem.h>
104: #include <machdep/ppc/pmap.h>
105: #include <machdep/ppc/pmap_internals.h>
106: #include <machdep/ppc/powermac.h>
107:
108:
109: #define NULL 0
110: #define DPRINTF(x) if(0) {kprintf("%s : ", __FUNCTION__);kprintf x;}
111:
112: /* forward */
113: void pmap_activate(pmap_t pmap, thread_t th, int which_cpu);
114: void pmap_deactivate(pmap_t pmap, thread_t th, int which_cpu);
115: void copy_to_phys(vm_offset_t sva, vm_offset_t dpa, int bytecount);
116:
117: static struct mapping *pmap_find_mapping(space_t space, vm_offset_t offset);
118:
119: static void pmap_free_mapping(register struct mapping *mp);
120:
121: static void pmap_reap_mappings(void);
122:
123: static struct mapping *pmap_enter_mapping(pmap_t pmap,
124: space_t space,
125: vm_offset_t va,
126: vm_offset_t pa,
127: pte_t *pte,
128: unsigned prot,
129: struct phys_entry *pp);
130:
131: #if DEBUG
132: #define PDB_USER 0x01 /* exported functions */
133: #define PDB_MAPPING 0x02 /* low-level mapping routines */
134: #define PDB_ENTER 0x04 /* pmap_enter specifics */
135: #define PDB_COPY 0x08 /* copy page debugging */
136: #define PDB_ZERO 0x10 /* zero page debugging */
137: #define PDB_WIRED 0x20 /* things concerning wired entries */
138: #define PDB_PTEG 0x40 /* PTEG overflows */
139: #define PDB_MASSIVE 0x80 /* Massive costly assert checks */
140: #define PDB_IO 0x100 /* Improper use of WIMG_IO checks - PCI machines */
141: int pmdebug = 0;
142:
143: #define PCI_BASE 0x80000000
144: #endif
145:
146: struct pmap kernel_pmap_store;
147: pmap_t kernel_pmap;
148: struct zone *pmap_zone; /* zone of pmap structures */
149: boolean_t pmap_initialized = FALSE;
150:
151: #define HASH_TABLE_FACTLOG2 0
152: int hash_table_factlog2 = HASH_TABLE_FACTLOG2;
153:
154: /*
155: * Physical-to-virtual translations are handled by inverted page table
156: * structures, phys_tables. Multiple mappings of a single page are handled
157: * by linking the affected mapping structures. We initialise one region
158: * for phys_tables of the physical memory we know about, but more may be
159: * added as it is discovered (eg. by drivers).
160: */
161: struct phys_entry *phys_table; /* For debugging */
162:
163: /*
164: * XXX use mpqueue_head_t's??
165: * (no one else does, are they coming or going?)
166: */
167: queue_head_t free_mapping; /* list of free mapping structs */
168: decl_simple_lock_data(,free_mapping_lock) /* and lock */
169:
170: pmap_t free_pmap; /* list of free pmaps */
171: decl_simple_lock_data(,free_pmap_lock) /* and lock */
172:
173: decl_simple_lock_data(,pmap_lock) /* XXX this is all broken */
174:
175: unsigned prot_bits[8];
176:
177: /*
178: * This is the master space ID counter, initially set to the kernel's
179: * SID. The counter is incremented (though not necessarily by one)
180: * whenever a new space ID is required. For PPC, the SID ranges from
181: * to 2**20 - 1.
182: */
183: int sid_counter=PPC_SID_KERNEL; /* seed for SID generator */
184:
185:
186:
187: /*
188: * pmap_find_physentry(pa)
189: *
190: * Function to get index into phys_table for a given physical address
191: */
192: struct phys_entry *
193: pmap_find_physentry(
194: vm_offset_t pa)
195: {
196: int i;
197: struct phys_entry *entry;
198:
199: for (i = pmap_mem_regions_count-1; i >= 0; i--) {
200: if (pa < pmap_mem_regions[i].start)
201: continue;
202: if (pa >= pmap_mem_regions[i].end)
203: {
204: return PHYS_NULL;
205: }
206:
207: entry = &pmap_mem_regions[i].
208: phys_table[(pa -
209: pmap_mem_regions[i].start) >> PPC_PGSHIFT];
210: return entry;
211: }
212: DPRINTF(("NMGS DEBUG : pmap_find_physentry 0x%08x out of range\n",pa));
213: return (struct phys_entry *)PHYS_NULL;
214: }
215:
216:
217:
218: /*
219: * kern_return_t
220: * pmap_add_physical_memory(vm_offset_t spa, vm_offset_t epa,
221: * boolean_t available, unsigned int attr)
222: * Allocate some extra physentries for the physical addresses given,
223: * specifying some default attribute that on the powerpc specifies
224: * the default cachability for any mappings using these addresses
225: * If the memory is marked as available, it is added to the general
226: * VM pool, otherwise it is not (it is reserved for card IO etc).
227: */
228: kern_return_t
229: pmap_add_physical_memory(
230: vm_offset_t spa,
231: vm_offset_t epa,
232: boolean_t available,
233: unsigned int attr)
234: {
235: int i,j;
236: spl_t s;
237: struct phys_entry *phys_table;
238:
239: /* Only map whole pages */
240:
241: spa = trunc_page(spa);
242: epa = round_page(epa);
243:
244: /* First check that the region doesn't already exist */
245:
246: assert (epa >= spa);
247: for (i = 0; i < pmap_mem_regions_count; i++) {
248: /* If we're below the next region, then no conflict */
249: if (epa <= pmap_mem_regions[i].start)
250: break;
251: if (spa < pmap_mem_regions[i].end) {
252: #if DEBUG
253: DPRINTF(("(0x%08x,0x%08x,0x%08x) - memory already present\n",spa,epa,attr));
254: #endif /* DEBUG */
255: return KERN_NO_SPACE;
256: }
257: }
258:
259: /* Check that we've got enough space for another region */
260: if (pmap_mem_regions_count == 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:
267: phys_table = (struct phys_entry *)
268: kalloc(sizeof(struct phys_entry) * atop(epa-spa));
269:
270: /* Initialise the new phys_table entries */
271: for (j = 0; j < atop(epa-spa); j++) {
272: queue_init(&phys_table[j].phys_link);
273: /* We currently only support these two attributes */
274: assert((attr == PTE_WIMG_DEFAULT) ||
275: (attr == PTE_WIMG_IO));
276: phys_table[j].pte1.bits.wimg = attr;
277: }
278: s = splhigh();
279:
280: /* Move all the phys_table entries up some to make room in
281: * the ordered list.
282: */
283: for (j = pmap_mem_regions_count; j > i ; j--)
284: pmap_mem_regions[j] = pmap_mem_regions[j-1];
285:
286: /* Insert a new entry with some memory to back it */
287:
288: pmap_mem_regions[i].start = spa;
289: pmap_mem_regions[i].end = epa;
290: pmap_mem_regions[i].phys_table = phys_table;
291:
292: pmap_mem_regions_count++;
293: splx(s);
294:
295: if (available) {
296: DPRINTF(("warning : pmap_add_physical_mem() "
297: "available not yet supported\n"));
298: }
299:
300: return KERN_SUCCESS;
301: }
302:
303:
304:
305: /*
306: * ppc_protection_init()
307: * Initialise the user/kern_prot_codes[] arrays which are
308: * used to translate machine independent protection codes
309: * to powerpc protection codes. The PowerPc can only provide
310: * [no rights, read-only, read-write]. Read implies execute.
311: * See PowerPC 601 User's Manual Table 6.9
312: */
313: void
314: ppc_protection_init(void)
315: {
316: prot_bits[VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE] = 0;
317: prot_bits[VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE] = 3;
318: prot_bits[VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE] = 3;
319: prot_bits[VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE] = 3;
320: prot_bits[VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE] = 2;
321: prot_bits[VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE] = 2;
322: prot_bits[VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE] = 2;
323: prot_bits[VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE] = 2;
324: }
325:
326:
327:
328: /*
329: * pmap_map(va, spa, epa, prot)
330: * is called during boot to map memory in the kernel's address map.
331: * A virtual address range starting at "va" is mapped to the physical
332: * address range "spa" to "epa" with machine independent protection
333: * "prot".
334: *
335: * "va", "spa", and "epa" are byte addresses and must be on machine
336: * independent page boundaries.
337: */
338: vm_offset_t
339: pmap_map(
340: vm_offset_t va,
341: vm_offset_t spa,
342: vm_offset_t epa,
343: vm_prot_t prot)
344: {
345:
346: if (spa == epa)
347: return(va);
348:
349: assert(epa > spa);
350:
351: while (spa < epa) {
352: pmap_enter(kernel_pmap, va, spa, prot, TRUE);
353:
354: va += PAGE_SIZE;
355: spa += PAGE_SIZE;
356: }
357: return(va);
358: }
359:
360:
361:
362: /*
363: * pmap_map_bd(va, spa, epa, prot)
364: * Back-door routine for mapping kernel VM at initialisation.
365: * Used for mapping memory outside the known physical memory
366: * space, with caching disabled. Designed for use by device probes.
367: *
368: * A virtual address range starting at "va" is mapped to the physical
369: * address range "spa" to "epa" with machine independent protection
370: * "prot".
371: *
372: * "va", "spa", and "epa" are byte addresses and must be on machine
373: * independent page boundaries.
374: *
375: * WARNING: The current version of memcpy() can use the dcbz instruction
376: * on the destination addresses. This will cause an alignment exception
377: * and consequent overhead if the destination is caching-disabled. So
378: * avoid memcpy()ing into the memory mapped by this function.
379: *
380: * also, many other pmap_ routines will misbehave if you try and change
381: * protections or remove these mappings, they are designed to be permanent.
382: */
383: vm_offset_t
384: pmap_map_bd(
385: vm_offset_t va,
386: vm_offset_t spa,
387: vm_offset_t epa,
388: vm_prot_t prot)
389: {
390: pte_t *pte;
391: struct phys_entry* pp;
392: struct mapping *mp;
393: spl_t s;
394:
395: if (spa == epa)
396: return(va);
397:
398: assert(epa > spa);
399:
400: #if DEBUG
401: DPRINTF(("va=0x%08X, spa=0x%08X, epa=0x%08X, prot=0x%x\n\n",va,spa,epa,prot));
402: #endif
403: s = splhigh();
404: while (spa < epa) {
405:
406: pte = find_or_allocate_pte(PPC_SID_KERNEL, va, TRUE);
407:
408: assert(pte != PTE_NULL);
409:
410: /* remapping of already-mapped addresses is OK, we just
411: * trample on the PTE, but make sure we're mapped to same
412: * address
413: */
414: if (pte->pte0.bits.valid)
415: assert(trunc_page(pte->pte1.word) == spa);
416:
417: /* Perform a general case PTE update designed to work
418: in SMP configurations. TODO - locks and tlbsync
419: */
420: assert(pte->pte0.bits.valid == TRUE);
421: pte->pte0.bits.valid = FALSE; /* Invalidate pte entry */
422: sync(); /* Force updates to complete */
423: tlbie(va); /* Wipe out this virtual address */
424: eieio(); /* Enforce ordering of v bit */
425: tlbsync();
426: sync();
427:
428: /* Allowable early PTE updates: RPN,R,C,WIMG,PP
429: */
430: pte->pte1.bits.protection = prot_bits[prot];
431: pte->pte1.bits.phys_page = spa >> PPC_PGSHIFT;
432: pte->pte1.bits.wimg = PTE_WIMG_IO;
433: eieio();
434:
435: /* Post tlbie updates: VSID,H,API,V
436: */
437: pte->pte0.bits.valid = TRUE; /* Validate pte entry */
438: sync();
439:
440:
441: /* If memory is mappable (is in phys table) then set
442: * default cach attributes to non-cached and verify
443: * that there aren't any non-cached mappings which would
444: * break the processor spec (and hang the machine).
445: */
446: pp = pmap_find_physentry(spa);
447: if (pp != PHYS_NULL) {
448: /* Set the default mapping type */
449: pp->pte1.bits.wimg = PTE_WIMG_IO;
450: #if DEBUG
451: /* Belt and braces check on mappings */
452: queue_iterate(&pp->phys_link, mp,
453: struct mapping *, phys_link) {
454: assert(mp->pte->pte1.bits.wimg ==
455: PTE_WIMG_IO);
456: }
457: #endif /* DEBUG */
458: }
459: va += PAGE_SIZE;
460: spa += PAGE_SIZE;
461: }
462: splx(s);
463: return(va);
464: }
465:
466:
467:
468: /*
469: * Bootstrap the system enough to run with virtual memory.
470: * Map the kernel's code and data, and allocate the system page table.
471: * Called with mapping done by BATs. Page_size must already be set.
472: *
473: * Parameters:
474: * first_avail PA of address where we can allocate structures.
475: */
476: void
477: pmap_bootstrap(
478: unsigned int mem_size,
479: vm_offset_t *first_avail)
480: {
481: struct mapping *mp;
482: vm_offset_t struct_addr;
483: vm_size_t struct_size, hash_table_align, phys_table_size,
484: mapping_table_size;
485: unsigned int mapping_table_num, phys_pages_num;
486: int i;
487:
488: *first_avail = round_page(*first_avail);
489:
490: assert(PAGE_SIZE == PPC_PGBYTES);
491:
492: ppc_protection_init();
493:
494: /*
495: * Initialize kernel pmap
496: */
497: kernel_pmap = &kernel_pmap_store;
498: #if NCPUS > 1
499: lock_init(&pmap_lock, FALSE, ETAP_VM_PMAP_SYS, ETAP_VM_PMAP_SYS_I);
500: #endif /* NCPUS > 1 */
501: simple_lock_init(&kernel_pmap->lock);
502: simple_lock_init(&free_pmap_lock);
503:
504: kernel_pmap->ref_count = 1;
505: kernel_pmap->space = PPC_SID_KERNEL;
506: kernel_pmap->next = PMAP_NULL;
507:
508: /*
509: * Allocate: (from first_avail up)
510: * aligned to its own size:
511: * hash table (for mem size 2**x, allocate 2**(x-10) entries)
512: * physical page entries (1 per physical page)
513: * physical -> virtual mappings (for multi phys->virt mappings)
514: */
515:
516: /*
517: * Table 7-21 on page 7-52 of the PowerPC Programming
518: * Environments book (32-bit) doesn't tell you how to
519: * size the hashed page table for strange memory sizes
520: * (i.e. not a power of 2). It has been empirically
521: * determined that splitting the difference and rounding
522: * can be used effectively in these circumstances.
523: */
524: {
525: vm_size_t rounded_mem_size;
526: int factor;
527:
528: /*
529: * The minimum size for the hash table is 64K
530: * and is bounded by a memory size of 8MB.
531: */
532: hash_table_size = 64*1024; rounded_mem_size = 8*1024*1024;
533: while (hash_table_size < 32*1024*104 &&
534: rounded_mem_size < mem_size) {
535: hash_table_size *= 2; rounded_mem_size *= 2;
536: }
537:
538: /*
539: * If we need to allocate more than a minimum
540: * sized hash table and our memory size is not
541: * a power of 2
542: *
543: * AND
544: *
545: * if we are less than half way to next higher
546: * power of 2, then use the next lower value.
547: */
548: if (hash_table_size > 64*1024 && rounded_mem_size != mem_size) {
549: if (
550: /*
551: * Special case for mem_size
552: * greater than 2G since
553: * rounded_mem_size is zero
554: * in this case.
555: */
556: (mem_size > 2*1024*1024*1024UL &&
557: mem_size < 3*1024*1024*1024UL)
558: ||
559: (mem_size < ((rounded_mem_size / 2) +
560: (rounded_mem_size / 4)))
561: ) hash_table_size /= 2;
562: }
563:
564: #ifdef notdef
565: printf("rounded_mem_size %x\n", rounded_mem_size);
566: #endif
567:
568: /*
569: * Determine the value of any additional
570: * factor to apply to the size of the
571: * hash table.
572: */
573: if (hash_table_factlog2 < 0)
574: factor = -1;
575: else
576: factor = 1;
577:
578: hash_table_factlog2 *= factor;
579:
580: while (hash_table_factlog2 > 0) {
581: factor *= 2; hash_table_factlog2--;
582: }
583:
584: if (factor > 0)
585: printf("hash table factor is %d\n", factor);
586: else
587: printf("hash table factor is 1/%d\n", -factor);
588:
589: /*
590: * Apply the factor, and catch out
591: * of bound sizes.
592: */
593: if (factor > 1) {
594: hash_table_size *= factor;
595:
596: if (hash_table_size < 64*1024)
597: hash_table_size = 64*1024;
598: }
599: else if (factor < -1) {
600: hash_table_size /= -factor;
601:
602: if (hash_table_size > 32*1024*1024 || hash_table_size == 0)
603: hash_table_size = 32*1024*1024;
604: }
605:
606: /*
607: * Notice a bit of handwaving here: since we
608: * use a BAT to statically map the kernel,
609: * the hashed page table and the ancillary
610: * mapping structures, using mem_size is a
611: * bit generous. However, we do need to allow
612: * for some extra mappings for I/O regions, so
613: * we'll just call it even.
614: */
615: }
616:
617: /* HASH TABLE MUST BE aligned to its size */
618:
619: struct_addr = (*first_avail + (hash_table_size - 1)) &~
620: (hash_table_size - 1);
621:
622: hash_table_align = struct_addr - *first_avail;
623:
624: if (round_page(*first_avail) + PPC_PGBYTES < round_page(struct_addr)) {
625: free_regions[free_regions_count].start =
626: round_page(*first_avail) + PPC_PGBYTES;
627: free_regions[free_regions_count].end = round_page(struct_addr);
628: free_regions_count++;
629: }
630:
631: phys_pages_num = atop(mem_size);
632:
633: phys_table_size = sizeof(struct phys_entry) * phys_pages_num;
634: mapping_table_size =
635: sizeof(struct mapping) * (hash_table_size/sizeof(pte_t));
636:
637: /* size of all structures that we're going to allocate */
638:
639: struct_size = (vm_size_t) (hash_table_size +
640: phys_table_size +
641: mapping_table_size);
642:
643: #ifdef notdef
644: printf("pmap static allocation:\n");
645: printf("hash table: %x (alignment) + %x (size) +\n",
646: hash_table_align, hash_table_size);
647: printf("ptov table: %x (phys entries) + %x (mappings) =\n",
648: phys_table_size, mapping_table_size);
649: printf("total: %x\n", hash_table_align + struct_size);
650: #endif
651:
652: struct_size = round_page(struct_size);
653:
654: /* Zero everything - this also invalidates the hash table entries */
655: bzero((char *)struct_addr, struct_size);
656:
657: /* Set up some pointers to our new structures */
658:
659: /*
660: * Set up hash table address, keeping alignment. These
661: * mappings are 1-1.
662: */
663: hash_table_base = struct_addr;
664: struct_addr += hash_table_size;
665:
666: /*
667: * phys_table is static to help debugging,
668: * this variable is no longer actually used
669: * outside of this scope
670: */
671: phys_table = (struct phys_entry *) struct_addr;
672:
673: for (i = 0; i < pmap_mem_regions_count; i++) {
674: pmap_mem_regions[i].phys_table = phys_table;
675: phys_table = phys_table +
676: atop(pmap_mem_regions[i].end -
677: pmap_mem_regions[i].start);
678: }
679:
680: /* restore phys_table for debug */
681: phys_table = (struct phys_entry *) struct_addr;
682: struct_addr += phys_table_size;
683:
684: /* Initialise the registers necessary for supporting the hashtable */
685: hash_table_init(hash_table_base, hash_table_size);
686:
687: /* Initialise the physical table mappings */
688: for (i = 0; i < phys_pages_num; i++) {
689: queue_init(&phys_table[i].phys_link);
690: phys_table[i].pte1.bits.wimg = PTE_WIMG_DEFAULT;
691: }
692:
693: /*
694: * Remaining space is for mapping entries. Chain them
695: * together (XXX can't use a zone
696: * since zone package hasn't been initialized yet).
697: */
698: mapping_table_num = mapping_table_size /
699: sizeof(struct mapping);
700:
701: mp = (struct mapping *) struct_addr;
702:
703: queue_init(&free_mapping);
704: simple_lock_init(&free_mapping_lock);
705:
706: while (mapping_table_num-- > 0) {
707: queue_enter(&free_mapping, mp, struct mapping *, phys_link);
708: mp++;
709: }
710:
711: *first_avail = round_page(mp);
712:
713: /* All the rest of memory is free - add it to the free
714: * regions so that it can be allocated by pmap_steal
715: */
716: free_regions[free_regions_count].start = *first_avail;
717: free_regions[free_regions_count].end = pmap_mem_regions[0].end;
718: free_regions_count++;
719: }
720:
721:
722:
723: /*
724: * pmap_init()
725: * finishes the initialization of the pmap module.
726: * This procedure is called from vm_mem_init() in vm/vm_init.c
727: * to initialize any remaining data structures that the pmap module
728: * needs to map virtual memory (VM is already ON).
729: */
730: /*ARGSUSED*/
731: void
732: pmap_init(void)
733: {
734: vm_size_t s;
735:
736: s = sizeof(struct pmap);
737: pmap_zone = zinit(s, 400*s, 4096, FALSE, "pmap"); /* XXX */
738:
739: pmap_initialized = TRUE;
740: }
741:
742:
743: /*
744: * pmap_create
745: *
746: * Create and return a physical map.
747: *
748: * If the size specified for the map is zero, the map is an actual physical
749: * map, and may be referenced by the hardware.
750: *
751: * If the size specified is non-zero, the map will be used in software
752: * only, and is bounded by that size.
753: */
754: pmap_t
755: pmap_create(
756: vm_size_t size)
757: {
758: pmap_t pmap;
759: spl_t s;
760:
761: #if DEBUG
762: if (pmdebug & PDB_USER)
763: DPRINTF(("(size=%x)%c", size, size ? '\n' : ' '));
764: #endif
765:
766: /*
767: * A software use-only map doesn't even need a pmap structure.
768: */
769: if (size)
770: return(PMAP_NULL);
771:
772: /*
773: * If there is a pmap in the pmap free list, reuse it.
774: */
775: s = splhigh();
776: simple_lock(&free_pmap_lock);
777: if (free_pmap != PMAP_NULL) {
778: pmap = free_pmap;
779: free_pmap = pmap->next;
780: } else
781: pmap = PMAP_NULL;
782: simple_unlock(&free_pmap_lock);
783:
784: /*
785: * Couldn't find a pmap on the free list, try to allocate a new one.
786: */
787: if (pmap == PMAP_NULL) {
788: pmap = (pmap_t) zalloc(pmap_zone);
789: if (pmap == PMAP_NULL)
790: {
791: splx(s);
792: return(PMAP_NULL);
793: }
794:
795: /*
796: * Allocate space IDs for the pmap.
797: * If all are allocated, there is nothing we can do.
798: */
799:
800: /* If sid_counter == MAX_SID, we've allocated
801: * all the possible SIDs and they're all live,
802: * we can't carry on, but this is HUGE, so don't
803: * expect it in normal operation.
804: */
805: assert(sid_counter != SID_MAX);
806:
807: /* Try to spread out the sid's through the possible
808: * name space to improve the hashing heuristics
809: */
810: #warning Get a better VSID allocation algorithm from the AIX folks.
811: /* sid_counter = (sid_counter + PPC_SID_PRIME) & PPC_SID_MASK; */
812: sid_counter ++; /* Replaced by a simpler algorithm */
813:
814:
815: /*
816: * Initialize the sids
817: */
818: pmap->space = sid_counter;
819: simple_lock_init(&pmap->lock);
820: }
821: pmap->ref_count = 1;
822: pmap->next = PMAP_NULL;
823: pmap->stats.resident_count = 0;
824: pmap->stats.wired_count = 0;
825: #if DEBUG
826: if (pmdebug & PDB_USER)
827: DPRINTF(("-> %x, space id = %d\n", pmap, pmap->space));
828: #endif
829: splx(s);
830: return(pmap);
831: }
832:
833:
834:
835: /*
836: * pmap_destroy
837: *
838: * Gives up a reference to the specified pmap. When the reference count
839: * reaches zero the pmap structure is added to the pmap free list.
840: *
841: * Should only be called if the map contains no valid mappings.
842: */
843: void
844: pmap_destroy(
845: pmap_t pmap)
846: {
847: int ref_count;
848: spl_t s;
849:
850: #if DEBUG
851: if (pmdebug & PDB_USER)
852: DPRINTF(("(pmap=%x)\n", pmap));
853: #endif
854:
855: if (pmap == PMAP_NULL)
856: return;
857:
858: s = splhigh();
859: simple_lock(&pmap->lock);
860: ref_count = --pmap->ref_count;
861: simple_unlock(&pmap->lock);
862:
863: if (ref_count < 0)
864: panic("pmap_destroy(): ref_count < 0");
865: if (ref_count > 0)
866: {
867: splx(s);
868: return;
869: }
870:
871: #if DEBUG
872: if (pmap->stats.resident_count != 0 || pmap->stats.wired_count != 0) {
873: kprintf("pmap_destroy: non_empty pmap\n");
874: }
875: #endif /* DEBUG */
876:
877: /*
878: * Add the pmap to the pmap free list.
879: */
880: simple_lock(&free_pmap_lock);
881: pmap->next = free_pmap;
882: free_pmap = pmap;
883: simple_unlock(&free_pmap_lock);
884: splx(s);
885: }
886:
887:
888:
889: /*
890: * pmap_reference(pmap)
891: *
892: * gains a reference to the specified pmap.
893: *
894: * This is used to indicate that the pmap is in use by multiple
895: * machine-independent maps and will prevent early deallocation
896: * of the pmap.
897: */
898: void
899: pmap_reference(
900: pmap_t pmap)
901: {
902: spl_t s;
903:
904: #if DEBUG
905: if (pmdebug & PDB_USER)
906: DPRINTF(("(pmap=%x)\n", pmap));
907: #endif
908:
909: if (pmap != PMAP_NULL) {
910: s = splhigh();
911: simple_lock(&pmap->lock);
912: pmap->ref_count++;
913: simple_unlock(&pmap->lock);
914: splx(s);
915: }
916: }
917:
918: /*
919: * pmap_remove(pmap, s, e)
920: * unmaps all virtual addresses v in the virtual address
921: * range determined by [s, e) and pmap.
922: * s and e must be on machine independent page boundaries and
923: * s must be less than or equal to e.
924: */
925: void
926: pmap_remove(
927: pmap_t pmap,
928: vm_offset_t sva,
929: vm_offset_t eva)
930: {
931: space_t space;
932: struct mapping *mp;
933: spl_t s;
934:
935: #if DEBUG
936: if (pmdebug & PDB_USER)
937: DPRINTF(("(pmap=%x, sva=%x, eva=%x)\n",
938: pmap, sva, eva));
939: #endif
940:
941: if (pmap == PMAP_NULL)
942: return;
943:
944: s = splhigh();
945: space = pmap->space;
946:
947: /* It is just possible that eva might have wrapped around to zero,
948: * and sometimes we get asked to liberate something of size zero
949: * even though it's dumb (eg. after zero length read_overwrites)
950: */
951: assert(eva >= sva);
952:
953: /* We liberate addresses from high to low, since the stack grows
954: * down. This means that we won't need to test addresses below
955: * the limit of stack growth
956: */
957: while ((pmap->stats.resident_count > 0) && (eva > sva)) {
958: eva -= PAGE_SIZE;
959: if ((mp = pmap_find_mapping(space, eva)) != MAPPING_NULL) {
960: pmap->stats.resident_count--;
961: pmap_free_mapping(mp);
962: }
963: }
964: splx(s);
965: }
966:
967:
968:
969: /*
970: * Routine:
971: * pmap_page_protect
972: *
973: * Function:
974: * Lower the permission for all mappings to a given page.
975: */
976: void
977: pmap_page_protect(
978: vm_offset_t pa,
979: vm_prot_t prot)
980: {
981: register struct phys_entry *pp;
982: register struct mapping *mp;
983: register struct mapping *mp2;
984: unsigned pteprot;
985: boolean_t remove;
986: spl_t s;
987:
988: #if DEBUG
989: if (pmdebug & PDB_USER)
990: DPRINTF(("(pa=%x, prot=%x)\n", pa, prot));
991: #endif
992:
993: switch (prot)
994: {
995: case VM_PROT_READ:
996: case VM_PROT_READ|VM_PROT_EXECUTE:
997: remove = FALSE;
998: break;
999: case VM_PROT_ALL:
1000: return;
1001: default:
1002: remove = TRUE;
1003: break;
1004: }
1005:
1006: pp = pmap_find_physentry(pa);
1007: if (pp == PHYS_NULL)
1008: return;
1009:
1010: s = splhigh();
1011: if (remove)
1012: {
1013: mp2 = MAPPING_NULL;
1014: while (!queue_empty(&pp->phys_link))
1015: {
1016: mp = (struct mapping *) queue_first(&pp->phys_link);
1017: if (mp->vm_info.bits.phys)
1018: {
1019: // Don't zap the phys page
1020: mp2 = mp;
1021: queue_remove(&pp->phys_link, mp2, struct mapping *, phys_link);
1022: } else
1023: {
1024: mp->pmap->stats.resident_count--;
1025: #if DEBUG
1026: if (mp->vm_info.bits.wired)
1027: {
1028: DPRINTF((": removing WIRED page!!\n"));
1029: }
1030: #endif /* DEBUG */
1031: pmap_free_mapping(mp);
1032: }
1033: }
1034: #if DEBUG
1035: if (queue_empty(&pp->phys_link) && (mp2 == MAPPING_NULL))
1036: {
1037: DPRINTF(("WHOOPS! removed and entire map\n"));
1038: }
1039: #endif /* DEBUG */
1040:
1041: if (mp2 != MAPPING_NULL)
1042: {
1043: // Restore the phys page
1044: queue_enter_first(&pp->phys_link, mp2, struct mapping *, phys_link);
1045: }
1046: splx(s);
1047: return;
1048: }
1049:
1050: /*
1051: * Modify mappings if necessary.
1052: */
1053: queue_iterate(&pp->phys_link, mp, struct mapping *, phys_link)
1054: {
1055: /* Compare the new protection bits with the old
1056: one to see if anything needs to be changed.
1057: Note: In mach 2.5, we must not reduce the
1058: protection status of the static logical mapping
1059: (the phys page), but we *do* want to record RC
1060: bits.
1061: */
1062: if (mp->vm_info.bits.phys)
1063: {
1064: // Phys page mapping - don't alter protection
1065: // Do not merge RC bits into pp.
1066: continue;
1067: }
1068:
1069: pteprot = prot_bits[prot];
1070: if ((mp->pte->pte1.bits.protection) != pteprot)
1071: {
1072: /*
1073: * Perform a sync to force saving
1074: * of change/reference bits, followed by a
1075: * fault and reload with the new protection.
1076: */
1077: assert(mp->pte->pte0.bits.valid == TRUE);
1078: mp->pte->pte0.bits.valid = FALSE;
1079: sync();
1080: tlbie(mp->vm_info.bits.page << PPC_PGSHIFT);
1081: eieio();
1082: tlbsync();
1083: sync();
1084:
1085: mp->pte->pte1.bits.protection = pteprot;
1086: eieio();
1087:
1088: mp->pte->pte0.bits.valid = TRUE;
1089: sync();
1090: }
1091: //pp->pte1.word |= mp->pte->pte1.word;
1092: pp->pte1.bits.protection |= mp->pte->pte1.bits.protection;
1093: }
1094: splx(s);
1095: }
1096:
1097:
1098:
1099: /*
1100: * pmap_protect(pmap, s, e, prot)
1101: * changes the protection on all virtual addresses v in the
1102: * virtual address range determined by [s, e] and pmap to prot.
1103: * s and e must be on machine independent page boundaries and
1104: * s must be less than or equal to e.
1105: */
1106: void
1107: pmap_protect(
1108: pmap_t pmap,
1109: vm_offset_t sva,
1110: vm_offset_t eva,
1111: vm_prot_t prot)
1112: {
1113: register struct mapping *mp;
1114: pte_t *pte;
1115: unsigned pteprot;
1116: space_t space;
1117: spl_t s;
1118:
1119: #if DEBUG
1120: if (pmdebug & PDB_USER)
1121: DPRINTF(("(pmap=%x, sva=%x, eva=%x, prot=%x)\n",
1122: pmap, sva, eva, prot));
1123: #endif
1124:
1125: if (pmap == PMAP_NULL)
1126: return;
1127:
1128: assert(sva <= eva);
1129:
1130: if (prot == VM_PROT_NONE) {
1131: pmap_remove(pmap, sva, eva);
1132: return;
1133: }
1134: #if MACH_30
1135: if (prot & VM_PROT_WRITE)
1136: return;
1137: #endif
1138:
1139: s = splhigh();
1140: space = pmap->space;
1141: for ( ; sva < eva; sva += PAGE_SIZE) {
1142: mp = pmap_find_mapping(space, sva);
1143: if (mp == MAPPING_NULL)
1144: continue;
1145: #if DEBUG
1146: if (pmap != mp->pmap)
1147: panic("protect: pmap mismatch");
1148: #endif
1149: /*
1150: * Determine if mapping is changing.
1151: * If not, nothing to do.
1152: */
1153: pte = mp->pte;
1154: pteprot = prot_bits[prot];
1155: if (pte->pte1.bits.protection == pteprot)
1156: continue;
1157:
1158: /*
1159: * Purge the current TLB entry (if any) to force
1160: * any modifications to changed/referenced bits, and so
1161: * that future references will fault and reload with the
1162: * new protection.
1163: */
1164:
1165: /* Perform a general case PTE update designed to work
1166: in SMP configurations. TODO - locks
1167: */
1168: assert(pte->pte0.bits.valid == TRUE);
1169: pte->pte0.bits.valid = FALSE; /* Invalidate pte entry */
1170: sync(); /* Force updates to complete */
1171: tlbie(sva);
1172: eieio();
1173: tlbsync();
1174: sync();
1175:
1176: /* Allowable early PTE updates: RPN,R,C,WIMG,PP
1177: */
1178: pte->pte1.bits.protection = pteprot; /* Change just the protection */
1179: eieio();
1180:
1181: /* Post tlbie updates: VSID,H,API,V
1182: */
1183: pte->pte0.bits.valid = TRUE; /* Validate pte entry */
1184: sync();
1185:
1186: }
1187: splx(s);
1188: }
1189:
1190:
1191:
1192: void
1193: pmap_enter_phys_page(
1194: vm_offset_t pa,
1195: vm_offset_t va)
1196: {
1197: struct mapping *mp;
1198:
1199: pmap_enter(kernel_pmap, va, pa, VM_PROT_READ|VM_PROT_WRITE, TRUE);
1200:
1201: if (mp = pmap_find_mapping(kernel_pmap->space, va)) {
1202: mp->vm_info.bits.phys = TRUE;
1203: }
1204: #if DEBUG
1205: else
1206: {
1207: DPRINTF(("pmap_enter_phys_page: mp == NULL\n"));
1208: DPRINTF(("pmap_enter_phys_page: mp == NULL\n"));
1209: panic("pmap_enter_phys_page: can't find mapping entry");
1210: }
1211: #endif /* DEBUG */
1212: }
1213:
1214:
1215:
1216: int pmap_enter_cnt = 0;
1217: int pmap_enter_valid_cnt = 0;
1218: int pmap_enter_invalid_cnt = 0;
1219: /*
1220: * pmap_enter
1221: *
1222: * Create a translation for the virtual address (virt) to the physical
1223: * address (phys) in the pmap with the protection requested. If the
1224: * translation is wired then we can not allow a page fault to occur
1225: * for this mapping.
1226: *
1227: * NB: This is the only routine which MAY NOT lazy-evaluate
1228: * or lose information. That is, this routine must actually
1229: * insert this page into the given map NOW.
1230: */
1231: void
1232: pmap_enter(
1233: pmap_t pmap,
1234: vm_offset_t va,
1235: vm_offset_t pa,
1236: vm_prot_t prot,
1237: boolean_t wired)
1238: {
1239: register struct mapping *mp;
1240: struct phys_entry *pp,*old_pp;
1241: pte_t *pte;
1242: space_t space;
1243: boolean_t was_wired;
1244: spl_t s;
1245:
1246: #if DEBUG
1247: if ((wired && (pmdebug & (PDB_WIRED))) ||
1248: ((pmdebug & (PDB_USER|PDB_ENTER)) == (PDB_USER | PDB_ENTER)))
1249: DPRINTF(("(pmap=%x, va=%x, pa=%x, prot=%x, wire=%x)\n", pmap, va, pa, prot, wired));
1250: pmap_enter_cnt++;
1251: #endif
1252: if (pmap == PMAP_NULL)
1253: return;
1254: #if DEBUG
1255: if (prot == VM_PROT_NONE) {
1256: pmap_remove(pmap, va, va + PAGE_SIZE);
1257: return;
1258: }
1259: #endif /* DEBUG */
1260:
1261: /* TODO NMGS - take lock on physentry? */
1262: pp = pmap_find_physentry(pa);
1263: if (pp == PHYS_NULL)
1264: return;
1265:
1266: /* Find the pte associated with the virtual address/space ID */
1267: space = pmap->space;
1268:
1269: /* TODO NMGS - take lock on pte?! */
1270: pte = find_or_allocate_pte(space,va,TRUE);
1271:
1272: assert(pte != PTE_NULL);
1273: /* Even if the pte is new, pte0 should be set up for the new mapping,
1274: * but with the valid bit set to FALSE
1275: */
1276: assert((pte->pte0.word & 0x7fffffff) != PTE_EMPTY);
1277:
1278: s = splhigh();
1279: if (pte->pte0.bits.valid == TRUE) {
1280:
1281: /* mapping is already valid, thus virtual address was
1282: * already mapped somewhere...
1283: */
1284:
1285: #if DEBUG
1286: pmap_enter_valid_cnt++;
1287: #endif /* DEBUG */
1288: /*
1289: ** invalidate tlb for previous mapping
1290: */
1291: pte->pte0.bits.valid = FALSE;/* Invalidate pte entry */
1292: sync(); /* Force updates to complete */
1293: tlbie(va); /* Wipe out this virtual address */
1294: eieio(); /* Enforce ordering of v bit */
1295: tlbsync();
1296: sync();
1297:
1298: if (((physical_addr_t *) &pa)->bits.page_no !=
1299: pte->pte1.bits.phys_page) {
1300:
1301: /* The current mapping is to a different
1302: * physical addr - release the mapping
1303: * before mapping the new address.
1304: */
1305:
1306: #if DEBUG
1307: if ((pmdebug & (PDB_USER|PDB_ENTER)) == (PDB_USER|PDB_ENTER))
1308: DPRINTF(("Virt 0x%08x was mapped to different address 0x%08x, changing mapping\n",va,((physical_addr_t *) &pa)->bits.page_no * PPC_PGBYTES));
1309: #endif
1310:
1311: /* Take advantage of the fact that pte1 can be
1312: * considered as a pointer to an address in
1313: * the physical page when looking for physentry.
1314: */
1315:
1316: old_pp = pmap_find_physentry(
1317: (vm_offset_t)(pte->pte1.word));
1318:
1319: queue_iterate(&old_pp->phys_link, mp,
1320: struct mapping *, phys_link) {
1321: if (mp->pte == pte)
1322: break;
1323: }
1324:
1325: /* pte entry must have good reverse mapping */
1326: assert(mp != NULL);
1327: assert(mp->pte == pte);
1328: assert(((mp->vm_info.bits.page >> 10) & 0x3f) ==
1329: mp->pte->pte0.bits.page_index);
1330:
1331: /* Wired/not wired is taken care of later on
1332: * in this function. We can remove wired mappings.
1333: */
1334:
1335: /* Do the equivalent of pmap_free_mapping followed
1336: * by a pmap_enter_mapping, recycling the pte and
1337: * the mapping
1338: */
1339:
1340: /* keep track of changed and referenced at old
1341: * address
1342: */
1343: old_pp->pte1.word |= mp->pte->pte1.word;
1344:
1345: queue_remove(&old_pp->phys_link, mp,
1346: struct mapping *, phys_link);
1347:
1348: mp->vm_info.bits.page = (va >> PPC_PGSHIFT);
1349:
1350: assert(mp->pte == pte);
1351:
1352: queue_enter_first(&pp->phys_link, mp,
1353: struct mapping *, phys_link);
1354:
1355:
1356: assert(mp->pmap == pmap);
1357:
1358: /* Set up pte as it would have been done by
1359: * find_or_allocate_pte() + pmap_enter_mapping()
1360: */
1361:
1362: /* Allowable early PTE updates: RPN,R,C,WIMG,PP
1363: */
1364: pte->pte1.word = 0;
1365: pte->pte1.bits.phys_page = pa >> PPC_PGSHIFT;
1366: pte->pte1.bits.wimg = pp->pte1.bits.wimg; /* default */
1367:
1368:
1369: /* Post tlbie updates: VSID,H,API,V
1370: */
1371: pte->pte0.bits.segment_id = (space << 4) | (va >> 28);
1372: pte->pte0.bits.page_index = ((va_abbrev_t *)&va)->page_index;
1373: eieio();
1374:
1375:
1376: } else {
1377: /* The current mapping is the same as the one
1378: * we're being asked to make, find the mapping
1379: * structure that goes along with it.
1380: */
1381: queue_iterate(&pp->phys_link, mp,
1382: struct mapping *, phys_link) {
1383: if (mp->pte == pte)
1384: break;
1385: }
1386: /* mapping struct must exist */
1387: assert(mp != NULL);
1388: assert(mp->pte == pte);
1389:
1390:
1391: #if DEBUG
1392:
1393:
1394: if ((wired && (pmdebug & (PDB_WIRED))) ||
1395: ((pmdebug & (PDB_USER|PDB_ENTER)) == (PDB_USER|PDB_ENTER))) {
1396: DPRINTF(("address already mapped, changing prots or wiring\n"));
1397: if (pte->pte1.bits.protection !=
1398: prot_bits[prot])
1399: DPRINTF(("Changing PROTS\n"));
1400: if (wired != mp->vm_info.bits.wired)
1401: DPRINTF(("changing WIRING\n"));
1402: }
1403: #endif
1404: }
1405: } else {
1406:
1407: #if DEBUG
1408: pmap_enter_invalid_cnt++;
1409: #endif /* DEBUG */
1410:
1411: /* There was no pte match, a new entry was created
1412: * (marked as invalid). We make sure that a new mapping
1413: * structure is allocated as it's partner.
1414: */
1415: mp = MAPPING_NULL;
1416: assert(pte->pte0.word != PTE_EMPTY);
1417: sync(); /* Force updates to complete */
1418: tlbie(va); /* Wipe out this virtual address */
1419: eieio(); /* Enforce ordering of v bit */
1420: tlbsync();
1421: sync();
1422:
1423: pte->pte1.bits.protection = prot_bits[prot];
1424: eieio();
1425: }
1426:
1427: /* Once here, pte contains a valid pointer to a structure
1428: * that we may use to map the virtual address (which may
1429: * already map this (and be valid) or something else (invalid)
1430: * and mp contains either MAPPING_NULL (new mapping) or
1431: * a pointer to the old mapping which may need it's
1432: * privileges modified.
1433: */
1434:
1435: /* set up the protection bits on new mapping
1436: */
1437:
1438:
1439: if (mp == MAPPING_NULL) {
1440: /*
1441: * Mapping for this virtual address doesn't exist.
1442: * Get a mapping structure and, and fill it in,
1443: * updating the pte that we already have, and
1444: * making it valid
1445: */
1446: mp = pmap_enter_mapping(pmap, space, va, pa, pte, prot, pp);
1447: pmap->stats.resident_count++;
1448: was_wired = FALSE;/* indicate that page was never wired */
1449: } else {
1450:
1451: /*
1452: * We are just changing the protection of a current mapping.
1453: */
1454: was_wired = mp->vm_info.bits.wired;
1455:
1456: /*
1457: * This is the pte that came in valid
1458: */
1459: pte->pte1.bits.protection = prot_bits[prot];
1460: eieio();
1461: pte->pte0.bits.valid = TRUE; /* !!! */
1462: sync();
1463: }
1464:
1465: assert(pte->pte0.bits.valid == TRUE);
1466:
1467: /* if wired status has changed, update stats and change bit */
1468: if (was_wired != wired) {
1469: pmap->stats.wired_count += wired ? 1 : -1;
1470: mp->vm_info.bits.wired = wired;
1471: #if DEBUG
1472: if (pmdebug & (PDB_WIRED))
1473: DPRINTF(("changing wired status to : %s\n",
1474: wired ? "TRUE" : "FALSE"));
1475: #endif /* DEBUG */
1476: }
1477:
1478:
1479: /* Belt and braces check to make sure we didn't give a bogus map,
1480: * this map is given once when mapping the kernel
1481: */
1482: assert((pte->pte1.bits.phys_page != 0) ||
1483: (kgdb_kernel_in_pmap == FALSE));
1484:
1485: #if DEBUG
1486:
1487: /* Assert a PTE of type WIMG_IO is not mapped to general RAM.
1488: */
1489: if (pmdebug & PDB_IO &&
1490: pte->pte1.bits.wimg == PTE_WIMG_IO)
1491: assert (((unsigned) pa) >= PCI_BASE)
1492:
1493: /* Assert that there are no other mappings with different
1494: * cachability information, as this can freeze the machine
1495: */
1496: {
1497: struct mapping *mp2;
1498: queue_iterate(&pp->phys_link, mp2,
1499: struct mapping *, phys_link) {
1500: assert(mp2->pte->pte1.bits.wimg ==
1501: pte->pte1.bits.wimg);
1502: }
1503: }
1504:
1505: if (pmdebug & PDB_MASSIVE) {
1506: register struct mapping *mp2;
1507: queue_iterate(&free_mapping, mp2,
1508: struct mapping *, phys_link) {
1509: assert(mp2->phys_link.next != NULL);
1510: }
1511: }
1512: #endif /* DEBUG */
1513: splx(s);
1514: #if DEBUG
1515: if ((pmdebug & (PDB_USER|PDB_ENTER)) == (PDB_USER | PDB_ENTER))
1516: DPRINTF(("leaving pmap_enter\n"));
1517: #endif
1518: }
1519:
1520:
1521:
1522: /*
1523: * Routine: pmap_change_wiring
1524: * Function: Change the wiring attribute for a map/virtual-address
1525: * pair.
1526: * In/out conditions:
1527: * The mapping must already exist in the pmap.
1528: *
1529: * Change the wiring for a given virtual page. This routine currently is
1530: * only used to unwire pages and hence the mapping entry will exist.
1531: */
1532: void
1533: pmap_change_wiring(
1534: register pmap_t pmap,
1535: vm_offset_t va,
1536: boolean_t wired)
1537: {
1538: register struct mapping *mp;
1539: boolean_t waswired;
1540: spl_t s;
1541:
1542: #if DEBUG
1543: if ((pmdebug & (PDB_USER | PDB_WIRED)) == (PDB_USER|PDB_WIRED))
1544: DPRINTF(("(pmap=%x, va=%x, wire=%x)\n",
1545: pmap, va, wired));
1546: #endif
1547: if (pmap == PMAP_NULL)
1548: return;
1549:
1550: s = splhigh();
1551: if ((mp = pmap_find_mapping(pmap->space, va)) == MAPPING_NULL)
1552: panic("pmap_change_wiring: can't find mapping entry");
1553:
1554: waswired = mp->vm_info.bits.wired;
1555: if (wired && !waswired) {
1556: mp->vm_info.bits.wired = TRUE;
1557: pmap->stats.wired_count++;
1558: } else if (!wired && waswired) {
1559: mp->vm_info.bits.wired = FALSE;
1560: pmap->stats.wired_count--;
1561: }
1562: splx(s);
1563: }
1564:
1565:
1566:
1567: /*
1568: * pmap_extract(pmap, va)
1569: * returns the physical address corrsponding to the
1570: * virtual address specified by pmap and va if the
1571: * virtual address is mapped and 0 if it is not.
1572: */
1573: vm_offset_t
1574: pmap_extract(
1575: pmap_t pmap,
1576: vm_offset_t va)
1577: {
1578: pte_t *pte;
1579: spl_t s;
1580:
1581: #if DEBUG
1582: if (pmdebug & PDB_USER)
1583: DPRINTF(("(pmap=%x, va=%x)\n", pmap, va));
1584: #endif
1585:
1586: if (pmap == PMAP_NULL)
1587: {
1588: DPRINTF((": pmap == PMAP_NULL\n"));
1589: return 0;
1590: }
1591:
1592: if (pmap == kernel_pmap) {
1593: extern vm_offset_t virtual_avail;
1594:
1595: if (va < virtual_avail)
1596: return va;
1597: }
1598:
1599: s = splhigh();
1600: pte = find_or_allocate_pte(pmap->space, trunc_page(va), FALSE);
1601: if (pte == NULL)
1602: {
1603: splx(s);
1604: return(0);
1605: }
1606: splx(s);
1607: return trunc_page(pte->pte1.word) | (va & page_mask);
1608: }
1609:
1610:
1611:
1612: /*
1613: * pmap_attributes:
1614: *
1615: * Set/Get special memory attributes
1616: *
1617: */
1618: kern_return_t
1619: pmap_attribute(
1620: pmap_t pmap,
1621: vm_offset_t address,
1622: vm_size_t size,
1623: vm_machine_attribute_t attribute,
1624: vm_machine_attribute_val_t* value)
1625: {
1626: vm_offset_t sva, eva;
1627: vm_offset_t addr;
1628: kern_return_t ret;
1629:
1630: if (attribute != MATTR_CACHE)
1631: return KERN_INVALID_ARGUMENT;
1632:
1633: /* We can't get the caching attribute for more than one page
1634: * at a time
1635: */
1636: if ((*value == MATTR_VAL_GET) &&
1637: (trunc_page(address) != trunc_page(address+size-1)))
1638: return KERN_INVALID_ARGUMENT;
1639:
1640: if (pmap == PMAP_NULL)
1641: return KERN_SUCCESS;
1642:
1643: sva = trunc_page(address);
1644: eva = round_page(address + size);
1645: ret = KERN_SUCCESS;
1646:
1647: simple_lock(&pmap->lock);
1648:
1649: switch (*value) {
1650: case MATTR_VAL_CACHE_FLUSH: /* flush from all caches */
1651: case MATTR_VAL_DCACHE_FLUSH: /* flush from data cache(s) */
1652: case MATTR_VAL_ICACHE_FLUSH: /* flush from instr cache(s) */
1653: sva = trunc_page(sva);
1654: for (; sva < eva; sva += PAGE_SIZE) {
1655: if ((addr = pmap_extract(pmap, sva)) == 0)
1656: continue;
1657: flush_cache(addr, PAGE_SIZE);
1658: }
1659: break;
1660:
1661: case MATTR_VAL_GET: /* return current value */
1662: case MATTR_VAL_OFF: /* turn attribute off */
1663: case MATTR_VAL_ON: /* turn attribute on */
1664: default:
1665: ret = KERN_INVALID_ARGUMENT;
1666: break;
1667: }
1668: simple_unlock(&pmap->lock);
1669:
1670: return ret;
1671: }
1672:
1673:
1674:
1675: /*
1676: * pmap_collect
1677: *
1678: * Garbage collects the physical map system for pages that are no longer used.
1679: */
1680: /* ARGSUSED */
1681: void
1682: pmap_collect(
1683: pmap_t pmap)
1684: {
1685: #if DEBUG
1686: if (pmdebug & PDB_USER)
1687: DPRINTF(("(pmap=%x)\n", pmap));
1688: #endif
1689: }
1690:
1691:
1692:
1693: /*
1694: * Routine: pmap_activate
1695: * Function:
1696: * Binds the given physical map to the given
1697: * processor, and returns a hardware map description.
1698: */
1699: /* ARGSUSED */
1700: void
1701: pmap_activate(
1702: pmap_t pmap,
1703: thread_t th,
1704: int which_cpu)
1705: {
1706: #if DEBUG
1707: if (pmdebug & PDB_USER)
1708: DPRINTF(("(pmap=%x, th=%x, cpu=%x)\n",
1709: pmap, th, which_cpu));
1710: #endif
1711: }
1712:
1713:
1714:
1715: /* ARGSUSED */
1716: void
1717: pmap_deactivate(
1718: pmap_t pmap,
1719: thread_t th,
1720: int which_cpu)
1721: {
1722: #if DEBUG
1723: if (pmdebug & PDB_USER)
1724: DPRINTF(("(pmap=%x, th=%x, cpu=%x)\n",
1725: pmap, th, which_cpu));
1726: #endif
1727: }
1728:
1729:
1730:
1731: #if DEBUG
1732:
1733: /*
1734: * pmap_zero_page
1735: * pmap_copy_page
1736: *
1737: * are implemented in movc.s, these
1738: * are just wrappers to help debugging
1739: */
1740:
1741: extern void pmap_zero_page_assembler(vm_offset_t p);
1742: extern void pmap_copy_page_assembler(vm_offset_t src, vm_offset_t dst);
1743:
1744:
1745:
1746: /*
1747: * pmap_zero_page(pa)
1748: *
1749: * pmap_zero_page zeros the specified (machine independent) page pa.
1750: */
1751: void
1752: pmap_zero_page(
1753: vm_offset_t p)
1754: {
1755:
1756: if ((pmdebug & (PDB_USER|PDB_ZERO)) == (PDB_USER|PDB_ZERO))
1757: DPRINTF(("(pa=%x)\n", p));
1758:
1759: /*
1760: * XXX can these happen?
1761: */
1762: if (pmap_find_physentry(p) == PHYS_NULL)
1763: panic("zero_page: physaddr out of range");
1764:
1765: /* TODO NMGS optimisation - if page has no mappings, set bit in
1766: * physentry to indicate 'needs zeroing', then zero page in
1767: * pmap_enter or pmap_copy_page if bit is set. This keeps the
1768: * cache 'hot'.
1769: */
1770:
1771: assert((p & 0xFFF) == 0);
1772: pmap_zero_page_assembler(p);
1773: }
1774:
1775:
1776:
1777: /*
1778: * pmap_copy_page(src, dst)
1779: *
1780: * pmap_copy_page copies the specified (machine independent)
1781: * page from physical address src to physical address dst.
1782: *
1783: * We need to invalidate the cache for address dst before
1784: * we do the copy. Apparently there won't be any mappings
1785: * to the dst address normally.
1786: */
1787: void
1788: pmap_copy_page(
1789: vm_offset_t src,
1790: vm_offset_t dst)
1791: {
1792:
1793: if ((pmdebug & (PDB_USER|PDB_COPY)) == (PDB_USER|PDB_COPY))
1794: DPRINTF(("(spa=%x, dpa=%x)\n", src, dst));
1795: if (pmdebug & PDB_COPY)
1796: DPRINTF((": phys_copy(%x, %x, %x)\n",
1797: src, dst, PAGE_SIZE));
1798:
1799: assert((src & 0xFFF) == 0);
1800: assert((dst & 0xFFF) == 0);
1801: pmap_copy_page_assembler(src, dst);
1802: }
1803: #endif /* DEBUG */
1804:
1805:
1806:
1807: /*
1808: * pmap_pageable(pmap, s, e, pageable)
1809: * Make the specified pages (by pmap, offset)
1810: * pageable (or not) as requested.
1811: *
1812: * A page which is not pageable may not take
1813: * a fault; therefore, its page table entry
1814: * must remain valid for the duration.
1815: *
1816: * This routine is merely advisory; pmap_enter()
1817: * will specify that these pages are to be wired
1818: * down (or not) as appropriate.
1819: *
1820: * (called from vm/vm_fault.c).
1821: */
1822: /* ARGSUSED */
1823: void
1824: pmap_pageable(
1825: pmap_t pmap,
1826: vm_offset_t start,
1827: vm_offset_t end,
1828: boolean_t pageable)
1829: {
1830: #if DEBUG
1831: if ((pmdebug & (PDB_USER | PDB_WIRED)) == (PDB_USER|PDB_WIRED))
1832: DPRINTF(("(pmap=%x, sva=%x, eva=%x, pageable=%s)\n",
1833: pmap, start, end, pageable ? "TRUE" : "FALSE"));
1834: #endif
1835: }
1836:
1837:
1838:
1839: /*
1840: * pmap_clear_modify(phys)
1841: * clears the hardware modified ("dirty") bit for one
1842: * machine independant page starting at the given
1843: * physical address. phys must be aligned on a machine
1844: * independant page boundary.
1845: */
1846: void
1847: pmap_clear_modify(
1848: vm_offset_t pa)
1849: {
1850: register struct phys_entry *pp;
1851: register struct mapping *mp;
1852: pte_t *pte;
1853: register vm_offset_t offset;
1854: spl_t s;
1855: boolean_t was_valid;
1856:
1857: #if DEBUG
1858: if (pmdebug & PDB_USER)
1859: DPRINTF(("(pa=%x)\n", pa));
1860: #endif
1861:
1862: pp = pmap_find_physentry(pa);
1863: if (pp == PHYS_NULL)
1864: return;
1865:
1866: s = splhigh();
1867: /*
1868: * invalidate any pte entries and remove them from tlb
1869: * TODO might it be faster to wipe all tlb entries outside loop? NO, rav.
1870: */
1871:
1872: /* Remove any reference to modified to the physical page */
1873: pp->pte1.bits.changed = FALSE;
1874:
1875: /* mark PTE entries as having no modifies, and flush tlbs */
1876: queue_iterate(&pp->phys_link, mp,
1877: struct mapping *, phys_link) {
1878: pte = mp->pte;
1879: offset = mp->vm_info.bits.page << PPC_PGSHIFT;
1880:
1881: was_valid = FALSE;
1882: if (pte->pte0.bits.valid == TRUE) {
1883: /* Perform a general case PTE update designed to work
1884: ** in SMP configurations. TODO - locks and tlbsync
1885: */
1886: pte->pte0.bits.valid = FALSE; /* Invalidate PTE */
1887: was_valid = TRUE;
1888: }
1889: sync(); /* Force updates to complete */
1890: tlbie(offset); /* Wipe out this virtual address */
1891: eieio(); /* Enforce ordering of v bit */
1892: tlbsync();
1893: sync();
1894:
1895: /* Allowable early PTE updates: RPN,R,C,WIMG,PP
1896: */
1897: pte->pte1.bits.changed = FALSE;
1898: eieio();
1899:
1900: /* Post tlbie updates: VSID,H,API,V
1901: */
1902: if (was_valid == TRUE)
1903: {
1904: pte->pte0.bits.valid = TRUE; /* Validate pte entry */
1905: }
1906: sync();
1907: }
1908:
1909: #if DEBUG
1910: /* Assert that there are no other mappings with different
1911: * cachability information, as this can freeze the machine
1912: */
1913: {
1914: struct mapping *mp2;
1915: queue_iterate(&pp->phys_link, mp2,
1916: struct mapping *, phys_link) {
1917: assert(mp2->pte->pte1.bits.wimg ==
1918: pte->pte1.bits.wimg);
1919: }
1920: }
1921: #endif /* DEBUG */
1922:
1923: splx(s);
1924: }
1925:
1926:
1927:
1928: /*
1929: * pmap_is_modified(phys)
1930: * returns TRUE if the given physical page has been modified
1931: * since the last call to pmap_clear_modify().
1932: */
1933: boolean_t
1934: pmap_is_modified(
1935: vm_offset_t pa)
1936: {
1937: struct phys_entry *pp;
1938: struct mapping *mp;
1939: spl_t s;
1940:
1941: #if DEBUG
1942: if (pmdebug & PDB_USER)
1943: DPRINTF(("(pa=%x)\n", pa));
1944: #endif
1945: pp = pmap_find_physentry(pa);
1946: if (pp == PHYS_NULL)
1947: return(FALSE);
1948:
1949: /* Check to see if we've already noted this as modified */
1950: if (pp->pte1.bits.changed)
1951: return(TRUE);
1952:
1953: s = splhigh();
1954: /* Make sure all TLB -> PTE updates have completed.
1955: */
1956: sync();
1957:
1958: queue_iterate(&pp->phys_link, mp,
1959: struct mapping *, phys_link) {
1960:
1961: /* Find the first changed page mapping but
1962: do not include the phys page mapping.
1963: */
1964: if (!mp->vm_info.bits.phys &&
1965: mp->pte->pte1.bits.changed)
1966: {
1967: pp->pte1.bits.changed = TRUE;
1968: splx(s);
1969: return TRUE;
1970: }
1971: }
1972:
1973: splx(s);
1974: return(FALSE);
1975: }
1976:
1977:
1978:
1979: /*
1980: * pmap_clear_reference(phys)
1981: * clears the hardware referenced bit in the given machine
1982: * independant physical page.
1983: *
1984: */
1985: void
1986: pmap_clear_reference(
1987: vm_offset_t pa)
1988: {
1989: register struct phys_entry *pp;
1990: register struct mapping *mp;
1991: spl_t s;
1992: boolean_t was_valid;
1993:
1994: #if DEBUG
1995: if (pmdebug & PDB_USER)
1996: DPRINTF(("(pa=%x)\n", pa));
1997: #endif
1998:
1999: pp = pmap_find_physentry(pa);
2000: if (pp == PHYS_NULL)
2001: return;
2002:
2003: s = splhigh();
2004: /* Run through all the virtual mappings to clear the reference
2005: bit in each PTE. Because the reference bit does not have to be
2006: maintained exactly, we can avoid issuing syncs but once.
2007: */
2008: queue_iterate(&pp->phys_link, mp,
2009: struct mapping *, phys_link) {
2010:
2011: was_valid = FALSE;
2012: if (mp->pte->pte0.bits.valid == TRUE) {
2013: mp->pte->pte0.bits.valid = FALSE;
2014: was_valid = TRUE;
2015: }
2016: /*
2017: ** Make sure there is no entry in the TBL, it is assumed
2018: ** that if there is an entry that the page has been referenced
2019: */
2020: sync();
2021: tlbie(mp->vm_info.bits.page << PPC_PGSHIFT);
2022: eieio();
2023: tlbsync();
2024: sync();
2025:
2026: /*
2027: ** Gotta drop both bits or the chip gets hosed!
2028: ** See section 7.5.3
2029: **
2030: ** Thanks Rene!
2031: */
2032: pp->pte1.bits.changed |=
2033: mp->pte->pte1.bits.changed;
2034: mp->pte->pte1.bits.changed = FALSE;
2035: mp->pte->pte1.bits.referenced = FALSE;
2036: eieio();
2037: if (was_valid == TRUE)
2038: {
2039: mp->pte->pte0.bits.valid = TRUE;
2040: }
2041: sync();
2042: }
2043:
2044: /* Mark the physical entry shadow copy as non-referenced too.
2045: */
2046: pp->pte1.bits.referenced = FALSE;
2047:
2048: splx(s);
2049: }
2050:
2051:
2052:
2053: /*
2054: * pmap_is_referenced(phys)
2055: * returns TRUE if the given physical page has been referenced
2056: * since the last call to pmap_clear_reference().
2057: */
2058: boolean_t
2059: pmap_is_referenced(
2060: vm_offset_t pa)
2061: {
2062: struct phys_entry *pp;
2063: register struct mapping *mp;
2064: spl_t s;
2065:
2066: #if DEBUG
2067: if (pmdebug & PDB_USER)
2068: DPRINTF(("(pa=%x)\n", pa));
2069: #endif
2070: pp = pmap_find_physentry(pa);
2071: if (pp == PHYS_NULL)
2072: return(FALSE);
2073:
2074: if (pp->pte1.bits.referenced)
2075: return (TRUE);
2076:
2077:
2078: s = splhigh();
2079: /* Make sure all TLB -> PTE updates have completed.
2080: */
2081: sync();
2082:
2083: /* Check all the mappings to see if any one of them
2084: have recorded a reference to this physical page.
2085: */
2086: queue_iterate(&pp->phys_link, mp,
2087: struct mapping *, phys_link) {
2088:
2089: /* Find the first referenced page mapping but
2090: do not include the phys page mapping.
2091: */
2092: if (!mp->vm_info.bits.phys &&
2093: mp->pte->pte1.bits.referenced)
2094: {
2095: pp->pte1.bits.referenced = TRUE;
2096: splx(s);
2097: return (TRUE);
2098: }
2099: }
2100: splx(s);
2101: return(FALSE);
2102: }
2103:
2104:
2105:
2106: /*
2107: * Auxilliary routines for manipulating mappings
2108: */
2109:
2110: static struct mapping *
2111: pmap_enter_mapping(
2112: pmap_t pmap,
2113: space_t space,
2114: vm_offset_t va,
2115: vm_offset_t pa,
2116: pte_t *pte,
2117: unsigned prot,
2118: struct phys_entry *pp)
2119: {
2120: register struct mapping *mp;
2121: spl_t s;
2122:
2123: #if DEBUG
2124: if (pmdebug & PDB_MAPPING)
2125: DPRINTF(("(pmap=%x, sp=%x, off=%x, &pte=%x, prot=%x)",
2126: pmap, space, va, pte, prot));
2127: #endif /* DEBUG */
2128:
2129: s = splhigh();
2130: simple_lock(&free_mapping_lock);
2131: if (queue_empty(&free_mapping))
2132: pmap_reap_mappings();
2133: queue_remove_first(&free_mapping, mp, struct mapping *, phys_link);
2134:
2135: simple_unlock(&free_mapping_lock);
2136: assert(mp != MAPPING_NULL);
2137:
2138: mp->pmap = pmap;
2139: mp->vm_info.bits.phys = FALSE;
2140: mp->vm_info.bits.wired = FALSE;
2141: mp->vm_info.bits.page = (va >> PPC_PGSHIFT);
2142: mp->pte = pte;
2143:
2144: /* Set up pte -
2145: * pte0 already contains everything except the valid bit.
2146: * pte1 already contains the protection information.
2147: */
2148:
2149: assert(pte->pte0.word != PTE_EMPTY);
2150:
2151: assert(pte->pte0.bits.valid == FALSE);
2152:
2153: sync();
2154: tlbie(mp->vm_info.bits.page << PPC_PGSHIFT);
2155: eieio();
2156: tlbsync();
2157: sync();
2158:
2159: pte->pte1.bits.phys_page = pa >> PPC_PGSHIFT;
2160: pte->pte1.bits.wimg = pp->pte1.bits.wimg; /* Set default cachability*/
2161:
2162: /* Make sure those pte1 writes are ordered ahead of
2163: of the v bit.
2164: */
2165: eieio();
2166:
2167:
2168: pte->pte0.bits.valid = TRUE; /* Validate pte entry */
2169: sync();
2170:
2171: queue_enter_first(&pp->phys_link, mp, struct mapping *, phys_link);
2172:
2173: #if DEBUG
2174: /* Assert a PTE of type WIMG_IO is not mapped to general RAM.
2175: */
2176: if (pmdebug & PDB_IO &&
2177: pte->pte1.bits.wimg == PTE_WIMG_IO)
2178: assert (((unsigned) pa) >= PCI_BASE)
2179:
2180: /* Assert that there are no other mappings with different
2181: * cachability information, as this can freeze the machine
2182: */
2183: {
2184: struct mapping *mp2;
2185: queue_iterate(&pp->phys_link, mp2,
2186: struct mapping *, phys_link) {
2187: assert(mp2->pte->pte1.bits.wimg ==
2188: pte->pte1.bits.wimg);
2189: }
2190: }
2191: #endif /* DEBUG */
2192: #if DEBUG
2193: if (pmdebug & PDB_MAPPING)
2194: DPRINTF((" -> %x\n"));
2195: #endif
2196: #if DEBUG
2197: if (pmdebug & PDB_MASSIVE) {
2198: register struct mapping *mp2;
2199: queue_iterate(&free_mapping, mp2,
2200: struct mapping *, phys_link) {
2201: assert(mp2->phys_link.next != NULL);
2202: }
2203: }
2204: #endif /* DEBUG */
2205: splx(s);
2206: return(mp);
2207: }
2208:
2209:
2210:
2211: /*
2212: * pmap_find_mapping(space, offset)
2213: * Lookup the virtual address <space,offset> in the mapping "table".
2214: * Returns a pointer to the mapping or NULL if none.
2215: *
2216: * XXX what about MP locking?
2217: */
2218: static struct mapping *
2219: pmap_find_mapping(
2220: register space_t space,
2221: vm_offset_t offset)
2222: {
2223: register struct mapping *mp;
2224: register struct phys_entry *pp;
2225: register pte_t *pte;
2226: spl_t s;
2227:
2228: #if DEBUG
2229: if (pmdebug & PDB_MAPPING)
2230: DPRINTF(("(sp=%x, off=%x) -> ", space, offset));
2231: #endif
2232: offset = trunc_page(offset);
2233:
2234: /* Locate the pte but don't allocate a new one if not found */
2235: pte = find_or_allocate_pte(space, offset, FALSE);
2236:
2237: if (pte == NULL) {
2238: #if DEBUG
2239: if (pmdebug & PDB_MAPPING)
2240: DPRINTF(("MAPPING_NULL\n"));
2241: #endif /* DEBUG */
2242: return MAPPING_NULL;
2243: }
2244:
2245: s = splhigh();
2246: /* Take advantage of the fact that pte1 can be
2247: * considered as a pointer to an address in
2248: * the physical page when looking for physentry.
2249: */
2250:
2251: pp = pmap_find_physentry((vm_offset_t)(pte->pte1.word));
2252:
2253: queue_iterate(&pp->phys_link, mp,
2254: struct mapping *, phys_link) {
2255: if (mp->pte == pte)
2256: break;
2257: }
2258: assert(mp != MAPPING_NULL); /* There must be mapping for a pte */
2259: assert(mp->pte == pte);
2260: assert(((mp->vm_info.bits.page >> 10) & 0x3f) ==
2261: mp->pte->pte0.bits.page_index);
2262:
2263: #if DEBUG
2264: if (pmdebug & PDB_MAPPING)
2265: DPRINTF(("%x\n", mp));
2266: #endif
2267: splx(s);
2268: return(mp);
2269: }
2270:
2271:
2272:
2273: static void
2274: pmap_free_mapping(
2275: register struct mapping *mp)
2276: {
2277: register vm_offset_t offset;
2278: struct phys_entry *pp;
2279: spl_t s;
2280:
2281: #if DEBUG
2282: if (pmdebug & PDB_MAPPING)
2283: DPRINTF(("(mp=%x), pte at 0x%x (0x%08x,0x%08x)\n",
2284: mp, mp->pte, mp->pte->pte0.word,mp->pte->pte1.word));
2285: #endif
2286:
2287: s = splhigh();
2288:
2289: offset = mp->vm_info.bits.page << PPC_PGSHIFT;
2290:
2291: pp = pmap_find_physentry((vm_offset_t)mp->pte->pte1.word);
2292: assert(pp != PHYS_NULL);
2293:
2294: /* Perform a general case PTE update designed to work
2295: in SMP configurations. TODO - locks and tlbsync
2296: */
2297: mp->pte->pte0.bits.valid = FALSE; /* Invalidate PTE */
2298: sync(); /* Force updates to complete */
2299: tlbie(offset); /* Wipe out this virtual address */
2300: eieio();
2301: tlbsync();
2302: sync(); /* force completion */
2303:
2304: /* Reflect back the modify and reference bits for the pager */
2305: if (!mp->vm_info.bits.phys)
2306: pp->pte1.word |= mp->pte->pte1.word;
2307:
2308: /*
2309: * Now remove from the PTOV/VTOP lists and return to the free list.
2310: * Note that we must block interrupts since they might cause TLB
2311: * misses which would search (potentially inconsistant) lists.
2312: */
2313:
2314:
2315: /* for now, just remove the mapping */
2316: mp->pte->pte0.word = PTE_EMPTY; /* Remove pte (v->p) lookup */
2317: #if DEBUG
2318: mp->pte->pte1.word = 0;
2319: #endif
2320:
2321: queue_remove(&pp->phys_link, mp, struct mapping *, phys_link);
2322:
2323: simple_lock(&free_mapping_lock);
2324: queue_enter(&free_mapping, mp, struct mapping *, phys_link);
2325: simple_unlock(&free_mapping_lock);
2326: #if DEBUG
2327: if (pmdebug & PDB_MASSIVE) {
2328: register struct mapping *mp2;
2329: queue_iterate(&free_mapping, mp2,
2330: struct mapping *, phys_link) {
2331: assert(mp2->phys_link.next != NULL);
2332: }
2333: }
2334: #endif /* DEBUG */
2335: splx(s);
2336: }
2337:
2338:
2339:
2340: /*
2341: * Deal with a hash-table pteg overflow. pmap_pteg_overflow is upcalled from
2342: * find_or_allocate_pte(), and assumes knowledge of the pteg hashing
2343: * structure
2344: */
2345:
2346: static int pteg_overflow_counter=0;
2347:
2348: static pte_t *pteg_pte_exchange(pte_t *pteg, pte0_t match);
2349: pte_t *
2350: pmap_pteg_overflow(
2351: pte_t *primary_hash,
2352: pte0_t primary_match,
2353: pte_t *secondary_hash,
2354: pte0_t secondary_match)
2355: {
2356: pte_t *pte;
2357: #if DEBUG
2358: int i;
2359: if (pmdebug & PDB_PTEG) {
2360: kprintf("pteg overflow for ptegs 0x%08x and 0x%08x\n",
2361: primary_hash,secondary_hash);
2362: kprintf("PRIMARY\t\t\t\t\tSECONDARY\n");
2363: for (i=0; i<8; i++) {
2364: kprintf("0x%08x : (0x%08x,0x%08x)\t"
2365: "0x%08x : (0x%08x,0x%08x)\n",
2366: &primary_hash[i],
2367: primary_hash[i].pte0.word,
2368: primary_hash[i].pte1.word,
2369: &secondary_hash[i],
2370: secondary_hash[i].pte0.word,
2371: secondary_hash[i].pte1.word);
2372: assert(primary_hash[i].pte0.word != PTE_EMPTY);
2373: assert(secondary_hash[i].pte0.word != PTE_EMPTY);
2374: }
2375: }
2376: #endif
2377: /* First try to replace an entry in the primary PTEG */
2378: pte = pteg_pte_exchange(primary_hash, primary_match);
2379: if (pte != PTE_NULL)
2380: return pte;
2381: pte = pteg_pte_exchange(secondary_hash, secondary_match);
2382: if (pte != PTE_NULL)
2383: return pte;
2384:
2385: panic("both ptegs are completely wired down\n");
2386: return PTE_NULL;
2387: }
2388:
2389:
2390:
2391: /*
2392: * Used by the pmap_pteg_overflow function to scan through a pteg
2393: */
2394: static pte_t *
2395: pteg_pte_exchange(
2396: pte_t *pteg,
2397: pte0_t match)
2398: {
2399: /* Try and replace an entry in a pteg */
2400:
2401: int i;
2402: register struct phys_entry *pp;
2403: register struct mapping *mp;
2404: pte_t *pte;
2405:
2406: /* TODO NMGS pteg overflow algorithm needs working on!
2407: * currently we just loop around the PTEGs rejecting
2408: * the first available entry.
2409: */
2410:
2411: for (i=0; i < 8; i++) {
2412:
2413: pte = &pteg[pteg_overflow_counter];
2414: pteg_overflow_counter = (pteg_overflow_counter+1) % 8;
2415:
2416: /* all mappings must be valid otherwise we wouldn't be here */
2417: assert(pte->pte0.bits.valid == TRUE);
2418:
2419: /* Take advantage of the fact that pte1 can be
2420: * considered as a pointer to an address in
2421: * the physical page when looking for physentry.
2422: */
2423: pp = pmap_find_physentry(pte->pte1.word);
2424:
2425: /* pte entry must have reverse mapping, otherwise we
2426: * cannot remove it (it was entered by pmap_map_bd)
2427: */
2428: if (pp == PHYS_NULL)
2429: continue;
2430:
2431: queue_iterate(&pp->phys_link, mp,
2432: struct mapping *, phys_link) {
2433: if (mp->pte == pte)
2434: break;
2435: }
2436: assert(mp != NULL);
2437: assert(mp->pte == pte);
2438:
2439: /* if this entry isn't wired, isn't in the kernel space,
2440: * and it doesn't have any special cachability attributes
2441: * we can remove mapping without losing any information.
2442: * XXX kernel space mustn't be touched as we may be doing
2443: * XXX an I/O on a non-wired page, and we must not take
2444: * XXX a page fault in an interrupt handler.
2445: */
2446: /* TODO better implementation for cache info? */
2447: if (!mp->vm_info.bits.wired &&
2448: mp->pmap != kernel_pmap &&
2449: mp->pte->pte1.bits.wimg == PTE_WIMG_DEFAULT) {
2450: #if DEBUG
2451: if (pmdebug & PDB_PTEG) {
2452: kprintf("entry chosen at 0x%08x in %s PTEG\n",
2453: pte,
2454: pte->pte0.bits.hash_id ?
2455: "SECONDARY" : "PRIMARY");
2456: kprintf("throwing away mapping from sp 0x%x, "
2457: "virtual 0x%08x to physical 0x%08x\n",
2458: mp->pmap->space,
2459: mp->vm_info.bits.page << PPC_PGSHIFT,
2460: trunc_page(mp->pte->pte1.word));
2461: kprintf("pteg_overflow_counter=%d\n",
2462: pteg_overflow_counter);
2463: kprintf("pte0.vsid=0x%08x\n",
2464: pte->pte0.bits.segment_id);
2465: }
2466: #endif /* DEBUG */
2467: mp->pmap->stats.resident_count--;
2468:
2469: /* release mapping structure and PTE, keeping
2470: * track of changed and referenced bits
2471: */
2472: pmap_free_mapping(mp);
2473:
2474: /* Replace the pte entry by the new one */
2475:
2476: match.bits.valid = FALSE;
2477: sync();
2478: pte->pte0 = match;
2479: sync();
2480:
2481: return pte;
2482: }
2483: }
2484: return PTE_NULL;
2485: }
2486:
2487:
2488:
2489: /*
2490: * Collect un-wired mappings. How best to do this??
2491: */
2492: static void
2493: pmap_reap_mappings(void)
2494: {
2495: #if DEBUG
2496: if (pmdebug & PDB_MAPPING)
2497: DPRINTF(("pmap_reap_mappings()\n"));
2498: #endif
2499:
2500: panic("out of mapping structs");
2501: }
2502:
2503:
2504: /*
2505: * kvtophys(addr)
2506: *
2507: * Convert a kernel virtual address to a physical address
2508: */
2509: vm_offset_t
2510: kvtophys(
2511: vm_offset_t va)
2512: {
2513: pte_t *pte;
2514: extern vm_offset_t virtual_avail;
2515:
2516: if (va < virtual_avail)
2517: return va;
2518:
2519: pte = find_or_allocate_pte(PPC_SID_KERNEL, trunc_page(va), FALSE);
2520: if (pte == NULL)
2521: return(0);
2522: return trunc_page(pte->pte1.word) | (va & page_mask);
2523: }
2524:
2525:
2526:
2527: /*
2528: * pmap_remove_all - Remove translations by physical address.
2529: *
2530: * This routine walks the pv_entry chain for the given va, and
2531: * removes all translations. It records modify bits.
2532: *
2533: * for 2.5vm <--> 3.0pmap this mapped to pmap_page_protect()
2534: */
2535: void
2536: pmap_remove_all(
2537: vm_offset_t phys)
2538: {
2539: pmap_page_protect(phys, VM_PROT_NONE);
2540: }
2541:
2542:
2543:
2544: /*
2545: * pmap_copy_on_write - Ready region for copy-on-write handling.
2546: *
2547: * This routine removes write privleges from all physical maps
2548: * for a given physical page.
2549: *
2550: * for 2.5vm <--> 3.0pmap this mapped to pmap_page_protect()
2551: *
2552: */
2553: void
2554: pmap_copy_on_write(
2555: vm_offset_t phys)
2556: {
2557: pmap_page_protect(phys, VM_PROT_READ);
2558: }
2559:
2560:
2561:
2562: /*
2563: * pmap_move_page - Move pages from one kernel vaddr to another.
2564: *
2565: * Parameters:
2566: * from - Original kernel va (Mach. indep. page boundary)
2567: * to - New kernel va (Mach. indep. page boundary)
2568: * size - Bytes to move. (Mach. indep. pages)
2569: *
2570: * Returns:
2571: * Nothing.
2572: */
2573: static void
2574: pmap_move_page(
2575: unsigned long from,
2576: unsigned long to,
2577: vm_size_t size)
2578: {
2579: spl_t s;
2580: pte_t *pte;
2581: struct phys_entry *pp;
2582: struct mapping *mp;
2583: vm_prot_t prot;
2584: boolean_t wired;
2585: int ppn;
2586:
2587: s = splhigh();
2588: if ((size & page_mask) != 0) {
2589: panic("pmap_move_page: partial mach indep page");
2590: }
2591: for (; size != (unsigned) 0; size -= PAGE_SIZE, from += PAGE_SIZE, to += PAGE_SIZE) {
2592: if ((pte = find_or_allocate_pte(kernel_pmap->space, trunc_page(from), FALSE)) == PTE_NULL) {
2593: panic("pmap_move_page: from not mapped");
2594: }
2595: /*
2596: * Make sure the damn thing is valid.
2597: */
2598: if (pte->pte0.bits.valid == FALSE) {
2599: panic("pmap_move_page: invalid pte!");
2600: }
2601: switch (pte->pte1.bits.protection) {
2602: case 3:
2603: prot = VM_PROT_READ;
2604: break;
2605: default:
2606: prot = VM_PROT_READ|VM_PROT_WRITE;
2607: break;
2608: }
2609:
2610: ppn = pte->pte1.bits.phys_page;
2611: pp = pmap_find_physentry((vm_offset_t)(pte->pte1.word));
2612: queue_iterate(&pp->phys_link, mp,
2613: struct mapping *, phys_link) {
2614: if (mp->pte == pte)
2615: break;
2616: }
2617: assert(mp != MAPPING_NULL);
2618: assert(mp->pte == pte);
2619: assert(((mp->vm_info.bits.page >> 10) & 0x3f) ==
2620: mp->pte->pte0.bits.page_index);
2621: wired = mp->vm_info.bits.wired;
2622:
2623: /*
2624: * Remove old mapping first (avoid aliasing)
2625: */
2626: pmap_remove(kernel_pmap, from, from + PAGE_SIZE);
2627: pmap_enter(kernel_pmap, to, PMAP_PTOB(ppn), prot, wired);
2628: }
2629: splx(s);
2630: }
2631:
2632:
2633:
2634: /*
2635: * Move pages from one kernel virtual address to another.
2636: * Both addresses are assumed to reside in the Sysmap,
2637: * and size must be a multiple of the page size.
2638: */
2639: void
2640: pagemove(
2641: register caddr_t from,
2642: register caddr_t to,
2643: int size)
2644: {
2645: pmap_move_page((unsigned long)from, (unsigned long)to, (vm_size_t)size);
2646: }
2647:
2648:
2649:
2650: #if DEBUG
2651: /* This function is included to test compiler functionality, it does
2652: * a simple slide through the bitfields of a pte to check
2653: * minimally correct bitfield behaviour. We need bitfields to work!
2654: */
2655: #define TEST(PTE0,PTE1) \
2656: if ((pte.pte0.word != (unsigned int)PTE0) || \
2657: (pte.pte1.word != (unsigned int)PTE1)) { \
2658: DPRINTF(("BITFIELD TEST FAILED AT LINE %d\n",__LINE__)); \
2659: DPRINTF(("EXPECTING 0x%08x and 0x%08x\n", \
2660: (unsigned int)PTE0,(unsigned int)PTE1)); \
2661: DPRINTF(("GOT 0x%08x and 0x%08x\n", \
2662: pte.pte0.word,pte.pte1.word)); \
2663: return 1; \
2664: }
2665:
2666: extern int pmap_test_bitfields(void); /* Prototyped also in go.c */
2667: int pmap_test_bitfields(void)
2668: {
2669: pte_t pte;
2670: pte.pte0.word = 0;
2671: pte.pte1.word = 0;
2672:
2673: pte.pte0.bits.segment_id = 0x103; TEST(0x103 << 7, 0);
2674: pte.pte0.bits.valid = 1;
2675: TEST((unsigned int)(0x80000000U| 0x103<<7), 0);
2676: pte.pte0.bits.hash_id = 1;
2677: TEST((unsigned int)(0x80000000U | 0x103 << 7 | 1<<6), 0);
2678: pte.pte0.bits.page_index = 3;
2679: TEST((unsigned int)(0x80000000U|0x103<<7|1<<6|3), 0);
2680:
2681: pte.pte0.bits.segment_id = 0;
2682: TEST((unsigned int)(0x80000000U|1<<6|3), 0);
2683: pte.pte0.bits.page_index = 0;
2684: TEST((unsigned int)(0x80000000U|1<<6), 0);
2685: pte.pte0.bits.valid = 0;
2686: TEST(1<<6, 0);
2687:
2688: pte.pte1.bits.referenced = 1; TEST(1<<6, 1<<8);
2689: pte.pte1.bits.protection = 3; TEST(1<<6, (unsigned int)(1<<8 | 3));
2690: pte.pte1.bits.changed = 1; TEST(1<<6,(unsigned int)(1<<8|1<<7|3));
2691: pte.pte1.bits.phys_page = 0xfffff;
2692: TEST(1<<6,(unsigned int)(0xfffff000U|1<<8|1<<7|3));
2693:
2694: pte.pte1.bits.changed = 0;
2695: TEST(1<<6,(unsigned int)(0xfffff000U|1<<8|3));
2696:
2697: return 0;
2698: }
2699: #endif /* DEBUG */
2700:
2701:
2702:
2703: void
2704: pmap_enter_cache_spec(
2705: pmap_t pmap,
2706: vm_offset_t va,
2707: vm_offset_t pa,
2708: vm_prot_t prot,
2709: boolean_t wired,
2710: cache_spec_t caching
2711: )
2712: {
2713: if (pmap == PMAP_NULL)
2714: return;
2715:
2716: pmap_enter(pmap, va, pa, prot, wired);
2717:
2718: }
2719:
2720:
2721:
2722: void
2723: pmap_update( void )
2724: {
2725: #if DEBUG
2726: if (pmdebug & PDB_USER)
2727: DPRINTF(("()\n"));
2728: #endif
2729: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.