Annotation of sys/arch/m88k/m88k/pmap.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: pmap.c,v 1.31 2007/05/27 20:59:25 miod Exp $ */
2: /*
3: * Copyright (c) 2001-2004, Miodrag Vallat
4: * Copyright (c) 1998-2001 Steve Murphree, Jr.
5: * Copyright (c) 1996 Nivas Madhur
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by Nivas Madhur.
19: * 4. The name of the author may not be used to endorse or promote products
20: * derived from this software without specific prior written permission
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: *
33: */
34: /*
35: * Mach Operating System
36: * Copyright (c) 1991 Carnegie Mellon University
37: * Copyright (c) 1991 OMRON Corporation
38: * All Rights Reserved.
39: *
40: * Permission to use, copy, modify and distribute this software and its
41: * documentation is hereby granted, provided that both the copyright
42: * notice and this permission notice appear in all copies of the
43: * software, derivative works or modified versions, and any portions
44: * thereof, and that both notices appear in supporting documentation.
45: *
46: */
47:
48: #include <sys/param.h>
49: #include <sys/systm.h>
50: #include <sys/proc.h>
51: #include <sys/malloc.h>
52: #include <sys/pool.h>
53: #include <sys/msgbuf.h>
54: #include <sys/user.h>
55:
56: #include <machine/asm_macro.h>
57: #include <machine/cmmu.h>
58: #include <machine/cpu.h>
59: #include <machine/lock.h>
60: #include <machine/pmap_table.h>
61: #ifdef M88100
62: #include <machine/m8820x.h>
63: #endif
64:
65: #include <uvm/uvm.h>
66:
67: /*
68: * VM externals
69: */
70: extern vaddr_t avail_start;
71: extern vaddr_t virtual_avail, virtual_end;
72: extern vaddr_t last_addr;
73:
74: /*
75: * Macros to operate pm_cpus field
76: */
77: #define SETBIT_CPUSET(cpu_number, cpuset) (*(cpuset)) |= (1 << (cpu_number));
78: #define CLRBIT_CPUSET(cpu_number, cpuset) (*(cpuset)) &= ~(1 << (cpu_number));
79:
80: #ifdef DEBUG
81: /*
82: * Static variables, functions and variables for debugging
83: */
84:
85: /*
86: * conditional debugging
87: */
88: #define CD_FULL 0x02
89:
90: #define CD_ACTIVATE 0x0000004 /* pmap_activate */
91: #define CD_KMAP 0x0000008 /* pmap_expand_kmap */
92: #define CD_MAP 0x0000010 /* pmap_map */
93: #define CD_CACHE 0x0000020 /* pmap_cache_ctrl */
94: #define CD_INIT 0x0000080 /* pmap_init */
95: #define CD_CREAT 0x0000100 /* pmap_create */
96: #define CD_FREE 0x0000200 /* pmap_release */
97: #define CD_DESTR 0x0000400 /* pmap_destroy */
98: #define CD_RM 0x0000800 /* pmap_remove */
99: #define CD_RMAL 0x0001000 /* pmap_remove_all */
100: #define CD_PROT 0x0002000 /* pmap_protect */
101: #define CD_EXP 0x0004000 /* pmap_expand */
102: #define CD_ENT 0x0008000 /* pmap_enter */
103: #define CD_UPD 0x0010000 /* pmap_update */
104: #define CD_COL 0x0020000 /* pmap_collect */
105: #define CD_CBIT 0x0040000 /* pmap_changebit */
106: #define CD_TBIT 0x0080000 /* pmap_testbit */
107: #define CD_USBIT 0x0100000 /* pmap_unsetbit */
108: #define CD_ALL 0x0FFFFFC
109:
110: int pmap_con_dbg = 0;
111:
112: #endif /* DEBUG */
113:
114: struct pool pmappool, pvpool;
115:
116: caddr_t vmmap;
117: pt_entry_t *vmpte, *msgbufmap;
118:
119: struct pmap kernel_pmap_store;
120: pmap_t kernel_pmap = &kernel_pmap_store;
121:
122: typedef struct kpdt_entry *kpdt_entry_t;
123: struct kpdt_entry {
124: kpdt_entry_t next;
125: paddr_t phys;
126: };
127:
128: kpdt_entry_t kpdt_free;
129:
130: /*
131: * Two pages of scratch space per cpu.
132: * Used in pmap_copy_page() and pmap_zero_page().
133: */
134: vaddr_t phys_map_vaddr, phys_map_vaddr_end;
135:
136: static pv_entry_t pg_to_pvh(struct vm_page *);
137:
138: static __inline pv_entry_t
139: pg_to_pvh(struct vm_page *pg)
140: {
141: return &pg->mdpage.pvent;
142: }
143:
144: /*
145: * Locking primitives
146: */
147:
148: #ifdef MULTIPROCESSOR
149: #define PMAP_LOCK(pmap) __cpu_simple_lock(&(pmap)->pm_lock)
150: #define PMAP_UNLOCK(pmap) __cpu_simple_unlock(&(pmap)->pm_lock)
151: #else
152: #define PMAP_LOCK(pmap) do { /* nothing */ } while (0)
153: #define PMAP_UNLOCK(pmap) do { /* nothing */ } while (0)
154: #endif
155:
156: vaddr_t kmapva = 0;
157:
158: /*
159: * Internal routines
160: */
161: static void flush_atc_entry(pmap_t, vaddr_t);
162: pt_entry_t *pmap_expand_kmap(vaddr_t, vm_prot_t, int);
163: void pmap_remove_pte(pmap_t, vaddr_t, pt_entry_t *);
164: void pmap_remove_range(pmap_t, vaddr_t, vaddr_t);
165: void pmap_expand(pmap_t, vaddr_t);
166: void pmap_release(pmap_t);
167: vaddr_t pmap_map(vaddr_t, paddr_t, paddr_t, vm_prot_t, u_int);
168: pt_entry_t *pmap_pte(pmap_t, vaddr_t);
169: void pmap_remove_all(struct vm_page *);
170: void pmap_changebit(struct vm_page *, int, int);
171: boolean_t pmap_unsetbit(struct vm_page *, int);
172: boolean_t pmap_testbit(struct vm_page *, int);
173:
174: /*
175: * quick PTE field checking macros
176: */
177: #define pmap_pte_w(pte) (*(pte) & PG_W)
178: #define pmap_pte_prot(pte) (*(pte) & PG_PROT)
179:
180: #define pmap_pte_w_chg(pte, nw) ((nw) ^ pmap_pte_w(pte))
181: #define pmap_pte_prot_chg(pte, np) ((np) ^ pmap_pte_prot(pte))
182:
183: #define m88k_protection(prot) ((prot) & VM_PROT_WRITE ? PG_RW : PG_RO)
184:
185: #define SDTENT(map, va) ((sdt_entry_t *)((map)->pm_stab + SDTIDX(va)))
186:
187: /*
188: * Routine: FLUSH_ATC_ENTRY
189: *
190: * Function:
191: * Flush atc (TLB) which maps given pmap and virtual address.
192: *
193: * Parameters:
194: * pmap affected pmap
195: * va virtual address that should be flushed
196: */
197: static
198: #ifndef MULTIPROCESSOR
199: __inline__
200: #endif
201: void
202: flush_atc_entry(pmap_t pmap, vaddr_t va)
203: {
204: #ifdef MULTIPROCESSOR
205: u_int32_t users;
206: int cpu;
207: boolean_t kernel;
208:
209: if ((users = pmap->pm_cpus) == 0)
210: return;
211:
212: kernel = pmap == kernel_pmap;
213: while ((cpu = ff1(users)) != 32) {
214: #ifdef DIAGNOSTIC
215: if (m88k_cpus[cpu].ci_alive)
216: #endif
217: cmmu_flush_tlb(cpu, kernel, va, 1);
218: users ^= 1 << cpu;
219: }
220: #else /* MULTIPROCESSOR */
221: if (pmap->pm_cpus != 0)
222: cmmu_flush_tlb(cpu_number(), pmap == kernel_pmap, va, 1);
223: #endif /* MULTIPROCESSOR */
224: }
225:
226: /*
227: * Routine: PMAP_PTE
228: *
229: * Function:
230: * Given a map and a virtual address, compute a (virtual) pointer
231: * to the page table entry (PTE) which maps the address .
232: * If the page table associated with the address does not
233: * exist, NULL is returned (and the map may need to grow).
234: *
235: * Parameters:
236: * pmap pointer to pmap structure
237: * virt virtual address for which page table entry is desired
238: *
239: * Otherwise the page table address is extracted from the segment table,
240: * the page table index is added, and the result is returned.
241: */
242:
243: static __inline__
244: pt_entry_t *
245: sdt_pte(sdt_entry_t *sdt, vaddr_t va)
246: {
247: return ((pt_entry_t *)
248: (PG_PFNUM(*(sdt + SDT_ENTRIES)) << PDT_SHIFT) + PDTIDX(va));
249: }
250:
251: pt_entry_t *
252: pmap_pte(pmap_t pmap, vaddr_t virt)
253: {
254: sdt_entry_t *sdt;
255:
256: sdt = SDTENT(pmap, virt);
257: /*
258: * Check whether page table exists.
259: */
260: if (!SDT_VALID(sdt))
261: return (NULL);
262:
263: return (sdt_pte(sdt, virt));
264: }
265:
266: /*
267: * Routine: PMAP_EXPAND_KMAP (internal)
268: *
269: * Function:
270: * Allocate a page descriptor table (pte_table) and validate associated
271: * segment table entry, returning pointer to page table entry. This is
272: * much like 'pmap_expand', except that table space is acquired
273: * from an area set up by pmap_bootstrap, instead of through
274: * uvm_km_zalloc. (Obviously, because uvm_km_zalloc uses the kernel map
275: * for allocation - which we can't do when trying to expand the
276: * kernel map!) Note that segment tables for the kernel map were
277: * all allocated at pmap_bootstrap time, so we only need to worry
278: * about the page table here.
279: *
280: * Parameters:
281: * virt VA for which translation tables are needed
282: * prot protection attributes for segment entries
283: *
284: * Extern/Global:
285: * kpdt_free kernel page table free queue
286: *
287: * This routine simply dequeues a table from the kpdt_free list,
288: * initializes all its entries (invalidates them), and sets the
289: * corresponding segment table entry to point to it. If the kpdt_free
290: * list is empty - we panic (no other places to get memory, sorry). (Such
291: * a panic indicates that pmap_bootstrap is not allocating enough table
292: * space for the kernel virtual address space).
293: *
294: */
295: pt_entry_t *
296: pmap_expand_kmap(vaddr_t virt, vm_prot_t prot, int canfail)
297: {
298: sdt_entry_t template, *sdt;
299: kpdt_entry_t kpdt_ent;
300:
301: #ifdef DEBUG
302: if ((pmap_con_dbg & (CD_KMAP | CD_FULL)) == (CD_KMAP | CD_FULL))
303: printf("(pmap_expand_kmap: %x) v %x\n", curproc, virt);
304: #endif
305:
306: template = m88k_protection(prot) | PG_M | SG_V;
307:
308: /* segment table entry derivate from map and virt. */
309: sdt = SDTENT(kernel_pmap, virt);
310: #ifdef DEBUG
311: if (SDT_VALID(sdt))
312: panic("pmap_expand_kmap: segment table entry VALID");
313: #endif
314:
315: kpdt_ent = kpdt_free;
316: if (kpdt_ent == NULL) {
317: if (canfail)
318: return (NULL);
319: else
320: panic("pmap_expand_kmap: Ran out of kernel pte tables");
321: }
322:
323: kpdt_free = kpdt_free->next;
324: /* physical table */
325: *sdt = kpdt_ent->phys | template;
326: /* virtual table */
327: *(sdt + SDT_ENTRIES) = (vaddr_t)kpdt_ent | template;
328:
329: /* Reinitialize this kpdt area to zero */
330: bzero((void *)kpdt_ent, PDT_SIZE);
331:
332: return (pt_entry_t *)(kpdt_ent) + PDTIDX(virt);
333: }
334:
335: /*
336: * Routine: PMAP_MAP
337: *
338: * Function:
339: * Map memory at initialization. The physical addresses being
340: * mapped are not managed and are never unmapped.
341: *
342: * Parameters:
343: * virt virtual address of range to map
344: * start physical address of range to map
345: * end physical address of end of range
346: * prot protection attributes
347: * cmode cache control attributes
348: *
349: * Calls:
350: * pmap_pte
351: * pmap_expand_kmap
352: *
353: * Special Assumptions
354: * For now, VM is already on, only need to map the specified
355: * memory. Used only by pmap_bootstrap() and vm_page_startup().
356: *
357: * For each page that needs mapping:
358: * pmap_pte is called to obtain the address of the page table
359: * table entry (PTE). If the page table does not exist,
360: * pmap_expand_kmap is called to allocate it. Finally, the page table
361: * entry is set to point to the physical page.
362: *
363: * initialize template with paddr, prot, dt
364: * look for number of phys pages in range
365: * {
366: * pmap_pte(virt) - expand if necessary
367: * stuff pte from template
368: * increment virt one page
369: * increment template paddr one page
370: * }
371: *
372: */
373: vaddr_t
374: pmap_map(vaddr_t virt, paddr_t start, paddr_t end, vm_prot_t prot, u_int cmode)
375: {
376: u_int npages;
377: u_int num_phys_pages;
378: pt_entry_t template, *pte;
379: paddr_t page;
380:
381: #ifdef DEBUG
382: if (pmap_con_dbg & CD_MAP)
383: printf ("(pmap_map: %x) phys address from %x to %x mapped at virtual %x, prot %x cmode %x\n",
384: curproc, start, end, virt, prot, cmode);
385: #endif
386:
387: #ifdef DEBUG
388: /* Check for zero if we map the very end of the address space... */
389: if (start > end && end != 0) {
390: panic("pmap_map: start greater than end address");
391: }
392: #endif
393:
394: template = m88k_protection(prot) | cmode | PG_V;
395: #ifdef M88110
396: if (CPU_IS88110 && m88k_protection(prot) != PG_RO)
397: template |= PG_M;
398: #endif
399:
400: page = trunc_page(start);
401: npages = atop(round_page(end) - page);
402: for (num_phys_pages = npages; num_phys_pages != 0; num_phys_pages--) {
403: if ((pte = pmap_pte(kernel_pmap, virt)) == NULL)
404: pte = pmap_expand_kmap(virt,
405: VM_PROT_READ | VM_PROT_WRITE, 0);
406:
407: #ifdef DEBUG
408: if ((pmap_con_dbg & (CD_MAP | CD_FULL)) == (CD_MAP | CD_FULL))
409: if (PDT_VALID(pte))
410: printf("(pmap_map: %x) pte @ %p already valid\n", curproc, pte);
411: #endif
412:
413: *pte = template | page;
414: virt += PAGE_SIZE;
415: page += PAGE_SIZE;
416: }
417: return virt;
418: }
419:
420: /*
421: * Routine: PMAP_CACHE_CONTROL
422: *
423: * Function:
424: * Set the cache-control bits in the page table entries(PTE) which maps
425: * the specified virtual address range.
426: *
427: * Parameters:
428: * pmap_t pmap
429: * vaddr_t s
430: * vaddr_t e
431: * u_int mode
432: *
433: * Calls:
434: * pmap_pte
435: * invalidate_pte
436: * flush_atc_entry
437: *
438: * This routine sequences through the pages of the specified range.
439: * For each, it calls pmap_pte to acquire a pointer to the page table
440: * entry (PTE). If the PTE is invalid, or non-existent, nothing is done.
441: * Otherwise, the cache-control bits in the PTE's are adjusted as specified.
442: *
443: */
444: void
445: pmap_cache_ctrl(pmap_t pmap, vaddr_t s, vaddr_t e, u_int mode)
446: {
447: int spl;
448: pt_entry_t opte, *pte;
449: vaddr_t va;
450: paddr_t pa;
451: cpuid_t cpu;
452:
453: #ifdef DEBUG
454: if ((mode & CACHE_MASK) != mode) {
455: printf("(cache_ctrl) illegal mode %x\n", mode);
456: return;
457: }
458: if (pmap_con_dbg & CD_CACHE) {
459: printf("(pmap_cache_ctrl: %x) pmap %x, va %x, mode %x\n", curproc, pmap, s, mode);
460: }
461:
462: if (pmap == NULL)
463: panic("pmap_cache_ctrl: pmap is NULL");
464: #endif /* DEBUG */
465:
466: spl = splvm();
467: PMAP_LOCK(pmap);
468:
469: for (va = s; va != e; va += PAGE_SIZE) {
470: if ((pte = pmap_pte(pmap, va)) == NULL)
471: continue;
472: #ifdef DEBUG
473: if (pmap_con_dbg & CD_CACHE) {
474: printf("(cache_ctrl) pte@%p\n", pte);
475: }
476: #endif /* DEBUG */
477: /*
478: * Invalidate pte temporarily to avoid being written back
479: * the modified bit and/or the reference bit by any other cpu.
480: * XXX
481: */
482: opte = invalidate_pte(pte);
483: *pte = (opte & ~CACHE_MASK) | mode;
484: flush_atc_entry(pmap, va);
485:
486: /*
487: * Data cache should be copied back and invalidated if
488: * the old mapping was cached.
489: */
490: if ((opte & CACHE_INH) == 0) {
491: pa = ptoa(PG_PFNUM(opte));
492: #ifdef MULTIPROCESSOR
493: for (cpu = 0; cpu < MAX_CPUS; cpu++)
494: if (m88k_cpus[cpu].ci_alive != 0)
495: #else
496: cpu = cpu_number();
497: #endif
498: cmmu_flush_cache(cpu, pa, PAGE_SIZE);
499: }
500: }
501: PMAP_UNLOCK(pmap);
502: splx(spl);
503: }
504:
505: /*
506: * Routine: PMAP_BOOTSTRAP
507: *
508: * Function:
509: * Bootstrap the system enough to run with virtual memory.
510: * Map the kernel's code and data, allocate the kernel
511: * translation table space, and map control registers
512: * and other IO addresses.
513: *
514: * Parameters:
515: * load_start PA where kernel was loaded
516: *
517: * Extern/Global:
518: *
519: * PAGE_SIZE VM (software) page size
520: * etext end of kernel text
521: * phys_map_vaddr VA of page mapped arbitrarily for debug/IO
522: *
523: * Calls:
524: * __cpu_simple_lock_init
525: * pmap_map
526: *
527: * The physical address 'load_start' is mapped at
528: * VM_MIN_KERNEL_ADDRESS, which maps the kernel code and data at the
529: * virtual address for which it was (presumably) linked. Immediately
530: * following the end of the kernel code/data, sufficient page of
531: * physical memory are reserved to hold translation tables for the kernel
532: * address space.
533: *
534: * A pair of virtual pages per cpu are reserved for debugging and
535: * IO purposes. They are arbitrarily mapped when needed. They are used,
536: * for example, by pmap_copy_page and pmap_zero_page.
537: *
538: * This implementation also assumes that the space below the kernel
539: * is reserved (typically from PROM purposes). We should ideally map it
540: * read only except when invoking its services...
541: */
542:
543: void
544: pmap_bootstrap(vaddr_t load_start)
545: {
546: kpdt_entry_t kpdt_virt;
547: sdt_entry_t *kmap;
548: vaddr_t vaddr, virt;
549: paddr_t s_text, e_text, kpdt_phys;
550: unsigned int kernel_pmap_size, pdt_size;
551: int i;
552: #ifndef MULTIPROCESSOR
553: cpuid_t cpu;
554: #endif
555: pmap_table_t ptable;
556: extern void *etext;
557:
558: #ifdef MULTIPROCESSOR
559: __cpu_simple_lock_init(&kernel_pmap->pm_lock);
560: #endif
561:
562: /*
563: * Allocate the kernel page table from the front of available
564: * physical memory, i.e. just after where the kernel image was loaded.
565: */
566: /*
567: * The calling sequence is
568: * ...
569: * pmap_bootstrap(&kernelstart, ...);
570: * kernelstart being the first symbol in the load image.
571: */
572:
573: avail_start = round_page(avail_start);
574: virtual_avail = avail_start;
575:
576: /*
577: * Initialize kernel_pmap structure
578: */
579: kernel_pmap->pm_count = 1;
580: kernel_pmap->pm_cpus = 0;
581: kmap = (sdt_entry_t *)(avail_start);
582: kernel_pmap->pm_stab = (sdt_entry_t *)virtual_avail;
583: kmapva = virtual_avail;
584:
585: /*
586: * Reserve space for segment table entries.
587: * One for the regular segment table and one for the shadow table
588: * The shadow table keeps track of the virtual address of page
589: * tables. This is used in virtual-to-physical address translation
590: * functions. Remember, MMU cares only for physical addresses of
591: * segment and page table addresses. For kernel page tables, we
592: * really don't need this virtual stuff (since the kernel will
593: * be mapped 1-to-1) but for user page tables, this is required.
594: * Just to be consistent, we will maintain the shadow table for
595: * kernel pmap also.
596: */
597: kernel_pmap_size = 2 * SDT_SIZE;
598:
599: #ifdef DEBUG
600: printf("kernel segment table size = 0x%x\n", kernel_pmap_size);
601: #endif
602: /* init all segment descriptors to zero */
603: bzero(kernel_pmap->pm_stab, kernel_pmap_size);
604:
605: avail_start += kernel_pmap_size;
606: virtual_avail += kernel_pmap_size;
607:
608: /* make sure page tables are page aligned!! XXX smurph */
609: avail_start = round_page(avail_start);
610: virtual_avail = round_page(virtual_avail);
611:
612: /* save pointers to where page table entries start in physical memory */
613: kpdt_phys = avail_start;
614: kpdt_virt = (kpdt_entry_t)virtual_avail;
615:
616: /* Compute how much space we need for the kernel page table */
617: pdt_size = atop(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS)
618: * sizeof(pt_entry_t);
619: for (ptable = pmap_table_build(); ptable->size != (vsize_t)-1; ptable++)
620: pdt_size += atop(ptable->size) * sizeof(pt_entry_t);
621: pdt_size = round_page(pdt_size);
622: kernel_pmap_size += pdt_size;
623: avail_start += pdt_size;
624: virtual_avail += pdt_size;
625:
626: /* init all page descriptors to zero */
627: bzero((void *)kpdt_phys, pdt_size);
628: #ifdef DEBUG
629: printf("--------------------------------------\n");
630: printf(" kernel page start = 0x%x\n", kpdt_phys);
631: printf(" kernel page table size = 0x%x\n", pdt_size);
632: printf(" kernel page end = 0x%x\n", avail_start);
633:
634: printf("kpdt_virt = 0x%x\n", kpdt_virt);
635: #endif
636: /*
637: * init the kpdt queue
638: */
639: kpdt_free = kpdt_virt;
640: for (i = pdt_size / PDT_SIZE; i != 0; i--) {
641: kpdt_virt->next = (kpdt_entry_t)((vaddr_t)kpdt_virt + PDT_SIZE);
642: kpdt_virt->phys = kpdt_phys;
643: kpdt_virt = kpdt_virt->next;
644: kpdt_phys += PDT_SIZE;
645: }
646: kpdt_virt->next = NULL; /* terminate the list */
647:
648: /*
649: * Map the kernel image into virtual space
650: */
651:
652: s_text = trunc_page(load_start); /* paddr of text */
653: e_text = round_page((vaddr_t)&etext); /* paddr of end of text */
654:
655: /* map the PROM area */
656: vaddr = pmap_map(0, 0, s_text, VM_PROT_WRITE | VM_PROT_READ, CACHE_INH);
657:
658: /* map the kernel text read only */
659: vaddr = pmap_map(s_text, s_text, e_text, VM_PROT_READ, 0);
660:
661: vaddr = pmap_map(vaddr, e_text, (paddr_t)kmap,
662: VM_PROT_WRITE | VM_PROT_READ, 0);
663:
664: /*
665: * Map system segment & page tables - should be cache inhibited?
666: * 88200 manual says that CI bit is driven on the Mbus while accessing
667: * the translation tree. I don't think we need to map it CACHE_INH
668: * here...
669: */
670: if (kmapva != vaddr) {
671: while (vaddr < (virtual_avail - kernel_pmap_size))
672: vaddr = round_page(vaddr + 1);
673: }
674: vaddr = pmap_map(vaddr, (paddr_t)kmap, avail_start,
675: VM_PROT_WRITE | VM_PROT_READ, CACHE_INH);
676:
677: vaddr = pmap_bootstrap_md(vaddr);
678:
679: virtual_avail = round_page(virtual_avail);
680: virtual_end = VM_MAX_KERNEL_ADDRESS;
681:
682: /*
683: * Map two pages per cpu for copying/zeroing.
684: */
685:
686: phys_map_vaddr = virtual_avail;
687: phys_map_vaddr_end = virtual_avail + 2 * (max_cpus << PAGE_SHIFT);
688: avail_start += 2 * (max_cpus << PAGE_SHIFT);
689: virtual_avail += 2 * (max_cpus << PAGE_SHIFT);
690:
691: /*
692: * Create all the machine-specific mappings.
693: */
694:
695: for (ptable = pmap_table_build(); ptable->size != (vsize_t)-1; ptable++)
696: if (ptable->size != 0) {
697: pmap_map(ptable->virt_start, ptable->phys_start,
698: ptable->phys_start + ptable->size,
699: ptable->prot, ptable->cacheability);
700: }
701:
702: /*
703: * Allocate all the submaps we need. Note that SYSMAP just allocates
704: * kernel virtual address with no physical backing memory. The idea
705: * is physical memory will be mapped at this va before using that va.
706: * This means that if different physical pages are going to be mapped
707: * at different times, we better do a tlb flush before using it -
708: * else we will be referencing the wrong page.
709: */
710:
711: #define SYSMAP(c, p, v, n) \
712: ({ \
713: v = (c)virt; \
714: if ((p = pmap_pte(kernel_pmap, virt)) == NULL) \
715: pmap_expand_kmap(virt, VM_PROT_READ | VM_PROT_WRITE, 0); \
716: virt += ((n) * PAGE_SIZE); \
717: })
718:
719: virt = virtual_avail;
720:
721: SYSMAP(caddr_t, vmpte, vmmap, 1);
722: invalidate_pte(vmpte);
723:
724: SYSMAP(struct msgbuf *, msgbufmap, msgbufp, btoc(MSGBUFSIZE));
725:
726: virtual_avail = virt;
727:
728: /*
729: * Switch to using new page tables
730: */
731:
732: kernel_pmap->pm_apr = (atop((paddr_t)kmap) << PG_SHIFT) |
733: CACHE_GLOBAL | CACHE_WT | APR_V;
734:
735: /* Invalidate entire kernel TLB and get ready for address translation */
736: #ifdef MULTIPROCESSOR
737: pmap_bootstrap_cpu(cpu_number());
738: #else
739: cpu = cpu_number();
740: cmmu_flush_tlb(cpu, TRUE, 0, -1);
741: /* Load supervisor pointer to segment table. */
742: cmmu_set_sapr(cpu, kernel_pmap->pm_apr);
743: #ifdef DEBUG
744: printf("cpu%d: running virtual\n", cpu);
745: #endif
746: SETBIT_CPUSET(cpu, &kernel_pmap->pm_cpus);
747: #endif /* MULTIPROCESSOR */
748: }
749:
750: #ifdef MULTIPROCESSOR
751: void
752: pmap_bootstrap_cpu(cpuid_t cpu)
753: {
754: if (cpu != master_cpu) {
755: cmmu_initialize_cpu(cpu);
756: } else {
757: cmmu_flush_tlb(cpu, TRUE, 0, -1);
758: }
759: /* Load supervisor pointer to segment table. */
760: cmmu_set_sapr(cpu, kernel_pmap->pm_apr);
761: #ifdef DEBUG
762: printf("cpu%d: running virtual\n", cpu);
763: #endif
764: SETBIT_CPUSET(cpu, &kernel_pmap->pm_cpus);
765: }
766: #endif
767:
768: /*
769: * Routine: PMAP_INIT
770: *
771: * Function:
772: * Initialize the pmap module. It is called by vm_init, to initialize
773: * any structures that the pmap system needs to map virtual memory.
774: *
775: * Calls:
776: * pool_init
777: *
778: * This routine does not really have much to do. It initializes
779: * pools for pmap structures and pv_entry structures.
780: */
781: void
782: pmap_init(void)
783: {
784: #ifdef DEBUG
785: if (pmap_con_dbg & CD_INIT)
786: printf("pmap_init()\n");
787: #endif
788:
789: pool_init(&pmappool, sizeof(struct pmap), 0, 0, 0, "pmappl",
790: &pool_allocator_nointr);
791: pool_init(&pvpool, sizeof(pv_entry_t), 0, 0, 0, "pvpl", NULL);
792: } /* pmap_init() */
793:
794: /*
795: * Routine: PMAP_ZERO_PAGE
796: *
797: * Function:
798: * Zeroes the specified page.
799: *
800: * Parameters:
801: * pg page to zero
802: *
803: * Extern/Global:
804: * phys_map_vaddr
805: *
806: * Special Assumptions:
807: * no locking required
808: *
809: * This routine maps the physical pages at the 'phys_map' virtual
810: * address set up in pmap_bootstrap. It flushes the TLB to make the new
811: * mappings effective, and zeros all the bits.
812: */
813: void
814: pmap_zero_page(struct vm_page *pg)
815: {
816: paddr_t pa = VM_PAGE_TO_PHYS(pg);
817: vaddr_t va;
818: int spl;
819: int cpu = cpu_number();
820: pt_entry_t *pte;
821:
822: va = (vaddr_t)(phys_map_vaddr + 2 * (cpu << PAGE_SHIFT));
823: pte = pmap_pte(kernel_pmap, va);
824:
825: spl = splvm();
826:
827: *pte = m88k_protection(VM_PROT_READ | VM_PROT_WRITE) |
828: PG_M /* 88110 */ | PG_V | pa;
829:
830: /*
831: * We don't need the flush_atc_entry() dance, as these pages are
832: * bound to only one cpu.
833: */
834: cmmu_flush_tlb(cpu, TRUE, va, 1);
835:
836: /*
837: * The page is likely to be a non-kernel mapping, and as
838: * such write back. Also, we might have split U/S caches!
839: * So be sure to have the pa flushed after the filling.
840: */
841: bzero((void *)va, PAGE_SIZE);
842: cmmu_flush_data_page(cpu, pa);
843:
844: splx(spl);
845: }
846:
847: /*
848: * Routine: PMAP_CREATE
849: *
850: * Function:
851: * Create and return a physical map. If the size specified for the
852: * map is zero, the map is an actual physical map, and may be referenced
853: * by the hardware. If the size specified is non-zero, the map will be
854: * used in software only, and is bounded by that size.
855: *
856: * This routines allocates a pmap structure.
857: */
858: pmap_t
859: pmap_create(void)
860: {
861: pmap_t pmap;
862: sdt_entry_t *segdt;
863: paddr_t stpa;
864: u_int s;
865:
866: pmap = pool_get(&pmappool, PR_WAITOK);
867: bzero(pmap, sizeof(*pmap));
868:
869: /*
870: * Allocate memory for *actual* segment table and *shadow* table.
871: */
872: s = round_page(2 * SDT_SIZE);
873: #ifdef DEBUG
874: if (pmap_con_dbg & CD_CREAT) {
875: printf("(pmap_create: %x) need %d pages for sdt\n",
876: curproc, atop(s));
877: }
878: #endif
879:
880: segdt = (sdt_entry_t *)uvm_km_zalloc(kernel_map, s);
881: if (segdt == NULL)
882: panic("pmap_create: uvm_km_zalloc failure");
883:
884: /*
885: * Initialize pointer to segment table both virtual and physical.
886: */
887: pmap->pm_stab = segdt;
888: if (pmap_extract(kernel_pmap, (vaddr_t)segdt,
889: (paddr_t *)&stpa) == FALSE)
890: panic("pmap_create: pmap_extract failed!");
891: pmap->pm_apr = (atop(stpa) << PG_SHIFT) | CACHE_GLOBAL | APR_V;
892:
893: #ifdef DEBUG
894: if (stpa & PAGE_MASK)
895: panic("pmap_create: sdt_table 0x%x not aligned on page boundary",
896: (int)stpa);
897:
898: if (pmap_con_dbg & CD_CREAT) {
899: printf("(pmap_create: %x) pmap=%p, pm_stab=0x%x (pa 0x%x)\n",
900: curproc, pmap, pmap->pm_stab, stpa);
901: }
902: #endif
903:
904: /* memory for page tables should not be writeback or local */
905: pmap_cache_ctrl(kernel_pmap,
906: (vaddr_t)segdt, (vaddr_t)segdt + s, CACHE_WT);
907:
908: /*
909: * Initialize SDT_ENTRIES.
910: */
911: /*
912: * There is no need to clear segment table, since uvm_km_zalloc
913: * provides us clean pages.
914: */
915:
916: /*
917: * Initialize pmap structure.
918: */
919: pmap->pm_count = 1;
920: #ifdef MULTIPROCESSOR
921: __cpu_simple_lock_init(&pmap->pm_lock);
922: #endif
923: pmap->pm_cpus = 0;
924:
925: return pmap;
926: }
927:
928: /*
929: * Routine: PMAP_RELEASE
930: *
931: * Internal procedure used by pmap_destroy() to actualy deallocate
932: * the tables.
933: *
934: * Parameters:
935: * pmap pointer to pmap structure
936: *
937: * Calls:
938: * pmap_pte
939: * uvm_km_free
940: *
941: * Special Assumptions:
942: * No locking is needed, since this is only called which the
943: * pm_count field of the pmap structure goes to zero.
944: *
945: * This routine sequences of through the user address space, releasing
946: * all translation table space back to the system using uvm_km_free.
947: * The loops are indexed by the virtual address space
948: * ranges represented by the table group sizes (1 << SDT_SHIFT).
949: */
950: void
951: pmap_release(pmap_t pmap)
952: {
953: u_int sdt; /* outer loop index */
954: sdt_entry_t *sdttbl; /* ptr to first entry in the segment table */
955: pt_entry_t *gdttbl; /* ptr to first entry in a page table */
956:
957: #ifdef DEBUG
958: if (pmap_con_dbg & CD_FREE)
959: printf("(pmap_release: %x) pmap %x\n", curproc, pmap);
960: #endif
961:
962: /* segment table loop */
963: for (sdt = VM_MIN_ADDRESS >> SDT_SHIFT;
964: sdt <= VM_MAX_ADDRESS >> SDT_SHIFT; sdt++) {
965: if ((gdttbl = pmap_pte(pmap, sdt << SDT_SHIFT)) != NULL) {
966: #ifdef DEBUG
967: if ((pmap_con_dbg & (CD_FREE | CD_FULL)) == (CD_FREE | CD_FULL))
968: printf("(pmap_release: %x) free page table = 0x%x\n",
969: curproc, gdttbl);
970: #endif
971: uvm_km_free(kernel_map, (vaddr_t)gdttbl, PAGE_SIZE);
972: }
973: }
974:
975: /*
976: * Freeing both *actual* and *shadow* segment tables
977: */
978: sdttbl = pmap->pm_stab; /* addr of segment table */
979: #ifdef DEBUG
980: if ((pmap_con_dbg & (CD_FREE | CD_FULL)) == (CD_FREE | CD_FULL))
981: printf("(pmap_release: %x) free segment table = 0x%x\n",
982: curproc, sdttbl);
983: #endif
984: uvm_km_free(kernel_map, (vaddr_t)sdttbl, round_page(2 * SDT_SIZE));
985:
986: #ifdef DEBUG
987: if (pmap_con_dbg & CD_FREE)
988: printf("(pmap_release: %x) pm_count = 0\n", curproc);
989: #endif
990: }
991:
992: /*
993: * Routine: PMAP_DESTROY
994: *
995: * Function:
996: * Retire the given physical map from service. Should only be called
997: * if the map contains no valid mappings.
998: *
999: * Parameters:
1000: * pmap pointer to pmap structure
1001: *
1002: * Calls:
1003: * pmap_release
1004: * pool_put
1005: *
1006: * Special Assumptions:
1007: * Map contains no valid mappings.
1008: *
1009: * This routine decrements the reference count in the pmap
1010: * structure. If it goes to zero, pmap_release is called to release
1011: * the memory space to the system. Then, call pool_put to free the
1012: * pmap structure.
1013: */
1014: void
1015: pmap_destroy(pmap_t pmap)
1016: {
1017: int count;
1018:
1019: #ifdef DEBUG
1020: if (pmap == kernel_pmap)
1021: panic("pmap_destroy: Attempt to destroy kernel pmap");
1022: #endif
1023:
1024: PMAP_LOCK(pmap);
1025: count = --pmap->pm_count;
1026: PMAP_UNLOCK(pmap);
1027: if (count == 0) {
1028: pmap_release(pmap);
1029: pool_put(&pmappool, pmap);
1030: }
1031: }
1032:
1033:
1034: /*
1035: * Routine: PMAP_REFERENCE
1036: *
1037: * Function:
1038: * Add a reference to the specified pmap.
1039: *
1040: * Parameters:
1041: * pmap pointer to pmap structure
1042: *
1043: * Under a pmap read lock, the pm_count field of the pmap structure
1044: * is incremented. The function then returns.
1045: */
1046: void
1047: pmap_reference(pmap_t pmap)
1048: {
1049: PMAP_LOCK(pmap);
1050: pmap->pm_count++;
1051: PMAP_UNLOCK(pmap);
1052: }
1053:
1054: /*
1055: * Routine: PMAP_REMOVE_PTE (internal)
1056: *
1057: * Function:
1058: * Invalidate a given page table entry associated with the
1059: * given virtual address.
1060: *
1061: * Parameters:
1062: * pmap pointer to pmap structure
1063: * va virtual address of page to remove
1064: * pte existing pte
1065: *
1066: * External/Global:
1067: * pv lists
1068: *
1069: * Calls:
1070: * pool_put
1071: * invalidate_pte
1072: * flush_atc_entry
1073: *
1074: * Special Assumptions:
1075: * The pmap must be locked.
1076: *
1077: * If the PTE is valid, the routine must invalidate the entry. The
1078: * 'modified' bit, if on, is referenced to the VM, and into the appropriate
1079: * entry in the PV list entry. Next, the function must find the PV
1080: * list entry associated with this pmap/va (if it doesn't exist - the function
1081: * panics). The PV list entry is unlinked from the list, and returned to
1082: * its zone.
1083: */
1084: void
1085: pmap_remove_pte(pmap_t pmap, vaddr_t va, pt_entry_t *pte)
1086: {
1087: pt_entry_t opte;
1088: pv_entry_t prev, cur, pvl;
1089: struct vm_page *pg;
1090: paddr_t pa;
1091:
1092: #ifdef DEBUG
1093: if (pmap_con_dbg & CD_RM) {
1094: if (pmap == kernel_pmap)
1095: printf("(pmap_remove_pte: %x) pmap kernel va %x\n", curproc, va);
1096: else
1097: printf("(pmap_remove_pte: %x) pmap %x va %x\n", curproc, pmap, va);
1098: }
1099: #endif
1100:
1101: if (pte == NULL || !PDT_VALID(pte)) {
1102: return; /* no page mapping, nothing to do! */
1103: }
1104:
1105: /*
1106: * Update statistics.
1107: */
1108: pmap->pm_stats.resident_count--;
1109: if (pmap_pte_w(pte))
1110: pmap->pm_stats.wired_count--;
1111:
1112: pa = ptoa(PG_PFNUM(*pte));
1113:
1114: /*
1115: * Invalidate the pte.
1116: */
1117:
1118: opte = invalidate_pte(pte) & PG_M_U;
1119: flush_atc_entry(pmap, va);
1120:
1121: pg = PHYS_TO_VM_PAGE(pa);
1122:
1123: /* If this isn't a managed page, just return. */
1124: if (pg == NULL)
1125: return;
1126:
1127: /*
1128: * Remove the mapping from the pvlist for
1129: * this physical page.
1130: */
1131: pvl = pg_to_pvh(pg);
1132:
1133: #ifdef DIAGNOSTIC
1134: if (pvl->pv_pmap == NULL)
1135: panic("pmap_remove_pte: null pv_list");
1136: #endif
1137:
1138: prev = NULL;
1139: for (cur = pvl; cur != NULL; cur = cur->pv_next) {
1140: if (cur->pv_va == va && cur->pv_pmap == pmap)
1141: break;
1142: prev = cur;
1143: }
1144: if (cur == NULL) {
1145: panic("pmap_remove_pte: mapping for va "
1146: "0x%lx (pa 0x%lx) not in pv list at %p",
1147: va, pa, pvl);
1148: }
1149:
1150: if (prev == NULL) {
1151: /*
1152: * Hander is the pv_entry. Copy the next one
1153: * to hander and free the next one (we can't
1154: * free the hander)
1155: */
1156: cur = cur->pv_next;
1157: if (cur != NULL) {
1158: cur->pv_flags = pvl->pv_flags;
1159: *pvl = *cur;
1160: pool_put(&pvpool, cur);
1161: } else {
1162: pvl->pv_pmap = NULL;
1163: }
1164: } else {
1165: prev->pv_next = cur->pv_next;
1166: pool_put(&pvpool, cur);
1167: }
1168:
1169: /* Update saved attributes for managed page */
1170: pvl->pv_flags |= opte;
1171: }
1172:
1173: /*
1174: * Routine: PMAP_REMOVE_RANGE (internal)
1175: *
1176: * Function:
1177: * Invalidate page table entries associated with the
1178: * given virtual address range. The entries given are the first
1179: * (inclusive) and last (exclusive) entries for the VM pages.
1180: *
1181: * Parameters:
1182: * pmap pointer to pmap structure
1183: * s virtual address of start of range to remove
1184: * e virtual address of end of range to remove
1185: *
1186: * External/Global:
1187: * pv lists
1188: *
1189: * Calls:
1190: * pmap_pte
1191: * pmap_remove_pte
1192: *
1193: * Special Assumptions:
1194: * The pmap must be locked.
1195: *
1196: * This routine sequences through the pages defined by the given
1197: * range. For each page, the associated page table entry (PTE) is
1198: * invalidated via pmap_remove_pte().
1199: *
1200: * Empty segments are skipped for performance.
1201: */
1202: void
1203: pmap_remove_range(pmap_t pmap, vaddr_t s, vaddr_t e)
1204: {
1205: vaddr_t va, eseg;
1206:
1207: #ifdef DEBUG
1208: if (pmap_con_dbg & CD_RM) {
1209: if (pmap == kernel_pmap)
1210: printf("(pmap_remove_range: %x) pmap kernel s %x e %x\n", curproc, s, e);
1211: else
1212: printf("(pmap_remove_range: %x) pmap %x s %x e %x\n", curproc, pmap, s, e);
1213: }
1214: #endif
1215:
1216: /*
1217: * Loop through the range in PAGE_SIZE increments.
1218: */
1219: va = s;
1220: while (va != e) {
1221: sdt_entry_t *sdt;
1222:
1223: eseg = (va & SDT_MASK) + (1 << SDT_SHIFT);
1224: if (eseg > e || eseg == 0)
1225: eseg = e;
1226:
1227: sdt = SDTENT(pmap, va);
1228:
1229: /* If no segment table, skip a whole segment */
1230: if (!SDT_VALID(sdt))
1231: va = eseg;
1232: else {
1233: while (va != eseg) {
1234: pmap_remove_pte(pmap, va, sdt_pte(sdt, va));
1235: va += PAGE_SIZE;
1236: }
1237: }
1238: }
1239: }
1240:
1241: /*
1242: * Routine: PMAP_REMOVE
1243: *
1244: * Function:
1245: * Remove the given range of addresses from the specified map.
1246: * It is assumed that start and end are properly rounded to the VM page
1247: * size.
1248: *
1249: * Parameters:
1250: * pmap pointer to pmap structure
1251: * s
1252: * e
1253: *
1254: * Special Assumptions:
1255: * Assumes not all entries must be valid in specified range.
1256: *
1257: * Calls:
1258: * pmap_remove_range
1259: *
1260: * After taking pmap read lock, pmap_remove_range is called to do the
1261: * real work.
1262: */
1263: void
1264: pmap_remove(pmap_t pmap, vaddr_t s, vaddr_t e)
1265: {
1266: int spl;
1267:
1268: if (pmap == NULL)
1269: return;
1270:
1271: #ifdef DEBUG
1272: if (s >= e)
1273: panic("pmap_remove: start greater than end address");
1274: #endif
1275:
1276: spl = splvm();
1277: PMAP_LOCK(pmap);
1278: pmap_remove_range(pmap, s, e);
1279: PMAP_UNLOCK(pmap);
1280: splx(spl);
1281: }
1282:
1283: /*
1284: * Routine: PMAP_REMOVE_ALL
1285: *
1286: * Function:
1287: * Removes this physical page from all physical maps in which it
1288: * resides. Reflects back modify bits to the pager.
1289: *
1290: * Parameters:
1291: * pg physical pages which is to
1292: * be removed from all maps
1293: *
1294: * Extern/Global:
1295: * pv lists
1296: *
1297: * Calls:
1298: * pmap_pte
1299: * pool_put
1300: *
1301: * If the page specified by the given address is not a managed page,
1302: * this routine simply returns. Otherwise, the PV list associated with
1303: * that page is traversed. For each pmap/va pair pmap_pte is called to
1304: * obtain a pointer to the page table entry (PTE) associated with the
1305: * va (the PTE must exist and be valid, otherwise the routine panics).
1306: * The hardware 'modified' bit in the PTE is examined. If it is on, the
1307: * corresponding bit in the PV list entry corresponding
1308: * to the physical page is set to 1.
1309: * Then, the PTE is invalidated, and the PV list entry is unlinked and
1310: * freed.
1311: *
1312: * At the end of this function, the PV list for the specified page
1313: * will be null.
1314: */
1315: void
1316: pmap_remove_all(struct vm_page *pg)
1317: {
1318: pt_entry_t *pte;
1319: pv_entry_t pvl;
1320: vaddr_t va;
1321: pmap_t pmap;
1322: int spl;
1323:
1324: if (pg == NULL) {
1325: /* not a managed page. */
1326: #ifdef DEBUG
1327: if (pmap_con_dbg & CD_RMAL)
1328: printf("(pmap_remove_all: %x) vm page 0x%x not a managed page\n", curproc, pg);
1329: #endif
1330: return;
1331: }
1332:
1333: #ifdef DEBUG
1334: if (pmap_con_dbg & CD_RMAL)
1335: printf("(pmap_remove_all: %x) va %x\n", curproc, pg, pg_to_pvh(pg)->pv_va);
1336: #endif
1337:
1338: spl = splvm();
1339: /*
1340: * Walk down PV list, removing all mappings.
1341: * We don't have to lock the pv list, since we have the entire pmap
1342: * system.
1343: */
1344: #ifdef MULTIPROCESSOR
1345: remove_all_Retry:
1346: #endif
1347:
1348: pvl = pg_to_pvh(pg);
1349:
1350: /*
1351: * Loop for each entry on the pv list
1352: */
1353: while (pvl != NULL && (pmap = pvl->pv_pmap) != NULL) {
1354: #ifdef MULTIPROCESSOR
1355: if (!__cpu_simple_lock_try(&pmap->pm_lock))
1356: goto remove_all_Retry;
1357: #endif
1358:
1359: va = pvl->pv_va;
1360: pte = pmap_pte(pmap, va);
1361:
1362: if (pte == NULL || !PDT_VALID(pte)) {
1363: pvl = pvl->pv_next;
1364: goto next; /* no page mapping */
1365: }
1366: if (pmap_pte_w(pte)) {
1367: #ifdef DEBUG
1368: if (pmap_con_dbg & CD_RMAL)
1369: printf("pmap_remove_all: wired mapping for %lx not removed\n",
1370: pg);
1371: #endif
1372: pvl = pvl->pv_next;
1373: goto next;
1374: }
1375:
1376: pmap_remove_pte(pmap, va, pte);
1377:
1378: /*
1379: * Do not free any page tables,
1380: * leaves that for when VM calls pmap_collect().
1381: */
1382: next:
1383: PMAP_UNLOCK(pmap);
1384: }
1385: splx(spl);
1386: }
1387:
1388: /*
1389: * Routine: PMAP_PROTECT
1390: *
1391: * Function:
1392: * Sets the physical protection on the specified range of this map
1393: * as requested.
1394: *
1395: * Parameters:
1396: * pmap pointer to pmap structure
1397: * s start address of start of range
1398: * e end address of end of range
1399: * prot desired protection attributes
1400: *
1401: * Calls:
1402: * PMAP_LOCK, PMAP_UNLOCK
1403: * pmap_pte
1404: * PDT_VALID
1405: *
1406: * This routine sequences through the pages of the specified range.
1407: * For each, it calls pmap_pte to acquire a pointer to the page table
1408: * entry (PTE). If the PTE is invalid, or non-existent, nothing is done.
1409: * Otherwise, the PTE's protection attributes are adjusted as specified.
1410: */
1411: void
1412: pmap_protect(pmap_t pmap, vaddr_t s, vaddr_t e, vm_prot_t prot)
1413: {
1414: int spl;
1415: pt_entry_t *pte, ap;
1416: vaddr_t va, eseg;
1417:
1418: if ((prot & VM_PROT_READ) == 0) {
1419: pmap_remove(pmap, s, e);
1420: return;
1421: }
1422:
1423: ap = m88k_protection(prot);
1424:
1425: spl = splvm();
1426: PMAP_LOCK(pmap);
1427:
1428: /*
1429: * Loop through the range in PAGE_SIZE increments.
1430: */
1431: va = s;
1432: while (va != e) {
1433: sdt_entry_t *sdt;
1434:
1435: eseg = (va & SDT_MASK) + (1 << SDT_SHIFT);
1436: if (eseg > e || eseg == 0)
1437: eseg = e;
1438:
1439: sdt = SDTENT(pmap, va);
1440:
1441: /* If no segment table, skip a whole segment */
1442: if (!SDT_VALID(sdt))
1443: va = eseg;
1444: else {
1445: while (va != eseg) {
1446: pte = sdt_pte(sdt, va);
1447: if (pte != NULL && PDT_VALID(pte)) {
1448: /*
1449: * Invalidate pte temporarily to avoid
1450: * the modified bit and/or the
1451: * reference bit being written back by
1452: * any other cpu.
1453: */
1454: *pte = ap |
1455: (invalidate_pte(pte) & ~PG_PROT);
1456: flush_atc_entry(pmap, va);
1457: }
1458: va += PAGE_SIZE;
1459: }
1460: }
1461: }
1462: PMAP_UNLOCK(pmap);
1463: splx(spl);
1464: }
1465:
1466: /*
1467: * Routine: PMAP_EXPAND
1468: *
1469: * Function:
1470: * Expands a pmap to be able to map the specified virtual address.
1471: * New kernel virtual memory is allocated for a page table.
1472: *
1473: * Must be called with the pmap system and the pmap unlocked, since
1474: * these must be unlocked to use vm_allocate or vm_deallocate (via
1475: * uvm_km_zalloc). Thus it must be called in a unlock/lock loop
1476: * that checks whether the map has been expanded enough. (We won't loop
1477: * forever, since page table aren't shrunk.)
1478: *
1479: * Parameters:
1480: * pmap point to pmap structure
1481: * v VA indicating which tables are needed
1482: *
1483: * Extern/Global:
1484: * user_pt_map
1485: * kernel_pmap
1486: *
1487: * Calls:
1488: * pmap_pte
1489: * uvm_km_free
1490: * uvm_km_zalloc
1491: * pmap_extract
1492: *
1493: * Special Assumptions
1494: * no pmap locks held
1495: * pmap != kernel_pmap
1496: *
1497: * 1: This routine immediately allocates space for a page table.
1498: *
1499: * 2: The page table entries (PTEs) are initialized (set invalid), and
1500: * the corresponding segment table entry is set to point to the new
1501: * page table.
1502: */
1503: void
1504: pmap_expand(pmap_t pmap, vaddr_t v)
1505: {
1506: int spl;
1507: vaddr_t pdt_vaddr;
1508: paddr_t pdt_paddr;
1509: sdt_entry_t *sdt;
1510: pt_entry_t *pte;
1511:
1512: #ifdef DEBUG
1513: if (pmap_con_dbg & CD_EXP)
1514: printf ("(pmap_expand: %x) map %x v %x\n", curproc, pmap, v);
1515: #endif
1516:
1517: /* XXX */
1518: pdt_vaddr = uvm_km_zalloc(kernel_map, PAGE_SIZE);
1519: if (pmap_extract(kernel_pmap, pdt_vaddr, &pdt_paddr) == FALSE)
1520: panic("pmap_expand: pmap_extract failed");
1521:
1522: /* memory for page tables should not be writeback or local */
1523: pmap_cache_ctrl(kernel_pmap,
1524: pdt_vaddr, pdt_vaddr + PAGE_SIZE, CACHE_WT);
1525:
1526: spl = splvm();
1527: PMAP_LOCK(pmap);
1528:
1529: if ((pte = pmap_pte(pmap, v)) != NULL) {
1530: /*
1531: * Someone else caused us to expand
1532: * during our vm_allocate.
1533: */
1534: PMAP_UNLOCK(pmap);
1535: uvm_km_free(kernel_map, pdt_vaddr, PAGE_SIZE);
1536:
1537: #ifdef DEBUG
1538: if (pmap_con_dbg & CD_EXP)
1539: printf("(pmap_expand: %x) table has already been allocated\n", curproc);
1540: #endif
1541: splx(spl);
1542: return;
1543: }
1544: /*
1545: * Apply a mask to V to obtain the vaddr of the beginning of
1546: * its containing page 'table group', i.e. the group of
1547: * page tables that fit eithin a single VM page.
1548: * Using that, obtain the segment table pointer that references the
1549: * first page table in the group, and initialize all the
1550: * segment table descriptions for the page 'table group'.
1551: */
1552: v &= ~((1 << (PDT_BITS + PG_BITS)) - 1);
1553:
1554: sdt = SDTENT(pmap, v);
1555:
1556: /*
1557: * Init each of the segment entries to point the freshly allocated
1558: * page tables.
1559: */
1560: *((sdt_entry_t *)sdt) = pdt_paddr | SG_RW | SG_V;
1561: *((sdt_entry_t *)(sdt + SDT_ENTRIES)) = pdt_vaddr | SG_RW | SG_V;
1562:
1563: PMAP_UNLOCK(pmap);
1564: splx(spl);
1565: }
1566:
1567: /*
1568: * Routine: PMAP_ENTER
1569: *
1570: * Function:
1571: * Insert the given physical page (p) at the specified virtual
1572: * address (v) in the target phisical map with the protecton requested.
1573: * If specified, the page will be wired down, meaning that the
1574: * related pte can not be reclaimed.
1575: *
1576: * N.B.: This is the only routine which MAY NOT lazy-evaluation or lose
1577: * information. That is, this routine must actually insert this page
1578: * into the given map NOW.
1579: *
1580: * Parameters:
1581: * pmap pointer to pmap structure
1582: * va VA of page to be mapped
1583: * pa PA of page to be mapped
1584: * prot protection attributes for page
1585: * wired wired attribute for page
1586: *
1587: * Extern/Global:
1588: * pv lists
1589: *
1590: * Calls:
1591: * pmap_pte
1592: * pmap_expand
1593: * pmap_remove_pte
1594: *
1595: * This routine starts off by calling pmap_pte to obtain a (virtual)
1596: * pointer to the page table entry corresponding to given virtual
1597: * address. If the page table itself does not exist, pmap_expand is
1598: * called to allocate it.
1599: *
1600: * If the page table entry (PTE) already maps the given physical page,
1601: * all that is needed is to set the protection and wired attributes as
1602: * given. TLB entries are flushed and pmap_enter returns.
1603: *
1604: * If the page table entry (PTE) maps a different physical page than
1605: * that given, the old mapping is removed by a call to map_remove_range.
1606: * And execution of pmap_enter continues.
1607: *
1608: * To map the new physical page, the routine first inserts a new
1609: * entry in the PV list exhibiting the given pmap and virtual address.
1610: * It then inserts the physical page address, protection attributes, and
1611: * wired attributes into the page table entry (PTE).
1612: *
1613: *
1614: * get machine-dependent prot code
1615: * get the pte for this page
1616: * if necessary pmap_expand(pmap, v)
1617: * if (changing wired attribute or protection) {
1618: * flush entry from TLB
1619: * update template
1620: * for (ptes per vm page)
1621: * stuff pte
1622: * } else if (mapped at wrong addr)
1623: * flush entry from TLB
1624: * pmap_remove_pte
1625: * } else {
1626: * enter mapping in pv_list
1627: * setup template and stuff ptes
1628: * }
1629: *
1630: */
1631: int
1632: pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
1633: {
1634: int spl;
1635: pt_entry_t *pte, template;
1636: paddr_t old_pa;
1637: pv_entry_t pv_e, pvl;
1638: boolean_t wired = (flags & PMAP_WIRED) != 0;
1639: struct vm_page *pg;
1640:
1641: #ifdef DEBUG
1642: if (pmap_con_dbg & CD_ENT) {
1643: if (pmap == kernel_pmap)
1644: printf("(pmap_enter: %x) pmap kernel va %x pa %x\n", curproc, va, pa);
1645: else
1646: printf("(pmap_enter: %x) pmap %x va %x pa %x\n", curproc, pmap, va, pa);
1647: }
1648: #endif
1649:
1650: template = m88k_protection(prot);
1651:
1652: spl = splvm();
1653: PMAP_LOCK(pmap);
1654:
1655: /*
1656: * Expand pmap to include this pte.
1657: */
1658: while ((pte = pmap_pte(pmap, va)) == NULL) {
1659: if (pmap == kernel_pmap) {
1660: /* will only return NULL if PMAP_CANFAIL is set */
1661: if (pmap_expand_kmap(va, VM_PROT_READ | VM_PROT_WRITE,
1662: flags & PMAP_CANFAIL) == NULL)
1663: return (ENOMEM);
1664: } else {
1665: /*
1666: * Must unlock to expand the pmap.
1667: */
1668: PMAP_UNLOCK(pmap);
1669: pmap_expand(pmap, va);
1670: PMAP_LOCK(pmap);
1671: }
1672: }
1673: /*
1674: * Special case if the physical page is already mapped at this address.
1675: */
1676: old_pa = ptoa(PG_PFNUM(*pte));
1677: #ifdef DEBUG
1678: if (pmap_con_dbg & CD_ENT)
1679: printf("(pmap_enter) old_pa %x pte %x\n", old_pa, *pte);
1680: #endif
1681:
1682: pg = PHYS_TO_VM_PAGE(pa);
1683: if (pg != NULL)
1684: pvl = pg_to_pvh(pg);
1685: else
1686: pvl = NULL;
1687:
1688: if (old_pa == pa) {
1689: /* May be changing its wired attributes or protection */
1690: if (wired && !(pmap_pte_w(pte)))
1691: pmap->pm_stats.wired_count++;
1692: else if (!wired && pmap_pte_w(pte))
1693: pmap->pm_stats.wired_count--;
1694: } else {
1695: /* Remove old mapping from the PV list if necessary. */
1696: pmap_remove_pte(pmap, va, pte);
1697:
1698: if (pvl != NULL) {
1699: /*
1700: * Enter the mapping in the PV list for this
1701: * managed page.
1702: */
1703: if (pvl->pv_pmap == NULL) {
1704: /*
1705: * No mappings yet
1706: */
1707: pvl->pv_va = va;
1708: pvl->pv_pmap = pmap;
1709: pvl->pv_next = NULL;
1710: pvl->pv_flags = 0;
1711:
1712: } else {
1713: /*
1714: * Add new pv_entry after header.
1715: */
1716: pv_e = pool_get(&pvpool, PR_NOWAIT);
1717: if (pv_e == NULL) {
1718: if (flags & PMAP_CANFAIL) {
1719: PMAP_UNLOCK(pmap);
1720: splx(spl);
1721: return (ENOMEM);
1722: } else
1723: panic("pmap_enter: "
1724: "pvpool exhausted");
1725: }
1726: pv_e->pv_va = va;
1727: pv_e->pv_pmap = pmap;
1728: pv_e->pv_next = pvl->pv_next;
1729: pv_e->pv_flags = 0;
1730: pvl->pv_next = pv_e;
1731: }
1732: }
1733:
1734: /*
1735: * And count the mapping.
1736: */
1737: pmap->pm_stats.resident_count++;
1738: if (wired)
1739: pmap->pm_stats.wired_count++;
1740: } /* if (pa == old_pa) ... else */
1741:
1742: template |= PG_V;
1743: if (wired)
1744: template |= PG_W;
1745:
1746: /*
1747: * If outside physical memory, disable cache on this (I/O) page.
1748: */
1749: if ((unsigned long)pa >= last_addr)
1750: template |= CACHE_INH;
1751:
1752: if (flags & VM_PROT_WRITE)
1753: template |= PG_M_U;
1754: else if (flags & VM_PROT_ALL)
1755: template |= PG_U;
1756:
1757: /*
1758: * Invalidate pte temporarily to avoid being written
1759: * back the modified bit and/or the reference bit by
1760: * any other cpu.
1761: */
1762: template |= invalidate_pte(pte) & PG_M_U;
1763: *pte = template | pa;
1764: flush_atc_entry(pmap, va);
1765: #ifdef DEBUG
1766: if (pmap_con_dbg & CD_ENT)
1767: printf("(pmap_enter) set pte to %x\n", *pte);
1768: #endif
1769:
1770: /*
1771: * Cache attribute flags
1772: */
1773: if (pvl != NULL)
1774: pvl->pv_flags |= template & PG_M_U;
1775:
1776: PMAP_UNLOCK(pmap);
1777: splx(spl);
1778:
1779: return 0;
1780: }
1781:
1782: /*
1783: * Routine: pmap_unwire
1784: *
1785: * Function: Change the wiring attributes for a map/virtual-address pair.
1786: *
1787: * Parameters:
1788: * pmap pointer to pmap structure
1789: * v virtual address of page to be unwired
1790: *
1791: * Calls:
1792: * pmap_pte
1793: *
1794: * Special Assumptions:
1795: * The mapping must already exist in the pmap.
1796: */
1797: void
1798: pmap_unwire(pmap_t pmap, vaddr_t v)
1799: {
1800: pt_entry_t *pte;
1801: int spl;
1802:
1803: spl = splvm();
1804: PMAP_LOCK(pmap);
1805:
1806: if ((pte = pmap_pte(pmap, v)) == NULL)
1807: panic("pmap_unwire: pte missing");
1808:
1809: if (pmap_pte_w(pte)) {
1810: /* unwired mapping */
1811: pmap->pm_stats.wired_count--;
1812: *pte &= ~PG_W;
1813: }
1814:
1815: PMAP_UNLOCK(pmap);
1816: splx(spl);
1817: }
1818:
1819: /*
1820: * Routine: PMAP_EXTRACT
1821: *
1822: * Function:
1823: * Extract the physical page address associoated
1824: * with the given map/virtual_address pair.
1825: *
1826: * Parameters:
1827: * pmap pointer to pmap structure
1828: * va virtual address
1829: * pap storage for result.
1830: *
1831: * Calls:
1832: * PMAP_LOCK, PMAP_UNLOCK
1833: * pmap_pte
1834: *
1835: * The routine calls pmap_pte to get a (virtual) pointer to
1836: * the page table entry (PTE) associated with the given virtual
1837: * address. If the page table does not exist, or if the PTE is not valid,
1838: * then 0 address is returned. Otherwise, the physical page address from
1839: * the PTE is returned.
1840: */
1841: boolean_t
1842: pmap_extract(pmap_t pmap, vaddr_t va, paddr_t *pap)
1843: {
1844: pt_entry_t *pte;
1845: paddr_t pa;
1846: int spl;
1847: boolean_t rv = FALSE;
1848:
1849: #ifdef DIAGNOSTIC
1850: if (pmap == NULL)
1851: panic("pmap_extract: pmap is NULL");
1852: #endif
1853:
1854: #ifdef M88100
1855: /*
1856: * 88100-based designs have two hardwired BATC entries which map
1857: * the upper 1MB 1:1 in supervisor space.
1858: */
1859: if (CPU_IS88100) {
1860: if (va >= BATC8_VA && pmap == kernel_pmap) {
1861: *pap = va;
1862: return (TRUE);
1863: }
1864: }
1865: #endif
1866:
1867: spl = splvm();
1868: PMAP_LOCK(pmap);
1869:
1870: pte = pmap_pte(pmap, va);
1871: if (pte != NULL && PDT_VALID(pte)) {
1872: rv = TRUE;
1873: if (pap != NULL) {
1874: pa = ptoa(PG_PFNUM(*pte));
1875: pa |= (va & PAGE_MASK); /* offset within page */
1876: *pap = pa;
1877: }
1878: }
1879:
1880: PMAP_UNLOCK(pmap);
1881: splx(spl);
1882: return rv;
1883: }
1884:
1885: /*
1886: * Routine: PMAP_COLLECT
1887: *
1888: * Runction:
1889: * Garbage collects the physical map system for pages which are
1890: * no longer used. there may well be pages which are not
1891: * referenced, but others may be collected as well.
1892: * Called by the pageout daemon when pages are scarce.
1893: *
1894: * Parameters:
1895: * pmap pointer to pmap structure
1896: *
1897: * Calls:
1898: * pmap_pte
1899: * pmap_remove_range
1900: * uvm_km_free
1901: *
1902: * The intent of this routine is to release memory pages being used
1903: * by translation tables. They can be release only if they contain no
1904: * valid mappings, and their parent table entry has been invalidated.
1905: *
1906: * The routine sequences through the entries user address space,
1907: * inspecting page-sized groups of page tables for wired entries. If
1908: * a full page of tables has no wired enties, any otherwise valid
1909: * entries are invalidated (via pmap_remove_range). Then, the segment
1910: * table entries corresponding to this group of page tables are
1911: * invalidated. Finally, uvm_km_free is called to return the page to the
1912: * system.
1913: *
1914: * If all entries in a segment table are invalidated, it too can
1915: * be returned to the system.
1916: */
1917: void
1918: pmap_collect(pmap_t pmap)
1919: {
1920: u_int sdt; /* outer loop index */
1921: vaddr_t sdt_va;
1922: sdt_entry_t *sdtp; /* ptr to index into segment table */
1923: pt_entry_t *gdttbl; /* ptr to first entry in a page table */
1924: pt_entry_t *gdttblend; /* ptr to byte after last entry in
1925: table group */
1926: pt_entry_t *gdtp; /* ptr to index into a page table */
1927: boolean_t found_gdt_wired; /* flag indicating a wired page exists
1928: in a page table's address range */
1929: int spl;
1930:
1931: #ifdef DEBUG
1932: if (pmap_con_dbg & CD_COL)
1933: printf ("(pmap_collect: %x) pmap %x\n", curproc, pmap);
1934: #endif
1935:
1936: spl = splvm();
1937: PMAP_LOCK(pmap);
1938:
1939: sdtp = pmap->pm_stab; /* addr of segment table */
1940:
1941: /* segment table loop */
1942: for (sdt = VM_MIN_ADDRESS >> SDT_SHIFT;
1943: sdt <= VM_MAX_ADDRESS >> SDT_SHIFT; sdt++, sdtp++) {
1944: sdt_va = sdt << SDT_SHIFT;
1945: gdttbl = pmap_pte(pmap, sdt_va);
1946: if (gdttbl == NULL)
1947: continue; /* no maps in this range */
1948:
1949: gdttblend = gdttbl + PDT_ENTRIES;
1950:
1951: /* scan page maps for wired pages */
1952: found_gdt_wired = FALSE;
1953: for (gdtp = gdttbl; gdtp < gdttblend; gdtp++) {
1954: if (pmap_pte_w(gdtp)) {
1955: found_gdt_wired = TRUE;
1956: break;
1957: }
1958: }
1959:
1960: if (found_gdt_wired)
1961: continue; /* can't free this range */
1962:
1963: /* invalidate all maps in this range */
1964: pmap_remove_range(pmap, sdt_va, sdt_va + (1 << SDT_SHIFT));
1965:
1966: /*
1967: * we can safely deallocate the page map(s)
1968: */
1969: *((sdt_entry_t *) sdtp) = 0;
1970: *((sdt_entry_t *)(sdtp + SDT_ENTRIES)) = 0;
1971:
1972: /*
1973: * we have to unlock before freeing the table, since
1974: * uvm_km_free will invoke another pmap routine
1975: */
1976: PMAP_UNLOCK(pmap);
1977: uvm_km_free(kernel_map, (vaddr_t)gdttbl, PAGE_SIZE);
1978: PMAP_LOCK(pmap);
1979: }
1980:
1981: PMAP_UNLOCK(pmap);
1982: splx(spl);
1983:
1984: #ifdef DEBUG
1985: if (pmap_con_dbg & CD_COL)
1986: printf("(pmap_collect: %x) done\n", curproc);
1987: #endif
1988: }
1989:
1990: /*
1991: * Routine: PMAP_ACTIVATE
1992: *
1993: * Function:
1994: * Binds the pmap associated to the process to the current processor.
1995: *
1996: * Parameters:
1997: * p pointer to proc structure
1998: *
1999: * Notes:
2000: * If the specified pmap is not kernel_pmap, this routine stores its
2001: * apr template into UAPR (user area pointer register) in the
2002: * CMMUs connected to the specified CPU.
2003: *
2004: * Then it flushes the TLBs mapping user virtual space, in the CMMUs
2005: * connected to the specified CPU.
2006: */
2007: void
2008: pmap_activate(struct proc *p)
2009: {
2010: pmap_t pmap = vm_map_pmap(&p->p_vmspace->vm_map);
2011: int cpu = cpu_number();
2012:
2013: #ifdef DEBUG
2014: if (pmap_con_dbg & CD_ACTIVATE)
2015: printf("(pmap_activate: %x) pmap %p\n", p, pmap);
2016: #endif
2017:
2018: if (pmap != kernel_pmap) {
2019: /*
2020: * Lock the pmap to put this cpu in its active set.
2021: */
2022: PMAP_LOCK(pmap);
2023:
2024: cmmu_set_uapr(pmap->pm_apr);
2025: cmmu_flush_tlb(cpu, FALSE, 0, -1);
2026:
2027: /*
2028: * Mark that this cpu is using the pmap.
2029: */
2030: SETBIT_CPUSET(cpu, &(pmap->pm_cpus));
2031:
2032: PMAP_UNLOCK(pmap);
2033: }
2034: }
2035:
2036: /*
2037: * Routine: PMAP_DEACTIVATE
2038: *
2039: * Function:
2040: * Unbinds the pmap associated to the process from the current processor.
2041: *
2042: * Parameters:
2043: * p pointer to proc structure
2044: */
2045: void
2046: pmap_deactivate(struct proc *p)
2047: {
2048: pmap_t pmap = vm_map_pmap(&p->p_vmspace->vm_map);
2049: int cpu = cpu_number();
2050:
2051: if (pmap != kernel_pmap) {
2052: /*
2053: * We expect the spl to already have been raised to sched level.
2054: */
2055: PMAP_LOCK(pmap);
2056: CLRBIT_CPUSET(cpu, &(pmap->pm_cpus));
2057: PMAP_UNLOCK(pmap);
2058: }
2059: }
2060:
2061: /*
2062: * Routine: PMAP_COPY_PAGE
2063: *
2064: * Function:
2065: * Copies the specified pages.
2066: *
2067: * Parameters:
2068: * src PA of source page
2069: * dst PA of destination page
2070: *
2071: * Extern/Global:
2072: * phys_map_vaddr
2073: *
2074: * Special Assumptions:
2075: * no locking required
2076: *
2077: * This routine maps the physical pages at the 'phys_map' virtual
2078: * addresses set up in pmap_bootstrap. It flushes the TLB to make the
2079: * new mappings effective, and performs the copy.
2080: */
2081: void
2082: pmap_copy_page(struct vm_page *srcpg, struct vm_page *dstpg)
2083: {
2084: paddr_t src = VM_PAGE_TO_PHYS(srcpg);
2085: paddr_t dst = VM_PAGE_TO_PHYS(dstpg);
2086: vaddr_t dstva, srcva;
2087: int spl;
2088: pt_entry_t *dstpte, *srcpte;
2089: int cpu = cpu_number();
2090:
2091: dstva = (vaddr_t)(phys_map_vaddr + 2 * (cpu << PAGE_SHIFT));
2092: srcva = dstva + PAGE_SIZE;
2093: dstpte = pmap_pte(kernel_pmap, dstva);
2094: srcpte = pmap_pte(kernel_pmap, srcva);
2095:
2096: spl = splvm();
2097:
2098: *dstpte = m88k_protection(VM_PROT_READ | VM_PROT_WRITE) |
2099: PG_M /* 88110 */ | PG_V | dst;
2100: *srcpte = m88k_protection(VM_PROT_READ) |
2101: PG_V | src;
2102:
2103: /*
2104: * We don't need the flush_atc_entry() dance, as these pages are
2105: * bound to only one cpu.
2106: */
2107: cmmu_flush_tlb(cpu, TRUE, dstva, 2);
2108:
2109: /*
2110: * The source page is likely to be a non-kernel mapping, and as
2111: * such write back. Also, we might have split U/S caches!
2112: * So be sure to have the source pa flushed before the copy is
2113: * attempted, and the destination pa flushed afterwards.
2114: */
2115: cmmu_flush_data_page(cpu, src);
2116: bcopy((const void *)srcva, (void *)dstva, PAGE_SIZE);
2117: cmmu_flush_data_page(cpu, dst);
2118:
2119: splx(spl);
2120: }
2121:
2122: /*
2123: * Routine: PMAP_CHANGEBIT
2124: *
2125: * Function:
2126: * Update the pte bits on the specified physical page.
2127: *
2128: * Parameters:
2129: * pg physical page
2130: * set bits to set
2131: * mask bits to mask
2132: *
2133: * Extern/Global:
2134: * pv_lists
2135: *
2136: * Calls:
2137: * pmap_pte
2138: *
2139: * The pte bits corresponding to the page's frame index will be changed as
2140: * requested. The PV list will be traversed.
2141: * For each pmap/va the hardware the necessary bits in the page descriptor
2142: * table entry will be altered as well if necessary. If any bits were changed,
2143: * a TLB flush will be performed.
2144: */
2145: void
2146: pmap_changebit(struct vm_page *pg, int set, int mask)
2147: {
2148: pv_entry_t pvl, pvep;
2149: pt_entry_t *pte, npte, opte;
2150: pmap_t pmap;
2151: int spl;
2152: vaddr_t va;
2153:
2154: spl = splvm();
2155:
2156: #ifdef MULTIPROCESSOR
2157: changebit_Retry:
2158: #endif
2159: pvl = pg_to_pvh(pg);
2160:
2161: /*
2162: * Clear saved attributes (modify, reference)
2163: */
2164: pvl->pv_flags &= mask;
2165:
2166: if (pvl->pv_pmap == NULL) {
2167: #ifdef DEBUG
2168: if (pmap_con_dbg & CD_CBIT)
2169: printf("(pmap_changebit: %x) vm page 0x%x not mapped\n",
2170: curproc, pg);
2171: #endif
2172: splx(spl);
2173: return;
2174: }
2175:
2176: /* for each listed pmap, update the affected bits */
2177: for (pvep = pvl; pvep != NULL; pvep = pvep->pv_next) {
2178: pmap = pvep->pv_pmap;
2179: #ifdef MULTIPROCESSOR
2180: if (!__cpu_simple_lock_try(&pmap->pm_lock)) {
2181: goto changebit_Retry;
2182: }
2183: #endif
2184: va = pvep->pv_va;
2185: pte = pmap_pte(pmap, va);
2186:
2187: /*
2188: * Check for existing and valid pte
2189: */
2190: if (pte == NULL || !PDT_VALID(pte)) {
2191: goto next; /* no page mapping */
2192: }
2193: #ifdef DIAGNOSTIC
2194: if (ptoa(PG_PFNUM(*pte)) != VM_PAGE_TO_PHYS(pg))
2195: panic("pmap_changebit: pte %x in pmap %p doesn't point to page %p %lx",
2196: *pte, pmap, pg, VM_PAGE_TO_PHYS(pg));
2197: #endif
2198:
2199: /*
2200: * Update bits
2201: */
2202: opte = *pte;
2203: npte = (opte | set) & mask;
2204:
2205: /*
2206: * Flush TLB of which cpus using pmap.
2207: *
2208: * Invalidate pte temporarily to avoid the modified bit
2209: * and/or the reference being written back by any other cpu.
2210: */
2211: if (npte != opte) {
2212: invalidate_pte(pte);
2213: *pte = npte;
2214: flush_atc_entry(pmap, va);
2215: }
2216: next:
2217: PMAP_UNLOCK(pmap);
2218: }
2219: splx(spl);
2220: }
2221:
2222: /*
2223: * Routine: PMAP_TESTBIT
2224: *
2225: * Function:
2226: * Test the modified/referenced bits of a physical page.
2227: *
2228: * Parameters:
2229: * pg physical page
2230: * bit bit to test
2231: *
2232: * Extern/Global:
2233: * pv lists
2234: *
2235: * Calls:
2236: * pmap_pte
2237: *
2238: * If the attribute list for the given page has the bit, this routine
2239: * returns TRUE.
2240: *
2241: * Otherwise, this routine walks the PV list corresponding to the
2242: * given page. For each pmap/va pair, the page descriptor table entry is
2243: * examined. If the selected bit is found on, the function returns TRUE
2244: * immediately (doesn't need to walk remainder of list), and updates the
2245: * attribute list.
2246: */
2247: boolean_t
2248: pmap_testbit(struct vm_page *pg, int bit)
2249: {
2250: pv_entry_t pvl, pvep;
2251: pt_entry_t *pte;
2252: pmap_t pmap;
2253: int spl;
2254:
2255: spl = splvm();
2256:
2257: #ifdef MULTIPROCESSOR
2258: testbit_Retry:
2259: #endif
2260: pvl = pg_to_pvh(pg);
2261:
2262: if (pvl->pv_flags & bit) {
2263: /* we've already cached this flag for this page,
2264: no use looking further... */
2265: #ifdef DEBUG
2266: if (pmap_con_dbg & CD_TBIT)
2267: printf("(pmap_testbit: %x) already cached a %x flag for this page\n",
2268: curproc, bit);
2269: #endif
2270: splx(spl);
2271: return (TRUE);
2272: }
2273:
2274: if (pvl->pv_pmap == NULL) {
2275: #ifdef DEBUG
2276: if (pmap_con_dbg & CD_TBIT)
2277: printf("(pmap_testbit: %x) vm page 0x%x not mapped\n",
2278: curproc, pg);
2279: #endif
2280: splx(spl);
2281: return (FALSE);
2282: }
2283:
2284: /* for each listed pmap, check modified bit for given page */
2285: for (pvep = pvl; pvep != NULL; pvep = pvep->pv_next) {
2286: pmap = pvep->pv_pmap;
2287: #ifdef MULTIPROCESSOR
2288: if (!__cpu_simple_lock_try(&pmap->pm_lock)) {
2289: goto testbit_Retry;
2290: }
2291: #endif
2292:
2293: pte = pmap_pte(pmap, pvep->pv_va);
2294: if (pte == NULL || !PDT_VALID(pte)) {
2295: goto next;
2296: }
2297:
2298: #ifdef DIAGNOSTIC
2299: if (ptoa(PG_PFNUM(*pte)) != VM_PAGE_TO_PHYS(pg))
2300: panic("pmap_testbit: pte %x in pmap %p %d doesn't point to page %p %lx",
2301: *pte, pmap, pmap == kernel_pmap ? 1 : 0, pg, VM_PAGE_TO_PHYS(pg));
2302: #endif
2303:
2304: if ((*pte & bit) != 0) {
2305: PMAP_UNLOCK(pmap);
2306: pvl->pv_flags |= bit;
2307: #ifdef DEBUG
2308: if ((pmap_con_dbg & (CD_TBIT | CD_FULL)) == (CD_TBIT | CD_FULL))
2309: printf("(pmap_testbit: %x) true on page pte@%p\n", curproc, pte);
2310: #endif
2311: splx(spl);
2312: return (TRUE);
2313: }
2314: next:
2315: PMAP_UNLOCK(pmap);
2316: }
2317:
2318: splx(spl);
2319: return (FALSE);
2320: }
2321:
2322: /*
2323: * Routine: PMAP_UNSETBIT
2324: *
2325: * Function:
2326: * Clears a pte bit and returns its previous state, for the
2327: * specified physical page.
2328: * This is an optimized version of:
2329: * rv = pmap_testbit(pg, bit);
2330: * pmap_changebit(pg, 0, ~bit);
2331: * return rv;
2332: */
2333: boolean_t
2334: pmap_unsetbit(struct vm_page *pg, int bit)
2335: {
2336: boolean_t rv = FALSE;
2337: pv_entry_t pvl, pvep;
2338: pt_entry_t *pte, opte;
2339: pmap_t pmap;
2340: int spl;
2341: vaddr_t va;
2342:
2343: spl = splvm();
2344:
2345: #ifdef MULTIPROCESSOR
2346: unsetbit_Retry:
2347: #endif
2348: pvl = pg_to_pvh(pg);
2349:
2350: /*
2351: * Clear saved attributes
2352: */
2353: pvl->pv_flags &= ~bit;
2354:
2355: if (pvl->pv_pmap == NULL) {
2356: #ifdef DEBUG
2357: if (pmap_con_dbg & CD_USBIT)
2358: printf("(pmap_unsetbit: %x) vm page 0x%x not mapped\n",
2359: curproc, pg);
2360: #endif
2361: splx(spl);
2362: return (FALSE);
2363: }
2364:
2365: /* for each listed pmap, update the specified bit */
2366: for (pvep = pvl; pvep != NULL; pvep = pvep->pv_next) {
2367: pmap = pvep->pv_pmap;
2368: #ifdef MULTIPROCESSOR
2369: if (!__cpu_simple_lock_try(&pmap->pm_lock)) {
2370: goto unsetbit_Retry;
2371: }
2372: #endif
2373: va = pvep->pv_va;
2374: pte = pmap_pte(pmap, va);
2375:
2376: /*
2377: * Check for existing and valid pte
2378: */
2379: if (pte == NULL || !PDT_VALID(pte)) {
2380: goto next; /* no page mapping */
2381: }
2382: #ifdef DIAGNOSTIC
2383: if (ptoa(PG_PFNUM(*pte)) != VM_PAGE_TO_PHYS(pg))
2384: panic("pmap_unsetbit: pte %x in pmap %p doesn't point to page %p %lx",
2385: *pte, pmap, pg, VM_PAGE_TO_PHYS(pg));
2386: #endif
2387:
2388: /*
2389: * Update bits
2390: */
2391: opte = *pte;
2392: if (opte & bit) {
2393: /*
2394: * Flush TLB of which cpus using pmap.
2395: *
2396: * Invalidate pte temporarily to avoid the specified
2397: * bit being written back by any other cpu.
2398: */
2399: invalidate_pte(pte);
2400: *pte = opte ^ bit;
2401: flush_atc_entry(pmap, va);
2402: } else
2403: rv = TRUE;
2404: next:
2405: PMAP_UNLOCK(pmap);
2406: }
2407: splx(spl);
2408:
2409: return (rv);
2410: }
2411:
2412: /*
2413: * Routine: PMAP_IS_MODIFIED
2414: *
2415: * Function:
2416: * Return whether or not the specified physical page is modified
2417: * by any physical maps.
2418: */
2419: boolean_t
2420: pmap_is_modified(struct vm_page *pg)
2421: {
2422: return pmap_testbit(pg, PG_M);
2423: }
2424:
2425: /*
2426: * Routine: PMAP_IS_REFERENCED
2427: *
2428: * Function:
2429: * Return whether or not the specified physical page is referenced by
2430: * any physical maps.
2431: */
2432: boolean_t
2433: pmap_is_referenced(struct vm_page *pg)
2434: {
2435: return pmap_testbit(pg, PG_U);
2436: }
2437:
2438: /*
2439: * Routine: PMAP_PAGE_PROTECT
2440: *
2441: * Calls:
2442: * pmap_changebit
2443: * pmap_remove_all
2444: *
2445: * Lower the permission for all mappings to a given page.
2446: */
2447: void
2448: pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
2449: {
2450: if ((prot & VM_PROT_READ) == VM_PROT_NONE)
2451: pmap_remove_all(pg);
2452: else if ((prot & VM_PROT_WRITE) == VM_PROT_NONE)
2453: pmap_changebit(pg, PG_RO, ~0);
2454: }
2455:
2456: void
2457: pmap_virtual_space(vaddr_t *startp, vaddr_t *endp)
2458: {
2459: *startp = virtual_avail;
2460: *endp = virtual_end;
2461: }
2462:
2463: void
2464: pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot)
2465: {
2466: int spl;
2467: pt_entry_t template, *pte;
2468:
2469: #ifdef DEBUG
2470: if (pmap_con_dbg & CD_ENT) {
2471: printf ("(pmap_kenter_pa: %x) va %x pa %x\n", curproc, va, pa);
2472: }
2473: #endif
2474:
2475: spl = splvm();
2476: PMAP_LOCK(kernel_pmap);
2477:
2478: template = m88k_protection(prot);
2479: #ifdef M88110
2480: if (CPU_IS88110 && m88k_protection(prot) != PG_RO)
2481: template |= PG_M;
2482: #endif
2483:
2484: /*
2485: * Expand pmap to include this pte.
2486: */
2487: while ((pte = pmap_pte(kernel_pmap, va)) == NULL)
2488: pmap_expand_kmap(va, VM_PROT_READ | VM_PROT_WRITE, 0);
2489:
2490: /*
2491: * And count the mapping.
2492: */
2493: kernel_pmap->pm_stats.resident_count++;
2494: kernel_pmap->pm_stats.wired_count++;
2495:
2496: invalidate_pte(pte);
2497:
2498: /*
2499: * If outside physical memory, disable cache on this (I/O) page.
2500: */
2501: if ((unsigned long)pa >= last_addr)
2502: template |= CACHE_INH | PG_V | PG_W;
2503: else
2504: template |= PG_V | PG_W;
2505: *pte = template | pa;
2506: flush_atc_entry(kernel_pmap, va);
2507:
2508: PMAP_UNLOCK(kernel_pmap);
2509: splx(spl);
2510: }
2511:
2512: void
2513: pmap_kremove(vaddr_t va, vsize_t len)
2514: {
2515: int spl;
2516: vaddr_t e, eseg;
2517:
2518: #ifdef DEBUG
2519: if (pmap_con_dbg & CD_RM)
2520: printf("(pmap_kremove: %x) va %x len %x\n", curproc, va, len);
2521: #endif
2522:
2523: spl = splvm();
2524: PMAP_LOCK(kernel_pmap);
2525:
2526: e = va + len;
2527: while (va != e) {
2528: sdt_entry_t *sdt;
2529: pt_entry_t *pte;
2530:
2531: eseg = (va & SDT_MASK) + (1 << SDT_SHIFT);
2532: if (eseg > e || eseg == 0)
2533: eseg = e;
2534:
2535: sdt = SDTENT(kernel_pmap, va);
2536:
2537: /* If no segment table, skip a whole segment */
2538: if (!SDT_VALID(sdt))
2539: va = eseg;
2540: else {
2541: while (va != eseg) {
2542: pte = sdt_pte(sdt, va);
2543: if (pte != NULL && PDT_VALID(pte)) {
2544: /* Update the counts */
2545: kernel_pmap->pm_stats.resident_count--;
2546: kernel_pmap->pm_stats.wired_count--;
2547:
2548: invalidate_pte(pte);
2549: flush_atc_entry(kernel_pmap, va);
2550: }
2551: va += PAGE_SIZE;
2552: }
2553: }
2554: }
2555: PMAP_UNLOCK(kernel_pmap);
2556: splx(spl);
2557: }
2558:
2559: void
2560: pmap_proc_iflush(struct proc *p, vaddr_t va, vsize_t len)
2561: {
2562: pmap_t pmap = vm_map_pmap(&p->p_vmspace->vm_map);
2563: paddr_t pa;
2564: vsize_t count;
2565: u_int32_t users;
2566: int cpu;
2567:
2568: while (len != 0) {
2569: count = min(len, PAGE_SIZE - (va & PAGE_MASK));
2570: if (pmap_extract(pmap, va, &pa)) {
2571: users = pmap->pm_cpus;
2572: while ((cpu = ff1(users)) != 32) {
2573: cmmu_flush_inst_cache(cpu, pa, count);
2574: users &= ~(1 << cpu);
2575: }
2576: }
2577: va += count;
2578: len -= count;
2579: }
2580: }
CVSweb