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