|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26: /*
27: * File: pmap.c
28: * Author: Avadis Tevanian, Jr., Michael Wayne Young
29: * (These guys wrote the Vax version)
30: *
31: * Physical Map management code for Intel i386, i486, and i860.
32: *
33: * Manages physical address maps.
34: *
35: * In addition to hardware address maps, this
36: * module is called upon to provide software-use-only
37: * maps which may or may not be stored in the same
38: * form as hardware maps. These pseudo-maps are
39: * used to store intermediate results from copy
40: * operations to and from address spaces.
41: *
42: * Since the information managed by this module is
43: * also stored by the logical address mapping module,
44: * this module may throw away valid virtual-to-physical
45: * mappings at almost any time. However, invalidations
46: * of virtual-to-physical mappings must be done as
47: * requested.
48: *
49: * In order to cope with hardware architectures which
50: * make virtual-to-physical map invalidates expensive,
51: * this module may delay invalidate or reduced protection
52: * operations until such time as they are actually
53: * necessary. This module is given full information as
54: * to which processors are currently using which maps,
55: * and to when physical maps must be made correct.
56: */
57:
58: #include <cpus.h>
59:
60: #include <mach/machine/vm_types.h>
61:
62: #include <mach/boolean.h>
63: #include <kern/thread.h>
64: #include <kern/zalloc.h>
65:
66: #include <kern/lock.h>
67:
68: #include <vm/pmap.h>
69: #include <vm/vm_map.h>
70: #include <vm/vm_kern.h>
71: #include "vm_param.h"
72: #include <mach/vm_prot.h>
73: #include <vm/vm_object.h>
74: #include <vm/vm_page.h>
75: #include <vm/vm_user.h>
76:
77: #include <oskit/x86/physmem.h>
78: #include <oskit/x86/base_cpu.h>
79:
80: #include <mach/machine/vm_param.h>
81: #include <machine/thread.h>
82: #include "cpu_number.h"
83: #if i860
84: #include <i860ipsc/nodehw.h>
85: #endif
86:
87: #ifdef ORC
88: #define OLIVETTICACHE 1
89: #endif /* ORC */
90:
91: #ifndef OLIVETTICACHE
92: #define WRITE_PTE(pte_p, pte_entry) *(pte_p) = (pte_entry);
93: #define WRITE_PTE_FAST(pte_p, pte_entry) *(pte_p) = (pte_entry);
94: #else /* OLIVETTICACHE */
95: #error might not work anymore
96:
97: /* This gross kludgery is needed for Olivetti XP7 & XP9 boxes to get
98: * around an apparent hardware bug. Other than at startup it doesn't
99: * affect run-time performacne very much, so we leave it in for all
100: * machines.
101: */
102: extern unsigned *pstart();
103: #define CACHE_LINE 8
104: #define CACHE_SIZE 512
105: #define CACHE_PAGE 0x1000;
106:
107: #define WRITE_PTE(pte_p, pte_entry) { write_pte(pte_p, pte_entry); }
108:
109: write_pte(pte_p, pte_entry)
110: pt_entry_t *pte_p, pte_entry;
111: {
112: unsigned long count;
113: volatile unsigned long hold, *addr1, *addr2;
114:
115: if ( pte_entry != *pte_p )
116: *pte_p = pte_entry;
117: else {
118: /* This isn't necessarily the optimal algorithm */
119: addr1 = (unsigned long *)pstart;
120: for (count = 0; count < CACHE_SIZE; count++) {
121: addr2 = addr1 + CACHE_PAGE;
122: hold = *addr1; /* clear cache bank - A - */
123: hold = *addr2; /* clear cache bank - B - */
124: addr1 += CACHE_LINE;
125: }
126: }
127: }
128:
129: #define WRITE_PTE_FAST(pte_p, pte_entry)*pte_p = pte_entry;
130:
131: #endif /* OLIVETTICACHE */
132:
133: /*
134: * Private data structures.
135: */
136:
137: /*
138: * For each vm_page_t, there is a list of all currently
139: * valid virtual mappings of that page. An entry is
140: * a pv_entry_t; the list is the pv_table.
141: */
142:
143: typedef struct pv_entry {
144: struct pv_entry *next; /* next pv_entry */
145: pmap_t pmap; /* pmap where mapping lies */
146: vm_offset_t va; /* virtual address for mapping */
147: } *pv_entry_t;
148:
149: #define PV_ENTRY_NULL ((pv_entry_t) 0)
150:
151: pv_entry_t pv_head_table; /* array of entries, one per page */
152:
153: /*
154: * pv_list entries are kept on a list that can only be accessed
155: * with the pmap system locked (at SPLVM, not in the cpus_active set).
156: * The list is refilled from the pv_list_zone if it becomes empty.
157: */
158: pv_entry_t pv_free_list; /* free list at SPLVM */
159: decl_simple_lock_data(, pv_free_list_lock)
160:
161: #define PV_ALLOC(pv_e) { \
162: simple_lock(&pv_free_list_lock); \
163: if ((pv_e = pv_free_list) != 0) { \
164: pv_free_list = pv_e->next; \
165: } \
166: simple_unlock(&pv_free_list_lock); \
167: }
168:
169: #define PV_FREE(pv_e) { \
170: simple_lock(&pv_free_list_lock); \
171: pv_e->next = pv_free_list; \
172: pv_free_list = pv_e; \
173: simple_unlock(&pv_free_list_lock); \
174: }
175:
176: zone_t pv_list_zone; /* zone of pv_entry structures */
177:
178: /*
179: * Each entry in the pv_head_table is locked by a bit in the
180: * pv_lock_table. The lock bits are accessed by the physical
181: * address of the page they lock.
182: */
183:
184: char *pv_lock_table; /* pointer to array of bits */
185: #define pv_lock_table_size(n) (((n)+BYTE_SIZE-1)/BYTE_SIZE)
186:
187: /* Has pmap_init completed? */
188: boolean_t pmap_initialized = FALSE;
189:
190: /*
191: * Range of kernel virtual addresses available for kernel memory mapping.
192: * Does not include the virtual addresses used to map physical memory 1-1.
193: * Initialized by pmap_bootstrap.
194: */
195: vm_offset_t kernel_virtual_start;
196: vm_offset_t kernel_virtual_end;
197:
198: /* XXX stupid fixed limit - get rid */
199: vm_size_t morevm = 40 * 1024 * 1024; /* VM space for kernel map */
200:
201: /*
202: * Index into pv_head table, its lock bits, and the modify/reference
203: * bits starting at phys_mem_min.
204: */
205: #define pa_index(pa) (atop(pa - phys_mem_min))
206:
207: #define pai_to_pvh(pai) (&pv_head_table[pai])
208: #define lock_pvh_pai(pai) (bit_lock(pai, pv_lock_table))
209: #define unlock_pvh_pai(pai) (bit_unlock(pai, pv_lock_table))
210:
211: /*
212: * Array of physical page attribites for managed pages.
213: * One byte per physical page.
214: */
215: char *pmap_phys_attributes;
216:
217: /*
218: * Physical page attributes. Copy bits from PTE definition.
219: */
220: #define PHYS_MODIFIED INTEL_PTE_MOD /* page modified */
221: #define PHYS_REFERENCED INTEL_PTE_REF /* page referenced */
222:
223: /*
224: * Amount of virtual memory mapped by one
225: * page-directory entry.
226: */
227: #define PDE_MAPPED_SIZE (pdenum2lin(1))
228:
229: /*
230: * We allocate page table pages directly from the VM system
231: * through this object. It maps physical memory.
232: */
233: vm_object_t pmap_object = VM_OBJECT_NULL;
234:
235: /*
236: * Locking and TLB invalidation
237: */
238:
239: /*
240: * Locking Protocols:
241: *
242: * There are two structures in the pmap module that need locking:
243: * the pmaps themselves, and the per-page pv_lists (which are locked
244: * by locking the pv_lock_table entry that corresponds to the pv_head
245: * for the list in question.) Most routines want to lock a pmap and
246: * then do operations in it that require pv_list locking -- however
247: * pmap_remove_all and pmap_copy_on_write operate on a physical page
248: * basis and want to do the locking in the reverse order, i.e. lock
249: * a pv_list and then go through all the pmaps referenced by that list.
250: * To protect against deadlock between these two cases, the pmap_lock
251: * is used. There are three different locking protocols as a result:
252: *
253: * 1. pmap operations only (pmap_extract, pmap_access, ...) Lock only
254: * the pmap.
255: *
256: * 2. pmap-based operations (pmap_enter, pmap_remove, ...) Get a read
257: * lock on the pmap_lock (shared read), then lock the pmap
258: * and finally the pv_lists as needed [i.e. pmap lock before
259: * pv_list lock.]
260: *
261: * 3. pv_list-based operations (pmap_remove_all, pmap_copy_on_write, ...)
262: * Get a write lock on the pmap_lock (exclusive write); this
263: * also guaranteees exclusive access to the pv_lists. Lock the
264: * pmaps as needed.
265: *
266: * At no time may any routine hold more than one pmap lock or more than
267: * one pv_list lock. Because interrupt level routines can allocate
268: * mbufs and cause pmap_enter's, the pmap_lock and the lock on the
269: * kernel_pmap can only be held at splvm.
270: */
271:
272: #if NCPUS > 1
273: /*
274: * We raise the interrupt level to splvm, to block interprocessor
275: * interrupts during pmap operations. We must take the CPU out of
276: * the cpus_active set while interrupts are blocked.
277: */
278: #define SPLVM(spl) { \
279: spl = splvm(); \
280: i_bit_clear(cpu_number(), &cpus_active); \
281: }
282:
283: #define SPLX(spl) { \
284: i_bit_set(cpu_number(), &cpus_active); \
285: splx(spl); \
286: }
287:
288: /*
289: * Lock on pmap system
290: */
291: lock_data_t pmap_system_lock;
292:
293: #define PMAP_READ_LOCK(pmap, spl) { \
294: SPLVM(spl); \
295: lock_read(&pmap_system_lock); \
296: simple_lock(&(pmap)->lock); \
297: }
298:
299: #define PMAP_WRITE_LOCK(spl) { \
300: SPLVM(spl); \
301: lock_write(&pmap_system_lock); \
302: }
303:
304: #define PMAP_READ_UNLOCK(pmap, spl) { \
305: simple_unlock(&(pmap)->lock); \
306: lock_read_done(&pmap_system_lock); \
307: SPLX(spl); \
308: }
309:
310: #define PMAP_WRITE_UNLOCK(spl) { \
311: lock_write_done(&pmap_system_lock); \
312: SPLX(spl); \
313: }
314:
315: #define PMAP_WRITE_TO_READ_LOCK(pmap) { \
316: simple_lock(&(pmap)->lock); \
317: lock_write_to_read(&pmap_system_lock); \
318: }
319:
320: #define LOCK_PVH(index) (lock_pvh_pai(index))
321:
322: #define UNLOCK_PVH(index) (unlock_pvh_pai(index))
323:
324: #define PMAP_UPDATE_TLBS(pmap, s, e) \
325: { \
326: cpu_set cpu_mask = 1 << cpu_number(); \
327: cpu_set users; \
328: \
329: /* Since the pmap is locked, other updates are locked */ \
330: /* out, and any pmap_activate has finished. */ \
331: \
332: /* find other cpus using the pmap */ \
333: users = (pmap)->cpus_using & ~cpu_mask; \
334: if (users) { \
335: /* signal them, and wait for them to finish */ \
336: /* using the pmap */ \
337: signal_cpus(users, (pmap), (s), (e)); \
338: while ((pmap)->cpus_using & cpus_active & ~cpu_mask) \
339: continue; \
340: } \
341: \
342: /* invalidate our own TLB if pmap is in use */ \
343: if ((pmap)->cpus_using & cpu_mask) { \
344: INVALIDATE_TLB((s), (e)); \
345: } \
346: }
347:
348: #else /* NCPUS > 1 */
349:
350: #define SPLVM(spl)
351: #define SPLX(spl)
352:
353: #define PMAP_READ_LOCK(pmap, spl) SPLVM(spl)
354: #define PMAP_WRITE_LOCK(spl) SPLVM(spl)
355: #define PMAP_READ_UNLOCK(pmap, spl) SPLX(spl)
356: #define PMAP_WRITE_UNLOCK(spl) SPLX(spl)
357: #define PMAP_WRITE_TO_READ_LOCK(pmap)
358:
359: #define LOCK_PVH(index)
360: #define UNLOCK_PVH(index)
361:
362: #define PMAP_UPDATE_TLBS(pmap, s, e) { \
363: /* invalidate our own TLB if pmap is in use */ \
364: if ((pmap)->cpus_using) { \
365: INVALIDATE_TLB((s), (e)); \
366: } \
367: }
368:
369: #endif /* NCPUS > 1 */
370:
371: #define MAX_TBIS_SIZE 32 /* > this -> TBIA */ /* XXX */
372:
373: static inline void
374: INVALIDATE_TLB(vm_offset_t start, vm_offset_t end)
375: {
376: if (base_cpuid.family != CPU_FAMILY_386 /* 486 or greater only */
377: && end - start < VM_MAX_ADDRESS - VM_MIN_ADDRESS) /* if not whole TLB */
378: {
379: /* Later x86 processors can invalidate individual TLB entries
380: one page at a time. (We don't bother with this if we are
381: invalidating the whole TLB anyway.) XXX do this anyway
382: if we don't have PGE?
383:
384: This requires addressing the page in a kernel-mode instruction
385: here, so we must compute from the linear addresses to kernel
386: segment offsets. Our loop then is in addresses relative to the
387: kernel segmentation, which will start high and wrap around to zero
388: at VM_MAX_ADDRESS. So a test of S < E would not work!
389:
390: XXX I saw all manner of inexplicable weirdness when I tried to
391: enable this code. I even thought I had it reliably working for
392: a while by inserting some nop's, but then I couldn't reproduce that.
393: This was on an Intel Pentium (100MHz). Your mileage may vary. --rm
394: */
395: oskit_addr_t s, e;
396: for (s = lintokv (start), e = lintokv (end);
397: s != e; /* note we wrap around zero! */
398: s += PAGE_SIZE) {
399: asm volatile ("invlpg %0" : : "m" (*(int *) s));
400: asm volatile ("invlpg %0" : : "m" (*(int *) kvtolin(s))); /* XXX ??? */
401: }
402: }
403: else
404: /* This is the only option on the 386, and we use it on later
405: processors as well when flushing all user-space mappings.
406: Note that if PGE is supported, this does not flush TLB entries
407: marked global (kernel-space mappings). Those mappings must be
408: flushed with invlpg. Any kernel-space mapping change will call here
409: to flush just the affected pages, and hit the invplg case above. */
410: inval_tlb ();
411: }
412:
413:
414: #if NCPUS > 1
415: /*
416: * Structures to keep track of pending TLB invalidations
417: */
418:
419: #define UPDATE_LIST_SIZE 4
420:
421: struct pmap_update_item {
422: pmap_t pmap; /* pmap to invalidate */
423: vm_offset_t start; /* start address to invalidate */
424: vm_offset_t end; /* end address to invalidate */
425: } ;
426:
427: typedef struct pmap_update_item *pmap_update_item_t;
428:
429: /*
430: * List of pmap updates. If the list overflows,
431: * the last entry is changed to invalidate all.
432: */
433: struct pmap_update_list {
434: decl_simple_lock_data(, lock)
435: int count;
436: struct pmap_update_item item[UPDATE_LIST_SIZE];
437: } ;
438: typedef struct pmap_update_list *pmap_update_list_t;
439:
440: struct pmap_update_list cpu_update_list[NCPUS];
441:
442: #endif /* NCPUS > 1 */
443:
444: /*
445: * Other useful macros.
446: */
447: #define current_pmap() (vm_map_pmap(current_thread()->task->map))
448: #define pmap_in_use(pmap, cpu) (((pmap)->cpus_using & (1 << (cpu))) != 0)
449:
450: struct pmap kernel_pmap_store;
451: pmap_t kernel_pmap;
452:
453: struct zone *pmap_zone; /* zone of pmap structures */
454:
455: int pmap_debug = 0; /* flag for debugging prints */
456:
457: #if 0
458: int ptes_per_vm_page; /* number of hardware ptes needed
459: to map one VM page. */
460: #else
461: #define ptes_per_vm_page 1
462: #endif
463:
464: unsigned int inuse_ptepages_count = 0; /* debugging */
465:
466: extern char end;
467:
468: /*
469: * Pointer to the basic page directory for the kernel.
470: * Initialized by pmap_bootstrap().
471: */
472: pt_entry_t *kernel_page_dir;
473:
474: void pmap_remove_range(); /* forward */
475: #if NCPUS > 1
476: void signal_cpus(); /* forward */
477: #endif /* NCPUS > 1 */
478:
479: #if i860
480: /*
481: * Paging flag
482: */
483: int paging_enabled = 0;
484: #endif
485:
486: static inline pt_entry_t *
487: pmap_pde(pmap_t pmap, vm_offset_t addr)
488: {
489: if (pmap == kernel_pmap)
490: addr = kvtolin(addr);
491: return &pmap->dirbase[lin2pdenum(addr)];
492: }
493:
494: /*
495: * Given an offset and a map, compute the address of the
496: * pte. If the address is invalid with respect to the map
497: * then PT_ENTRY_NULL is returned (and the map may need to grow).
498: *
499: * This is only used internally.
500: */
501: pt_entry_t *
502: pmap_pte(pmap_t pmap, vm_offset_t addr)
503: {
504: pt_entry_t *ptp;
505: pt_entry_t pte;
506:
507: if (pmap->dirbase == 0)
508: return(PT_ENTRY_NULL);
509: pte = *pmap_pde(pmap, addr);
510: if ((pte & INTEL_PTE_VALID) == 0)
511: return(PT_ENTRY_NULL);
512: ptp = (pt_entry_t *)ptetokv(pte);
513: return(&ptp[ptenum(addr)]);
514: }
515:
516: #define DEBUG_PTE_PAGE 0
517:
518: #if DEBUG_PTE_PAGE
519: void ptep_check(ptep)
520: ptep_t ptep;
521: {
522: register pt_entry_t *pte, *epte;
523: int ctu, ctw;
524:
525: /* check the use and wired counts */
526: if (ptep == PTE_PAGE_NULL)
527: return;
528: pte = pmap_pte(ptep->pmap, ptep->va);
529: epte = pte + INTEL_PGBYTES/sizeof(pt_entry_t);
530: ctu = 0;
531: ctw = 0;
532: while (pte < epte) {
533: if (pte->pfn != 0) {
534: ctu++;
535: if (pte->wired)
536: ctw++;
537: }
538: pte += ptes_per_vm_page;
539: }
540:
541: if (ctu != ptep->use_count || ctw != ptep->wired_count) {
542: printf("use %d wired %d - actual use %d wired %d\n",
543: ptep->use_count, ptep->wired_count, ctu, ctw);
544: panic("pte count");
545: }
546: }
547: #endif /* DEBUG_PTE_PAGE */
548:
549: /*
550: * Map memory at initialization. The physical addresses being
551: * mapped are not managed and are never unmapped.
552: *
553: * For now, VM is already on, we only need to map the
554: * specified memory.
555: */
556: vm_offset_t pmap_map(virt, start, end, prot)
557: register vm_offset_t virt;
558: register vm_offset_t start;
559: register vm_offset_t end;
560: register int prot;
561: {
562: register int ps;
563:
564: ps = PAGE_SIZE;
565: while (start < end) {
566: pmap_enter(kernel_pmap, virt, start, prot, FALSE);
567: virt += ps;
568: start += ps;
569: }
570: return(virt);
571: }
572:
573: /*
574: * Back-door routine for mapping kernel VM at initialization.
575: * Useful for mapping memory outside the range
576: * [phys_mem_min, phys_mem_max) (i.e., devices).
577: * Otherwise like pmap_map.
578: #if i860
579: * Sets no-cache bit.
580: #endif
581: */
582: vm_offset_t pmap_map_bd(virt, start, end, prot)
583: register vm_offset_t virt;
584: register vm_offset_t start;
585: register vm_offset_t end;
586: vm_prot_t prot;
587: {
588: register pt_entry_t template;
589: register pt_entry_t *pte;
590:
591: template = pa_to_pte(start)
592: #if i860
593: | INTEL_PTE_NCACHE
594: #endif
595: | INTEL_PTE_VALID;
596: if (prot & VM_PROT_WRITE)
597: template |= INTEL_PTE_WRITE;
598:
599: while (start < end) {
600: pte = pmap_pte(kernel_pmap, virt);
601: if (pte == PT_ENTRY_NULL)
602: panic("pmap_map_bd: Invalid kernel address\n");
603: WRITE_PTE_FAST(pte, template)
604: pte_increment_pa(template);
605: virt += PAGE_SIZE;
606: start += PAGE_SIZE;
607: }
608: return(virt);
609: }
610:
611: static pt_entry_t kernel_pte_global;
612:
613: /*
614: * Bootstrap the system enough to run with virtual memory.
615: * Allocate the kernel page directory and page tables,
616: * and direct-map all physical memory.
617: * Called with mapping off.
618: */
619: void pmap_bootstrap()
620: {
621: /*
622: * Mapping is turned off; we must reference only physical addresses.
623: * The load image of the system is to be mapped 1-1 physical = virtual.
624: */
625:
626: /*
627: * Set ptes_per_vm_page for general use.
628: */
629: #if 0
630: ptes_per_vm_page = PAGE_SIZE / INTEL_PGBYTES;
631: #endif
632:
633: /*
634: * The kernel's pmap is statically allocated so we don't
635: * have to use pmap_create, which is unlikely to work
636: * correctly at this part of the boot sequence.
637: */
638:
639: kernel_pmap = &kernel_pmap_store;
640:
641: #if NCPUS > 1
642: lock_init(&pmap_system_lock, FALSE); /* NOT a sleep lock */
643: #endif /* NCPUS > 1 */
644:
645: simple_lock_init(&kernel_pmap->lock);
646:
647: kernel_pmap->ref_count = 1;
648:
649: /*
650: * Determine the kernel virtual address range.
651: * It starts at the end of the physical memory
652: * mapped into the kernel address space,
653: * and extends to a stupid arbitrary limit beyond that.
654: */
655: kernel_virtual_start = phys_mem_max;
656: kernel_virtual_end = phys_mem_max + morevm;
657:
658: /*
659: * Allocate and clear a kernel page directory.
660: */
661: kernel_pmap->dirbase = kernel_page_dir = (pt_entry_t*)pmap_grab_page();
662: {
663: int i;
664: for (i = 0; i < NPDES; i++)
665: kernel_pmap->dirbase[i] = 0;
666: }
667:
668: if (base_cpuid.feature_flags & CPUF_PAGE_GLOBAL_EXT) {
669: /*
670: * The processor supports the "global" bit to avoid flushing
671: * kernel TLB entries, if we turn it on.
672: */
673: kernel_pte_global = INTEL_PTE_GLOBAL;
674: }
675:
676: /*
677: * Allocate and set up the kernel page tables.
678: */
679: {
680: vm_offset_t va;
681:
682: /*
683: * Map virtual memory for all known physical memory, 1-1,
684: * from phys_mem_min to phys_mem_max.
685: * Make any mappings completely in the kernel's text segment read-only.
686: *
687: * Also allocate some additional all-null page tables afterwards
688: * for kernel virtual memory allocation,
689: * because this PMAP module is too stupid
690: * to allocate new kernel page tables later.
691: * XX fix this
692: */
693: for (va = phys_mem_min; va < phys_mem_max + morevm; )
694: {
695: pt_entry_t *pde = kernel_page_dir + lin2pdenum(kvtolin(va));
696: pt_entry_t *ptable = (pt_entry_t*)pmap_grab_page();
697: pt_entry_t *pte;
698: vm_offset_t pteva;
699:
700: /* Initialize the page directory entry. */
701: *pde = (pa_to_pte((vm_offset_t)ptable)
702: | INTEL_PTE_VALID | INTEL_PTE_WRITE
703: | kernel_pte_global);
704:
705: /* Initialize the page table. */
706: for (pte = ptable; (va < phys_mem_max) && (pte < ptable+NPTES); pte++)
707: {
708: pt_entry_t entry = kernel_pte_global;
709: if ((pte - ptable) < ptenum(va))
710: entry |= 0; /* nada */
711: else
712: {
713: extern char _start[], etext[];
714:
715: entry |= pa_to_pte(va) | INTEL_PTE_VALID;
716: if ((va < (vm_offset_t)_start)
717: || (va + INTEL_PGBYTES > (vm_offset_t)etext))
718: entry |= INTEL_PTE_WRITE;
719: va += INTEL_PGBYTES;
720: }
721: WRITE_PTE_FAST(pte, entry);
722: }
723: for (; pte < ptable+NPTES; pte++)
724: {
725: WRITE_PTE_FAST(pte, kernel_pte_global);
726: va += INTEL_PGBYTES;
727: }
728: }
729: }
730:
731: #if i860
732: #error probably doesnt work anymore
733: XXX move to architecture-specific code just after the pmap_bootstrap call.
734:
735: /* kvtophys should now work in phys range */
736:
737: /*
738: * Mark page table pages non-cacheable
739: */
740:
741: pt_pte = (pt_entry_t *)pte_to_pa(*(kpde + pdenum(sva))) + ptenum(sva);
742:
743: for (va = load_start; va < tva; va += INTEL_PGBYTES*NPTES) {
744: /* Mark page table non-cacheable */
745: *pt_pte |= INTEL_PTE_NCACHE;
746: pt_pte++;
747: }
748:
749: /*
750: * Map I/O space
751: */
752:
753: ppde = kpde;
754: ppde += pdenum(IO_BASE);
755:
756: if (pte_to_pa(*ppde) == 0) {
757: /* This pte has not been allocated */
758: ppte = (pt_entry_t *)kvtophys(virtual_avail);
759: ptend = ppte + NPTES;
760: virtual_avail = phystokv((vm_offset_t)ptend);
761: *ppde = pa_to_pte((vm_offset_t)ppte)
762: | INTEL_PTE_VALID
763: | INTEL_PTE_WRITE;
764: pte = ptend;
765:
766: /* Mark page table non-cacheable */
767: *pt_pte |= INTEL_PTE_NCACHE;
768: pt_pte++;
769:
770: bzero((char *)ppte, INTEL_PGBYTES);
771: } else {
772: ppte = (pt_entry_t *)(*ppde); /* first pte of page */
773: }
774: *ppde |= INTEL_PTE_USER;
775:
776:
777: WRITE_PTE(ppte + ptenum(FIFO_ADDR),
778: pa_to_pte(FIFO_ADDR_PH)
779: | INTEL_PTE_VALID | INTEL_PTE_WRITE | INTEL_PTE_NCACHE);
780:
781: WRITE_PTE(ppte + ptenum(FIFO_ADDR + XEOD_OFF),
782: pa_to_pte(FIFO_ADDR_PH + XEOD_OFF_PH)
783: | INTEL_PTE_VALID | INTEL_PTE_WRITE | INTEL_PTE_NCACHE);
784:
785: /* XXX Allowed user access to control reg - cfj */
786: WRITE_PTE(ppte + ptenum(CSR_ADDR),
787: pa_to_pte(CSR_ADDR_PH)
788: | INTEL_PTE_VALID | INTEL_PTE_WRITE | INTEL_PTE_NCACHE | INTEL_PTE_USER);
789:
790: /* XXX Allowed user access to perf reg - cfj */
791: WRITE_PTE(ppte + ptenum(PERFCNT_ADDR),
792: pa_to_pte(PERFCNT_ADDR_PH)
793: | INTEL_PTE_VALID | INTEL_PTE_USER | INTEL_PTE_NCACHE | INTEL_PTE_USER);
794:
795: WRITE_PTE(ppte + ptenum(UART_ADDR),
796: pa_to_pte(UART_ADDR_PH)
797: | INTEL_PTE_VALID | INTEL_PTE_WRITE | INTEL_PTE_NCACHE);
798:
799: WRITE_PTE(ppte + ptenum(0xFFFFF000),
800: pa_to_pte(avail_end)
801: | INTEL_PTE_VALID | INTEL_PTE_WRITE);
802: avail_start = kvtophys(virtual_avail);
803:
804: /*
805: * Turn on mapping
806: */
807:
808: flush_and_ctxsw(kernel_pmap->dirbase);
809: paging_enabled = 1;
810:
811: printf("Paging enabled.\n");
812: #endif
813:
814: /* Architecture-specific code will turn on paging
815: soon after we return from here. */
816: }
817:
818: void pmap_virtual_space(startp, endp)
819: vm_offset_t *startp;
820: vm_offset_t *endp;
821: {
822: *startp = kernel_virtual_start;
823: *endp = kernel_virtual_end;
824: }
825:
826: /*
827: * Initialize the pmap module.
828: * Called by vm_init, to initialize any structures that the pmap
829: * system needs to map virtual memory.
830: */
831: void pmap_init()
832: {
833: register long npages;
834: vm_offset_t addr;
835: register vm_size_t s;
836: int i;
837:
838: /*
839: * Allocate memory for the pv_head_table and its lock bits,
840: * the modify bit array, and the pte_page table.
841: */
842:
843: npages = atop(phys_mem_max - phys_mem_min);
844: s = (vm_size_t) (sizeof(struct pv_entry) * npages
845: + pv_lock_table_size(npages)
846: + npages);
847:
848: s = round_page(s);
849: if (kmem_alloc_wired(kernel_map, &addr, s) != KERN_SUCCESS)
850: panic("pmap_init");
851: bzero((char *) addr, s);
852:
853: /*
854: * Allocate the structures first to preserve word-alignment.
855: */
856: pv_head_table = (pv_entry_t) addr;
857: addr = (vm_offset_t) (pv_head_table + npages);
858:
859: pv_lock_table = (char *) addr;
860: addr = (vm_offset_t) (pv_lock_table + pv_lock_table_size(npages));
861:
862: pmap_phys_attributes = (char *) addr;
863:
864: /*
865: * Create the zone of physical maps,
866: * and of the physical-to-virtual entries.
867: */
868: s = (vm_size_t) sizeof(struct pmap);
869: pmap_zone = zinit(s, 400*s, 4096, 0, "pmap"); /* XXX */
870: s = (vm_size_t) sizeof(struct pv_entry);
871: pv_list_zone = zinit(s, 10000*s, 4096, 0, "pv_list"); /* XXX */
872:
873: #if NCPUS > 1
874: /*
875: * Set up the pmap request lists
876: */
877: for (i = 0; i < NCPUS; i++) {
878: pmap_update_list_t up = &cpu_update_list[i];
879:
880: simple_lock_init(&up->lock);
881: up->count = 0;
882: }
883: #endif /* NCPUS > 1 */
884:
885: /*
886: * Indicate that the PMAP module is now fully initialized.
887: */
888: pmap_initialized = TRUE;
889: }
890:
891: #define valid_page(x) (pmap_initialized && pmap_valid_page(x))
892:
893: boolean_t pmap_verify_free(phys)
894: vm_offset_t phys;
895: {
896: pv_entry_t pv_h;
897: int pai;
898: int spl;
899: boolean_t result;
900:
901: assert(phys != vm_page_fictitious_addr);
902: if (!pmap_initialized)
903: return(TRUE);
904:
905: if (!pmap_valid_page(phys))
906: return(FALSE);
907:
908: PMAP_WRITE_LOCK(spl);
909:
910: pai = pa_index(phys);
911: pv_h = pai_to_pvh(pai);
912:
913: result = (pv_h->pmap == PMAP_NULL);
914: PMAP_WRITE_UNLOCK(spl);
915:
916: return(result);
917: }
918:
919: /*
920: * Routine: pmap_page_table_page_alloc
921: *
922: * Allocates a new physical page to be used as a page-table page.
923: *
924: * Must be called with the pmap system and the pmap unlocked,
925: * since these must be unlocked to use vm_page_grab.
926: */
927: vm_offset_t
928: pmap_page_table_page_alloc()
929: {
930: register vm_page_t m;
931: register vm_offset_t pa;
932:
933: check_simple_locks();
934:
935: /*
936: * We cannot allocate the pmap_object in pmap_init,
937: * because it is called before the zone package is up.
938: * Allocate it now if it is missing.
939: */
940: if (pmap_object == VM_OBJECT_NULL)
941: pmap_object = vm_object_allocate(phys_mem_max - phys_mem_min);
942:
943: /*
944: * Allocate a VM page for the level 2 page table entries.
945: */
946: while ((m = vm_page_grab(FALSE)) == VM_PAGE_NULL)
947: VM_PAGE_WAIT((void (*)()) 0);
948:
949: /*
950: * Map the page to its physical address so that it
951: * can be found later.
952: */
953: pa = m->phys_addr;
954: debug_unprotect_page(pa);
955: vm_object_lock(pmap_object);
956: vm_page_insert(m, pmap_object, pa);
957: vm_page_lock_queues();
958: vm_page_wire(m);
959: inuse_ptepages_count++;
960: vm_page_unlock_queues();
961: vm_object_unlock(pmap_object);
962:
963: #if i860
964: /*
965: * Mark the page table page(s) non-cacheable.
966: */
967: {
968: int i = ptes_per_vm_page;
969: pt_entry_t *pdp;
970:
971: pdp = pmap_pte(kernel_pmap, pa);
972: do {
973: *pdp |= INTEL_PTE_NCACHE;
974: pdp++;
975: } while (--i > 0);
976: }
977: #endif
978: return pa;
979: }
980:
981: /*
982: * Deallocate a page-table page.
983: * The page-table page must have all mappings removed,
984: * and be removed from its page directory.
985: */
986: void
987: pmap_page_table_page_dealloc(pa)
988: vm_offset_t pa;
989: {
990: vm_page_t m;
991:
992: vm_object_lock(pmap_object);
993: m = vm_page_lookup(pmap_object, pa);
994: vm_page_lock_queues();
995: vm_page_free(m);
996: inuse_ptepages_count--;
997: vm_page_unlock_queues();
998: vm_object_unlock(pmap_object);
999: }
1000:
1001: /*
1002: * Create and return a physical map.
1003: *
1004: * If the size specified for the map
1005: * is zero, the map is an actual physical
1006: * map, and may be referenced by the
1007: * hardware.
1008: *
1009: * If the size specified is non-zero,
1010: * the map will be used in software only, and
1011: * is bounded by that size.
1012: */
1013: pmap_t pmap_create(size)
1014: vm_size_t size;
1015: {
1016: register pmap_t p;
1017: register pmap_statistics_t stats;
1018:
1019: /*
1020: * A software use-only map doesn't even need a map.
1021: */
1022:
1023: if (size != 0) {
1024: return(PMAP_NULL);
1025: }
1026:
1027: /*
1028: * Allocate a pmap struct from the pmap_zone. Then allocate
1029: * the page descriptor table from the pd_zone.
1030: */
1031:
1032: p = (pmap_t) zalloc(pmap_zone);
1033: if (p == PMAP_NULL)
1034: panic("pmap_create");
1035:
1036: /* This gets a physical page with a direct-mapped address,
1037: rather than assigning a new kernel virtual address.
1038: This saves us having to do the translation at task-switch time. */
1039: p->dirbase = (pt_entry_t *) phystokv(pmap_page_table_page_alloc());
1040: #if 0
1041: if (kmem_alloc_wired(kernel_map,
1042: (vm_offset_t *)&p->dirbase, INTEL_PGBYTES)
1043: != KERN_SUCCESS)
1044: panic("pmap_create");
1045: #endif
1046:
1047: bcopy(kernel_page_dir, p->dirbase, INTEL_PGBYTES);
1048: p->ref_count = 1;
1049:
1050: simple_lock_init(&p->lock);
1051: p->cpus_using = 0;
1052:
1053: /*
1054: * Initialize statistics.
1055: */
1056:
1057: stats = &p->stats;
1058: stats->resident_count = 0;
1059: stats->wired_count = 0;
1060:
1061: return(p);
1062: }
1063:
1064: /*
1065: * Retire the given physical map from service.
1066: * Should only be called if the map contains
1067: * no valid mappings.
1068: */
1069:
1070: void pmap_destroy(p)
1071: register pmap_t p;
1072: {
1073: register pt_entry_t *pdep;
1074: register vm_offset_t pa;
1075: register int c, s;
1076: register vm_page_t m;
1077:
1078: if (p == PMAP_NULL)
1079: return;
1080:
1081: SPLVM(s);
1082: simple_lock(&p->lock);
1083: c = --p->ref_count;
1084: simple_unlock(&p->lock);
1085: SPLX(s);
1086:
1087: if (c != 0) {
1088: return; /* still in use */
1089: }
1090:
1091: /*
1092: * Free the memory maps, then the
1093: * pmap structure.
1094: */
1095: for (pdep = p->dirbase;
1096: pdep < &p->dirbase[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS)];
1097: pdep += ptes_per_vm_page) {
1098: if (*pdep & INTEL_PTE_VALID) {
1099: pa = pte_to_pa(*pdep);
1100: vm_object_lock(pmap_object);
1101: m = vm_page_lookup(pmap_object, pa);
1102: if (m == VM_PAGE_NULL)
1103: panic("pmap_destroy: pte page not in object");
1104: vm_page_lock_queues();
1105: vm_page_free(m);
1106: inuse_ptepages_count--;
1107: vm_page_unlock_queues();
1108: vm_object_unlock(pmap_object);
1109: }
1110: }
1111: /* See comment in pmap_create. */
1112: pmap_page_table_page_dealloc(kvtophys(p->dirbase));
1113: #if 0
1114: kmem_free(kernel_map, p->dirbase, INTEL_PGBYTES);
1115: #endif
1116: zfree(pmap_zone, (vm_offset_t) p);
1117: }
1118:
1119: /*
1120: * Add a reference to the specified pmap.
1121: */
1122:
1123: void pmap_reference(p)
1124: register pmap_t p;
1125: {
1126: int s;
1127: if (p != PMAP_NULL) {
1128: SPLVM(s);
1129: simple_lock(&p->lock);
1130: p->ref_count++;
1131: simple_unlock(&p->lock);
1132: SPLX(s);
1133: }
1134: }
1135:
1136: /*
1137: * Remove a range of hardware page-table entries.
1138: * The entries given are the first (inclusive)
1139: * and last (exclusive) entries for the VM pages.
1140: * The virtual address is the va for the first pte.
1141: *
1142: * The pmap must be locked.
1143: * If the pmap is not the kernel pmap, the range must lie
1144: * entirely within one pte-page. This is NOT checked.
1145: * Assumes that the pte-page exists.
1146: */
1147:
1148: /* static */
1149: void pmap_remove_range(pmap, va, spte, epte)
1150: pmap_t pmap;
1151: vm_offset_t va;
1152: pt_entry_t *spte;
1153: pt_entry_t *epte;
1154: {
1155: register pt_entry_t *cpte;
1156: int num_removed, num_unwired;
1157: int pai;
1158: vm_offset_t pa;
1159:
1160: #if DEBUG_PTE_PAGE
1161: if (pmap != kernel_pmap)
1162: ptep_check(get_pte_page(spte));
1163: #endif /* DEBUG_PTE_PAGE */
1164: num_removed = 0;
1165: num_unwired = 0;
1166:
1167: for (cpte = spte; cpte < epte;
1168: cpte += ptes_per_vm_page, va += PAGE_SIZE) {
1169:
1170: if (*cpte == 0)
1171: continue;
1172: pa = pte_to_pa(*cpte);
1173:
1174: num_removed++;
1175: if (*cpte & INTEL_PTE_WIRED)
1176: num_unwired++;
1177:
1178: if (!valid_page(pa)) {
1179:
1180: /*
1181: * Outside range of managed physical memory.
1182: * Just remove the mappings.
1183: */
1184: register int i = ptes_per_vm_page;
1185: register pt_entry_t *lpte = cpte;
1186: do {
1187: *lpte = 0;
1188: lpte++;
1189: } while (--i > 0);
1190: continue;
1191: }
1192:
1193: pai = pa_index(pa);
1194: LOCK_PVH(pai);
1195:
1196: /*
1197: * Get the modify and reference bits.
1198: */
1199: {
1200: register int i;
1201: register pt_entry_t *lpte;
1202:
1203: i = ptes_per_vm_page;
1204: lpte = cpte;
1205: do {
1206: pmap_phys_attributes[pai] |=
1207: *lpte & (PHYS_MODIFIED|PHYS_REFERENCED);
1208: *lpte = 0;
1209: lpte++;
1210: } while (--i > 0);
1211: }
1212:
1213: /*
1214: * Remove the mapping from the pvlist for
1215: * this physical page.
1216: */
1217: {
1218: register pv_entry_t pv_h, prev, cur;
1219:
1220: pv_h = pai_to_pvh(pai);
1221: if (pv_h->pmap == PMAP_NULL) {
1222: panic("pmap_remove: null pv_list!");
1223: }
1224: if (pv_h->va == va && pv_h->pmap == pmap) {
1225: /*
1226: * Header is the pv_entry. Copy the next one
1227: * to header and free the next one (we cannot
1228: * free the header)
1229: */
1230: cur = pv_h->next;
1231: if (cur != PV_ENTRY_NULL) {
1232: *pv_h = *cur;
1233: PV_FREE(cur);
1234: }
1235: else {
1236: pv_h->pmap = PMAP_NULL;
1237: }
1238: }
1239: else {
1240: cur = pv_h;
1241: do {
1242: prev = cur;
1243: if ((cur = prev->next) == PV_ENTRY_NULL) {
1244: panic("pmap-remove: mapping not in pv_list!");
1245: }
1246: } while (cur->va != va || cur->pmap != pmap);
1247: prev->next = cur->next;
1248: PV_FREE(cur);
1249: }
1250: UNLOCK_PVH(pai);
1251: }
1252: }
1253:
1254: /*
1255: * Update the counts
1256: */
1257: pmap->stats.resident_count -= num_removed;
1258: pmap->stats.wired_count -= num_unwired;
1259: }
1260:
1261: /*
1262: * Remove the given range of addresses
1263: * from the specified map.
1264: *
1265: * It is assumed that the start and end are properly
1266: * rounded to the hardware page size.
1267: */
1268:
1269: void pmap_remove(map, s, e)
1270: pmap_t map;
1271: vm_offset_t s, e;
1272: {
1273: int spl;
1274: register pt_entry_t *pde;
1275: register pt_entry_t *spte, *epte;
1276: vm_offset_t l;
1277:
1278: if (map == PMAP_NULL)
1279: return;
1280:
1281: PMAP_READ_LOCK(map, spl);
1282:
1283: /*
1284: * Invalidate the translation buffer first
1285: */
1286: PMAP_UPDATE_TLBS(map, s, e);
1287:
1288: pde = pmap_pde(map, s);
1289: while (s < e) {
1290: l = (s + PDE_MAPPED_SIZE) & ~(PDE_MAPPED_SIZE-1);
1291: if (l > e)
1292: l = e;
1293: if (*pde & INTEL_PTE_VALID) {
1294: spte = (pt_entry_t *)ptetokv(*pde);
1295: spte = &spte[ptenum(s)];
1296: epte = &spte[intel_btop(l-s)];
1297: pmap_remove_range(map, s, spte, epte);
1298: }
1299: s = l;
1300: pde++;
1301: }
1302:
1303: PMAP_READ_UNLOCK(map, spl);
1304: }
1305:
1306: /*
1307: * Routine: pmap_page_protect
1308: *
1309: * Function:
1310: * Lower the permission for all mappings to a given
1311: * page.
1312: */
1313: void pmap_page_protect(phys, prot)
1314: vm_offset_t phys;
1315: vm_prot_t prot;
1316: {
1317: pv_entry_t pv_h, prev;
1318: register pv_entry_t pv_e;
1319: register pt_entry_t *pte;
1320: int pai;
1321: register pmap_t pmap;
1322: int spl;
1323: boolean_t remove;
1324:
1325: assert(phys != vm_page_fictitious_addr);
1326: if (!valid_page(phys)) {
1327: /*
1328: * Not a managed page.
1329: */
1330: return;
1331: }
1332:
1333: /*
1334: * Determine the new protection.
1335: */
1336: switch (prot) {
1337: case VM_PROT_READ:
1338: case VM_PROT_READ|VM_PROT_EXECUTE:
1339: remove = FALSE;
1340: break;
1341: case VM_PROT_ALL:
1342: return; /* nothing to do */
1343: default:
1344: remove = TRUE;
1345: break;
1346: }
1347:
1348: /*
1349: * Lock the pmap system first, since we will be changing
1350: * several pmaps.
1351: */
1352:
1353: PMAP_WRITE_LOCK(spl);
1354:
1355: pai = pa_index(phys);
1356: pv_h = pai_to_pvh(pai);
1357:
1358: /*
1359: * Walk down PV list, changing or removing all mappings.
1360: * We do not have to lock the pv_list because we have
1361: * the entire pmap system locked.
1362: */
1363: if (pv_h->pmap != PMAP_NULL) {
1364:
1365: prev = pv_e = pv_h;
1366: do {
1367: pmap = pv_e->pmap;
1368: /*
1369: * Lock the pmap to block pmap_extract and similar routines.
1370: */
1371: simple_lock(&pmap->lock);
1372:
1373: {
1374: register vm_offset_t va;
1375:
1376: va = pv_e->va;
1377: pte = pmap_pte(pmap, va);
1378:
1379: /*
1380: * Consistency checks.
1381: */
1382: /* assert(*pte & INTEL_PTE_VALID); XXX */
1383: /* assert(pte_to_phys(*pte) == phys); */
1384:
1385: /*
1386: * Invalidate TLBs for all CPUs using this mapping.
1387: */
1388: PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE);
1389: }
1390:
1391: /*
1392: * Remove the mapping if new protection is NONE
1393: * or if write-protecting a kernel mapping.
1394: */
1395: if (remove || pmap == kernel_pmap) {
1396: /*
1397: * Remove the mapping, collecting any modify bits.
1398: */
1399: if (*pte & INTEL_PTE_WIRED)
1400: panic("pmap_remove_all removing a wired page");
1401:
1402: {
1403: register int i = ptes_per_vm_page;
1404:
1405: do {
1406: pmap_phys_attributes[pai] |=
1407: *pte & (PHYS_MODIFIED|PHYS_REFERENCED);
1408: *pte++ = 0;
1409: } while (--i > 0);
1410: }
1411:
1412: pmap->stats.resident_count--;
1413:
1414: /*
1415: * Remove the pv_entry.
1416: */
1417: if (pv_e == pv_h) {
1418: /*
1419: * Fix up head later.
1420: */
1421: pv_h->pmap = PMAP_NULL;
1422: }
1423: else {
1424: /*
1425: * Delete this entry.
1426: */
1427: prev->next = pv_e->next;
1428: PV_FREE(pv_e);
1429: }
1430: }
1431: else {
1432: /*
1433: * Write-protect.
1434: */
1435: register int i = ptes_per_vm_page;
1436:
1437: do {
1438: *pte &= ~INTEL_PTE_WRITE;
1439: pte++;
1440: } while (--i > 0);
1441:
1442: /*
1443: * Advance prev.
1444: */
1445: prev = pv_e;
1446: }
1447:
1448: simple_unlock(&pmap->lock);
1449:
1450: } while ((pv_e = prev->next) != PV_ENTRY_NULL);
1451:
1452: /*
1453: * If pv_head mapping was removed, fix it up.
1454: */
1455: if (pv_h->pmap == PMAP_NULL) {
1456: pv_e = pv_h->next;
1457: if (pv_e != PV_ENTRY_NULL) {
1458: *pv_h = *pv_e;
1459: PV_FREE(pv_e);
1460: }
1461: }
1462: }
1463:
1464: PMAP_WRITE_UNLOCK(spl);
1465: }
1466:
1467: /*
1468: * Set the physical protection on the
1469: * specified range of this map as requested.
1470: * Will not increase permissions.
1471: */
1472: void pmap_protect(map, s, e, prot)
1473: pmap_t map;
1474: vm_offset_t s, e;
1475: vm_prot_t prot;
1476: {
1477: register pt_entry_t *pde;
1478: register pt_entry_t *spte, *epte;
1479: vm_offset_t l;
1480: int spl;
1481:
1482: if (map == PMAP_NULL)
1483: return;
1484:
1485: /*
1486: * Determine the new protection.
1487: */
1488: switch (prot) {
1489: case VM_PROT_READ:
1490: case VM_PROT_READ|VM_PROT_EXECUTE:
1491: break;
1492: case VM_PROT_READ|VM_PROT_WRITE:
1493: case VM_PROT_ALL:
1494: return; /* nothing to do */
1495: default:
1496: pmap_remove(map, s, e);
1497: return;
1498: }
1499:
1500: /*
1501: * If write-protecting in the kernel pmap,
1502: * remove the mappings; the i386 ignores
1503: * the write-permission bit in kernel mode.
1504: *
1505: * XXX should be #if'd for i386
1506: */
1507: if (map == kernel_pmap) {
1508: pmap_remove(map, s, e);
1509: return;
1510: }
1511:
1512: SPLVM(spl);
1513: simple_lock(&map->lock);
1514:
1515: /*
1516: * Invalidate the translation buffer first
1517: */
1518: PMAP_UPDATE_TLBS(map, s, e);
1519:
1520: pde = pmap_pde(map, s);
1521: while (s < e) {
1522: l = (s + PDE_MAPPED_SIZE) & ~(PDE_MAPPED_SIZE-1);
1523: if (l > e)
1524: l = e;
1525: if (*pde & INTEL_PTE_VALID) {
1526: spte = (pt_entry_t *)ptetokv(*pde);
1527: spte = &spte[ptenum(s)];
1528: epte = &spte[intel_btop(l-s)];
1529:
1530: while (spte < epte) {
1531: if (*spte & INTEL_PTE_VALID)
1532: *spte &= ~INTEL_PTE_WRITE;
1533: spte++;
1534: }
1535: }
1536: s = l;
1537: pde++;
1538: }
1539:
1540: simple_unlock(&map->lock);
1541: SPLX(spl);
1542: }
1543:
1544: /*
1545: * Insert the given physical page (p) at
1546: * the specified virtual address (v) in the
1547: * target physical map with the protection requested.
1548: *
1549: * If specified, the page will be wired down, meaning
1550: * that the related pte can not be reclaimed.
1551: *
1552: * NB: This is the only routine which MAY NOT lazy-evaluate
1553: * or lose information. That is, this routine must actually
1554: * insert this page into the given map NOW.
1555: */
1556: void pmap_enter(pmap, v, pa, prot, wired)
1557: register pmap_t pmap;
1558: vm_offset_t v;
1559: register vm_offset_t pa;
1560: vm_prot_t prot;
1561: boolean_t wired;
1562: {
1563: register pt_entry_t *pte;
1564: register pv_entry_t pv_h;
1565: register int i, pai;
1566: pv_entry_t pv_e;
1567: pt_entry_t template;
1568: int spl;
1569: vm_offset_t old_pa;
1570:
1571: assert(pa != vm_page_fictitious_addr);
1572: if (pmap_debug) printf("pmap(%x, %x)\n", v, pa);
1573: if (pmap == PMAP_NULL)
1574: return;
1575:
1576: if (pmap == kernel_pmap && (prot & VM_PROT_WRITE) == 0
1577: && !wired /* hack for io_wire */ ) {
1578: /*
1579: * Because the 386 ignores write protection in kernel mode,
1580: * we cannot enter a read-only kernel mapping, and must
1581: * remove an existing mapping if changing it.
1582: *
1583: * XXX should be #if'd for i386
1584: */
1585: PMAP_READ_LOCK(pmap, spl);
1586:
1587: pte = pmap_pte(pmap, v);
1588: if (pte != PT_ENTRY_NULL && *pte != 0) {
1589: /*
1590: * Invalidate the translation buffer,
1591: * then remove the mapping.
1592: */
1593: PMAP_UPDATE_TLBS(pmap, v, v + PAGE_SIZE);
1594: pmap_remove_range(pmap, v, pte,
1595: pte + ptes_per_vm_page);
1596: }
1597: PMAP_READ_UNLOCK(pmap, spl);
1598: return;
1599: }
1600:
1601: /*
1602: * Must allocate a new pvlist entry while we're unlocked;
1603: * zalloc may cause pageout (which will lock the pmap system).
1604: * If we determine we need a pvlist entry, we will unlock
1605: * and allocate one. Then we will retry, throughing away
1606: * the allocated entry later (if we no longer need it).
1607: */
1608: pv_e = PV_ENTRY_NULL;
1609: Retry:
1610: PMAP_READ_LOCK(pmap, spl);
1611:
1612: /*
1613: * Expand pmap to include this pte. Assume that
1614: * pmap is always expanded to include enough hardware
1615: * pages to map one VM page.
1616: */
1617:
1618: while ((pte = pmap_pte(pmap, v)) == PT_ENTRY_NULL) {
1619: /*
1620: * Need to allocate a new page-table page.
1621: */
1622: vm_offset_t ptp;
1623: pt_entry_t *pdp;
1624: int i;
1625:
1626: if (pmap == kernel_pmap) {
1627: /*
1628: * Would have to enter the new page-table page in
1629: * EVERY pmap.
1630: */
1631: panic("pmap_expand kernel pmap to %#x", v);
1632: }
1633:
1634: /*
1635: * Unlock the pmap and allocate a new page-table page.
1636: */
1637: PMAP_READ_UNLOCK(pmap, spl);
1638:
1639: ptp = pmap_page_table_page_alloc();
1640: /*
1641: * Zero the page.
1642: */
1643: bzero(phystokv(ptp), PAGE_SIZE);
1644:
1645: /*
1646: * Re-lock the pmap and check that another thread has
1647: * not already allocated the page-table page. If it
1648: * has, discard the new page-table page (and try
1649: * again to make sure).
1650: */
1651: PMAP_READ_LOCK(pmap, spl);
1652:
1653: if (pmap_pte(pmap, v) != PT_ENTRY_NULL) {
1654: /*
1655: * Oops...
1656: */
1657: PMAP_READ_UNLOCK(pmap, spl);
1658: pmap_page_table_page_dealloc(ptp);
1659: PMAP_READ_LOCK(pmap, spl);
1660: continue;
1661: }
1662:
1663: /*
1664: * Enter the new page table page in the page directory.
1665: */
1666: i = ptes_per_vm_page;
1667: /*XX pdp = &pmap->dirbase[pdenum(v) & ~(i-1)];*/
1668: pdp = pmap_pde(pmap, v);
1669: do {
1670: *pdp = pa_to_pte(ptp) | INTEL_PTE_VALID
1671: | INTEL_PTE_USER
1672: | INTEL_PTE_WRITE;
1673: pdp++;
1674: ptp += INTEL_PGBYTES;
1675: } while (--i > 0);
1676: #if i860
1677: /*
1678: * Flush the data cache.
1679: */
1680: flush();
1681: #endif /* i860 */
1682:
1683: /*
1684: * Now, get the address of the page-table entry.
1685: */
1686: continue;
1687: }
1688:
1689: template = pmap == kernel_pmap ? kernel_pte_global : 0;
1690:
1691: /*
1692: * Special case if the physical page is already mapped
1693: * at this address.
1694: */
1695: old_pa = pte_to_pa(*pte);
1696: if (*pte && old_pa == pa) {
1697: /*
1698: * May be changing its wired attribute or protection
1699: */
1700:
1701: if (wired && !(*pte & INTEL_PTE_WIRED))
1702: pmap->stats.wired_count++;
1703: else if (!wired && (*pte & INTEL_PTE_WIRED))
1704: pmap->stats.wired_count--;
1705:
1706: template |= pa_to_pte(pa) | INTEL_PTE_VALID;
1707: if (pmap != kernel_pmap)
1708: template |= INTEL_PTE_USER;
1709: if (prot & VM_PROT_WRITE)
1710: template |= INTEL_PTE_WRITE;
1711: if (wired)
1712: template |= INTEL_PTE_WIRED;
1713: PMAP_UPDATE_TLBS(pmap, v, v + PAGE_SIZE);
1714: i = ptes_per_vm_page;
1715: do {
1716: if (*pte & INTEL_PTE_MOD)
1717: template |= INTEL_PTE_MOD;
1718: WRITE_PTE(pte, template)
1719: pte++;
1720: pte_increment_pa(template);
1721: } while (--i > 0);
1722: }
1723: else {
1724:
1725: /*
1726: * Remove old mapping from the PV list if necessary.
1727: */
1728: if (*pte) {
1729: /*
1730: * Invalidate the translation buffer,
1731: * then remove the mapping.
1732: */
1733: PMAP_UPDATE_TLBS(pmap, v, v + PAGE_SIZE);
1734:
1735: /*
1736: * Don't free the pte page if removing last
1737: * mapping - we will immediately replace it.
1738: */
1739: pmap_remove_range(pmap, v, pte,
1740: pte + ptes_per_vm_page);
1741: }
1742:
1743: if (valid_page(pa)) {
1744:
1745: /*
1746: * Enter the mapping in the PV list for this
1747: * physical page.
1748: */
1749:
1750: pai = pa_index(pa);
1751: LOCK_PVH(pai);
1752: pv_h = pai_to_pvh(pai);
1753:
1754: if (pv_h->pmap == PMAP_NULL) {
1755: /*
1756: * No mappings yet
1757: */
1758: pv_h->va = v;
1759: pv_h->pmap = pmap;
1760: pv_h->next = PV_ENTRY_NULL;
1761: }
1762: else {
1763: #if DEBUG
1764: {
1765: /* check that this mapping is not already there */
1766: pv_entry_t e = pv_h;
1767: while (e != PV_ENTRY_NULL) {
1768: if (e->pmap == pmap && e->va == v)
1769: panic("pmap_enter: already in pv_list");
1770: e = e->next;
1771: }
1772: }
1773: #endif /* DEBUG */
1774:
1775: /*
1776: * Add new pv_entry after header.
1777: */
1778: if (pv_e == PV_ENTRY_NULL) {
1779: PV_ALLOC(pv_e);
1780: if (pv_e == PV_ENTRY_NULL) {
1781: UNLOCK_PVH(pai);
1782: PMAP_READ_UNLOCK(pmap, spl);
1783:
1784: /*
1785: * Refill from zone.
1786: */
1787: pv_e = (pv_entry_t) zalloc(pv_list_zone);
1788: goto Retry;
1789: }
1790: }
1791: pv_e->va = v;
1792: pv_e->pmap = pmap;
1793: pv_e->next = pv_h->next;
1794: pv_h->next = pv_e;
1795: /*
1796: * Remember that we used the pvlist entry.
1797: */
1798: pv_e = PV_ENTRY_NULL;
1799: }
1800: UNLOCK_PVH(pai);
1801: }
1802:
1803: /*
1804: * And count the mapping.
1805: */
1806:
1807: pmap->stats.resident_count++;
1808: if (wired)
1809: pmap->stats.wired_count++;
1810:
1811: /*
1812: * Build a template to speed up entering -
1813: * only the pfn changes.
1814: */
1815: template |= pa_to_pte(pa) | INTEL_PTE_VALID;
1816: if (pmap != kernel_pmap)
1817: template |= INTEL_PTE_USER;
1818: if (prot & VM_PROT_WRITE)
1819: template |= INTEL_PTE_WRITE;
1820: if (wired)
1821: template |= INTEL_PTE_WIRED;
1822: i = ptes_per_vm_page;
1823: do {
1824: WRITE_PTE(pte, template)
1825: pte++;
1826: pte_increment_pa(template);
1827: } while (--i > 0);
1828: }
1829:
1830: if (pv_e != PV_ENTRY_NULL) {
1831: PV_FREE(pv_e);
1832: }
1833:
1834: PMAP_READ_UNLOCK(pmap, spl);
1835: }
1836:
1837: /*
1838: * Routine: pmap_change_wiring
1839: * Function: Change the wiring attribute for a map/virtual-address
1840: * pair.
1841: * In/out conditions:
1842: * The mapping must already exist in the pmap.
1843: */
1844: void pmap_change_wiring(map, v, wired)
1845: register pmap_t map;
1846: vm_offset_t v;
1847: boolean_t wired;
1848: {
1849: register pt_entry_t *pte;
1850: register int i;
1851: int spl;
1852:
1853: /*
1854: * We must grab the pmap system lock because we may
1855: * change a pte_page queue.
1856: */
1857: PMAP_READ_LOCK(map, spl);
1858:
1859: if ((pte = pmap_pte(map, v)) == PT_ENTRY_NULL)
1860: panic("pmap_change_wiring: pte missing");
1861:
1862: if (wired && !(*pte & INTEL_PTE_WIRED)) {
1863: /*
1864: * wiring down mapping
1865: */
1866: map->stats.wired_count++;
1867: i = ptes_per_vm_page;
1868: do {
1869: *pte++ |= INTEL_PTE_WIRED;
1870: } while (--i > 0);
1871: }
1872: else if (!wired && (*pte & INTEL_PTE_WIRED)) {
1873: /*
1874: * unwiring mapping
1875: */
1876: map->stats.wired_count--;
1877: i = ptes_per_vm_page;
1878: do {
1879: *pte &= ~INTEL_PTE_WIRED;
1880: } while (--i > 0);
1881: }
1882:
1883: PMAP_READ_UNLOCK(map, spl);
1884: }
1885:
1886: /*
1887: * Routine: pmap_extract
1888: * Function:
1889: * Extract the physical page address associated
1890: * with the given map/virtual_address pair.
1891: */
1892:
1893: vm_offset_t pmap_extract(pmap, va)
1894: register pmap_t pmap;
1895: vm_offset_t va;
1896: {
1897: register pt_entry_t *pte;
1898: register vm_offset_t pa;
1899: int spl;
1900:
1901: SPLVM(spl);
1902: simple_lock(&pmap->lock);
1903: if ((pte = pmap_pte(pmap, va)) == PT_ENTRY_NULL)
1904: pa = (vm_offset_t) 0;
1905: else if (!(*pte & INTEL_PTE_VALID))
1906: pa = (vm_offset_t) 0;
1907: else
1908: pa = pte_to_pa(*pte) + (va & INTEL_OFFMASK);
1909: simple_unlock(&pmap->lock);
1910: SPLX(spl);
1911: return(pa);
1912: }
1913:
1914: /*
1915: * Copy the range specified by src_addr/len
1916: * from the source map to the range dst_addr/len
1917: * in the destination map.
1918: *
1919: * This routine is only advisory and need not do anything.
1920: */
1921: #if 0
1922: void pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr)
1923: pmap_t dst_pmap;
1924: pmap_t src_pmap;
1925: vm_offset_t dst_addr;
1926: vm_size_t len;
1927: vm_offset_t src_addr;
1928: {
1929: #ifdef lint
1930: dst_pmap++; src_pmap++; dst_addr++; len++; src_addr++;
1931: #endif /* lint */
1932: }
1933: #endif /* 0 */
1934:
1935: /*
1936: * Routine: pmap_collect
1937: * Function:
1938: * Garbage collects the physical map system for
1939: * pages which are no longer used.
1940: * Success need not be guaranteed -- that is, there
1941: * may well be pages which are not referenced, but
1942: * others may be collected.
1943: * Usage:
1944: * Called by the pageout daemon when pages are scarce.
1945: */
1946: void pmap_collect(p)
1947: pmap_t p;
1948: {
1949: register pt_entry_t *pdp, *ptp;
1950: pt_entry_t *eptp;
1951: vm_offset_t pa;
1952: int spl, wired;
1953:
1954: if (p == PMAP_NULL)
1955: return;
1956:
1957: if (p == kernel_pmap)
1958: return;
1959:
1960: /*
1961: * Garbage collect map.
1962: */
1963: PMAP_READ_LOCK(p, spl);
1964: PMAP_UPDATE_TLBS(p, VM_MIN_ADDRESS, VM_MAX_ADDRESS);
1965:
1966: for (pdp = p->dirbase;
1967: pdp < &p->dirbase[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS)];
1968: pdp += ptes_per_vm_page)
1969: {
1970: if (*pdp & INTEL_PTE_VALID) {
1971:
1972: pa = pte_to_pa(*pdp);
1973: ptp = (pt_entry_t *)phystokv(pa);
1974: eptp = ptp + NPTES*ptes_per_vm_page;
1975:
1976: /*
1977: * If the pte page has any wired mappings, we cannot
1978: * free it.
1979: */
1980: wired = 0;
1981: {
1982: register pt_entry_t *ptep;
1983: for (ptep = ptp; ptep < eptp; ptep++) {
1984: if (*ptep & INTEL_PTE_WIRED) {
1985: wired = 1;
1986: break;
1987: }
1988: }
1989: }
1990: if (!wired) {
1991: /*
1992: * Remove the virtual addresses mapped by this pte page.
1993: */
1994: { /*XXX big hack*/
1995: vm_offset_t va = pdenum2lin(pdp - p->dirbase);
1996: if (p == kernel_pmap)
1997: va = lintokv(va);
1998: pmap_remove_range(p,
1999: va,
2000: ptp,
2001: eptp);
2002: }
2003:
2004: /*
2005: * Invalidate the page directory pointer.
2006: */
2007: {
2008: register int i = ptes_per_vm_page;
2009: register pt_entry_t *pdep = pdp;
2010: do {
2011: *pdep++ = 0;
2012: } while (--i > 0);
2013: }
2014:
2015: PMAP_READ_UNLOCK(p, spl);
2016:
2017: /*
2018: * And free the pte page itself.
2019: */
2020: {
2021: register vm_page_t m;
2022:
2023: vm_object_lock(pmap_object);
2024: m = vm_page_lookup(pmap_object, pa);
2025: if (m == VM_PAGE_NULL)
2026: panic("pmap_collect: pte page not in object");
2027: vm_page_lock_queues();
2028: vm_page_free(m);
2029: inuse_ptepages_count--;
2030: vm_page_unlock_queues();
2031: vm_object_unlock(pmap_object);
2032: }
2033:
2034: PMAP_READ_LOCK(p, spl);
2035: }
2036: }
2037: }
2038: PMAP_READ_UNLOCK(p, spl);
2039: return;
2040:
2041: }
2042:
2043: /*
2044: * Routine: pmap_activate
2045: * Function:
2046: * Binds the given physical map to the given
2047: * processor, and returns a hardware map description.
2048: */
2049: #if 0
2050: void pmap_activate(my_pmap, th, my_cpu)
2051: register pmap_t my_pmap;
2052: thread_t th;
2053: int my_cpu;
2054: {
2055: PMAP_ACTIVATE(my_pmap, th, my_cpu);
2056: }
2057: #endif /* 0 */
2058:
2059: /*
2060: * Routine: pmap_deactivate
2061: * Function:
2062: * Indicates that the given physical map is no longer
2063: * in use on the specified processor. (This is a macro
2064: * in pmap.h)
2065: */
2066: #if 0
2067: void pmap_deactivate(pmap, th, which_cpu)
2068: pmap_t pmap;
2069: thread_t th;
2070: int which_cpu;
2071: {
2072: #ifdef lint
2073: pmap++; th++; which_cpu++;
2074: #endif /* lint */
2075: PMAP_DEACTIVATE(pmap, th, which_cpu);
2076: }
2077: #endif /* 0 */
2078:
2079: /*
2080: * Routine: pmap_kernel
2081: * Function:
2082: * Returns the physical map handle for the kernel.
2083: */
2084: #if 0
2085: pmap_t pmap_kernel()
2086: {
2087: return (kernel_pmap);
2088: }
2089: #endif /* 0 */
2090:
2091: /*
2092: * pmap_zero_page zeros the specified (machine independent) page.
2093: * See machine/phys.c or machine/phys.s for implementation.
2094: */
2095: #if 0
2096: pmap_zero_page(phys)
2097: register vm_offset_t phys;
2098: {
2099: register int i;
2100:
2101: assert(phys != vm_page_fictitious_addr);
2102: i = PAGE_SIZE / INTEL_PGBYTES;
2103: phys = intel_pfn(phys);
2104:
2105: while (i--)
2106: zero_phys(phys++);
2107: }
2108: #endif /* 0 */
2109:
2110: /*
2111: * pmap_copy_page copies the specified (machine independent) page.
2112: * See machine/phys.c or machine/phys.s for implementation.
2113: */
2114: #if 0
2115: pmap_copy_page(src, dst)
2116: vm_offset_t src, dst;
2117: {
2118: int i;
2119:
2120: assert(src != vm_page_fictitious_addr);
2121: assert(dst != vm_page_fictitious_addr);
2122: i = PAGE_SIZE / INTEL_PGBYTES;
2123:
2124: while (i--) {
2125: copy_phys(intel_pfn(src), intel_pfn(dst));
2126: src += INTEL_PGBYTES;
2127: dst += INTEL_PGBYTES;
2128: }
2129: }
2130: #endif /* 0 */
2131:
2132: /*
2133: * Routine: pmap_pageable
2134: * Function:
2135: * Make the specified pages (by pmap, offset)
2136: * pageable (or not) as requested.
2137: *
2138: * A page which is not pageable may not take
2139: * a fault; therefore, its page table entry
2140: * must remain valid for the duration.
2141: *
2142: * This routine is merely advisory; pmap_enter
2143: * will specify that these pages are to be wired
2144: * down (or not) as appropriate.
2145: */
2146: pmap_pageable(pmap, start, end, pageable)
2147: pmap_t pmap;
2148: vm_offset_t start;
2149: vm_offset_t end;
2150: boolean_t pageable;
2151: {
2152: #ifdef lint
2153: pmap++; start++; end++; pageable++;
2154: #endif /* lint */
2155: }
2156:
2157: /*
2158: * Clear specified attribute bits.
2159: */
2160: void
2161: phys_attribute_clear(phys, bits)
2162: vm_offset_t phys;
2163: int bits;
2164: {
2165: pv_entry_t pv_h;
2166: register pv_entry_t pv_e;
2167: register pt_entry_t *pte;
2168: int pai;
2169: register pmap_t pmap;
2170: int spl;
2171:
2172: assert(phys != vm_page_fictitious_addr);
2173: if (!valid_page(phys)) {
2174: /*
2175: * Not a managed page.
2176: */
2177: return;
2178: }
2179:
2180: /*
2181: * Lock the pmap system first, since we will be changing
2182: * several pmaps.
2183: */
2184:
2185: PMAP_WRITE_LOCK(spl);
2186:
2187: pai = pa_index(phys);
2188: pv_h = pai_to_pvh(pai);
2189:
2190: /*
2191: * Walk down PV list, clearing all modify or reference bits.
2192: * We do not have to lock the pv_list because we have
2193: * the entire pmap system locked.
2194: */
2195: if (pv_h->pmap != PMAP_NULL) {
2196: /*
2197: * There are some mappings.
2198: */
2199: for (pv_e = pv_h; pv_e != PV_ENTRY_NULL; pv_e = pv_e->next) {
2200:
2201: pmap = pv_e->pmap;
2202: /*
2203: * Lock the pmap to block pmap_extract and similar routines.
2204: */
2205: simple_lock(&pmap->lock);
2206:
2207: {
2208: register vm_offset_t va;
2209:
2210: va = pv_e->va;
2211: pte = pmap_pte(pmap, va);
2212:
2213: #if 0
2214: /*
2215: * Consistency checks.
2216: */
2217: assert(*pte & INTEL_PTE_VALID);
2218: /* assert(pte_to_phys(*pte) == phys); */
2219: #endif
2220:
2221: /*
2222: * Invalidate TLBs for all CPUs using this mapping.
2223: */
2224: PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE);
2225: }
2226:
2227: /*
2228: * Clear modify or reference bits.
2229: */
2230: {
2231: register int i = ptes_per_vm_page;
2232: do {
2233: *pte &= ~bits;
2234: } while (--i > 0);
2235: }
2236: simple_unlock(&pmap->lock);
2237: }
2238: }
2239:
2240: pmap_phys_attributes[pai] &= ~bits;
2241:
2242: PMAP_WRITE_UNLOCK(spl);
2243: }
2244:
2245: /*
2246: * Check specified attribute bits.
2247: */
2248: boolean_t
2249: phys_attribute_test(phys, bits)
2250: vm_offset_t phys;
2251: int bits;
2252: {
2253: pv_entry_t pv_h;
2254: register pv_entry_t pv_e;
2255: register pt_entry_t *pte;
2256: int pai;
2257: register pmap_t pmap;
2258: int spl;
2259:
2260: assert(phys != vm_page_fictitious_addr);
2261: if (!valid_page(phys)) {
2262: /*
2263: * Not a managed page.
2264: */
2265: return (FALSE);
2266: }
2267:
2268: /*
2269: * Lock the pmap system first, since we will be checking
2270: * several pmaps.
2271: */
2272:
2273: PMAP_WRITE_LOCK(spl);
2274:
2275: pai = pa_index(phys);
2276: pv_h = pai_to_pvh(pai);
2277:
2278: if (pmap_phys_attributes[pai] & bits) {
2279: PMAP_WRITE_UNLOCK(spl);
2280: return (TRUE);
2281: }
2282:
2283: /*
2284: * Walk down PV list, checking all mappings.
2285: * We do not have to lock the pv_list because we have
2286: * the entire pmap system locked.
2287: */
2288: if (pv_h->pmap != PMAP_NULL) {
2289: /*
2290: * There are some mappings.
2291: */
2292: for (pv_e = pv_h; pv_e != PV_ENTRY_NULL; pv_e = pv_e->next) {
2293:
2294: pmap = pv_e->pmap;
2295: /*
2296: * Lock the pmap to block pmap_extract and similar routines.
2297: */
2298: simple_lock(&pmap->lock);
2299:
2300: {
2301: register vm_offset_t va;
2302:
2303: va = pv_e->va;
2304: pte = pmap_pte(pmap, va);
2305:
2306: #if 0
2307: /*
2308: * Consistency checks.
2309: */
2310: assert(*pte & INTEL_PTE_VALID);
2311: /* assert(pte_to_phys(*pte) == phys); */
2312: #endif
2313: }
2314:
2315: /*
2316: * Check modify or reference bits.
2317: */
2318: {
2319: register int i = ptes_per_vm_page;
2320:
2321: do {
2322: if (*pte & bits) {
2323: simple_unlock(&pmap->lock);
2324: PMAP_WRITE_UNLOCK(spl);
2325: return (TRUE);
2326: }
2327: } while (--i > 0);
2328: }
2329: simple_unlock(&pmap->lock);
2330: }
2331: }
2332: PMAP_WRITE_UNLOCK(spl);
2333: return (FALSE);
2334: }
2335:
2336: /*
2337: * Clear the modify bits on the specified physical page.
2338: */
2339:
2340: void pmap_clear_modify(phys)
2341: register vm_offset_t phys;
2342: {
2343: phys_attribute_clear(phys, PHYS_MODIFIED);
2344: }
2345:
2346: /*
2347: * pmap_is_modified:
2348: *
2349: * Return whether or not the specified physical page is modified
2350: * by any physical maps.
2351: */
2352:
2353: boolean_t pmap_is_modified(phys)
2354: register vm_offset_t phys;
2355: {
2356: return (phys_attribute_test(phys, PHYS_MODIFIED));
2357: }
2358:
2359: /*
2360: * pmap_clear_reference:
2361: *
2362: * Clear the reference bit on the specified physical page.
2363: */
2364:
2365: void pmap_clear_reference(phys)
2366: vm_offset_t phys;
2367: {
2368: phys_attribute_clear(phys, PHYS_REFERENCED);
2369: }
2370:
2371: /*
2372: * pmap_is_referenced:
2373: *
2374: * Return whether or not the specified physical page is referenced
2375: * by any physical maps.
2376: */
2377:
2378: boolean_t pmap_is_referenced(phys)
2379: vm_offset_t phys;
2380: {
2381: return (phys_attribute_test(phys, PHYS_REFERENCED));
2382: }
2383:
2384: #if NCPUS > 1
2385: /*
2386: * TLB Coherence Code (TLB "shootdown" code)
2387: *
2388: * Threads that belong to the same task share the same address space and
2389: * hence share a pmap. However, they may run on distinct cpus and thus
2390: * have distinct TLBs that cache page table entries. In order to guarantee
2391: * the TLBs are consistent, whenever a pmap is changed, all threads that
2392: * are active in that pmap must have their TLB updated. To keep track of
2393: * this information, the set of cpus that are currently using a pmap is
2394: * maintained within each pmap structure (cpus_using). Pmap_activate() and
2395: * pmap_deactivate add and remove, respectively, a cpu from this set.
2396: * Since the TLBs are not addressable over the bus, each processor must
2397: * flush its own TLB; a processor that needs to invalidate another TLB
2398: * needs to interrupt the processor that owns that TLB to signal the
2399: * update.
2400: *
2401: * Whenever a pmap is updated, the lock on that pmap is locked, and all
2402: * cpus using the pmap are signaled to invalidate. All threads that need
2403: * to activate a pmap must wait for the lock to clear to await any updates
2404: * in progress before using the pmap. They must ACQUIRE the lock to add
2405: * their cpu to the cpus_using set. An implicit assumption made
2406: * throughout the TLB code is that all kernel code that runs at or higher
2407: * than splvm blocks out update interrupts, and that such code does not
2408: * touch pageable pages.
2409: *
2410: * A shootdown interrupt serves another function besides signaling a
2411: * processor to invalidate. The interrupt routine (pmap_update_interrupt)
2412: * waits for the both the pmap lock (and the kernel pmap lock) to clear,
2413: * preventing user code from making implicit pmap updates while the
2414: * sending processor is performing its update. (This could happen via a
2415: * user data write reference that turns on the modify bit in the page
2416: * table). It must wait for any kernel updates that may have started
2417: * concurrently with a user pmap update because the IPC code
2418: * changes mappings.
2419: * Spinning on the VALUES of the locks is sufficient (rather than
2420: * having to acquire the locks) because any updates that occur subsequent
2421: * to finding the lock unlocked will be signaled via another interrupt.
2422: * (This assumes the interrupt is cleared before the low level interrupt code
2423: * calls pmap_update_interrupt()).
2424: *
2425: * The signaling processor must wait for any implicit updates in progress
2426: * to terminate before continuing with its update. Thus it must wait for an
2427: * acknowledgement of the interrupt from each processor for which such
2428: * references could be made. For maintaining this information, a set
2429: * cpus_active is used. A cpu is in this set if and only if it can
2430: * use a pmap. When pmap_update_interrupt() is entered, a cpu is removed from
2431: * this set; when all such cpus are removed, it is safe to update.
2432: *
2433: * Before attempting to acquire the update lock on a pmap, a cpu (A) must
2434: * be at least at the priority of the interprocessor interrupt
2435: * (splip<=splvm). Otherwise, A could grab a lock and be interrupted by a
2436: * kernel update; it would spin forever in pmap_update_interrupt() trying
2437: * to acquire the user pmap lock it had already acquired. Furthermore A
2438: * must remove itself from cpus_active. Otherwise, another cpu holding
2439: * the lock (B) could be in the process of sending an update signal to A,
2440: * and thus be waiting for A to remove itself from cpus_active. If A is
2441: * spinning on the lock at priority this will never happen and a deadlock
2442: * will result.
2443: */
2444:
2445: /*
2446: * Signal another CPU that it must flush its TLB
2447: */
2448: void signal_cpus(use_list, pmap, start, end)
2449: cpu_set use_list;
2450: pmap_t pmap;
2451: vm_offset_t start, end;
2452: {
2453: register int which_cpu, j;
2454: register pmap_update_list_t update_list_p;
2455:
2456: while ((which_cpu = ffs(use_list)) != 0) {
2457: which_cpu -= 1; /* convert to 0 origin */
2458:
2459: update_list_p = &cpu_update_list[which_cpu];
2460: simple_lock(&update_list_p->lock);
2461:
2462: j = update_list_p->count;
2463: if (j >= UPDATE_LIST_SIZE) {
2464: /*
2465: * list overflowed. Change last item to
2466: * indicate overflow.
2467: */
2468: update_list_p->item[UPDATE_LIST_SIZE-1].pmap = kernel_pmap;
2469: update_list_p->item[UPDATE_LIST_SIZE-1].start = VM_MIN_ADDRESS;
2470: update_list_p->item[UPDATE_LIST_SIZE-1].end = VM_MAX_KERNEL_ADDRESS;
2471: }
2472: else {
2473: update_list_p->item[j].pmap = pmap;
2474: update_list_p->item[j].start = start;
2475: update_list_p->item[j].end = end;
2476: update_list_p->count = j+1;
2477: }
2478: cpu_update_needed[which_cpu] = TRUE;
2479: simple_unlock(&update_list_p->lock);
2480:
2481: if ((cpus_idle & (1 << which_cpu)) == 0)
2482: interrupt_processor(which_cpu);
2483: use_list &= ~(1 << which_cpu);
2484: }
2485: }
2486:
2487: void process_pmap_updates(my_pmap)
2488: register pmap_t my_pmap;
2489: {
2490: register int my_cpu = cpu_number();
2491: register pmap_update_list_t update_list_p;
2492: register int j;
2493: register pmap_t pmap;
2494:
2495: update_list_p = &cpu_update_list[my_cpu];
2496: simple_lock(&update_list_p->lock);
2497:
2498: for (j = 0; j < update_list_p->count; j++) {
2499: pmap = update_list_p->item[j].pmap;
2500: if (pmap == my_pmap ||
2501: pmap == kernel_pmap) {
2502:
2503: INVALIDATE_TLB(update_list_p->item[j].start,
2504: update_list_p->item[j].end);
2505: }
2506: }
2507: update_list_p->count = 0;
2508: cpu_update_needed[my_cpu] = FALSE;
2509: simple_unlock(&update_list_p->lock);
2510: }
2511:
2512: /*
2513: * Interrupt routine for TBIA requested from other processor.
2514: */
2515: void pmap_update_interrupt()
2516: {
2517: register int my_cpu;
2518: register pmap_t my_pmap;
2519: int s;
2520:
2521: my_cpu = cpu_number();
2522:
2523: /*
2524: * Exit now if we're idle. We'll pick up the update request
2525: * when we go active, and we must not put ourselves back in
2526: * the active set because we'll never process the interrupt
2527: * while we're idle (thus hanging the system).
2528: */
2529: if (cpus_idle & (1 << my_cpu))
2530: return;
2531:
2532: if (current_thread() == THREAD_NULL)
2533: my_pmap = kernel_pmap;
2534: else {
2535: my_pmap = current_pmap();
2536: if (!pmap_in_use(my_pmap, my_cpu))
2537: my_pmap = kernel_pmap;
2538: }
2539:
2540: /*
2541: * Raise spl to splvm (above splip) to block out pmap_extract
2542: * from IO code (which would put this cpu back in the active
2543: * set).
2544: */
2545: s = splvm();
2546:
2547: do {
2548:
2549: /*
2550: * Indicate that we're not using either user or kernel
2551: * pmap.
2552: */
2553: i_bit_clear(my_cpu, &cpus_active);
2554:
2555: /*
2556: * Wait for any pmap updates in progress, on either user
2557: * or kernel pmap.
2558: */
2559: while (*(volatile int *)&my_pmap->lock.lock_data ||
2560: *(volatile int *)&kernel_pmap->lock.lock_data)
2561: continue;
2562:
2563: process_pmap_updates(my_pmap);
2564:
2565: i_bit_set(my_cpu, &cpus_active);
2566:
2567: } while (cpu_update_needed[my_cpu]);
2568:
2569: splx(s);
2570: }
2571: #else /* NCPUS > 1 */
2572: /*
2573: * Dummy routine to satisfy external reference.
2574: */
2575: void pmap_update_interrupt()
2576: {
2577: /* should never be called. */
2578: }
2579: #endif /* NCPUS > 1 */
2580:
2581: #if i860 /* akp */
2582: void set_dirbase(dirbase)
2583: register vm_offset_t dirbase;
2584: {
2585: /*flush();*/
2586: /*flush_tlb();*/
2587: flush_and_ctxsw(dirbase);
2588: }
2589: #endif /* i860 */
2590:
2591: #ifdef i386
2592: /* Unmap page 0 to trap NULL references. */
2593: void
2594: pmap_unmap_page_zero ()
2595: {
2596: int *pte;
2597:
2598: pte = (int *) pmap_pte (kernel_pmap, 0);
2599: assert (pte);
2600: *pte = 0;
2601: inval_tlb ();
2602: }
2603: #endif /* i386 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.