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