|
|
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: * Copyright (c) 1992 NeXT Computer, Inc.
27: *
28: * Intel386 Family: Hardware page mapping.
29: *
30: * HISTORY
31: *
32: * 9 April 1992 ? at NeXT
33: * Created.
34: */
35:
36: #import <cpus.h>
37:
38: #import <mach/mach_types.h>
39:
40: #import <vm/vm_kern.h>
41: #import <vm/vm_page.h>
42:
43: #import <machdep/i386/pmap_private.h>
44: #import <machdep/i386/pmap_inline.h>
45: #import <machdep/i386/cpu_inline.h>
46:
47: /*
48: * Setup structures to map from mach vm_prot_t
49: * to machine protections.
50: */
51: unsigned int user_prot_codes[8];
52: unsigned int kernel_prot_codes[8];
53: #define kernel_pmap_prot(x) (kernel_prot_codes[(x)])
54:
55: static
56: void
57: pte_prot_init(
58: void
59: )
60: {
61: unsigned int *kp, *up;
62: int prot;
63:
64: kp = kernel_prot_codes;
65: up = user_prot_codes;
66: for (prot = 0; prot < 8; prot++) {
67: switch ((vm_prot_t)prot) {
68: case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE:
69: *kp++ = 0;
70: *up++ = 0;
71: break;
72: case VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE:
73: case VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE:
74: case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE:
75: *kp++ = PT_PROT_KR;
76: *up++ = PT_PROT_UR;
77: break;
78: case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE:
79: case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE:
80: case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE:
81: case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
82: *kp++ = PT_PROT_KRW;
83: *up++ = PT_PROT_URW;
84: break;
85: }
86: }
87: }
88:
89: /*
90: * Given a map and a machine independent protection code,
91: * set the protection code in the given pte
92: */
93: static inline
94: void
95: pte_prot(
96: pmap_t pmap,
97: vm_prot_t prot,
98: int valid, /* valid bit for pte */
99: pt_entry_t * pte /* IN/OUT */
100: )
101: {
102: if (pmap == kernel_pmap)
103: pte->prot = kernel_prot_codes[prot];
104: else
105: pte->prot = user_prot_codes[prot];
106:
107: pte->valid = valid;
108: }
109:
110: /*
111: * Return a ptr to the page
112: * table entry at the indicated
113: * offset in the pmap. Return
114: * PT_ENTRY_NULL if the page table
115: * does not exist.
116: */
117: inline
118: pt_entry_t *
119: pmap_pt_entry(
120: pmap_t pmap,
121: vm_offset_t va
122: )
123: {
124: pd_entry_t * pde;
125:
126: pde = pd_to_pd_entry(pmap->root, va);
127:
128: if (!pde->valid)
129: return (PT_ENTRY_NULL);
130:
131: return (pd_entry_to_pt_entry(pde, va));
132: }
133:
134: /*
135: * Return a ptr to the page
136: * directory entry at the indicated
137: * offset in the pmap.
138: */
139: inline
140: pd_entry_t *
141: pmap_pd_entry(
142: pmap_t pmap,
143: vm_offset_t va
144: )
145: {
146: return (pd_to_pd_entry(pmap->root, va));
147: }
148:
149: /*
150: * Return the physical address
151: * corresponding to the indicated
152: * offset in the pmap. Only used
153: * internally since no locking is
154: * done.
155: */
156: static inline
157: unsigned int
158: pmap_phys(
159: pmap_t pmap,
160: vm_offset_t va
161: )
162: {
163: pt_entry_t *pte;
164:
165: pte = pmap_pt_entry(pmap, va);
166: if (pte == PT_ENTRY_NULL || !pte->valid)
167: return (0);
168:
169: return (pfn_to_phys(pte->pfn) + page_offset(va));
170: }
171:
172: static inline
173: void
174: pmap_update_tlbs(
175: pmap_t pmap,
176: vm_offset_t start,
177: vm_offset_t end
178: )
179: {
180: if (pmap == kernel_pmap || pmap->cpus_using) {
181: tlb_stat.total++;
182: if (end - start > PAGE_SIZE)
183: flush_tlb();
184: else {
185: for (; start < end; start += I386_PGBYTES)
186: invlpg(start, pmap == kernel_pmap);
187:
188: tlb_stat.single++;
189: }
190: }
191: }
192:
193: /*
194: * Allocate a new page table
195: * in the kernel pmap at the
196: * given offset when one does
197: * not already exist.
198: */
199: static
200: void
201: pmap_kernel_pt_alloc(
202: vm_offset_t addr
203: )
204: {
205: pd_entry_t template, *pde;
206: vm_offset_t pt;
207: unsigned int phys;
208: int i;
209:
210: pde = pmap_pd_entry(kernel_pmap, trunc_section(addr));
211: if (pde->valid)
212: panic("pmap_kernel_pt_alloc");
213:
214: if (!pmap_initialized) {
215: pt = alloc_pages(PAGE_SIZE);
216: if (!pt)
217: panic("pmap_kernel_pt_alloc 2");
218:
219: bzero(pt, PAGE_SIZE);
220:
221: phys = pt - VM_MIN_KERNEL_ADDRESS;
222: }
223: else {
224: if (kmem_alloc_wired(kernel_map, &pt, PAGE_SIZE) != KERN_SUCCESS)
225: panic("pmap_kernel_pt_alloc 3");
226:
227: phys = pmap_phys(kernel_pmap, pt);
228: }
229:
230: template = (pd_entry_t) { 0 };
231: template.valid = 1;
232: template.prot = PT_PROT_KRW;
233: template.pfn = phys_to_pfn(phys);
234:
235: for (i = ptes_per_vm_page; i-- > 0; pde++) {
236: *pde = template;
237: template.pfn++;
238: }
239: }
240:
241: /*
242: * Map memory at initialization. The physical addresses being
243: * mapped are not managed and are never unmapped.
244: */
245: vm_offset_t
246: pmap_map(
247: vm_offset_t virt,
248: vm_offset_t start,
249: vm_offset_t end,
250: vm_prot_t prot
251: )
252: {
253: pt_entry_t template, *pte;
254:
255: template = (pt_entry_t) { 0 };
256:
257: if (prot != VM_PROT_NONE) {
258: template.valid = 1;
259: template.prot = kernel_pmap_prot(prot);
260: template.pfn = phys_to_pfn(start);
261: }
262:
263: while (start < end) {
264: pte = pmap_pt_entry(kernel_pmap, virt);
265: if (pte == PT_ENTRY_NULL) {
266: pmap_kernel_pt_alloc(virt);
267: pte = pmap_pt_entry(kernel_pmap, virt);
268: }
269:
270: /*
271: * Is this necessary ??
272: */
273: if ( start >= (640 * 1024) &&
274: start < (1024 * 1024))
275: template.cachewrt = 1;
276: else
277: template.cachewrt = 0;
278:
279: *pte = template;
280: if (prot != VM_PROT_NONE)
281: template.pfn++;
282:
283: virt += I386_PGBYTES;
284: start += I386_PGBYTES;
285: }
286:
287: flush_tlb();
288:
289: return (virt);
290: }
291:
292: static
293: void
294: pmap_enable_pg(
295: vm_offset_t kernel_pd
296: )
297: {
298: pd_entry_t *kpde, *end_kpde;
299: pd_entry_t *pde;
300: cr0_t _cr0 = cr0();
301:
302: /*
303: * Double map the kernel memory
304: * into the low end of the kernel
305: * pmap linear space. This is
306: * necessary in order to enable
307: * paging.
308: */
309: pde = (pd_entry_t *)kernel_pd;
310:
311: kpde =
312: pmap_pd_entry(kernel_pmap,
313: VM_MIN_KERNEL_ADDRESS);
314: end_kpde =
315: pmap_pd_entry(kernel_pmap,
316: VM_MAX_KERNEL_ADDRESS);
317:
318: while (kpde < end_kpde)
319: *pde++ = *kpde++;
320:
321: /*
322: * Use the kernel pmap
323: * as our initial translation
324: * tree.
325: */
326: kernel_pmap->cr3 =
327: pmap_phys(kernel_pmap, kernel_pd);
328:
329: set_cr3(kernel_pmap->cr3);
330:
331: /*
332: * Now, enable paging by
333: * turning on the PG bit
334: * in CR0. Also turn on
335: * the WP bit to allow
336: * the write protecting of
337: * memory with repect to
338: * the kernel.
339: */
340: _cr0.pg = _cr0.wp = TRUE;
341: set_cr0(_cr0);
342: }
343:
344: /*
345: */
346: void
347: pmap_bootstrap(
348: mem_region_t mem_region,
349: int num_regions,
350: vm_offset_t * virt_avail, /* OUT */
351: vm_offset_t * virt_end /* OUT */
352: )
353: {
354: vm_offset_t va;
355: unsigned int phys_end = mem_region[0].last_phys_addr;
356: vm_offset_t kernel_pd;
357:
358: /*
359: * Setup section_size variable.
360: */
361: section_size = SECTION_SIZE;
362:
363: /*
364: * Set ptes_per_vm_page for general use.
365: */
366: ptes_per_vm_page = PAGE_SIZE / I386_PGBYTES;
367:
368: /*
369: * Initialize pte protection arrays.
370: */
371: pte_prot_init();
372:
373: /*
374: * The kernel's pmap is statically allocated so we don't
375: * have to use pmap_create, which does not work
376: * correctly at this part of the boot sequence.
377: */
378: kernel_pmap = &kernel_pmap_store;
379:
380: simple_lock_init(&kernel_pmap->lock);
381:
382: /*
383: * Allocate a page directory for the
384: * kernel pmap.
385: */
386: (vm_offset_t)kernel_pmap->root =
387: kernel_pd = alloc_cnvmem(I386_PGBYTES, I386_PGBYTES);
388:
389: bzero((vm_offset_t)kernel_pmap->root, I386_PGBYTES);
390:
391: kernel_pmap->ref_count = 1;
392:
393: kernel_pmap->root +=
394: (KERNEL_LINEAR_BASE - VM_MIN_KERNEL_ADDRESS) / I386_SECTBYTES;
395:
396: /*
397: * Map all physical memory V == P.
398: */
399: va = pmap_map(VM_MIN_KERNEL_ADDRESS,
400: 0,
401: phys_end,
402: VM_PROT_READ | VM_PROT_WRITE);
403:
404: /*
405: * Allocate additional kernel page tables
406: * needed for allocating kernel virtual memory later.
407: */
408: *virt_avail = va;
409: va = pmap_map(va,
410: 0,
411: 64*1024*1024 + /* base size */
412: zone_map_sizer() + /* zone allocator */
413: buffer_map_sizer(), /* buffer cache */
414: VM_PROT_NONE);
415:
416: *virt_end = va;
417:
418: /*
419: * Finish initialization
420: * of the kernel pmap, and
421: * then enable paging.
422: */
423: pmap_enable_pg(kernel_pd);
424: }
425:
426: /*
427: * Initialize the pmap module.
428: * Called by vm_init, to initialize any structures that the pmap
429: * system needs to map virtual memory.
430: */
431: void
432: pmap_init(
433: mem_region_t mem_region,
434: int num_regions
435: )
436: {
437: unsigned int phys_start, phys_end;
438: int npages;
439: vm_size_t s;
440:
441: phys_start = mem_region[0].first_phys_addr;
442: phys_end = mem_region[0].last_phys_addr;
443:
444: npages = mem_region[0].num_pages;
445:
446: /*
447: * Allocate memory for the page descriptor
448: * table.
449: */
450: s = sizeof(struct pg_desc) * npages;
451: (void) kmem_alloc_wired(kernel_map, (vm_offset_t *)&pg_desc_tbl, s);
452: pg_first_phys = phys_start;
453:
454: /*
455: * Create the zone of physical maps,
456: * and of the physical-to-virtual entries.
457: */
458: s = sizeof (struct pmap);
459: pmap_zone = zinit(s, 400*s, 0, FALSE, "pmap"); /* XXX */
460:
461: s = sizeof (struct pv_entry);
462: pv_entry_zone = zinit(s, 10000*s, 0, FALSE, "pv_entry"); /* XXX */
463:
464: /*
465: * Create the zone of page
466: * extensions.
467: */
468: s = sizeof (struct pg_exten);
469: pg_exten_zone = zinit(s, npages*s, 0, FALSE, "pg_exten");
470:
471: /*
472: * Initialize the queues of active and
473: * free page tables and free page directories.
474: */
475: queue_init(&pt_active_queue);
476: queue_init(&pt_free_queue);
477: queue_init(&pd_free_queue);
478:
479: /*
480: * Only now, when all of the data structures are allocated,
481: * can we set vm_first_phys and vm_last_phys. If we set them
482: * too soon, the kmem_alloc above will try to use these
483: * data structures and blow up.
484: */
485:
486: vm_first_phys = phys_start;
487: vm_last_phys = phys_end;
488:
489: pmap_initialized = TRUE;
490: }
491:
492: static
493: pg_exten_t *
494: pg_exten_alloc(
495: vm_offset_t page
496: )
497: {
498: pg_exten_t *pe;
499: pg_desc_t *pd;
500:
501: (vm_offset_t)pe = zalloc(pg_exten_zone);
502:
503: pe->phys = pmap_phys(kernel_pmap, page);
504:
505: pd = pg_desc(pe->phys);
506:
507: pd->pg_exten = pe; pe->pg_desc = pd;
508:
509: pe->alloc_count = pe->wired_count = pe->unrefd_age = pe->alloc_bmap = 0;
510:
511: return (pe);
512: }
513:
514: static
515: void
516: pg_exten_free(
517: pg_exten_t *pe
518: )
519: {
520: pe->pg_desc->pg_exten = PG_EXTEN_NULL;
521:
522: zfree(pg_exten_zone, (vm_offset_t)pe);
523: }
524:
525: static
526: void
527: pmap_alloc_pd(
528: pmap_t pmap
529: )
530: {
531: pg_exten_t *pe;
532: int i;
533:
534: if (pe = pd_free_obtain()) {
535: if (++pe->alloc_count == ptes_per_vm_page)
536: pd_free_remove(pe);
537:
538: i = ffs(~pe->alloc_bmap) - 1;
539: pe->alloc_bmap |= (1 << i);
540:
541: (vm_offset_t)pmap->root = pe->pg_desc->pv_list.va + (I386_PGBYTES * i);
542: }
543: else {
544: if (kmem_alloc_wired(kernel_map,
545: (vm_offset_t *)&pmap->root, PAGE_SIZE) != KERN_SUCCESS)
546: panic("pmap_alloc_pd");
547:
548: pd_alloc_count++;
549:
550: pe = pg_exten_alloc((vm_offset_t)pmap->root);
551:
552: if (++pe->alloc_count < ptes_per_vm_page)
553: pd_free_add(pe);
554:
555: pe->alloc_bmap |= 1;
556: }
557: }
558:
559: static
560: void
561: pmap_free_pd(
562: pmap_t pmap
563: )
564: {
565: pg_exten_t *pe;
566: pg_desc_t *pd;
567: int i;
568:
569: pd = pg_desc(pmap_phys(kernel_pmap, (vm_offset_t)pmap->root));
570:
571: pe = pd->pg_exten;
572:
573: if (pe->alloc_count-- == ptes_per_vm_page)
574: pd_free_add(pe);
575:
576: i = ((vm_offset_t)pmap->root - pd->pv_list.va) / I386_PGBYTES;
577:
578: pe->alloc_bmap &= ~(1 << i);
579: }
580:
581: /*
582: * Allocate and setup the page directory
583: * for a new pmap. The pd_entries that
584: * correspond to the kernel address space
585: * are initialized by copying them from
586: * the kernel pmap. This works correctly
587: * since we never expand the kernel pmap.
588: */
589: static
590: void
591: pmap_create_pd(
592: pmap_t pmap
593: )
594: {
595: pd_entry_t *pde;
596: pd_entry_t *kpde, *end_kpde;
597:
598: pmap_alloc_pd(pmap);
599:
600: if (pmap->root == PD_ENTRY_NULL)
601: panic("pmap_create_page_directory");
602:
603: if (i386_trunc_page(pmap->root) != (vm_offset_t)pmap->root)
604: panic("pmap_create_page_directory 1");
605:
606: pmap->cr3 = pmap_phys(kernel_pmap, (vm_offset_t)pmap->root);
607:
608: kpde =
609: pmap_pd_entry(kernel_pmap,
610: VM_MIN_KERNEL_ADDRESS);
611: end_kpde =
612: pmap_pd_entry(kernel_pmap,
613: VM_MAX_KERNEL_ADDRESS);
614:
615: pde = pmap_pd_entry(pmap, KERNEL_LINEAR_BASE);
616:
617: while (kpde < end_kpde)
618: *pde++ = *kpde++;
619: }
620:
621: /*
622: * Create and return a physical map.
623: *
624: * If the size specified for the map
625: * is zero, the map is an actual physical
626: * map, and may be referenced by the
627: * hardware.
628: *
629: * If the size specified is non-zero,
630: * the map will be used in software only, and
631: * is bounded by that size.
632: */
633: pmap_t
634: pmap_create(
635: vm_size_t size
636: )
637: {
638: pmap_t pmap;
639:
640: /*
641: * A software use-only map doesn't even need a pmap.
642: */
643: if (size != 0)
644: return (PMAP_NULL);
645:
646: /*
647: * Allocate a pmap struct from the pmap_zone.
648: */
649: pmap = (pmap_t) zalloc(pmap_zone);
650: if (pmap == PMAP_NULL)
651: panic("pmap_create pmap");
652:
653: bzero((vm_offset_t)pmap, sizeof (struct pmap));
654:
655: /*
656: * Create the page directory.
657: */
658: pmap_create_pd(pmap);
659:
660: pmap->ref_count = 1;
661:
662: simple_lock_init(&pmap->lock);
663:
664: return (pmap);
665: }
666:
667: /*
668: * Retire the given physical map from service.
669: * Should only be called if the map contains
670: * no valid mappings.
671: */
672: void
673: pmap_destroy(
674: pmap_t pmap
675: )
676: {
677: int c, s;
678:
679: if (pmap == PMAP_NULL)
680: return;
681:
682: SPLVM(s);
683: simple_lock(&pmap->lock);
684:
685: c = --pmap->ref_count;
686:
687: simple_unlock(&pmap->lock);
688: SPLX(s);
689:
690: if (c != 0)
691: return;
692:
693: pmap_free_pd(pmap);
694:
695: zfree(pmap_zone, (vm_offset_t)pmap);
696: }
697:
698: /*
699: * Add a reference to the specified pmap.
700: */
701:
702: void
703: pmap_reference(
704: pmap_t pmap
705: )
706: {
707: int s;
708:
709: if (pmap != PMAP_NULL) {
710: SPLVM(s);
711: simple_lock(&pmap->lock);
712:
713: pmap->ref_count++;
714:
715: simple_unlock(&pmap->lock);
716: SPLX(s);
717: }
718: }
719:
720: /*
721: * Remove a range of mappings from
722: * a pmap. The indicated range must
723: * lie completely within one section,
724: * i.e. the ptes must be within one
725: * page table.
726: */
727: static
728: void
729: pmap_remove_range(
730: pmap_t pmap,
731: vm_offset_t start,
732: vm_offset_t end,
733: boolean_t free_table
734: )
735: {
736: pt_entry_t *pte, *epte;
737: pg_desc_t *pd;
738: pv_entry_t pv_h;
739: pv_entry_t cur, prev;
740: unsigned int pa;
741: vm_offset_t va = start;
742: int i, num_removed = 0, num_unwired = 0;
743:
744: if ((pte = pmap_pt_entry(pmap, start)) == PT_ENTRY_NULL)
745: return;
746:
747: epte = pmap_pt_entry(pmap, end);
748: if (trunc_page(pte) != trunc_page(epte))
749: epte = (pt_entry_t *)round_page(pte + ptes_per_vm_page);
750:
751: for (; pte < epte; va += PAGE_SIZE) {
752: if (!pte->valid) {
753: pte += ptes_per_vm_page;
754: continue;
755: }
756:
757: num_removed++;
758: if (pte->wired)
759: num_unwired++;
760:
761: pa = pfn_to_phys(pte->pfn);
762: if (!managed_page(pa)) {
763: for (i = ptes_per_vm_page; i-- > 0; pte++)
764: *pte = (pt_entry_t) { 0 };
765: continue;
766: }
767:
768: pd = pg_desc(pa);
769: LOCK_PVH(pd);
770:
771: /*
772: * Collect the referenced & dirty bits
773: * and clear the mapping.
774: */
775: for (i = ptes_per_vm_page; i-- > 0; pte++) {
776: if (pte->dirty) {
777: vm_page_t m = PHYS_TO_VM_PAGE(pa);
778:
779: vm_page_set_modified(m);
780: pd->page_attrib |= PG_DIRTY;
781: }
782:
783: if (pte->refer)
784: pd->page_attrib |= PG_REFER;
785:
786: *pte = (pt_entry_t) { 0 };
787: }
788:
789: /*
790: * Remove the mapping from the pvlist for
791: * this physical page.
792: */
793: pv_h = pg_desc_pvh(pd);
794: if (pv_h->pmap == PMAP_NULL)
795: panic("pmap_remove_range");
796:
797: if (pv_h->va == va && pv_h->pmap == pmap) {
798: /*
799: * Header is the pv_entry. Copy the next one
800: * to header and free the next one (we can't
801: * free the header)
802: */
803: cur = pv_h->next;
804: if (cur != PV_ENTRY_NULL) {
805: *pv_h = *cur;
806: zfree(pv_entry_zone, (vm_offset_t) cur);
807: }
808: else
809: pv_h->pmap = PMAP_NULL;
810: }
811: else {
812: prev = pv_h;
813: while ((cur = prev->next) != PV_ENTRY_NULL) {
814: if (cur->va == va && cur->pmap == pmap)
815: break;
816: prev = cur;
817: }
818: if (cur == PV_ENTRY_NULL)
819: panic("pmap_remove_range 2");
820:
821: prev->next = cur->next;
822: zfree(pv_entry_zone, (vm_offset_t) cur);
823: }
824:
825: UNLOCK_PVH(pd);
826: }
827:
828: /*
829: * Free the mappings from the page table.
830: */
831: pmap_deallocate_mappings(
832: pmap, start,
833: num_removed, num_unwired, free_table);
834: }
835:
836: /*
837: * Remove the given range of addresses
838: * from the specified pmap.
839: *
840: * It is assumed that the start and end are properly
841: * rounded to the page size.
842: */
843: void
844: pmap_remove(
845: pmap_t pmap,
846: vm_offset_t start,
847: vm_offset_t end
848: )
849: {
850: vm_offset_t sect_end;
851: int s;
852:
853: if (pmap == PMAP_NULL)
854: return;
855:
856: PMAP_READ_LOCK(pmap, s);
857:
858: /*
859: * Invalidate the translation buffer first
860: */
861: PMAP_UPDATE_TLBS(pmap, start, end);
862:
863: while (start < end) {
864: sect_end = round_section(start + PAGE_SIZE);
865: if (sect_end > end)
866: sect_end = end;
867:
868: pmap_remove_range(pmap, start, sect_end, TRUE);
869: start = sect_end;
870: }
871:
872: PMAP_READ_UNLOCK(pmap, s);
873: }
874:
875: /*
876: * Remove all references to
877: * the indicated page from
878: * all pmaps.
879: */
880: void
881: pmap_remove_all(
882: unsigned int pa
883: )
884: {
885: pt_entry_t *pte;
886: pv_entry_t pv_h, cur;
887: pg_desc_t *pd;
888: vm_offset_t va;
889: pmap_t pmap;
890: int s, i;
891:
892: if (!managed_page(pa))
893: return;
894:
895: /*
896: * Lock the pmap system first, since we will be changing
897: * several pmaps.
898: */
899: PMAP_WRITE_LOCK(s);
900:
901: /*
902: * Walk down PV list, removing all mappings.
903: * We have to do the same work as in pmap_remove_range
904: * since that routine locks the pv_head. We don't have
905: * to lock the pv_head, since we have the entire pmap system.
906: */
907: pd = pg_desc(pa);
908: pv_h = pg_desc_pvh(pd);
909:
910: while ((pmap = pv_h->pmap) != PMAP_NULL) {
911: va = pv_h->va;
912:
913: simple_lock(&pmap->lock);
914:
915: pte = pmap_pt_entry(pmap, va);
916: if (pte == PT_ENTRY_NULL || !pte->valid)
917: panic("pmap_remove_all");
918:
919: if (pfn_to_phys(pte->pfn) != pa)
920: panic("pmap_remove_all 2");
921:
922: if (pte->wired)
923: panic("pmap_remove_all 3");
924:
925: /*
926: * Tell CPU using pmap to invalidate its TLB
927: */
928: PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE);
929:
930: if ((cur = pv_h->next) != PV_ENTRY_NULL) {
931: *pv_h = *cur;
932: zfree(pv_entry_zone, (vm_offset_t) cur);
933: }
934: else
935: pv_h->pmap = PMAP_NULL;
936:
937: /*
938: * Collect the referenced & dirty bits
939: * and clear the mapping.
940: */
941: for (i = ptes_per_vm_page; i-- > 0; pte++) {
942: if (pte->dirty) {
943: vm_page_t m = PHYS_TO_VM_PAGE(pa);
944:
945: vm_page_set_modified(m);
946: pd->page_attrib |= PG_DIRTY;
947: }
948:
949: if (pte->refer)
950: pd->page_attrib |= PG_REFER;
951:
952: *pte = (pt_entry_t) { 0 };
953: }
954:
955: pmap_deallocate_mappings(pmap, va, 1, 0, TRUE);
956:
957: simple_unlock(&pmap->lock);
958: }
959:
960: PMAP_WRITE_UNLOCK(s);
961: }
962:
963: /*
964: * Remove write access to the
965: * indicated page from all pmaps.
966: */
967: void
968: pmap_copy_on_write(
969: unsigned int pa
970: )
971: {
972: pt_entry_t *pte;
973: pv_entry_t pv_e;
974: int i, s;
975:
976: if (!managed_page(pa))
977: return;
978:
979: /*
980: * Lock the entire pmap system, since we may be changing
981: * several maps.
982: */
983: PMAP_WRITE_LOCK(s);
984:
985: pv_e = pg_desc_pvh(pg_desc(pa));
986: if (pv_e->pmap == PMAP_NULL) {
987: PMAP_WRITE_UNLOCK(s);
988: return;
989: }
990:
991: /*
992: * Run down the list of mappings to this physical page,
993: * disabling write privileges on each one.
994: */
995: while (pv_e != PV_ENTRY_NULL) {
996: pmap_t pmap;
997: vm_offset_t va;
998:
999: pmap = pv_e->pmap;
1000: va = pv_e->va;
1001:
1002: simple_lock(&pmap->lock);
1003:
1004: pte = pmap_pt_entry(pmap, va);
1005:
1006: if (pte == PT_ENTRY_NULL || !pte->valid)
1007: panic("pmap_copy_on_write");
1008:
1009: /*
1010: * Ask cpus using pmap to invalidate their TLBs
1011: */
1012: PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE);
1013:
1014: if (pte->prot == PT_PROT_URW || pte->prot == PT_PROT_KRW)
1015: for (i = ptes_per_vm_page; i-- > 0; pte++)
1016: pte_prot(pmap, VM_PROT_READ, pte->valid, pte);
1017:
1018: simple_unlock(&pmap->lock);
1019:
1020: pv_e = pv_e->next;
1021: }
1022:
1023: PMAP_WRITE_UNLOCK(s);
1024: }
1025:
1026: /*
1027: * Change the page protection
1028: * on a range of addresses in
1029: * the indicated pmap. If protect
1030: * is being changed to VM_PROT_NONE,
1031: * remove the mappings.
1032: */
1033: void
1034: pmap_protect(
1035: pmap_t pmap,
1036: vm_offset_t start,
1037: vm_offset_t end,
1038: vm_prot_t prot
1039: )
1040: {
1041: pt_entry_t *pte, *epte;
1042: vm_offset_t sect_end;
1043: int i, s;
1044:
1045: if (pmap == PMAP_NULL)
1046: return;
1047:
1048: if (prot == VM_PROT_NONE) {
1049: pmap_remove(pmap, start, end);
1050: return;
1051: }
1052:
1053: SPLVM(s);
1054: simple_lock(&pmap->lock);
1055:
1056: /*
1057: * Invalidate the translation buffer first
1058: */
1059: PMAP_UPDATE_TLBS(pmap, start, end);
1060:
1061: while (start < end) {
1062: sect_end = round_section(start + PAGE_SIZE);
1063: if (sect_end > end)
1064: sect_end = end;
1065:
1066: pte = pmap_pt_entry(pmap, start);
1067: if (pte != PT_ENTRY_NULL) {
1068: epte = pmap_pt_entry(pmap, sect_end);
1069: if (trunc_page(pte) != trunc_page(epte))
1070: epte = (pt_entry_t *)round_page(pte + ptes_per_vm_page);
1071:
1072: while (pte < epte) {
1073: if (!pte->valid) {
1074: pte += ptes_per_vm_page;
1075: continue;
1076: }
1077:
1078: for (i = ptes_per_vm_page; i-- > 0; pte++)
1079: pte_prot(pmap, prot, pte->valid, pte);
1080: }
1081: }
1082:
1083: start = sect_end;
1084: }
1085:
1086: simple_unlock(&pmap->lock);
1087: SPLX(s);
1088: }
1089:
1090: /*
1091: * Insert the given physical page (p) at
1092: * the specified virtual address (v) in the
1093: * target physical map with the protection requested.
1094: *
1095: * If specified, the page will be wired down, meaning
1096: * that the related pte can not be reclaimed.
1097: *
1098: * NB: This is the only routine which MAY NOT lazy-evaluate
1099: * or lose information. That is, this routine must actually
1100: * insert this page into the given map NOW.
1101: */
1102: void inline
1103: pmap_enter_cache_spec(
1104: pmap_t pmap,
1105: vm_offset_t va,
1106: vm_offset_t pa,
1107: vm_prot_t prot,
1108: boolean_t wired,
1109: cache_spec_t caching
1110: )
1111: {
1112: pt_entry_t *pte;
1113: pv_entry_t pv_h;
1114: pg_desc_t *pd;
1115: int i, s;
1116: pv_entry_t pv_e;
1117: pt_entry_t template;
1118: vm_offset_t old_pa;
1119:
1120: if (pmap == PMAP_NULL)
1121: return;
1122:
1123: if (prot == VM_PROT_NONE) {
1124: pmap_remove(pmap, va, va + PAGE_SIZE);
1125: return;
1126: }
1127:
1128: /*
1129: * Must allocate a new pvlist entry while we're unlocked;
1130: * zalloc may cause pageout (which will lock the pmap system).
1131: * If we determine we need a pvlist entry, we will unlock
1132: * and allocate one. Then we will retry, throwing away
1133: * the allocated entry later (if we no longer need it).
1134: */
1135: pv_e = PV_ENTRY_NULL;
1136: template = (pt_entry_t) { 0 };
1137:
1138: Retry:
1139: PMAP_READ_LOCK(pmap, s);
1140:
1141: /*
1142: * Expand pmap to include this pte. Assume that
1143: * pmap is always expanded to include enough
1144: * pages to map one VM page.
1145: */
1146: while ((pte = pmap_pt_entry(pmap, va)) == PT_ENTRY_NULL) {
1147: /*
1148: * Must unlock to expand the pmap.
1149: */
1150: PMAP_READ_UNLOCK(pmap, s);
1151:
1152: pmap_expand(pmap, va);
1153:
1154: PMAP_READ_LOCK(pmap, s);
1155: }
1156:
1157: /*
1158: * Special case if the physical page is already mapped
1159: * at this address.
1160: */
1161: old_pa = pfn_to_phys(pte->pfn);
1162: if (pte->valid && old_pa == pa) {
1163: /*
1164: * May be changing its wired attribute or protection
1165: */
1166: if (wired && !pte->wired)
1167: pmap_wire_mapping(pmap, va);
1168: else
1169: if (!wired && pte->wired)
1170: pmap_unwire_mapping(pmap, va);
1171:
1172: pte_prot(pmap, prot, 1, &template);
1173: template.pfn = phys_to_pfn(pa);
1174: if (wired)
1175: template.wired = 1;
1176:
1177: if (caching == cache_disable)
1178: template.cachedis = 1;
1179: else
1180: if (caching == cache_writethrough)
1181: template.cachewrt = 1;
1182:
1183: PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE);
1184:
1185: for (i = ptes_per_vm_page; i-- > 0; pte++) {
1186: if (pte->dirty)
1187: template.dirty = 1;
1188: *pte = template;
1189: template.pfn++;
1190: }
1191: }
1192: else {
1193:
1194: /*
1195: * Remove old mapping from the PV list if necessary.
1196: */
1197: if (pte->valid) {
1198: /*
1199: * Invalidate the translation buffer,
1200: * then remove the mapping.
1201: */
1202: PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE);
1203:
1204: pmap_remove_range(pmap, va, va + PAGE_SIZE, FALSE);
1205: }
1206:
1207: if (managed_page(pa)) {
1208:
1209: /*
1210: * Enter the mapping in the PV list for this
1211: * physical page.
1212: */
1213: pd = pg_desc(pa);
1214: LOCK_PVH(pd);
1215: pv_h = pg_desc_pvh(pd);
1216:
1217: if (pv_h->pmap == PMAP_NULL) {
1218:
1219: /*
1220: * No mappings yet
1221: */
1222: pv_h->va = va;
1223: pv_h->pmap = pmap;
1224: pv_h->next = PV_ENTRY_NULL;
1225: }
1226: else {
1227:
1228: /*
1229: * Add new pv_entry after header.
1230: */
1231: if (pv_e == PV_ENTRY_NULL) {
1232: UNLOCK_PVH(pd);
1233: PMAP_READ_UNLOCK(pmap, s);
1234: pv_e = (pv_entry_t) zalloc(pv_entry_zone);
1235: goto Retry;
1236: }
1237: pv_e->va = va;
1238: pv_e->pmap = pmap;
1239: pv_e->next = pv_h->next;
1240: pv_h->next = pv_e;
1241: /*
1242: * Remember that we used the pvlist entry.
1243: */
1244: pv_e = PV_ENTRY_NULL;
1245: }
1246:
1247: UNLOCK_PVH(pd);
1248: }
1249:
1250: pmap_allocate_mapping(pmap, va, wired);
1251:
1252: /*
1253: * Build a template to speed up entering -
1254: * only the pfn changes.
1255: */
1256: pte_prot(pmap, prot, 1, &template);
1257: template.pfn = phys_to_pfn(pa);
1258: if (wired)
1259: template.wired = 1;
1260:
1261: if (caching == cache_disable)
1262: template.cachedis = 1;
1263: else
1264: if (caching == cache_writethrough)
1265: template.cachewrt = 1;
1266:
1267: for (i = ptes_per_vm_page; i-- > 0; pte++) {
1268: *pte = template;
1269: template.pfn++;
1270: }
1271: }
1272:
1273: PMAP_READ_UNLOCK(pmap, s);
1274:
1275: if (pv_e != PV_ENTRY_NULL)
1276: zfree(pv_entry_zone, (vm_offset_t) pv_e);
1277: }
1278:
1279: void
1280: pmap_enter(
1281: pmap_t pmap,
1282: vm_offset_t va,
1283: vm_offset_t pa,
1284: vm_prot_t prot,
1285: boolean_t wired
1286: )
1287: {
1288: pmap_enter_cache_spec(
1289: pmap,
1290: va,
1291: pa,
1292: prot,
1293: wired,
1294: cache_default);
1295: }
1296:
1297: void
1298: pmap_enter_shared_range(
1299: pmap_t pmap,
1300: vm_offset_t va,
1301: vm_size_t size,
1302: vm_offset_t kern
1303: )
1304: {
1305: vm_offset_t end = round_page(va + size);
1306:
1307: while (va < end) {
1308: pmap_enter(
1309: pmap,
1310: va,
1311: pmap_resident_extract(kernel_pmap, kern),
1312: VM_PROT_READ|VM_PROT_WRITE,
1313: TRUE);
1314:
1315: va += PAGE_SIZE; kern += PAGE_SIZE;
1316: }
1317: }
1318:
1319: /*
1320: * Change the wiring attribute for a
1321: * pmap/virtual-address pair.
1322: *
1323: * The mapping must already exist in the pmap.
1324: */
1325: void
1326: pmap_change_wiring(
1327: pmap_t pmap,
1328: vm_offset_t va,
1329: boolean_t wired
1330: )
1331: {
1332: pt_entry_t *pte;
1333: int i, s;
1334:
1335: /*
1336: * We must grab the pmap system lock because we may
1337: * change a pte_page queue.
1338: */
1339: PMAP_READ_LOCK(pmap, s);
1340:
1341: if ((pte = pmap_pt_entry(pmap, va)) == PT_ENTRY_NULL)
1342: panic("pmap_change_wiring");
1343:
1344: if (wired && !pte->wired) {
1345: /*
1346: * wiring down mapping
1347: */
1348: pmap_wire_mapping(pmap, va);
1349: }
1350: else
1351: if (!wired && pte->wired) {
1352: /*
1353: * unwiring mapping
1354: */
1355: pmap_unwire_mapping(pmap, va);
1356: }
1357:
1358: for (i = ptes_per_vm_page; i-- > 0; pte++)
1359: pte->wired = wired;
1360:
1361: PMAP_READ_UNLOCK(map, s);
1362: }
1363:
1364: vm_offset_t
1365: pmap_extract(
1366: pmap_t pmap,
1367: vm_offset_t va
1368: )
1369: {
1370: vm_offset_t pa;
1371: int s;
1372:
1373: SPLVM(s);
1374: simple_lock(&pmap->lock);
1375:
1376: pa = pmap_phys(pmap, va);
1377:
1378: simple_unlock(&pmap->lock);
1379: SPLX(s);
1380:
1381: return (pa);
1382: }
1383:
1384: vm_offset_t
1385: pmap_resident_extract(
1386: pmap_t pmap,
1387: vm_offset_t va
1388: )
1389: {
1390: return ((vm_offset_t) pmap_phys(pmap, va));
1391: }
1392:
1393: /*
1394: * Expand a pmap to be able to map the
1395: * specified virtual address by allocating
1396: * a single page table either from the list
1397: * of free page tables or directly from kernel
1398: * memory.
1399: */
1400: static
1401: void
1402: pmap_expand(
1403: pmap_t pmap,
1404: vm_offset_t va
1405: )
1406: {
1407: pd_entry_t template, *pde;
1408: pg_exten_t *pe;
1409: vm_offset_t pt;
1410: int i, s;
1411:
1412: if (pmap == kernel_pmap)
1413: panic("pmap_expand");
1414:
1415: if (pe = pt_free_obtain())
1416: pt = pe->pg_desc->pv_list.va;
1417: else {
1418: if (kmem_alloc_wired(kernel_map, &pt, PAGE_SIZE) != KERN_SUCCESS)
1419: return;
1420:
1421: pt_alloc_count++;
1422:
1423: pe = pg_exten_alloc(pt);
1424: }
1425:
1426: PMAP_READ_LOCK(pmap, s);
1427:
1428: /*
1429: * See if someone else expanded us first.
1430: */
1431: if (pmap_pt_entry(pmap, va) != PT_ENTRY_NULL) {
1432: PMAP_READ_UNLOCK(pmap, s);
1433:
1434: pg_exten_free(pe);
1435:
1436: kmem_free(kernel_map, pt, PAGE_SIZE);
1437:
1438: pt_alloc_count--;
1439:
1440: return;
1441: }
1442:
1443: /*
1444: * What virtual memory does this
1445: * page table map ?
1446: */
1447: pe->offset = trunc_section(va);
1448: pe->pmap = pmap;
1449:
1450: /*
1451: * Clear the reference aging
1452: * tick count.
1453: */
1454: pe->unrefd_age = 0;
1455:
1456: /*
1457: * Add this page table
1458: * to the active queue.
1459: */
1460: pt_active_add(pe);
1461:
1462: /*
1463: * Setup entry template.
1464: */
1465: template = (pd_entry_t) { 0 };
1466: template.valid = 1;
1467: template.prot = PT_PROT_URW;
1468: template.pfn = phys_to_pfn(pe->phys);
1469:
1470: /*
1471: * Set the page directory entries for this page table
1472: */
1473: pde = pmap_pd_entry(pmap, pe->offset);
1474: for (i = ptes_per_vm_page; i-- > 0; pde++) {
1475: *pde = template;
1476: template.pfn++;
1477: }
1478:
1479: PMAP_READ_UNLOCK(pmap, s);
1480: }
1481:
1482: /*
1483: * Allocate one additional mapping
1484: * in a page table. Note: pmap is
1485: * already locked.
1486: */
1487: static
1488: void
1489: pmap_allocate_mapping(
1490: pmap_t pmap,
1491: vm_offset_t va,
1492: boolean_t wired
1493: )
1494: {
1495: pd_entry_t *pde;
1496: pg_exten_t *pe;
1497:
1498: pmap->stats.resident_count++;
1499: if (wired)
1500: pmap->stats.wired_count++;
1501:
1502: if (pmap == kernel_pmap)
1503: return;
1504:
1505: pde = pmap_pd_entry(pmap, trunc_section(va));
1506: if (pde->valid) {
1507: pe = pg_desc(pfn_to_phys(pde->pfn))->pg_exten;
1508: pe->alloc_count++;
1509: if (wired)
1510: pe->wired_count++;
1511: }
1512: }
1513:
1514: /*
1515: * Deallocate one or more mappings
1516: * in a page table. The page table
1517: * is freed if no mappings remain.
1518: * Note: pmap is already locked.
1519: */
1520: static
1521: void
1522: pmap_deallocate_mappings(
1523: pmap_t pmap,
1524: vm_offset_t va,
1525: int count,
1526: int unwire_count,
1527: boolean_t free_table
1528: )
1529: {
1530: pd_entry_t *pde;
1531: pg_exten_t *pe;
1532: int i;
1533:
1534: pmap->stats.wired_count -= unwire_count;
1535: pmap->stats.resident_count -= count;
1536:
1537: if (pmap == kernel_pmap)
1538: return;
1539:
1540: pde = pmap_pd_entry(pmap, trunc_section(va));
1541: if (pde->valid) {
1542: pe = pg_desc(pfn_to_phys(pde->pfn))->pg_exten;
1543: if (pe->wired_count < unwire_count)
1544: panic("pmap_deallocate_mappings unwire");
1545: pe->wired_count -= unwire_count;
1546: if (pe->alloc_count < count)
1547: panic("pmap_deallocate_mappings");
1548: pe->alloc_count -= count;
1549:
1550: if (free_table && pe->alloc_count == 0) {
1551: for (i = ptes_per_vm_page; i-- > 0; pde++)
1552: pde->valid = 0;
1553:
1554: pt_active_remove(pe);
1555:
1556: pt_free_add(pe);
1557: }
1558: }
1559: }
1560:
1561: static
1562: void
1563: pmap_wire_mapping(
1564: pmap_t pmap,
1565: vm_offset_t va
1566: )
1567: {
1568: pd_entry_t *pde;
1569: pg_exten_t *pe;
1570:
1571: pmap->stats.wired_count++;
1572:
1573: if (pmap == kernel_pmap)
1574: return;
1575:
1576: pde = pmap_pd_entry(pmap, trunc_section(va));
1577: if (pde->valid) {
1578: pe = pg_desc(pfn_to_phys(pde->pfn))->pg_exten;
1579: pe->wired_count++;
1580: }
1581: }
1582:
1583: static
1584: void
1585: pmap_unwire_mapping(
1586: pmap_t pmap,
1587: vm_offset_t va
1588: )
1589: {
1590: pd_entry_t *pde;
1591: pg_exten_t *pe;
1592:
1593: pmap->stats.wired_count--;
1594:
1595: if (pmap == kernel_pmap)
1596: return;
1597:
1598: pde = pmap_pd_entry(pmap, trunc_section(va));
1599: if (pde->valid) {
1600: pe = pg_desc(pfn_to_phys(pde->pfn))->pg_exten;
1601: pe->wired_count--;
1602: }
1603: }
1604:
1605: /*
1606: * Copy the range specified by src_addr/len
1607: * from the source map to the range dst_addr/len
1608: * in the destination map.
1609: *
1610: * This routine is only advisory and need not do anything.
1611: */
1612: void
1613: pmap_copy(
1614: pmap_t dst_pmap,
1615: pmap_t src_pmap,
1616: vm_offset_t dst_addr,
1617: vm_size_t len,
1618: vm_offset_t src_addr
1619: )
1620: {
1621: /* OPTIONAL */
1622: }
1623:
1624: /*
1625: * Require that all active physical maps contain no
1626: * incorrect entries NOW. [This update includes
1627: * forcing updates of any address map caching.]
1628: *
1629: * Generally used to insure that a thread about
1630: * to run will see a semantically correct world.
1631: */
1632: void
1633: pmap_update(
1634: void
1635: )
1636: {
1637: pg_exten_t *pe, *npe;
1638: vm_offset_t page;
1639: pd_entry_t *pde;
1640: int tick_delta;
1641: static unsigned int last_tick;
1642:
1643: if (!last_tick)
1644: last_tick = sched_tick; /* initialization */
1645:
1646: tick_delta = sched_tick - last_tick;
1647:
1648: if (tick_delta > 1) {
1649: /*
1650: * Free all of the pages in
1651: * the free page table list.
1652: */
1653: while (pe = pt_free_obtain()) {
1654: page = pe->pg_desc->pv_list.va;
1655:
1656: pg_exten_free(pe);
1657:
1658: kmem_free(kernel_map, page, PAGE_SIZE);
1659: pt_alloc_count--;
1660: }
1661:
1662: /*
1663: * Run through the page directory
1664: * free list, freeing any that are
1665: * not in use.
1666: */
1667: (queue_entry_t)pe = queue_first(&pd_free_queue);
1668: while (!queue_end(&pd_free_queue, (queue_entry_t)pe)) {
1669: if (pe->alloc_count == 0) {
1670: remqueue(&pd_free_queue, (queue_entry_t)pe);
1671:
1672: pd_free_count--;
1673:
1674: page = pe->pg_desc->pv_list.va;
1675:
1676: pg_exten_free(pe);
1677:
1678: kmem_free(kernel_map, page, PAGE_SIZE);
1679: pd_alloc_count--;
1680:
1681: (queue_entry_t)pe = queue_first(&pd_free_queue);
1682: }
1683: else
1684: (queue_entry_t)pe = queue_next((queue_entry_t)pe);
1685: }
1686: }
1687:
1688: /*
1689: * Age the active page tables. Remove
1690: * all of the mappings from the tables
1691: * which have not been used for address
1692: * translation recently (excluding those
1693: * with wired mappings). Removing all of
1694: * a table's mappings causes the table to
1695: * be removed from the pmap and added to
1696: * the free page table list.
1697: */
1698: {
1699: static int pt_aging_k[] = { 8, 12, 16, 24, 32 },
1700: pt_aging_n = sizeof pt_aging_k / sizeof pt_aging_k[0];
1701: int tick_age;
1702:
1703: tick_age = ((tick_age = tick_delta >> 3) > (pt_aging_n - 1)) ?
1704: pt_aging_k[pt_aging_n - 1] :
1705: pt_aging_k[tick_age];
1706:
1707: (queue_entry_t)pe = queue_first(&pt_active_queue);
1708: while (!queue_end(&pt_active_queue, (queue_entry_t)pe)) {
1709: pde = pmap_pd_entry(pe->pmap, pe->offset);
1710: if (pe->wired_count == 0 && pde->valid) {
1711: (queue_entry_t)npe = queue_next((queue_entry_t)pe);
1712:
1713: if (tick_delta > 0 && !pde->refer) {
1714: int old_age = pe->unrefd_age;
1715:
1716: pe->unrefd_age += tick_delta;
1717: if (old_age > pe->unrefd_age || pe->unrefd_age > tick_age)
1718: pmap_remove(
1719: pe->pmap,
1720: pe->offset,
1721: pe->offset + section_size);
1722: }
1723: else if (pde->refer) {
1724: pde->refer = FALSE;
1725: pe->unrefd_age = 0;
1726: }
1727:
1728: pe = npe;
1729: }
1730: else {
1731: pe->unrefd_age = 0;
1732: (queue_entry_t)pe = queue_next((queue_entry_t)pe);
1733: }
1734: }
1735: }
1736:
1737: last_tick += tick_delta;
1738: }
1739:
1740: /*
1741: * Garbage collects the physical map system for
1742: * pages which are no longer used.
1743: * Success need not be guaranteed -- that is, there
1744: * may well be pages which are not referenced, but
1745: * others may be collected.
1746: *
1747: * Called by the pageout daemon when pages are scarce.
1748: */
1749: void
1750: pmap_collect(
1751: pmap_t pmap
1752: )
1753: {
1754: /* OPTIONAL */
1755: }
1756:
1757: /*
1758: * Bind the given pmap to the given
1759: * processor.
1760: */
1761: void
1762: pmap_activate(
1763: pmap_t pmap,
1764: thread_t thread,
1765: int cpu
1766: )
1767: {
1768: PMAP_ACTIVATE(pmap, thread, cpu);
1769: }
1770:
1771:
1772: /*
1773: * Indicates that the given physical map is no longer
1774: * in use on the specified processor.
1775: */
1776: void
1777: pmap_deactivate(
1778: pmap_t pmap,
1779: thread_t thread,
1780: int cpu
1781: )
1782: {
1783: PMAP_DEACTIVATE(pmap, thread, cpu);
1784: }
1785:
1786: /*
1787: * Return the pmap handle for the kernel.
1788: */
1789: pmap_t
1790: pmap_kernel(
1791: void
1792: )
1793: {
1794: return (kernel_pmap);
1795: }
1796:
1797: /*
1798: * pmap_zero_page zeros the specified (machine independent)
1799: * page.
1800: */
1801: void
1802: pmap_zero_page(
1803: vm_offset_t pa
1804: )
1805: {
1806: page_set(pmap_phys_to_kern(pa), 0, PAGE_SIZE);
1807: }
1808:
1809: /*
1810: * pmap_copy_page copies the specified (machine independent)
1811: * pages.
1812: */
1813: void
1814: pmap_copy_page(
1815: vm_offset_t src,
1816: vm_offset_t dst
1817: )
1818: {
1819: page_copy(pmap_phys_to_kern(dst), pmap_phys_to_kern(src), PAGE_SIZE);
1820: }
1821:
1822: void
1823: copy_to_phys(
1824: vm_offset_t src,
1825: vm_offset_t dst,
1826: vm_size_t count
1827: )
1828: {
1829: bcopy(src, pmap_phys_to_kern(dst), count);
1830: }
1831:
1832: void
1833: copy_from_phys(
1834: vm_offset_t src,
1835: vm_offset_t dst,
1836: vm_size_t count
1837: )
1838: {
1839: bcopy(pmap_phys_to_kern(src), dst, count);
1840: }
1841:
1842: /*
1843: * Make the specified pages (by pmap, offset)
1844: * pageable (or not) as requested.
1845: *
1846: * A page which is not pageable may not take
1847: * a fault; therefore, its page table entry
1848: * must remain valid for the duration.
1849: *
1850: * This routine is merely advisory; pmap_enter
1851: * will specify that these pages are to be wired
1852: * down (or not) as appropriate.
1853: */
1854: pmap_pageable(
1855: pmap_t pmap,
1856: vm_offset_t start,
1857: vm_offset_t end,
1858: boolean_t pageable
1859: )
1860: {
1861: /* OPTIONAL */
1862: }
1863:
1864: kern_return_t
1865: pmap_attribute(
1866: pmap_t pmap,
1867: vm_offset_t address,
1868: vm_size_t size,
1869: vm_machine_attribute_t attribute,
1870: vm_machine_attribute_val_t *value
1871: )
1872: {
1873: kern_return_t ret;
1874:
1875: if (attribute != MATTR_CACHE)
1876: return KERN_INVALID_ARGUMENT;
1877:
1878: /*
1879: ** We can't get the caching attribute for more than one page
1880: ** at a time
1881: */
1882: if ((*value == MATTR_VAL_GET) &&
1883: (trunc_page(address) != trunc_page(address+size-1)))
1884: return KERN_INVALID_ARGUMENT;
1885:
1886: if (pmap == PMAP_NULL)
1887: return KERN_SUCCESS;
1888:
1889: ret = KERN_SUCCESS;
1890:
1891: simple_lock(&pmap->lock);
1892:
1893: switch (*value) {
1894: case MATTR_VAL_CACHE_FLUSH: /* flush from all caches */
1895: case MATTR_VAL_DCACHE_FLUSH: /* flush from data cache(s) */
1896: case MATTR_VAL_ICACHE_FLUSH: /* flush from instr cache(s) */
1897: break;
1898:
1899: case MATTR_VAL_GET: /* return current value */
1900: case MATTR_VAL_OFF: /* turn attribute off */
1901: case MATTR_VAL_ON: /* turn attribute on */
1902: default:
1903: ret = KERN_INVALID_ARGUMENT;
1904: break;
1905: }
1906: simple_unlock(&pmap->lock);
1907:
1908: return ret;
1909:
1910: }
1911:
1912: /*
1913: * Clear the modify bits on the specified physical page.
1914: */
1915: void
1916: pmap_clear_modify(
1917: vm_offset_t pa
1918: )
1919: {
1920: if (managed_page(pa))
1921: pmap_clear_page_attrib(pa, PG_DIRTY);
1922: }
1923:
1924: /*
1925: * Return whether or not the specified physical page is modified
1926: * by any pmaps.
1927: */
1928: boolean_t
1929: pmap_is_modified(
1930: vm_offset_t pa
1931: )
1932: {
1933: if (managed_page(pa))
1934: return (pmap_check_page_attrib(pa, PG_DIRTY));
1935: else
1936: return (FALSE);
1937: }
1938:
1939: /*
1940: * Clear the reference bit on the specified physical page.
1941: */
1942: void
1943: pmap_clear_reference(
1944: vm_offset_t pa
1945: )
1946: {
1947: if (managed_page(pa))
1948: pmap_clear_page_attrib(pa, PG_REFER);
1949: }
1950:
1951: /*
1952: * Return whether or not the specified physical page is referenced
1953: * by any physical maps.
1954: */
1955: boolean_t
1956: pmap_is_referenced(
1957: vm_offset_t pa
1958: )
1959: {
1960: if (managed_page(pa))
1961: return (pmap_check_page_attrib(pa, PG_REFER));
1962: else
1963: return (FALSE);
1964: }
1965:
1966: /*
1967: * Clear the specified page attributes both in the
1968: * pmap_page_attributes table and the address translation
1969: * tables. Note that we DO have to flush the entries from
1970: * the TLB since the processor uses the bits in the TLB to
1971: * determine whether it has to write the bits out to memory.
1972: */
1973: static
1974: void
1975: pmap_clear_page_attrib(
1976: vm_offset_t pa,
1977: int attrib
1978: )
1979: {
1980: pt_entry_t *pte;
1981: pv_entry_t pv_h;
1982: pmap_t pmap;
1983: vm_offset_t va;
1984: pg_desc_t *pd;
1985: int i, s;
1986:
1987: pd = pg_desc(pa);
1988:
1989: PMAP_WRITE_LOCK(s);
1990:
1991: pd->page_attrib &= ~attrib;
1992:
1993: pv_h = pg_desc_pvh(pd);
1994:
1995: while ((pmap = pv_h->pmap) != PMAP_NULL) {
1996: va = pv_h->va;
1997:
1998: simple_lock(&pmap->lock);
1999:
2000: PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE);
2001:
2002: pte = pmap_pt_entry(pmap, va);
2003: if (pte != PT_ENTRY_NULL) {
2004: for (i = ptes_per_vm_page; i-- > 0; pte++) {
2005: if (attrib & PG_DIRTY)
2006: pte->dirty = 0;
2007: if (attrib & PG_REFER)
2008: pte->refer = 0;
2009: }
2010: }
2011:
2012: simple_unlock(&pmap->lock);
2013:
2014: if ((pv_h = pv_h->next) == PV_ENTRY_NULL)
2015: break;
2016: }
2017:
2018: PMAP_WRITE_UNLOCK(s);
2019: }
2020:
2021: /*
2022: * Check for the specified attributes for the
2023: * physical page. if all bits are true in
2024: * the pmap_page_attributes table, we can trust
2025: * it. otherwise, we must check the address
2026: * translation tables ourselves. Note that we
2027: * DO NOT have to flush the entry from the TLB
2028: * before looking at the address translation
2029: * table since the TLB is write-through for the bits.
2030: */
2031: static
2032: boolean_t
2033: pmap_check_page_attrib(
2034: vm_offset_t pa,
2035: int attrib
2036: )
2037: {
2038: pt_entry_t *pte;
2039: pv_entry_t pv_h;
2040: pmap_t pmap;
2041: vm_offset_t va;
2042: pg_desc_t *pd;
2043: int i, s;
2044:
2045: pd = pg_desc(pa);
2046:
2047: if ((pd->page_attrib & attrib) == attrib)
2048: return (TRUE);
2049:
2050: pv_h = pg_desc_pvh(pd);
2051:
2052: PMAP_WRITE_LOCK(s);
2053:
2054: while ((pmap = pv_h->pmap) != PMAP_NULL) {
2055: va = pv_h->va;
2056:
2057: simple_lock(&pmap->lock);
2058:
2059: pte = pmap_pt_entry(pmap, va);
2060: if (pte != PT_ENTRY_NULL) {
2061: for (i = ptes_per_vm_page; i-- > 0; pte++) {
2062: if (pte->dirty)
2063: pd->page_attrib |= PG_DIRTY;
2064: if (pte->refer)
2065: pd->page_attrib |= PG_REFER;
2066: }
2067:
2068: if ((pd->page_attrib & attrib) == attrib) {
2069: simple_unlock(&pmap->lock);
2070:
2071: PMAP_WRITE_UNLOCK(s);
2072:
2073: return (TRUE);
2074: }
2075: }
2076:
2077: simple_unlock(&pmap->lock);
2078:
2079: if ((pv_h = pv_h->next) == PV_ENTRY_NULL)
2080: break;
2081: }
2082:
2083: PMAP_WRITE_UNLOCK(s);
2084:
2085: return (FALSE);
2086: }
2087:
2088: /*
2089: * Dummy routine to satisfy external reference.
2090: */
2091: void
2092: pmap_update_interrupt(
2093: void
2094: )
2095: {
2096: /* should never be called. */
2097: panic("pmap_update_interrupt");
2098: }
2099:
2100: /*
2101: * Lower the permission for all mappings to a given page.
2102: */
2103: void
2104: pmap_page_protect(
2105: vm_offset_t pa,
2106: vm_prot_t prot
2107: )
2108: {
2109: switch (prot) {
2110: case VM_PROT_READ:
2111: case VM_PROT_READ|VM_PROT_EXECUTE:
2112: pmap_copy_on_write(pa);
2113: break;
2114:
2115: case VM_PROT_ALL:
2116: break;
2117:
2118: default:
2119: pmap_remove_all(pa);
2120: break;
2121: }
2122: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.