]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/alpha/alpha/pmap.c
This commit was generated by cvs2svn to compensate for changes in r57419,
[FreeBSD/FreeBSD.git] / sys / alpha / alpha / pmap.c
1 /*
2  * Copyright (c) 1991 Regents of the University of California.
3  * All rights reserved.
4  * Copyright (c) 1994 John S. Dyson
5  * All rights reserved.
6  * Copyright (c) 1994 David Greenman
7  * All rights reserved.
8  * Copyright (c) 1998 Doug Rabson
9  * All rights reserved.
10  *
11  * This code is derived from software contributed to Berkeley by
12  * the Systems Programming Group of the University of Utah Computer
13  * Science Department and William Jolitz of UUNET Technologies Inc.
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  * 3. All advertising materials mentioning features or use of this software
24  *    must display the following acknowledgement:
25  *      This product includes software developed by the University of
26  *      California, Berkeley and its contributors.
27  * 4. Neither the name of the University nor the names of its contributors
28  *    may be used to endorse or promote products derived from this software
29  *    without specific prior written permission.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
32  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
35  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41  * SUCH DAMAGE.
42  *
43  *      from:   @(#)pmap.c      7.7 (Berkeley)  5/12/91
44  *      from:   i386 Id: pmap.c,v 1.193 1998/04/19 15:22:48 bde Exp
45  *              with some ideas from NetBSD's alpha pmap
46  * $FreeBSD$
47  */
48
49 /*
50  *      Manages physical address maps.
51  *
52  *      In addition to hardware address maps, this
53  *      module is called upon to provide software-use-only
54  *      maps which may or may not be stored in the same
55  *      form as hardware maps.  These pseudo-maps are
56  *      used to store intermediate results from copy
57  *      operations to and from address spaces.
58  *
59  *      Since the information managed by this module is
60  *      also stored by the logical address mapping module,
61  *      this module may throw away valid virtual-to-physical
62  *      mappings at almost any time.  However, invalidations
63  *      of virtual-to-physical mappings must be done as
64  *      requested.
65  *
66  *      In order to cope with hardware architectures which
67  *      make virtual-to-physical map invalidates expensive,
68  *      this module may delay invalidate or reduced protection
69  *      operations until such time as they are actually
70  *      necessary.  This module is given full information as
71  *      to which processors are currently using which maps,
72  *      and to when physical maps must be made correct.
73  */
74
75 /*
76  * Notes for alpha pmap.
77  * 
78  * On alpha, pm_pdeobj will hold lev1, lev2 and lev3 page tables.
79  * Indices from 0 to NUSERLEV3MAPS-1 will map user lev3 page tables,
80  * indices from NUSERLEV3MAPS to NUSERLEV3MAPS+NUSERLEV2MAPS-1 will
81  * map user lev2 page tables and index NUSERLEV3MAPS+NUSERLEV2MAPS
82  * will map the lev1 page table.  The lev1 table will self map at
83  * address VADDR(PTLEV1I,0,0).
84  * 
85  * The vm_object kptobj holds the kernel page tables on i386 (62 or 63
86  * of them, depending on whether the system is SMP).  On alpha, kptobj
87  * will hold the lev3 and lev2 page tables for K1SEG.  Indices 0 to
88  * NKLEV3MAPS-1 will map kernel lev3 page tables and indices
89  * NKLEV3MAPS to NKLEV3MAPS+NKLEV2MAPS will map lev2 page tables. (XXX
90  * should the kernel Lev1map be inserted into this object?).
91  * 
92  * pvtmmap is not needed for alpha since K0SEG maps all of physical
93  * memory. CADDR1 and CADDR2 are not needed for the same reason.  The
94  * only places outside pmap and machdep which use CADDR1 are xxdump
95  * routines which use them for dumping physical pages.
96  * 
97  * 
98  * alpha virtual memory map:
99  * 
100  * 
101  *  Address                                                     Lev1 index
102  * 
103  *                      ---------------------------------
104  *  0000000000000000    |                               |       0
105  *                      |                               |
106  *                      |                               |
107  *                      |                               |
108  *                      |                               |
109  *                     ---                             ---
110  *                              User space (USEG)
111  *                     ---                             ---
112  *                      |                               |
113  *                      |                               |
114  *                      |                               |
115  *                      |                               |
116  *  000003ffffffffff    |                               |       511=UMAXLEV1I
117  *                      ---------------------------------
118  *  fffffc0000000000    |                               |       512=K0SEGLEV1I
119  *                      |       Kernel code/data/bss    |
120  *                      |                               |
121  *                      |                               |
122  *                      |                               |
123  *                     ---                             ---
124  *                              K0SEG
125  *                     ---                             ---
126  *                      |                               |
127  *                      |       1-1 physical/virtual    |
128  *                      |                               |
129  *                      |                               |
130  *  fffffdffffffffff    |                               |
131  *                      ---------------------------------
132  *  fffffe0000000000    |                               |       768=K1SEGLEV1I
133  *                      |       Kernel dynamic data     |
134  *                      |                               |
135  *                      |                               |
136  *                      |                               |
137  *                     ---                             ---
138  *                              K1SEG
139  *                     ---                             ---
140  *                      |                               |
141  *                      |       mapped by ptes          |
142  *                      |                               |
143  *                      |                               |
144  *  fffffff7ffffffff    |                               |
145  *                      ---------------------------------
146  *  fffffffe00000000    |                               |       1023=PTLEV1I
147  *                      |       PTmap (pte self map)    |
148  *  ffffffffffffffff    |                               |
149  *                      ---------------------------------
150  * 
151  */
152
153 #include <sys/param.h>
154 #include <sys/systm.h>
155 #include <sys/proc.h>
156 #include <sys/msgbuf.h>
157 #include <sys/vmmeter.h>
158 #include <sys/mman.h>
159
160 #include <vm/vm.h>
161 #include <vm/vm_param.h>
162 #include <sys/lock.h>
163 #include <vm/vm_kern.h>
164 #include <vm/vm_page.h>
165 #include <vm/vm_map.h>
166 #include <vm/vm_object.h>
167 #include <vm/vm_extern.h>
168 #include <vm/vm_pageout.h>
169 #include <vm/vm_pager.h>
170 #include <vm/vm_zone.h>
171
172 #include <sys/user.h>
173
174 #include <machine/md_var.h>
175
176 #ifndef PMAP_SHPGPERPROC
177 #define PMAP_SHPGPERPROC 200
178 #endif
179
180 #if defined(DIAGNOSTIC)
181 #define PMAP_DIAGNOSTIC
182 #endif
183
184 #define MINPV 2048
185
186 #if 0
187 #define PMAP_DIAGNOSTIC
188 #define PMAP_DEBUG
189 #endif
190
191 #if !defined(PMAP_DIAGNOSTIC)
192 #define PMAP_INLINE __inline
193 #else
194 #define PMAP_INLINE
195 #endif
196
197 #if 0
198
199 static void
200 pmap_break(void)
201 {
202 }
203
204 /* #define PMAP_DEBUG_VA(va) if ((va) == 0x120058000) pmap_break(); else */
205
206 #endif
207
208 #ifndef PMAP_DEBUG_VA
209 #define PMAP_DEBUG_VA(va) do {} while(0)
210 #endif
211
212 /*
213  * Some macros for manipulating virtual addresses
214  */
215 #define ALPHA_L1SIZE            (1L << ALPHA_L1SHIFT)
216 #define ALPHA_L2SIZE            (1L << ALPHA_L2SHIFT)
217
218 #define alpha_l1trunc(va)       ((va) & ~(ALPHA_L1SIZE-1))
219 #define alpha_l2trunc(va)       ((va) & ~(ALPHA_L2SIZE-1))
220
221 /*
222  * Get PDEs and PTEs for user/kernel address space
223  */
224 #define pmap_pte_w(pte)         ((*(pte) & PG_W) != 0)
225 #define pmap_pte_managed(pte)   ((*(pte) & PG_MANAGED) != 0)
226 #define pmap_pte_v(pte)         ((*(pte) & PG_V) != 0)
227 #define pmap_pte_pa(pte)        alpha_ptob(ALPHA_PTE_TO_PFN(*(pte)))
228 #define pmap_pte_prot(pte)      (*(pte) & PG_PROT)
229
230 #define pmap_pte_set_w(pte, v) ((v)?(*pte |= PG_W):(*pte &= ~PG_W))
231 #define pmap_pte_set_prot(pte, v) ((*pte &= ~PG_PROT), (*pte |= (v)))
232
233 /*
234  * Given a map and a machine independent protection code,
235  * convert to an alpha protection code.
236  */
237 #define pte_prot(m, p)          (protection_codes[m == pmap_kernel() ? 0 : 1][p])
238 int     protection_codes[2][8];
239
240 #define pa_index(pa)            atop((pa) - vm_first_phys)
241 #define pa_to_pvh(pa)           (&pv_table[pa_index(pa)])
242
243 /*
244  * Return non-zero if this pmap is currently active
245  */
246 #define pmap_isactive(pmap)     (pmap->pm_active)
247
248 /* 
249  * Extract level 1, 2 and 3 page table indices from a va
250  */
251 #define PTMASK  ((1 << ALPHA_PTSHIFT) - 1)
252
253 #define pmap_lev1_index(va)     (((va) >> ALPHA_L1SHIFT) & PTMASK)
254 #define pmap_lev2_index(va)     (((va) >> ALPHA_L2SHIFT) & PTMASK)
255 #define pmap_lev3_index(va)     (((va) >> ALPHA_L3SHIFT) & PTMASK)
256
257 /*
258  * Given a physical address, construct a pte
259  */
260 #define pmap_phys_to_pte(pa)    ALPHA_PTE_FROM_PFN(alpha_btop(pa))
261
262 /*
263  * Given a page frame number, construct a k0seg va
264  */
265 #define pmap_k0seg_to_pfn(va)   alpha_btop(ALPHA_K0SEG_TO_PHYS(va))
266
267 /*
268  * Given a pte, construct a k0seg va
269  */
270 #define pmap_k0seg_to_pte(va)   ALPHA_PTE_FROM_PFN(pmap_k0seg_to_pfn(va))
271
272 /*
273  * Lev1map:
274  *
275  *      Kernel level 1 page table.  This maps all kernel level 2
276  *      page table pages, and is used as a template for all user
277  *      pmap level 1 page tables.  When a new user level 1 page
278  *      table is allocated, all Lev1map PTEs for kernel addresses
279  *      are copied to the new map.
280  *
281  * Lev2map:
282  *
283  *      Initial set of kernel level 2 page table pages.  These
284  *      map the kernel level 3 page table pages.  As kernel
285  *      level 3 page table pages are added, more level 2 page
286  *      table pages may be added to map them.  These pages are
287  *      never freed.
288  *
289  * Lev3map:
290  *
291  *      Initial set of kernel level 3 page table pages.  These
292  *      map pages in K1SEG.  More level 3 page table pages may
293  *      be added at run-time if additional K1SEG address space
294  *      is required.  These pages are never freed.
295  *
296  * Lev2mapsize:
297  *
298  *      Number of entries in the initial Lev2map.
299  *
300  * Lev3mapsize:
301  *
302  *      Number of entries in the initial Lev3map.
303  *
304  * NOTE: When mappings are inserted into the kernel pmap, all
305  * level 2 and level 3 page table pages must already be allocated
306  * and mapped into the parent page table.
307  */
308 pt_entry_t      *Lev1map, *Lev2map, *Lev3map;
309 vm_size_t       Lev2mapsize, Lev3mapsize;
310
311 /*
312  * Statically allocated kernel pmap
313  */
314 static struct pmap kernel_pmap_store;
315 pmap_t kernel_pmap;
316
317 vm_offset_t avail_start;        /* PA of first available physical page */
318 vm_offset_t avail_end;          /* PA of last available physical page */
319 vm_offset_t virtual_avail;      /* VA of first avail page (after kernel bss) */
320 vm_offset_t virtual_end;        /* VA of last avail page (end of kernel AS) */
321 static boolean_t pmap_initialized = FALSE;      /* Has pmap_init completed? */
322 static vm_offset_t vm_first_phys;
323 static int pv_npg;
324
325 static vm_object_t kptobj;
326
327 static int nklev3, nklev2;
328 vm_offset_t kernel_vm_end;
329
330 /*
331  * Data for the ASN allocator
332  */
333 static int pmap_maxasn;
334 static int pmap_nextasn = 0;
335 static u_int pmap_current_asngen = 1;
336 static pmap_t pmap_active = 0;
337
338 /*
339  * Data for the pv entry allocation mechanism
340  */
341 static vm_zone_t pvzone;
342 static struct vm_zone pvzone_store;
343 static struct vm_object pvzone_obj;
344 static int pv_entry_count=0, pv_entry_max=0, pv_entry_high_water=0;
345 static int pmap_pagedaemon_waken = 0;
346 static struct pv_entry *pvinit;
347
348 /*
349  * All those kernel PT submaps that BSD is so fond of
350  */
351 pt_entry_t *CMAP1 = 0;
352 static pt_entry_t *CMAP2;
353 static pv_table_t *pv_table;
354 caddr_t CADDR1;
355 static caddr_t CADDR2;
356
357 static PMAP_INLINE void free_pv_entry __P((pv_entry_t pv));
358 static pv_entry_t get_pv_entry __P((void));
359 static void     alpha_protection_init __P((void));
360 static void     pmap_changebit __P((vm_offset_t pa, int bit, boolean_t setem));
361
362 static PMAP_INLINE int  pmap_is_managed __P((vm_offset_t pa));
363 static void     pmap_remove_all __P((vm_offset_t pa));
364 static vm_page_t pmap_enter_quick __P((pmap_t pmap, vm_offset_t va,
365                                       vm_offset_t pa, vm_page_t mpte));
366 static int pmap_remove_pte __P((pmap_t pmap, pt_entry_t* ptq, vm_offset_t sva));
367 static void pmap_remove_page __P((struct pmap *pmap, vm_offset_t va));
368 static int pmap_remove_entry __P((struct pmap *pmap, pv_table_t *pv,
369                                         vm_offset_t va));
370 static void pmap_insert_entry __P((pmap_t pmap, vm_offset_t va,
371                 vm_page_t mpte, vm_offset_t pa));
372
373 static vm_page_t pmap_allocpte __P((pmap_t pmap, vm_offset_t va));
374
375 static int pmap_release_free_page __P((pmap_t pmap, vm_page_t p));
376 static vm_page_t _pmap_allocpte __P((pmap_t pmap, unsigned ptepindex));
377 static vm_page_t pmap_page_lookup __P((vm_object_t object, vm_pindex_t pindex));
378 static int pmap_unuse_pt __P((pmap_t, vm_offset_t, vm_page_t));
379
380
381 /*
382  *      Routine:        pmap_lev1pte
383  *      Function:
384  *              Extract the level 1 page table entry associated
385  *              with the given map/virtual_address pair.
386  */
387 static PMAP_INLINE pt_entry_t*
388 pmap_lev1pte(pmap_t pmap, vm_offset_t va)
389 {
390         if (!pmap)
391                 return 0;
392         return &pmap->pm_lev1[pmap_lev1_index(va)];
393 }
394
395 /*
396  *      Routine:        pmap_lev2pte
397  *      Function:
398  *              Extract the level 2 page table entry associated
399  *              with the given map/virtual_address pair.
400  */
401 static PMAP_INLINE pt_entry_t*
402 pmap_lev2pte(pmap_t pmap, vm_offset_t va)
403 {
404         pt_entry_t* l1pte;
405         pt_entry_t* l2map;
406
407         l1pte = pmap_lev1pte(pmap, va);
408         if (!pmap_pte_v(l1pte))
409                 return 0;
410
411         l2map = (pt_entry_t*) ALPHA_PHYS_TO_K0SEG(pmap_pte_pa(l1pte));
412         return &l2map[pmap_lev2_index(va)];
413 }
414
415 /*
416  *      Routine:        pmap_lev3pte
417  *      Function:
418  *              Extract the level 3 page table entry associated
419  *              with the given map/virtual_address pair.
420  */
421 static PMAP_INLINE pt_entry_t*
422 pmap_lev3pte(pmap_t pmap, vm_offset_t va)
423 {
424         pt_entry_t* l2pte;
425         pt_entry_t* l3map;
426
427         l2pte = pmap_lev2pte(pmap, va);
428         if (!l2pte || !pmap_pte_v(l2pte))
429                 return 0;
430
431         l3map = (pt_entry_t*) ALPHA_PHYS_TO_K0SEG(pmap_pte_pa(l2pte));
432         return &l3map[pmap_lev3_index(va)];
433 }
434
435 vm_offset_t
436 pmap_steal_memory(vm_size_t size)
437 {
438         vm_size_t bank_size;
439         vm_offset_t pa, va;
440
441         size = round_page(size);
442
443         bank_size = phys_avail[1] - phys_avail[0];
444         while (size > bank_size) {
445                 int i;
446                 for (i = 0; phys_avail[i+2]; i+= 2) {
447                         phys_avail[i] = phys_avail[i+2];
448                         phys_avail[i+1] = phys_avail[i+3];
449                 }
450                 phys_avail[i] = 0;
451                 phys_avail[i+1] = 0;
452                 if (!phys_avail[0])
453                         panic("pmap_steal_memory: out of memory");
454                 bank_size = phys_avail[1] - phys_avail[0];
455         }
456
457         pa = phys_avail[0];
458         phys_avail[0] += size;
459
460         va = ALPHA_PHYS_TO_K0SEG(pa);
461         bzero((caddr_t) va, size);
462         return va;
463 }
464
465 extern pt_entry_t rom_pte;                      /* XXX */
466 extern int prom_mapped;                         /* XXX */
467
468 /*
469  *      Bootstrap the system enough to run with virtual memory.
470  */
471 void
472 pmap_bootstrap(vm_offset_t ptaddr, u_int maxasn)
473 {
474         pt_entry_t newpte;
475         pt_entry_t* pte;
476         vm_offset_t va;
477         int i;
478
479         /*
480          * Setup ASNs
481          */
482         pmap_nextasn = 0;
483         pmap_maxasn = maxasn;
484         pmap_current_asngen = 1;
485
486         /*
487          * Allocate a level 1 map for the kernel.
488          */
489         Lev1map = (pt_entry_t*) pmap_steal_memory(PAGE_SIZE);
490
491         /*
492          * Allocate a level 2 map for the kernel
493          */
494         Lev2map = (pt_entry_t*) pmap_steal_memory(PAGE_SIZE);
495         Lev2mapsize = PAGE_SIZE;
496
497         /*
498          * Allocate some level 3 maps for the kernel
499          */
500         Lev3map = (pt_entry_t*) pmap_steal_memory(PAGE_SIZE*NKPT);
501         Lev3mapsize = NKPT * PAGE_SIZE;
502
503         /* Map all of the level 2 maps */
504         for (i = 0; i < howmany(Lev2mapsize, PAGE_SIZE); i++) {
505                 unsigned long pfn =
506                         pmap_k0seg_to_pfn((vm_offset_t) Lev2map) + i;
507                 newpte = ALPHA_PTE_FROM_PFN(pfn);
508                 newpte |= PG_V | PG_ASM | PG_KRE | PG_KWE | PG_W;
509                 Lev1map[K1SEGLEV1I + i] = newpte;
510         }
511
512
513         /* Setup the mapping for the prom console */
514         {
515
516                 if (pmap_uses_prom_console()) {
517                         /* XXX save old pte so that we can remap prom if necessary */
518                         rom_pte = *(pt_entry_t *)ptaddr & ~PG_ASM;      /* XXX */
519                 }
520                 prom_mapped = 0;
521
522                 /*
523                  * Actually, this code lies.  The prom is still mapped, and will
524                  * remain so until the context switch after alpha_init() returns.
525                  * Printfs using the firmware before then will end up frobbing
526                  * Lev1map unnecessarily, but that's OK.
527                  */
528         }
529
530         /*
531          * Level 1 self mapping.
532          *
533          * Don't set PG_ASM since the self-mapping is different for each
534          * address space.
535          */
536         newpte = pmap_k0seg_to_pte((vm_offset_t) Lev1map);
537         newpte |= PG_V | PG_KRE | PG_KWE;
538         Lev1map[PTLEV1I] = newpte;
539
540         /* Map all of the level 3 maps */
541         for (i = 0; i < howmany(Lev3mapsize, PAGE_SIZE); i++) {
542                 unsigned long pfn =
543                         pmap_k0seg_to_pfn((vm_offset_t) Lev3map) + i;
544                 newpte = ALPHA_PTE_FROM_PFN(pfn);
545                 newpte |= PG_V | PG_ASM | PG_KRE | PG_KWE | PG_W;
546                 Lev2map[i] = newpte;
547         }
548
549         avail_start = phys_avail[0];
550         for (i = 0; phys_avail[i+2]; i+= 2) ;
551         avail_end = phys_avail[i+1];
552
553         virtual_avail = VM_MIN_KERNEL_ADDRESS;
554         virtual_end = VPTBASE;
555
556         /*
557          * Initialize protection array.
558          */
559         alpha_protection_init();
560
561         /*
562          * The kernel's pmap is statically allocated so we don't have to use
563          * pmap_create, which is unlikely to work correctly at this part of
564          * the boot sequence (XXX and which no longer exists).
565          */
566         kernel_pmap = &kernel_pmap_store;
567         kernel_pmap->pm_lev1 = Lev1map;
568         kernel_pmap->pm_count = 1;
569         kernel_pmap->pm_active = 1;
570         kernel_pmap->pm_asn = 0;
571         kernel_pmap->pm_asngen = pmap_current_asngen;
572         pmap_nextasn = 1;
573         TAILQ_INIT(&kernel_pmap->pm_pvlist);
574         nklev3 = NKPT;
575         nklev2 = 1;
576
577         /*
578          * Reserve some special page table entries/VA space for temporary
579          * mapping of pages.
580          */
581 #define SYSMAP(c, p, v, n)      \
582         v = (c)va; va += ((n)*PAGE_SIZE); p = pte; pte += (n);
583
584         va = virtual_avail;
585         pte = pmap_lev3pte(kernel_pmap, va);
586
587         /*
588          * CMAP1/CMAP2 are used for zeroing and copying pages.
589          */
590         SYSMAP(caddr_t, CMAP1, CADDR1, 1)
591         SYSMAP(caddr_t, CMAP2, CADDR2, 1)
592
593         virtual_avail = va;
594
595         *CMAP1 = *CMAP2 = 0;
596
597         /*
598          * Set up proc0's PCB such that the ptbr points to the right place
599          * and has the kernel pmap's.
600          */
601         proc0.p_addr->u_pcb.pcb_hw.apcb_ptbr =
602             ALPHA_K0SEG_TO_PHYS((vm_offset_t)Lev1map) >> PAGE_SHIFT;
603         proc0.p_addr->u_pcb.pcb_hw.apcb_asn = 0;
604 }
605
606 int
607 pmap_uses_prom_console()
608 {
609 #if 0
610         extern int cputype;
611
612 #if defined(NEW_SCC_DRIVER)
613         return (cputype == ST_DEC_21000);
614 #else
615         return (cputype == ST_DEC_21000
616              || cputype == ST_DEC_3000_300
617              || cputype == ST_DEC_3000_500);
618 #endif /* NEW_SCC_DRIVER */
619 #endif
620
621         return 1;
622 }
623
624 /*
625  *      Initialize the pmap module.
626  *      Called by vm_init, to initialize any structures that the pmap
627  *      system needs to map virtual memory.
628  *      pmap_init has been enhanced to support in a fairly consistant
629  *      way, discontiguous physical memory.
630  */
631 void
632 pmap_init(phys_start, phys_end)
633         vm_offset_t phys_start, phys_end;
634 {
635         vm_offset_t addr;
636         vm_size_t s;
637         int i;
638         int initial_pvs;
639
640         /*
641          * calculate the number of pv_entries needed
642          */
643         vm_first_phys = phys_avail[0];
644         for (i = 0; phys_avail[i + 1]; i += 2);
645         pv_npg = (phys_avail[(i - 2) + 1] - vm_first_phys) / PAGE_SIZE;
646
647         /*
648          * Allocate memory for random pmap data structures.  Includes the
649          * pv_head_table.
650          */
651         s = (vm_size_t) (sizeof(pv_table_t) * pv_npg);
652         s = round_page(s);
653
654         addr = (vm_offset_t) kmem_alloc(kernel_map, s);
655         pv_table = (pv_table_t *) addr;
656         for(i = 0; i < pv_npg; i++) {
657                 vm_offset_t pa;
658                 TAILQ_INIT(&pv_table[i].pv_list);
659                 pv_table[i].pv_list_count = 0;
660                 pa = vm_first_phys + i * PAGE_SIZE;
661                 pv_table[i].pv_vm_page = PHYS_TO_VM_PAGE(pa);
662         }
663
664         /*
665          * init the pv free list
666          */
667         initial_pvs = pv_npg;
668         if (initial_pvs < MINPV)
669                 initial_pvs = MINPV;
670         pvzone = &pvzone_store;
671         pvinit = (struct pv_entry *) kmem_alloc(kernel_map,
672                 initial_pvs * sizeof (struct pv_entry));
673         zbootinit(pvzone, "PV ENTRY", sizeof (struct pv_entry), pvinit, pv_npg);
674         /*
675          * object for kernel page table pages
676          */
677         kptobj = vm_object_allocate(OBJT_DEFAULT, NKLEV3MAPS + NKLEV2MAPS);
678
679         /*
680          * Now it is safe to enable pv_table recording.
681          */
682         pmap_initialized = TRUE;
683 }
684
685 /*
686  * Initialize the address space (zone) for the pv_entries.  Set a
687  * high water mark so that the system can recover from excessive
688  * numbers of pv entries.
689  */
690 void
691 pmap_init2()
692 {
693         pv_entry_max = PMAP_SHPGPERPROC * maxproc + pv_npg;
694         pv_entry_high_water = 9 * (pv_entry_max / 10);
695         zinitna(pvzone, &pvzone_obj, NULL, 0, pv_entry_max, ZONE_INTERRUPT, 1);
696 }
697
698 /*
699  *      Used to map a range of physical addresses into kernel
700  *      virtual address space.
701  *
702  *      For now, VM is already on, we only need to map the
703  *      specified memory.
704  */
705 vm_offset_t
706 pmap_map(vm_offset_t virt, vm_offset_t start, vm_offset_t end, int prot)
707 {
708         while (start < end) {
709                 pmap_enter(kernel_pmap, virt, start, prot, FALSE);
710                 virt += PAGE_SIZE;
711                 start += PAGE_SIZE;
712         }
713         return (virt);
714 }
715
716
717 /***************************************************
718  * Manipulate TLBs for a pmap
719  ***************************************************/
720
721 static void
722 pmap_invalidate_asn(pmap_t pmap)
723 {
724         pmap->pm_asngen = 0;
725 }
726
727 static void
728 pmap_invalidate_page(pmap_t pmap, vm_offset_t va)
729 {
730         if (pmap_isactive(pmap)) {
731                 ALPHA_TBIS(va);
732                 alpha_pal_imb();                /* XXX overkill? */
733         } else
734                 pmap_invalidate_asn(pmap);
735 }
736
737 static void
738 pmap_invalidate_all(pmap_t pmap)
739 {
740         if (pmap_isactive(pmap)) {
741                 ALPHA_TBIA();
742                 alpha_pal_imb();                /* XXX overkill? */
743         } else
744                 pmap_invalidate_asn(pmap);
745 }
746
747 static void
748 pmap_get_asn(pmap_t pmap)
749 {
750         if (pmap->pm_asngen != pmap_current_asngen) {
751                 if (pmap_nextasn > pmap_maxasn) {
752                         /*
753                          * Start a new ASN generation.
754                          *
755                          * Invalidate all per-process mappings and I-cache
756                          */
757                         pmap_nextasn = 0;
758                         pmap_current_asngen++;
759
760                         if (pmap_current_asngen == 0) {
761                                 /*
762                                  * Clear the pm_asngen of all pmaps.
763                                  * This is safe since it is only called from
764                                  * pmap_activate after it has deactivated
765                                  * the old pmap.
766                                  */
767                                 struct proc *p;
768                                 pmap_t tpmap;
769                                
770 #ifdef PMAP_DIAGNOSTIC
771                                 printf("pmap_get_asn: generation rollover\n");
772 #endif
773                                 pmap_current_asngen = 1;
774                                 LIST_FOREACH(p, &allproc, p_list) {
775                                         if (p->p_vmspace) {
776                                                 tpmap = vmspace_pmap(p->p_vmspace);
777                                                 tpmap->pm_asngen = 0;
778                                         }
779                                 }
780                         }
781
782                         /*
783                          * Since we are about to start re-using ASNs, we must
784                          * clear out the TLB and the I-cache since they are tagged
785                          * with the ASN.
786                          */
787                         ALPHA_TBIAP();
788                         alpha_pal_imb();        /* XXX overkill? */
789                 }
790                 pmap->pm_asn = pmap_nextasn++;
791                 pmap->pm_asngen = pmap_current_asngen;
792         }
793 }
794
795 /***************************************************
796  * Low level helper routines.....
797  ***************************************************/
798
799
800
801 /*
802  * this routine defines the region(s) of memory that should
803  * not be tested for the modified bit.
804  */
805 static PMAP_INLINE int
806 pmap_track_modified(vm_offset_t va)
807 {
808         if ((va < clean_sva) || (va >= clean_eva)) 
809                 return 1;
810         else
811                 return 0;
812 }
813
814 /*
815  *      Routine:        pmap_extract
816  *      Function:
817  *              Extract the physical page address associated
818  *              with the given map/virtual_address pair.
819  */
820 vm_offset_t 
821 pmap_extract(pmap, va)
822         register pmap_t pmap;
823         vm_offset_t va;
824 {
825         pt_entry_t* pte = pmap_lev3pte(pmap, va);
826         if (pte)
827                 return alpha_ptob(ALPHA_PTE_TO_PFN(*pte));
828         else
829                 return 0;
830 }
831
832 /*
833  * determine if a page is managed (memory vs. device)
834  */
835 static PMAP_INLINE int
836 pmap_is_managed(pa)
837         vm_offset_t pa;
838 {
839         int i;
840
841         if (!pmap_initialized)
842                 return 0;
843
844         for (i = 0; phys_avail[i + 1]; i += 2) {
845                 if (pa < phys_avail[i + 1] && pa >= phys_avail[i])
846                         return 1;
847         }
848         return 0;
849 }
850
851
852 /***************************************************
853  * Low level mapping routines.....
854  ***************************************************/
855
856 /*
857  * Add a list of wired pages to the kva
858  * this routine is only used for temporary
859  * kernel mappings that do not need to have
860  * page modification or references recorded.
861  * Note that old mappings are simply written
862  * over.  The page *must* be wired.
863  */
864 void
865 pmap_qenter(vm_offset_t va, vm_page_t *m, int count)
866 {
867         int i;
868         pt_entry_t *pte;
869
870         for (i = 0; i < count; i++) {
871                 vm_offset_t tva = va + i * PAGE_SIZE;
872                 pt_entry_t npte = pmap_phys_to_pte(VM_PAGE_TO_PHYS(m[i]))
873                         | PG_ASM | PG_KRE | PG_KWE | PG_V;
874                 pt_entry_t opte;
875                 pte = vtopte(tva);
876                 opte = *pte;
877                 PMAP_DEBUG_VA(va);
878                 *pte = npte;
879                 if (opte)
880                         pmap_invalidate_page(kernel_pmap, tva);
881         }
882 }
883
884 /*
885  * this routine jerks page mappings from the
886  * kernel -- it is meant only for temporary mappings.
887  */
888 void
889 pmap_qremove(va, count)
890         vm_offset_t va;
891         int count;
892 {
893         int i;
894         register pt_entry_t *pte;
895
896         for (i = 0; i < count; i++) {
897                 pte = vtopte(va);
898                 PMAP_DEBUG_VA(va);
899                 *pte = 0;
900                 pmap_invalidate_page(kernel_pmap, va);
901                 va += PAGE_SIZE;
902         }
903 }
904
905 /*
906  * add a wired page to the kva
907  * note that in order for the mapping to take effect -- you
908  * should do a invltlb after doing the pmap_kenter...
909  */
910 PMAP_INLINE void 
911 pmap_kenter(vm_offset_t va, vm_offset_t pa)
912 {
913         pt_entry_t *pte;
914         pt_entry_t npte, opte;
915
916         npte = pmap_phys_to_pte(pa) | PG_ASM | PG_KRE | PG_KWE | PG_V;
917         pte = vtopte(va);
918         opte = *pte;
919         PMAP_DEBUG_VA(va);
920         *pte = npte;
921         if (opte)
922                 pmap_invalidate_page(kernel_pmap, va);
923 }
924
925 /*
926  * remove a page from the kernel pagetables
927  */
928 PMAP_INLINE void
929 pmap_kremove(vm_offset_t va)
930 {
931         register pt_entry_t *pte;
932
933         pte = vtopte(va);
934         PMAP_DEBUG_VA(va);
935         *pte = 0;
936         pmap_invalidate_page(kernel_pmap, va);
937 }
938
939 static vm_page_t
940 pmap_page_lookup(vm_object_t object, vm_pindex_t pindex)
941 {
942         vm_page_t m;
943 retry:
944         m = vm_page_lookup(object, pindex);
945         if (m && vm_page_sleep_busy(m, FALSE, "pplookp"))
946                 goto retry;
947         return m;
948 }
949
950 /*
951  * Create the UPAGES for a new process.
952  * This routine directly affects the fork perf for a process.
953  */
954 void
955 pmap_new_proc(struct proc *p)
956 {
957         int i;
958         vm_object_t upobj;
959         vm_page_t m;
960         struct user *up;
961         pt_entry_t *ptek, oldpte;
962
963         /*
964          * allocate object for the upages
965          */
966         if ((upobj = p->p_upages_obj) == NULL) {
967                 upobj = vm_object_allocate( OBJT_DEFAULT, UPAGES);
968                 p->p_upages_obj = upobj;
969         }
970
971         /* get a kernel virtual address for the UPAGES for this proc */
972         if ((up = p->p_addr) == NULL) {
973                 up = (struct user *) kmem_alloc_nofault(kernel_map,
974                                 UPAGES * PAGE_SIZE);
975 #if !defined(MAX_PERF)
976                 if (up == NULL)
977                         panic("pmap_new_proc: u_map allocation failed");
978 #endif
979                 p->p_addr = up;
980         }
981
982         ptek = vtopte((vm_offset_t) up);
983
984         for(i=0;i<UPAGES;i++) {
985                 /*
986                  * Get a kernel stack page
987                  */
988                 m = vm_page_grab(upobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY);
989
990                 /*
991                  * Wire the page
992                  */
993                 m->wire_count++;
994                 cnt.v_wire_count++;
995
996                 oldpte = *(ptek + i);
997                 /*
998                  * Enter the page into the kernel address space.
999                  */
1000                 *(ptek + i) = pmap_phys_to_pte(VM_PAGE_TO_PHYS(m))
1001                         | PG_ASM | PG_KRE | PG_KWE | PG_V;
1002                 if (oldpte) 
1003                         pmap_invalidate_page(kernel_pmap,
1004                                              (vm_offset_t)up + i * PAGE_SIZE);
1005
1006                 vm_page_wakeup(m);
1007                 vm_page_flag_clear(m, PG_ZERO);
1008                 vm_page_flag_set(m, PG_MAPPED | PG_WRITEABLE);
1009                 m->valid = VM_PAGE_BITS_ALL;
1010         }
1011 }
1012
1013 /*
1014  * Dispose the UPAGES for a process that has exited.
1015  * This routine directly impacts the exit perf of a process.
1016  */
1017 void
1018 pmap_dispose_proc(p)
1019         struct proc *p;
1020 {
1021         int i;
1022         vm_object_t upobj;
1023         vm_page_t m;
1024         pt_entry_t *ptek, oldpte;
1025
1026         upobj = p->p_upages_obj;
1027
1028         ptek = vtopte((vm_offset_t) p->p_addr);
1029         for(i=0;i<UPAGES;i++) {
1030
1031                 if ((m = vm_page_lookup(upobj, i)) == NULL)
1032                         panic("pmap_dispose_proc: upage already missing???");
1033
1034                 vm_page_busy(m);
1035
1036                 oldpte = *(ptek + i);
1037                 *(ptek + i) = 0;
1038                 pmap_invalidate_page(kernel_pmap, 
1039                                      (vm_offset_t)p->p_addr + i * PAGE_SIZE);
1040                 vm_page_unwire(m, 0);
1041                 vm_page_free(m);
1042         }
1043 }
1044
1045 /*
1046  * Allow the UPAGES for a process to be prejudicially paged out.
1047  */
1048 void
1049 pmap_swapout_proc(p)
1050         struct proc *p;
1051 {
1052         int i;
1053         vm_object_t upobj;
1054         vm_page_t m;
1055
1056         /*
1057          * Make sure we aren't fpcurproc.
1058          */
1059         alpha_fpstate_save(p, 1);
1060
1061         upobj = p->p_upages_obj;
1062         /*
1063          * let the upages be paged
1064          */
1065         for(i=0;i<UPAGES;i++) {
1066                 if ((m = vm_page_lookup(upobj, i)) == NULL)
1067                         panic("pmap_swapout_proc: upage already missing???");
1068                 vm_page_dirty(m);
1069                 vm_page_unwire(m, 0);
1070                 pmap_kremove((vm_offset_t)p->p_addr + PAGE_SIZE * i);
1071         }
1072 }
1073
1074 /*
1075  * Bring the UPAGES for a specified process back in.
1076  */
1077 void
1078 pmap_swapin_proc(p)
1079         struct proc *p;
1080 {
1081         int i,rv;
1082         vm_object_t upobj;
1083         vm_page_t m;
1084
1085         upobj = p->p_upages_obj;
1086         for(i=0;i<UPAGES;i++) {
1087
1088                 m = vm_page_grab(upobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY);
1089
1090                 pmap_kenter(((vm_offset_t) p->p_addr) + i * PAGE_SIZE,
1091                         VM_PAGE_TO_PHYS(m));
1092
1093                 if (m->valid != VM_PAGE_BITS_ALL) {
1094                         rv = vm_pager_get_pages(upobj, &m, 1, 0);
1095 #if !defined(MAX_PERF)
1096                         if (rv != VM_PAGER_OK)
1097                                 panic("pmap_swapin_proc: cannot get upages for proc: %d\n", p->p_pid);
1098 #endif
1099                         m = vm_page_lookup(upobj, i);
1100                         m->valid = VM_PAGE_BITS_ALL;
1101                 }
1102
1103                 vm_page_wire(m);
1104                 vm_page_wakeup(m);
1105                 vm_page_flag_set(m, PG_MAPPED | PG_WRITEABLE);
1106         }
1107
1108         /*
1109          * The pcb may be at a different physical address now so cache the
1110          * new address.
1111          */
1112         p->p_md.md_pcbpaddr = (void*) vtophys((vm_offset_t) &p->p_addr->u_pcb);
1113 }
1114
1115 /***************************************************
1116  * Page table page management routines.....
1117  ***************************************************/
1118
1119 /*
1120  * This routine unholds page table pages, and if the hold count
1121  * drops to zero, then it decrements the wire count.
1122  */
1123 static int 
1124 _pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m)
1125 {
1126
1127         while (vm_page_sleep_busy(m, FALSE, "pmuwpt"))
1128                 ;
1129
1130         if (m->hold_count == 0) {
1131                 vm_offset_t pteva;
1132                 pt_entry_t* pte;
1133
1134                 /*
1135                  * unmap the page table page
1136                  */
1137                 if (m->pindex >= NUSERLEV3MAPS) {
1138                         /* Level 2 page table */
1139                         pte = pmap_lev1pte(pmap, va);
1140                         pteva = (vm_offset_t) PTlev2 + alpha_ptob(m->pindex - NUSERLEV3MAPS);
1141                 } else {
1142                         /* Level 3 page table */
1143                         pte = pmap_lev2pte(pmap, va);
1144                         pteva = (vm_offset_t) PTmap + alpha_ptob(m->pindex);
1145                 }
1146
1147                 *pte = 0;
1148
1149                 if (m->pindex < NUSERLEV3MAPS) {
1150                         /* unhold the level 2 page table */
1151                         vm_page_t lev2pg;
1152                         lev2pg = pmap_page_lookup(pmap->pm_pteobj,
1153                                                   NUSERLEV3MAPS + pmap_lev1_index(va));
1154                         vm_page_unhold(lev2pg);
1155                         if (lev2pg->hold_count == 0)
1156                                 _pmap_unwire_pte_hold(pmap, va, lev2pg);
1157                 }
1158
1159                 --pmap->pm_stats.resident_count;
1160                 /*
1161                  * Do a invltlb to make the invalidated mapping
1162                  * take effect immediately.
1163                  */
1164                 pmap_invalidate_page(pmap, pteva);
1165
1166                 if (pmap->pm_ptphint == m)
1167                         pmap->pm_ptphint = NULL;
1168
1169                 /*
1170                  * If the page is finally unwired, simply free it.
1171                  */
1172                 --m->wire_count;
1173                 if (m->wire_count == 0) {
1174
1175                         if (m->flags & PG_WANTED) {
1176                                 vm_page_flag_clear(m, PG_WANTED);
1177                                 wakeup(m);
1178                         }
1179
1180                         vm_page_busy(m);
1181                         vm_page_free_zero(m);
1182                         --cnt.v_wire_count;
1183                 }
1184                 return 1;
1185         }
1186         return 0;
1187 }
1188
1189 static PMAP_INLINE int
1190 pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m)
1191 {
1192         vm_page_unhold(m);
1193         if (m->hold_count == 0)
1194                 return _pmap_unwire_pte_hold(pmap, va, m);
1195         else
1196                 return 0;
1197 }
1198
1199 /*
1200  * After removing a page table entry, this routine is used to
1201  * conditionally free the page, and manage the hold/wire counts.
1202  */
1203 static int
1204 pmap_unuse_pt(pmap_t pmap, vm_offset_t va, vm_page_t mpte)
1205 {
1206         unsigned ptepindex;
1207         if (va >= VM_MAXUSER_ADDRESS)
1208                 return 0;
1209
1210         if (mpte == NULL) {
1211                 ptepindex = (va >> ALPHA_L2SHIFT);
1212                 if (pmap->pm_ptphint &&
1213                         (pmap->pm_ptphint->pindex == ptepindex)) {
1214                         mpte = pmap->pm_ptphint;
1215                 } else {
1216                         mpte = pmap_page_lookup( pmap->pm_pteobj, ptepindex);
1217                         pmap->pm_ptphint = mpte;
1218                 }
1219         }
1220
1221         return pmap_unwire_pte_hold(pmap, va, mpte);
1222 }
1223
1224 void
1225 pmap_pinit0(pmap)
1226         struct pmap *pmap;
1227 {
1228         pmap->pm_lev1 = Lev1map;
1229         pmap->pm_flags = 0;
1230         pmap->pm_count = 1;
1231         pmap->pm_ptphint = NULL;
1232         pmap->pm_active = 0;
1233         pmap->pm_asn = 0;
1234         pmap->pm_asngen = 0;
1235         TAILQ_INIT(&pmap->pm_pvlist);
1236         bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
1237 }
1238
1239 /*
1240  * Initialize a preallocated and zeroed pmap structure,
1241  * such as one in a vmspace structure.
1242  */
1243 void
1244 pmap_pinit(pmap)
1245         register struct pmap *pmap;
1246 {
1247         vm_page_t lev1pg;
1248
1249         /*
1250          * allocate object for the ptes
1251          */
1252         if (pmap->pm_pteobj == NULL)
1253                 pmap->pm_pteobj = vm_object_allocate(OBJT_DEFAULT, NUSERLEV3MAPS + NUSERLEV2MAPS + 1);
1254
1255         /*
1256          * allocate the page directory page
1257          */
1258         lev1pg = vm_page_grab(pmap->pm_pteobj, NUSERLEV3MAPS + NUSERLEV2MAPS,
1259                               VM_ALLOC_NORMAL | VM_ALLOC_RETRY);
1260
1261         lev1pg->wire_count = 1;
1262         ++cnt.v_wire_count;
1263
1264         vm_page_flag_clear(lev1pg, PG_MAPPED | PG_BUSY);        /* not mapped normally */
1265         lev1pg->valid = VM_PAGE_BITS_ALL;
1266
1267         pmap->pm_lev1 = (pt_entry_t*) ALPHA_PHYS_TO_K0SEG(VM_PAGE_TO_PHYS(lev1pg));
1268         if ((lev1pg->flags & PG_ZERO) == 0)
1269                 bzero(pmap->pm_lev1, PAGE_SIZE);
1270
1271
1272         /* install self-referential address mapping entry (not PG_ASM) */
1273         pmap->pm_lev1[PTLEV1I] = pmap_phys_to_pte(VM_PAGE_TO_PHYS(lev1pg))
1274                 | PG_V | PG_KRE | PG_KWE;
1275
1276         pmap->pm_flags = 0;
1277         pmap->pm_count = 1;
1278         pmap->pm_ptphint = NULL;
1279         pmap->pm_active = 0;
1280         pmap->pm_asn = 0;
1281         pmap->pm_asngen = 0;
1282         TAILQ_INIT(&pmap->pm_pvlist);
1283         bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
1284 }
1285
1286 /*
1287  * Wire in kernel global address entries.  To avoid a race condition
1288  * between pmap initialization and pmap_growkernel, this procedure
1289  * should be called after the vmspace is attached to the process
1290  * but before this pmap is activated.
1291  */
1292 void
1293 pmap_pinit2(pmap)
1294         struct pmap *pmap;
1295 {
1296         bcopy(PTlev1 + K1SEGLEV1I, pmap->pm_lev1 + K1SEGLEV1I, nklev2 * PTESIZE);
1297 }
1298
1299 static int
1300 pmap_release_free_page(pmap_t pmap, vm_page_t p)
1301 {
1302         pt_entry_t* pte;
1303         pt_entry_t* l2map;
1304
1305         if (p->pindex >= NUSERLEV3MAPS + NUSERLEV2MAPS)
1306                 /* level 1 page table */
1307                 pte = &pmap->pm_lev1[PTLEV1I];
1308         else if (p->pindex >= NUSERLEV3MAPS)
1309                 /* level 2 page table */
1310                 pte = &pmap->pm_lev1[p->pindex - NUSERLEV3MAPS];
1311         else {
1312                 /* level 3 page table */
1313                 pte = &pmap->pm_lev1[p->pindex >> ALPHA_PTSHIFT];
1314                 l2map = (pt_entry_t*) ALPHA_PHYS_TO_K0SEG(pmap_pte_pa(pte));
1315                 pte = &l2map[p->pindex & ((1 << ALPHA_PTSHIFT) - 1)];
1316         }
1317
1318         /*
1319          * This code optimizes the case of freeing non-busy
1320          * page-table pages.  Those pages are zero now, and
1321          * might as well be placed directly into the zero queue.
1322          */
1323         if (vm_page_sleep_busy(p, FALSE, "pmaprl"))
1324                 return 0;
1325
1326         vm_page_busy(p);
1327
1328         /*
1329          * Remove the page table page from the processes address space.
1330          */
1331         *pte = 0;
1332         pmap->pm_stats.resident_count--;
1333
1334 #ifdef PMAP_DEBUG
1335         if (p->hold_count)  {
1336                 panic("pmap_release: freeing held page table page");
1337         }
1338 #endif
1339         /*
1340          * Level1  pages need to have the kernel
1341          * stuff cleared, so they can go into the zero queue also.
1342          */
1343         if (p->pindex == NUSERLEV3MAPS + NUSERLEV2MAPS)
1344                 bzero(pmap->pm_lev1 + K1SEGLEV1I, nklev2 * PTESIZE);
1345
1346         if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == p->pindex))
1347                 pmap->pm_ptphint = NULL;
1348
1349 #ifdef PMAP_DEBUG
1350         {
1351             u_long *lp = (u_long*) ALPHA_PHYS_TO_K0SEG(VM_PAGE_TO_PHYS(p));
1352             u_long *ep = (u_long*) ((char*) lp + PAGE_SIZE);
1353             for (; lp < ep; lp++)
1354                 if (*lp != 0)
1355                     panic("pmap_release_free_page: page not zero");
1356         }
1357 #endif
1358
1359         p->wire_count--;
1360         cnt.v_wire_count--;
1361         vm_page_free_zero(p);
1362         return 1;
1363 }
1364
1365 /*
1366  * this routine is called if the page table page is not
1367  * mapped correctly.
1368  */
1369 static vm_page_t
1370 _pmap_allocpte(pmap, ptepindex)
1371         pmap_t  pmap;
1372         unsigned ptepindex;
1373 {
1374         pt_entry_t* pte;
1375         vm_offset_t ptepa;
1376         vm_page_t m;
1377
1378         /*
1379          * Find or fabricate a new pagetable page
1380          */
1381         m = vm_page_grab(pmap->pm_pteobj, ptepindex,
1382                         VM_ALLOC_ZERO | VM_ALLOC_RETRY);
1383
1384         KASSERT(m->queue == PQ_NONE,
1385                 ("_pmap_allocpte: %p->queue != PQ_NONE", m));
1386
1387         if (m->wire_count == 0)
1388                 cnt.v_wire_count++;
1389         m->wire_count++;
1390
1391         /*
1392          * Increment the hold count for the page table page
1393          * (denoting a new mapping.)
1394          */
1395         m->hold_count++;
1396
1397         /*
1398          * Map the pagetable page into the process address space, if
1399          * it isn't already there.
1400          */
1401
1402         pmap->pm_stats.resident_count++;
1403
1404         ptepa = VM_PAGE_TO_PHYS(m);
1405
1406         if (ptepindex >= NUSERLEV3MAPS) {
1407                 pte = &pmap->pm_lev1[ptepindex - NUSERLEV3MAPS];
1408         } else {
1409                 int l1index = ptepindex >> ALPHA_PTSHIFT;
1410                 pt_entry_t* l1pte = &pmap->pm_lev1[l1index];
1411                 pt_entry_t* l2map;
1412                 if (!pmap_pte_v(l1pte))
1413                         _pmap_allocpte(pmap, NUSERLEV3MAPS + l1index);
1414                 else {
1415                         vm_page_t l2page =
1416                                 pmap_page_lookup(pmap->pm_pteobj,
1417                                                  NUSERLEV3MAPS + l1index);
1418                         l2page->hold_count++;
1419                 }
1420                 l2map = (pt_entry_t*) ALPHA_PHYS_TO_K0SEG(pmap_pte_pa(l1pte));
1421                 pte = &l2map[ptepindex & ((1 << ALPHA_PTSHIFT) - 1)];
1422         }
1423
1424         *pte = pmap_phys_to_pte(ptepa) | PG_KRE | PG_KWE | PG_V;
1425
1426         /*
1427          * Set the page table hint
1428          */
1429         pmap->pm_ptphint = m;
1430
1431         if ((m->flags & PG_ZERO) == 0)
1432                 bzero((caddr_t) ALPHA_PHYS_TO_K0SEG(ptepa), PAGE_SIZE);
1433
1434         m->valid = VM_PAGE_BITS_ALL;
1435         vm_page_flag_clear(m, PG_ZERO | PG_BUSY);
1436         vm_page_flag_set(m, PG_MAPPED);
1437
1438         return m;
1439 }
1440
1441 static vm_page_t
1442 pmap_allocpte(pmap_t pmap, vm_offset_t va)
1443 {
1444         unsigned ptepindex;
1445         pt_entry_t* lev2pte;
1446         vm_page_t m;
1447
1448         /*
1449          * Calculate pagetable page index
1450          */
1451         ptepindex = va >> (PAGE_SHIFT + ALPHA_PTSHIFT);
1452
1453         /*
1454          * Get the level2 entry
1455          */
1456         lev2pte = pmap_lev2pte(pmap, va);
1457
1458         /*
1459          * If the page table page is mapped, we just increment the
1460          * hold count, and activate it.
1461          */
1462         if (lev2pte && pmap_pte_v(lev2pte)) {
1463                 /*
1464                  * In order to get the page table page, try the
1465                  * hint first.
1466                  */
1467                 if (pmap->pm_ptphint &&
1468                         (pmap->pm_ptphint->pindex == ptepindex)) {
1469                         m = pmap->pm_ptphint;
1470                 } else {
1471                         m = pmap_page_lookup( pmap->pm_pteobj, ptepindex);
1472                         pmap->pm_ptphint = m;
1473                 }
1474                 m->hold_count++;
1475                 return m;
1476         }
1477         /*
1478          * Here if the pte page isn't mapped, or if it has been deallocated.
1479          */
1480         return _pmap_allocpte(pmap, ptepindex);
1481 }
1482
1483
1484 /***************************************************
1485 * Pmap allocation/deallocation routines.
1486  ***************************************************/
1487
1488 /*
1489  * Release any resources held by the given physical map.
1490  * Called when a pmap initialized by pmap_pinit is being released.
1491  * Should only be called if the map contains no valid mappings.
1492  */
1493 void
1494 pmap_release(pmap_t pmap)
1495 {
1496         vm_page_t p,n,lev1pg;
1497         vm_object_t object = pmap->pm_pteobj;
1498         int curgeneration;
1499
1500 #if defined(DIAGNOSTIC)
1501         if (object->ref_count != 1)
1502                 panic("pmap_release: pteobj reference count != 1");
1503 #endif
1504         
1505         lev1pg = NULL;
1506 retry:
1507         curgeneration = object->generation;
1508         for (p = TAILQ_FIRST(&object->memq); p != NULL; p = n) {
1509                 n = TAILQ_NEXT(p, listq);
1510                 if (p->pindex >= NUSERLEV3MAPS) {
1511                         continue;
1512                 }
1513                 while (1) {
1514                         if (!pmap_release_free_page(pmap, p) &&
1515                                 (object->generation != curgeneration))
1516                                 goto retry;
1517                 }
1518         }
1519         for (p = TAILQ_FIRST(&object->memq); p != NULL; p = n) {
1520                 n = TAILQ_NEXT(p, listq);
1521                 if (p->pindex < NUSERLEV3MAPS) {
1522                         /* can this happen?  maybe panic */
1523                         goto retry;
1524                 }
1525                 if (p->pindex >= NUSERLEV3MAPS + NUSERLEV2MAPS) {
1526                         lev1pg = p;
1527                         continue;
1528                 }
1529                 while (1) {
1530                         if (!pmap_release_free_page(pmap, p) &&
1531                                 (object->generation != curgeneration))
1532                                 goto retry;
1533                 }
1534         }
1535
1536         if (lev1pg && !pmap_release_free_page(pmap, lev1pg))
1537                 goto retry;
1538 }
1539
1540 /*
1541  * grow the number of kernel page table entries, if needed
1542  */
1543 void
1544 pmap_growkernel(vm_offset_t addr)
1545 {
1546         /* XXX come back to this */
1547         struct proc *p;
1548         struct pmap *pmap;
1549         int s;
1550         pt_entry_t* pte;
1551         pt_entry_t newlev1, newlev2;
1552         vm_offset_t pa;
1553         vm_page_t nkpg;
1554
1555         s = splhigh();
1556
1557         if (kernel_vm_end == 0) {
1558                 kernel_vm_end = VM_MIN_KERNEL_ADDRESS;;
1559
1560                 /* Count the level 2 page tables */
1561                 nklev2 = 0;
1562                 nklev3 = 0;
1563                 while (pmap_pte_v(pmap_lev1pte(kernel_pmap, kernel_vm_end))) {
1564                         nklev2++;
1565                         nklev3 += (1L << ALPHA_PTSHIFT);
1566                         kernel_vm_end += ALPHA_L1SIZE;
1567                 }
1568                         
1569                 /* Count the level 3 page tables in the last level 2 page table */
1570                 kernel_vm_end -= ALPHA_L1SIZE;
1571                 nklev3 -= (1 << ALPHA_PTSHIFT);
1572                 while (pmap_pte_v(pmap_lev2pte(kernel_pmap, kernel_vm_end))) {
1573                         nklev3++;
1574                         kernel_vm_end += ALPHA_L2SIZE;
1575                 }
1576         }
1577
1578         addr = (addr + ALPHA_L2SIZE) & ~(ALPHA_L2SIZE - 1);
1579         while (kernel_vm_end < addr) {
1580                 /*
1581                  * If the level 1 pte is invalid, allocate a new level 2 page table
1582                  */
1583                 pte = pmap_lev1pte(kernel_pmap, kernel_vm_end);
1584                 if (!pmap_pte_v(pte)) {
1585                         int pindex = NKLEV3MAPS + pmap_lev1_index(kernel_vm_end) - K1SEGLEV1I;
1586
1587                         nkpg = vm_page_alloc(kptobj, pindex, VM_ALLOC_SYSTEM);
1588 #if !defined(MAX_PERF)
1589                         if (!nkpg)
1590                                 panic("pmap_growkernel: no memory to grow kernel");
1591 #endif
1592                         printf("pmap_growkernel: growing to %lx\n", addr);
1593                         printf("pmap_growkernel: adding new level2 page table\n");
1594
1595                         nklev2++;
1596                         vm_page_wire(nkpg);
1597                         pa = VM_PAGE_TO_PHYS(nkpg);
1598                         pmap_zero_page(pa);
1599
1600                         newlev1 = pmap_phys_to_pte(pa)
1601                                 | PG_V | PG_ASM | PG_KRE | PG_KWE;
1602
1603                         LIST_FOREACH(p, &allproc, p_list) {
1604                                 if (p->p_vmspace) {
1605                                         pmap = vmspace_pmap(p->p_vmspace);
1606                                         *pmap_lev1pte(pmap, kernel_vm_end) = newlev1;
1607                                 }
1608                         }
1609                         *pte = newlev1;
1610                         pmap_invalidate_all(kernel_pmap);
1611                 }
1612
1613                 /*
1614                  * If the level 2 pte is invalid, allocate a new level 3 page table
1615                  */
1616                 pte = pmap_lev2pte(kernel_pmap, kernel_vm_end);
1617                 if (pmap_pte_v(pte)) {
1618                         kernel_vm_end = (kernel_vm_end + ALPHA_L2SIZE) & ~(ALPHA_L2SIZE - 1);
1619                         continue;
1620                 }
1621
1622                 /*
1623                  * This index is bogus, but out of the way
1624                  */
1625                 nkpg = vm_page_alloc(kptobj, nklev3, VM_ALLOC_SYSTEM);
1626 #if !defined(MAX_PERF)
1627                 if (!nkpg)
1628                         panic("pmap_growkernel: no memory to grow kernel");
1629 #endif
1630
1631                 nklev3++;
1632
1633                 vm_page_wire(nkpg);
1634                 pa = VM_PAGE_TO_PHYS(nkpg);
1635                 pmap_zero_page(pa);
1636                 newlev2 = pmap_phys_to_pte(pa) | PG_V | PG_ASM | PG_KRE | PG_KWE;
1637                 *pte = newlev2;
1638
1639                 kernel_vm_end = (kernel_vm_end + ALPHA_L2SIZE) & ~(ALPHA_L2SIZE - 1);
1640         }
1641         splx(s);
1642 }
1643
1644 /*
1645  *      Retire the given physical map from service.
1646  *      Should only be called if the map contains
1647  *      no valid mappings.
1648  */
1649 void
1650 pmap_destroy(pmap_t pmap)
1651 {
1652         int count;
1653
1654         if (pmap == NULL)
1655                 return;
1656
1657         count = --pmap->pm_count;
1658         if (count == 0) {
1659                 pmap_release(pmap);
1660 #if !defined(MAX_PERF)
1661                 panic("destroying a pmap is not yet implemented");
1662 #endif
1663         }
1664 }
1665
1666 /*
1667  *      Add a reference to the specified pmap.
1668  */
1669 void
1670 pmap_reference(pmap_t pmap)
1671 {
1672         if (pmap != NULL) {
1673                 pmap->pm_count++;
1674         }
1675 }
1676
1677 /***************************************************
1678 * page management routines.
1679  ***************************************************/
1680
1681 /*
1682  * free the pv_entry back to the free list
1683  */
1684 static PMAP_INLINE void
1685 free_pv_entry(pv_entry_t pv)
1686 {
1687         pv_entry_count--;
1688         zfreei(pvzone, pv);
1689 }
1690
1691 /*
1692  * get a new pv_entry, allocating a block from the system
1693  * when needed.
1694  * the memory allocation is performed bypassing the malloc code
1695  * because of the possibility of allocations at interrupt time.
1696  */
1697 static pv_entry_t
1698 get_pv_entry(void)
1699 {
1700         pv_entry_count++;
1701         if (pv_entry_high_water &&
1702                 (pv_entry_count > pv_entry_high_water) &&
1703                 (pmap_pagedaemon_waken == 0)) {
1704                 pmap_pagedaemon_waken = 1;
1705                 wakeup (&vm_pages_needed);
1706         }
1707         return zalloci(pvzone);
1708 }
1709
1710 /*
1711  * This routine is very drastic, but can save the system
1712  * in a pinch.
1713  */
1714 void
1715 pmap_collect()
1716 {
1717         pv_table_t *ppv;
1718         int i;
1719         vm_offset_t pa;
1720         vm_page_t m;
1721         static int warningdone=0;
1722
1723         if (pmap_pagedaemon_waken == 0)
1724                 return;
1725
1726         if (warningdone < 5) {
1727                 printf("pmap_collect: collecting pv entries -- suggest increasing PMAP_SHPGPERPROC\n");
1728                 warningdone++;
1729         }
1730
1731         for(i = 0; i < pv_npg; i++) {
1732                 if ((ppv = &pv_table[i]) == 0)
1733                         continue;
1734                 m = ppv->pv_vm_page;
1735                 if ((pa = VM_PAGE_TO_PHYS(m)) == 0)
1736                         continue;
1737                 if (m->wire_count || m->hold_count || m->busy ||
1738                         (m->flags & PG_BUSY))
1739                         continue;
1740                 pmap_remove_all(pa);
1741         }
1742         pmap_pagedaemon_waken = 0;
1743 }
1744         
1745
1746 /*
1747  * If it is the first entry on the list, it is actually
1748  * in the header and we must copy the following entry up
1749  * to the header.  Otherwise we must search the list for
1750  * the entry.  In either case we free the now unused entry.
1751  */
1752
1753 static int
1754 pmap_remove_entry(pmap_t pmap, pv_table_t* ppv, vm_offset_t va)
1755 {
1756         pv_entry_t pv;
1757         int rtval;
1758         int s;
1759
1760         s = splvm();
1761         if (ppv->pv_list_count < pmap->pm_stats.resident_count) {
1762                 for (pv = TAILQ_FIRST(&ppv->pv_list);
1763                         pv;
1764                         pv = TAILQ_NEXT(pv, pv_list)) {
1765                         if (pmap == pv->pv_pmap && va == pv->pv_va) 
1766                                 break;
1767                 }
1768         } else {
1769                 for (pv = TAILQ_FIRST(&pmap->pm_pvlist);
1770                         pv;
1771                         pv = TAILQ_NEXT(pv, pv_plist)) {
1772                         if (va == pv->pv_va) 
1773                                 break;
1774                 }
1775         }
1776
1777         rtval = 0;
1778         if (pv) {
1779                 rtval = pmap_unuse_pt(pmap, va, pv->pv_ptem);
1780                 TAILQ_REMOVE(&ppv->pv_list, pv, pv_list);
1781                 ppv->pv_list_count--;
1782                 if (TAILQ_FIRST(&ppv->pv_list) == NULL)
1783                         vm_page_flag_clear(ppv->pv_vm_page, PG_MAPPED | PG_WRITEABLE);
1784
1785                 TAILQ_REMOVE(&pmap->pm_pvlist, pv, pv_plist);
1786                 free_pv_entry(pv);
1787         }
1788                         
1789         splx(s);
1790         return rtval;
1791 }
1792
1793 /*
1794  * Create a pv entry for page at pa for
1795  * (pmap, va).
1796  */
1797 static void
1798 pmap_insert_entry(pmap_t pmap, vm_offset_t va, vm_page_t mpte, vm_offset_t pa)
1799 {
1800
1801         int s;
1802         pv_entry_t pv;
1803         pv_table_t *ppv;
1804
1805         s = splvm();
1806         pv = get_pv_entry();
1807         pv->pv_va = va;
1808         pv->pv_pmap = pmap;
1809         pv->pv_ptem = mpte;
1810
1811         TAILQ_INSERT_TAIL(&pmap->pm_pvlist, pv, pv_plist);
1812
1813         ppv = pa_to_pvh(pa);
1814         TAILQ_INSERT_TAIL(&ppv->pv_list, pv, pv_list);
1815         ppv->pv_list_count++;
1816
1817         splx(s);
1818 }
1819
1820 /*
1821  * pmap_remove_pte: do the things to unmap a page in a process
1822  */
1823 static int
1824 pmap_remove_pte(pmap_t pmap, pt_entry_t* ptq, vm_offset_t va)
1825 {
1826         pt_entry_t oldpte;
1827         pv_table_t *ppv;
1828
1829         oldpte = *ptq;
1830         PMAP_DEBUG_VA(va);
1831         *ptq = 0;
1832         if (oldpte & PG_W)
1833                 pmap->pm_stats.wired_count -= 1;
1834
1835         pmap->pm_stats.resident_count -= 1;
1836         if (oldpte & PG_MANAGED) {
1837                 ppv = pa_to_pvh(pmap_pte_pa(&oldpte));
1838                 return pmap_remove_entry(pmap, ppv, va);
1839         } else {
1840                 return pmap_unuse_pt(pmap, va, NULL);
1841         }
1842
1843         return 0;
1844 }
1845
1846 /*
1847  * Remove a single page from a process address space
1848  */
1849 static void
1850 pmap_remove_page(pmap_t pmap, vm_offset_t va)
1851 {
1852         register pt_entry_t *ptq;
1853
1854         ptq = pmap_lev3pte(pmap, va);
1855         
1856         /*
1857          * if there is no pte for this address, just skip it!!!
1858          */
1859         if (!ptq || !pmap_pte_v(ptq))
1860                 return;
1861
1862         /*
1863          * get a local va for mappings for this pmap.
1864          */
1865         (void) pmap_remove_pte(pmap, ptq, va);
1866         pmap_invalidate_page(pmap, va);
1867
1868         return;
1869 }
1870
1871 /*
1872  *      Remove the given range of addresses from the specified map.
1873  *
1874  *      It is assumed that the start and end are properly
1875  *      rounded to the page size.
1876  */
1877 void
1878 pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
1879 {
1880         vm_offset_t va, nva;
1881
1882         if (pmap == NULL)
1883                 return;
1884
1885         if (pmap->pm_stats.resident_count == 0)
1886                 return;
1887
1888         /*
1889          * special handling of removing one page.  a very
1890          * common operation and easy to short circuit some
1891          * code.
1892          */
1893         if (sva + PAGE_SIZE == eva) {
1894                 pmap_remove_page(pmap, sva);
1895                 return;
1896         }
1897
1898         for (va = sva; va < eva; va = nva) {
1899                 if (!pmap_pte_v(pmap_lev1pte(pmap, va))) {
1900                         nva = alpha_l1trunc(va + ALPHA_L1SIZE);
1901                         continue;
1902                 }
1903
1904                 if (!pmap_pte_v(pmap_lev2pte(pmap, va))) {
1905                         nva = alpha_l2trunc(va + ALPHA_L2SIZE);
1906                         continue;
1907                 }
1908
1909                 pmap_remove_page(pmap, va);
1910                 nva = va + PAGE_SIZE;
1911         }
1912 }
1913
1914 /*
1915  *      Routine:        pmap_remove_all
1916  *      Function:
1917  *              Removes this physical page from
1918  *              all physical maps in which it resides.
1919  *              Reflects back modify bits to the pager.
1920  *
1921  *      Notes:
1922  *              Original versions of this routine were very
1923  *              inefficient because they iteratively called
1924  *              pmap_remove (slow...)
1925  */
1926
1927 static void
1928 pmap_remove_all(vm_offset_t pa)
1929 {
1930         register pv_entry_t pv;
1931         pv_table_t *ppv;
1932         pt_entry_t *pte, tpte;
1933         int nmodify;
1934         int s;
1935
1936         nmodify = 0;
1937 #if defined(PMAP_DIAGNOSTIC)
1938         /*
1939          * XXX this makes pmap_page_protect(NONE) illegal for non-managed
1940          * pages!
1941          */
1942         if (!pmap_is_managed(pa)) {
1943                 panic("pmap_page_protect: illegal for unmanaged page, va: 0x%lx", pa);
1944         }
1945 #endif
1946
1947         s = splvm();
1948         ppv = pa_to_pvh(pa);
1949         while ((pv = TAILQ_FIRST(&ppv->pv_list)) != NULL) {
1950                 pte = pmap_lev3pte(pv->pv_pmap, pv->pv_va);
1951
1952                 pv->pv_pmap->pm_stats.resident_count--;
1953
1954                 if (pmap_pte_pa(pte) != pa)
1955                         panic("pmap_remove_all: pv_table for %lx is inconsistent", pa);
1956
1957                 tpte = *pte;
1958
1959                 PMAP_DEBUG_VA(pv->pv_va);
1960                 *pte = 0;
1961                 if (tpte & PG_W)
1962                         pv->pv_pmap->pm_stats.wired_count--;
1963
1964                 pmap_invalidate_page(pv->pv_pmap, pv->pv_va);
1965
1966                 TAILQ_REMOVE(&pv->pv_pmap->pm_pvlist, pv, pv_plist);
1967                 TAILQ_REMOVE(&ppv->pv_list, pv, pv_list);
1968                 ppv->pv_list_count--;
1969                 pmap_unuse_pt(pv->pv_pmap, pv->pv_va, pv->pv_ptem);
1970                 free_pv_entry(pv);
1971         }
1972
1973         vm_page_flag_clear(ppv->pv_vm_page, PG_MAPPED | PG_WRITEABLE);
1974
1975         splx(s);
1976         return;
1977 }
1978
1979 /*
1980  *      Set the physical protection on the
1981  *      specified range of this map as requested.
1982  */
1983 void
1984 pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
1985 {
1986         pt_entry_t* pte;
1987         int newprot;
1988
1989         if (pmap == NULL)
1990                 return;
1991
1992         if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
1993                 pmap_remove(pmap, sva, eva);
1994                 return;
1995         }
1996
1997         if (prot & VM_PROT_WRITE)
1998                 return;
1999
2000         newprot = pte_prot(pmap, prot);
2001
2002         if ((sva & PAGE_MASK) || (eva & PAGE_MASK))
2003                 panic("pmap_protect: unaligned addresses");
2004
2005         while (sva < eva) {
2006
2007                 /*
2008                  * If level 1 pte is invalid, skip this segment
2009                  */
2010                 pte = pmap_lev1pte(pmap, sva);
2011                 if (!pmap_pte_v(pte)) {
2012                         sva = alpha_l1trunc(sva) + ALPHA_L1SIZE;
2013                         continue;
2014                 }
2015
2016                 /*
2017                  * If level 2 pte is invalid, skip this segment
2018                  */
2019                 pte = pmap_lev2pte(pmap, sva);
2020                 if (!pmap_pte_v(pte)) {
2021                         sva = alpha_l2trunc(sva) + ALPHA_L2SIZE;
2022                         continue;
2023                 }
2024
2025                 /* 
2026                  * If level 3 pte is invalid, skip this page
2027                  */
2028                 pte = pmap_lev3pte(pmap, sva);
2029                 if (!pmap_pte_v(pte)) {
2030                         sva += PAGE_SIZE;
2031                         continue;
2032                 }
2033
2034                 if (pmap_pte_prot(pte) != newprot) {
2035                         pmap_pte_set_prot(pte, newprot);
2036                         pmap_invalidate_page(pmap, sva);
2037                 }
2038
2039                 sva += PAGE_SIZE;
2040         }
2041 }
2042
2043 /*
2044  *      Insert the given physical page (p) at
2045  *      the specified virtual address (v) in the
2046  *      target physical map with the protection requested.
2047  *
2048  *      If specified, the page will be wired down, meaning
2049  *      that the related pte can not be reclaimed.
2050  *
2051  *      NB:  This is the only routine which MAY NOT lazy-evaluate
2052  *      or lose information.  That is, this routine must actually
2053  *      insert this page into the given map NOW.
2054  */
2055 void
2056 pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot,
2057            boolean_t wired)
2058 {
2059         pt_entry_t *pte;
2060         vm_offset_t opa;
2061         pt_entry_t origpte, newpte;
2062         vm_page_t mpte;
2063         int managed;
2064
2065         if (pmap == NULL)
2066                 return;
2067
2068         va &= ~PAGE_MASK;
2069 #ifdef PMAP_DIAGNOSTIC
2070         if (va > VM_MAX_KERNEL_ADDRESS)
2071                 panic("pmap_enter: toobig");
2072 #endif
2073
2074         mpte = NULL;
2075         /*
2076          * In the case that a page table page is not
2077          * resident, we are creating it here.
2078          */
2079         if (va < VM_MAXUSER_ADDRESS) {
2080                 mpte = pmap_allocpte(pmap, va);
2081         }
2082
2083         pte = pmap_lev3pte(pmap, va);
2084
2085 #if !defined(MAX_PERF)
2086         /*
2087          * Page Directory table entry not valid, we need a new PT page
2088          */
2089         if (pte == NULL) {
2090                 panic("pmap_enter: invalid kernel page tables pmap=%p, va=0x%lx\n", pmap, va);
2091         }
2092 #endif
2093
2094         origpte = *pte;
2095         pa &= ~PAGE_MASK;
2096         managed = 0;
2097         opa = pmap_pte_pa(pte);
2098
2099         /*
2100          * Mapping has not changed, must be protection or wiring change.
2101          */
2102         if (origpte && (opa == pa)) {
2103                 /*
2104                  * Wiring change, just update stats. We don't worry about
2105                  * wiring PT pages as they remain resident as long as there
2106                  * are valid mappings in them. Hence, if a user page is wired,
2107                  * the PT page will be also.
2108                  */
2109                 if (wired && ((origpte & PG_W) == 0))
2110                         pmap->pm_stats.wired_count++;
2111                 else if (!wired && (origpte & PG_W))
2112                         pmap->pm_stats.wired_count--;
2113
2114                 /*
2115                  * Remove extra pte reference
2116                  */
2117                 if (mpte)
2118                         mpte->hold_count--;
2119
2120                 managed = origpte & PG_MANAGED;
2121                 goto validate;
2122         } 
2123         /*
2124          * Mapping has changed, invalidate old range and fall through to
2125          * handle validating new mapping.
2126          */
2127         if (opa) {
2128                 int err;
2129                 err = pmap_remove_pte(pmap, pte, va);
2130 #if !defined(MAX_PERF)
2131                 if (err)
2132                         panic("pmap_enter: pte vanished, va: 0x%lx", va);
2133 #endif
2134         }
2135
2136         /*
2137          * Enter on the PV list if part of our managed memory Note that we
2138          * raise IPL while manipulating pv_table since pmap_enter can be
2139          * called at interrupt time.
2140          */
2141         if (pmap_is_managed(pa)) {
2142                 pmap_insert_entry(pmap, va, mpte, pa);
2143                 managed |= PG_MANAGED;
2144         }
2145
2146         /*
2147          * Increment counters
2148          */
2149         pmap->pm_stats.resident_count++;
2150         if (wired)
2151                 pmap->pm_stats.wired_count++;
2152
2153 validate:
2154         /*
2155          * Now validate mapping with desired protection/wiring.
2156          */
2157         newpte = pmap_phys_to_pte(pa) | pte_prot(pmap, prot) | PG_V | managed;
2158
2159         if (managed) {
2160                 pv_table_t* ppv;
2161
2162                 /*
2163                  * Set up referenced/modified emulation for the new mapping
2164                  */
2165                 ppv = pa_to_pvh(pa);
2166                 if ((ppv->pv_flags & PV_TABLE_REF) == 0)
2167                         newpte |= PG_FOR | PG_FOW | PG_FOE;
2168                 else if ((ppv->pv_flags & PV_TABLE_MOD) == 0)
2169                         newpte |= PG_FOW;
2170         }
2171
2172         if (wired)
2173                 newpte |= PG_W;
2174
2175         /*
2176          * if the mapping or permission bits are different, we need
2177          * to update the pte.
2178          */
2179         if (origpte != newpte) {
2180                 PMAP_DEBUG_VA(va);
2181                 *pte = newpte;
2182                 if (origpte)
2183                         pmap_invalidate_page(pmap, va);
2184                 if (prot & VM_PROT_EXECUTE)
2185                         alpha_pal_imb();
2186         }
2187 }
2188
2189 /*
2190  * this code makes some *MAJOR* assumptions:
2191  * 1. Current pmap & pmap exists.
2192  * 2. Not wired.
2193  * 3. Read access.
2194  * 4. No page table pages.
2195  * 5. Tlbflush is deferred to calling procedure.
2196  * 6. Page IS managed.
2197  * but is *MUCH* faster than pmap_enter...
2198  */
2199
2200 static vm_page_t
2201 pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_page_t mpte)
2202 {
2203         register pt_entry_t *pte;
2204
2205
2206         /*
2207          * In the case that a page table page is not
2208          * resident, we are creating it here.
2209          */
2210         if (va < VM_MAXUSER_ADDRESS) {
2211                 unsigned ptepindex;
2212                 pt_entry_t* l2pte;
2213
2214                 /*
2215                  * Calculate lev2 page index
2216                  */
2217                 ptepindex = va >> ALPHA_L2SHIFT;
2218                 if (mpte && (mpte->pindex == ptepindex)) {
2219                         mpte->hold_count++;
2220                 } else {
2221 retry:
2222                         /*
2223                          * Get the level 2 entry
2224                          */
2225                         l2pte = pmap_lev2pte(pmap, va);
2226
2227                         /*
2228                          * If the level 2 page table is mapped, we just increment
2229                          * the hold count, and activate it.
2230                          */
2231                         if (l2pte && pmap_pte_v(l2pte)) {
2232                                 if (pmap->pm_ptphint &&
2233                                         (pmap->pm_ptphint->pindex == ptepindex)) {
2234                                         mpte = pmap->pm_ptphint;
2235                                 } else {
2236                                         mpte = pmap_page_lookup( pmap->pm_pteobj, ptepindex);
2237                                         pmap->pm_ptphint = mpte;
2238                                 }
2239                                 if (mpte == NULL)
2240                                         goto retry;
2241                                 mpte->hold_count++;
2242                         } else {
2243                                 mpte = _pmap_allocpte(pmap, ptepindex);
2244                         }
2245                 }
2246         } else {
2247                 mpte = NULL;
2248         }
2249
2250         /*
2251          * This call to vtopte makes the assumption that we are
2252          * entering the page into the current pmap.  In order to support
2253          * quick entry into any pmap, one would likely use pmap_pte_quick.
2254          * But that isn't as quick as vtopte.
2255          */
2256         pte = vtopte(va);
2257         if (*pte) {
2258                 if (mpte)
2259                         pmap_unwire_pte_hold(pmap, va, mpte);
2260                 alpha_pal_imb();                /* XXX overkill? */
2261                 return 0;
2262         }
2263
2264         /*
2265          * Enter on the PV list if part of our managed memory Note that we
2266          * raise IPL while manipulating pv_table since pmap_enter can be
2267          * called at interrupt time.
2268          */
2269         PMAP_DEBUG_VA(va);
2270         pmap_insert_entry(pmap, va, mpte, pa);
2271
2272         /*
2273          * Increment counters
2274          */
2275         pmap->pm_stats.resident_count++;
2276
2277         /*
2278          * Now validate mapping with RO protection
2279          */
2280         *pte = pmap_phys_to_pte(pa) | PG_V | PG_KRE | PG_URE | PG_MANAGED;
2281
2282         alpha_pal_imb();                        /* XXX overkill? */
2283         return mpte;
2284 }
2285
2286 #define MAX_INIT_PT (96)
2287 /*
2288  * pmap_object_init_pt preloads the ptes for a given object
2289  * into the specified pmap.  This eliminates the blast of soft
2290  * faults on process startup and immediately after an mmap.
2291  */
2292 void
2293 pmap_object_init_pt(pmap_t pmap, vm_offset_t addr,
2294                     vm_object_t object, vm_pindex_t pindex,
2295                     vm_size_t size, int limit)
2296 {
2297         vm_offset_t tmpidx;
2298         int psize;
2299         vm_page_t p, mpte;
2300         int objpgs;
2301
2302         if (pmap == NULL || object == NULL)
2303                 return;
2304
2305         psize = alpha_btop(size);
2306
2307         if ((object->type != OBJT_VNODE) ||
2308                 (limit && (psize > MAX_INIT_PT) &&
2309                         (object->resident_page_count > MAX_INIT_PT))) {
2310                 return;
2311         }
2312
2313         if (psize + pindex > object->size)
2314                 psize = object->size - pindex;
2315
2316         mpte = NULL;
2317         /*
2318          * if we are processing a major portion of the object, then scan the
2319          * entire thing.
2320          */
2321         if (psize > (object->resident_page_count >> 2)) {
2322                 objpgs = psize;
2323
2324                 for (p = TAILQ_FIRST(&object->memq);
2325                     ((objpgs > 0) && (p != NULL));
2326                     p = TAILQ_NEXT(p, listq)) {
2327
2328                         tmpidx = p->pindex;
2329                         if (tmpidx < pindex) {
2330                                 continue;
2331                         }
2332                         tmpidx -= pindex;
2333                         if (tmpidx >= psize) {
2334                                 continue;
2335                         }
2336                         if (((p->valid & VM_PAGE_BITS_ALL) == VM_PAGE_BITS_ALL) &&
2337                             (p->flags & (PG_BUSY | PG_FICTITIOUS)) == 0) {
2338                                 if ((p->queue - p->pc) == PQ_CACHE)
2339                                         vm_page_deactivate(p);
2340                                 vm_page_busy(p);
2341                                 mpte = pmap_enter_quick(pmap, 
2342                                         addr + alpha_ptob(tmpidx),
2343                                         VM_PAGE_TO_PHYS(p), mpte);
2344                                 vm_page_flag_set(p, PG_MAPPED);
2345                                 vm_page_wakeup(p);
2346                         }
2347                         objpgs -= 1;
2348                 }
2349         } else {
2350                 /*
2351                  * else lookup the pages one-by-one.
2352                  */
2353                 for (tmpidx = 0; tmpidx < psize; tmpidx += 1) {
2354                         p = vm_page_lookup(object, tmpidx + pindex);
2355                         if (p &&
2356                             ((p->valid & VM_PAGE_BITS_ALL) == VM_PAGE_BITS_ALL) &&
2357                             (p->flags & (PG_BUSY | PG_FICTITIOUS)) == 0) {
2358                                 if ((p->queue - p->pc) == PQ_CACHE)
2359                                         vm_page_deactivate(p);
2360                                 vm_page_busy(p);
2361                                 mpte = pmap_enter_quick(pmap, 
2362                                         addr + alpha_ptob(tmpidx),
2363                                         VM_PAGE_TO_PHYS(p), mpte);
2364                                 vm_page_flag_set(p, PG_MAPPED);
2365                                 vm_page_wakeup(p);
2366                         }
2367                 }
2368         }
2369         return;
2370 }
2371
2372 /*
2373  * pmap_prefault provides a quick way of clustering
2374  * pagefaults into a processes address space.  It is a "cousin"
2375  * of pmap_object_init_pt, except it runs at page fault time instead
2376  * of mmap time.
2377  */
2378 #define PFBAK 4
2379 #define PFFOR 4
2380 #define PAGEORDER_SIZE (PFBAK+PFFOR)
2381
2382 static int pmap_prefault_pageorder[] = {
2383         -PAGE_SIZE, PAGE_SIZE,
2384         -2 * PAGE_SIZE, 2 * PAGE_SIZE,
2385         -3 * PAGE_SIZE, 3 * PAGE_SIZE
2386         -4 * PAGE_SIZE, 4 * PAGE_SIZE
2387 };
2388
2389 void
2390 pmap_prefault(pmap, addra, entry)
2391         pmap_t pmap;
2392         vm_offset_t addra;
2393         vm_map_entry_t entry;
2394 {
2395         int i;
2396         vm_offset_t starta;
2397         vm_offset_t addr;
2398         vm_pindex_t pindex;
2399         vm_page_t m, mpte;
2400         vm_object_t object;
2401
2402         if (!curproc || (pmap != vmspace_pmap(curproc->p_vmspace)))
2403                 return;
2404
2405         object = entry->object.vm_object;
2406
2407         starta = addra - PFBAK * PAGE_SIZE;
2408         if (starta < entry->start) {
2409                 starta = entry->start;
2410         } else if (starta > addra) {
2411                 starta = 0;
2412         }
2413
2414         mpte = NULL;
2415         for (i = 0; i < PAGEORDER_SIZE; i++) {
2416                 vm_object_t lobject;
2417                 pt_entry_t *pte;
2418
2419                 addr = addra + pmap_prefault_pageorder[i];
2420                 if (addr > addra + (PFFOR * PAGE_SIZE))
2421                         addr = 0;
2422
2423                 if (addr < starta || addr >= entry->end)
2424                         continue;
2425
2426                 if (!pmap_pte_v(pmap_lev1pte(pmap, addr))
2427                     || !pmap_pte_v(pmap_lev2pte(pmap, addr)))
2428                         continue;
2429
2430                 pte = vtopte(addr);
2431                 if (*pte)
2432                         continue;
2433
2434                 pindex = ((addr - entry->start) + entry->offset) >> PAGE_SHIFT;
2435                 lobject = object;
2436                 for (m = vm_page_lookup(lobject, pindex);
2437                     (!m && (lobject->type == OBJT_DEFAULT) && (lobject->backing_object));
2438                     lobject = lobject->backing_object) {
2439                         if (lobject->backing_object_offset & PAGE_MASK)
2440                                 break;
2441                         pindex += (lobject->backing_object_offset >> PAGE_SHIFT);
2442                         m = vm_page_lookup(lobject->backing_object, pindex);
2443                 }
2444
2445                 /*
2446                  * give-up when a page is not in memory
2447                  */
2448                 if (m == NULL)
2449                         break;
2450
2451                 if (((m->valid & VM_PAGE_BITS_ALL) == VM_PAGE_BITS_ALL) &&
2452                     (m->flags & (PG_BUSY | PG_FICTITIOUS)) == 0) {
2453
2454                         if ((m->queue - m->pc) == PQ_CACHE) {
2455                                 vm_page_deactivate(m);
2456                         }
2457                         vm_page_busy(m);
2458                         mpte = pmap_enter_quick(pmap, addr,
2459                                 VM_PAGE_TO_PHYS(m), mpte);
2460                         vm_page_flag_set(m, PG_MAPPED);
2461                         vm_page_wakeup(m);
2462                 }
2463         }
2464 }
2465
2466 /*
2467  *      Routine:        pmap_change_wiring
2468  *      Function:       Change the wiring attribute for a map/virtual-address
2469  *                      pair.
2470  *      In/out conditions:
2471  *                      The mapping must already exist in the pmap.
2472  */
2473 void
2474 pmap_change_wiring(pmap, va, wired)
2475         register pmap_t pmap;
2476         vm_offset_t va;
2477         boolean_t wired;
2478 {
2479         pt_entry_t *pte;
2480
2481         if (pmap == NULL)
2482                 return;
2483
2484         pte = pmap_lev3pte(pmap, va);
2485
2486         if (wired && !pmap_pte_w(pte))
2487                 pmap->pm_stats.wired_count++;
2488         else if (!wired && pmap_pte_w(pte))
2489                 pmap->pm_stats.wired_count--;
2490
2491         /*
2492          * Wiring is not a hardware characteristic so there is no need to
2493          * invalidate TLB.
2494          */
2495         pmap_pte_set_w(pte, wired);
2496 }
2497
2498
2499
2500 /*
2501  *      Copy the range specified by src_addr/len
2502  *      from the source map to the range dst_addr/len
2503  *      in the destination map.
2504  *
2505  *      This routine is only advisory and need not do anything.
2506  */
2507
2508 void
2509 pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
2510           vm_offset_t src_addr)
2511 {
2512 }       
2513
2514 /*
2515  *      Routine:        pmap_kernel
2516  *      Function:
2517  *              Returns the physical map handle for the kernel.
2518  */
2519 pmap_t
2520 pmap_kernel()
2521 {
2522         return (kernel_pmap);
2523 }
2524
2525 /*
2526  *      pmap_zero_page zeros the specified hardware page by
2527  *      mapping it into virtual memory and using bzero to clear
2528  *      its contents.
2529  */
2530
2531 void
2532 pmap_zero_page(vm_offset_t pa)
2533 {
2534         vm_offset_t va = ALPHA_PHYS_TO_K0SEG(pa);
2535         bzero((caddr_t) va, PAGE_SIZE);
2536 }
2537
2538
2539 /*
2540  *      pmap_zero_page_area zeros the specified hardware page by
2541  *      mapping it into virtual memory and using bzero to clear
2542  *      its contents.
2543  *
2544  *      off and size must reside within a single page.
2545  */
2546
2547 void
2548 pmap_zero_page_area(vm_offset_t pa, int off, int size)
2549 {
2550         vm_offset_t va = ALPHA_PHYS_TO_K0SEG(pa);
2551         bzero((char *)(caddr_t)va + off, size);
2552 }
2553
2554 /*
2555  *      pmap_copy_page copies the specified (machine independent)
2556  *      page by mapping the page into virtual memory and using
2557  *      bcopy to copy the page, one machine dependent page at a
2558  *      time.
2559  */
2560 void
2561 pmap_copy_page(vm_offset_t src, vm_offset_t dst)
2562 {
2563         src = ALPHA_PHYS_TO_K0SEG(src);
2564         dst = ALPHA_PHYS_TO_K0SEG(dst);
2565         bcopy((caddr_t) src, (caddr_t) dst, PAGE_SIZE);
2566 }
2567
2568
2569 /*
2570  *      Routine:        pmap_pageable
2571  *      Function:
2572  *              Make the specified pages (by pmap, offset)
2573  *              pageable (or not) as requested.
2574  *
2575  *              A page which is not pageable may not take
2576  *              a fault; therefore, its page table entry
2577  *              must remain valid for the duration.
2578  *
2579  *              This routine is merely advisory; pmap_enter
2580  *              will specify that these pages are to be wired
2581  *              down (or not) as appropriate.
2582  */
2583 void
2584 pmap_pageable(pmap, sva, eva, pageable)
2585         pmap_t pmap;
2586         vm_offset_t sva, eva;
2587         boolean_t pageable;
2588 {
2589 }
2590
2591 /*
2592  * this routine returns true if a physical page resides
2593  * in the given pmap.
2594  */
2595 boolean_t
2596 pmap_page_exists(pmap, pa)
2597         pmap_t pmap;
2598         vm_offset_t pa;
2599 {
2600         register pv_entry_t pv;
2601         pv_table_t *ppv;
2602         int s;
2603
2604         if (!pmap_is_managed(pa))
2605                 return FALSE;
2606
2607         s = splvm();
2608
2609         ppv = pa_to_pvh(pa);
2610         /*
2611          * Not found, check current mappings returning immediately if found.
2612          */
2613         for (pv = TAILQ_FIRST(&ppv->pv_list);
2614                 pv;
2615                 pv = TAILQ_NEXT(pv, pv_list)) {
2616                 if (pv->pv_pmap == pmap) {
2617                         splx(s);
2618                         return TRUE;
2619                 }
2620         }
2621         splx(s);
2622         return (FALSE);
2623 }
2624
2625 #define PMAP_REMOVE_PAGES_CURPROC_ONLY
2626 /*
2627  * Remove all pages from specified address space
2628  * this aids process exit speeds.  Also, this code
2629  * is special cased for current process only, but
2630  * can have the more generic (and slightly slower)
2631  * mode enabled.  This is much faster than pmap_remove
2632  * in the case of running down an entire address space.
2633  */
2634 void
2635 pmap_remove_pages(pmap, sva, eva)
2636         pmap_t pmap;
2637         vm_offset_t sva, eva;
2638 {
2639         pt_entry_t *pte, tpte;
2640         pv_table_t *ppv;
2641         pv_entry_t pv, npv;
2642         int s;
2643
2644 #ifdef PMAP_REMOVE_PAGES_CURPROC_ONLY
2645         if (!curproc || (pmap != vmspace_pmap(curproc->p_vmspace))) {
2646                 printf("warning: pmap_remove_pages called with non-current pmap\n");
2647                 return;
2648         }
2649 #endif
2650
2651         s = splvm();
2652         for(pv = TAILQ_FIRST(&pmap->pm_pvlist);
2653                 pv;
2654                 pv = npv) {
2655
2656                 if (pv->pv_va >= eva || pv->pv_va < sva) {
2657                         npv = TAILQ_NEXT(pv, pv_plist);
2658                         continue;
2659                 }
2660
2661 #ifdef PMAP_REMOVE_PAGES_CURPROC_ONLY
2662                 pte = vtopte(pv->pv_va);
2663 #else
2664                 pte = pmap_pte_quick(pv->pv_pmap, pv->pv_va);
2665 #endif
2666                 if (!pmap_pte_v(pte))
2667                         panic("pmap_remove_pages: page on pm_pvlist has no pte\n");
2668                 tpte = *pte;
2669
2670
2671 /*
2672  * We cannot remove wired pages from a process' mapping at this time
2673  */
2674                 if (tpte & PG_W) {
2675                         npv = TAILQ_NEXT(pv, pv_plist);
2676                         continue;
2677                 }
2678                 PMAP_DEBUG_VA(pv->pv_va);
2679                 *pte = 0;
2680
2681                 ppv = pa_to_pvh(pmap_pte_pa(&tpte));
2682
2683                 pv->pv_pmap->pm_stats.resident_count--;
2684
2685                 npv = TAILQ_NEXT(pv, pv_plist);
2686                 TAILQ_REMOVE(&pv->pv_pmap->pm_pvlist, pv, pv_plist);
2687
2688                 ppv->pv_list_count--;
2689                 TAILQ_REMOVE(&ppv->pv_list, pv, pv_list);
2690                 if (TAILQ_FIRST(&ppv->pv_list) == NULL) {
2691                         vm_page_flag_clear(ppv->pv_vm_page, PG_MAPPED | PG_WRITEABLE);
2692                 }
2693
2694                 pmap_unuse_pt(pv->pv_pmap, pv->pv_va, pv->pv_ptem);
2695                 free_pv_entry(pv);
2696         }
2697         splx(s);
2698         pmap_invalidate_all(pmap);
2699 }
2700
2701 /*
2702  * this routine is used to modify bits in ptes
2703  */
2704 static void
2705 pmap_changebit(vm_offset_t pa, int bit, boolean_t setem)
2706 {
2707         pv_entry_t pv;
2708         pv_table_t *ppv;
2709         pt_entry_t *pte;
2710         int changed;
2711         int s;
2712
2713         if (!pmap_is_managed(pa))
2714                 return;
2715
2716         s = splvm();
2717         changed = 0;
2718         ppv = pa_to_pvh(pa);
2719
2720         /*
2721          * Loop over all current mappings setting/clearing as appropos If
2722          * setting RO do we need to clear the VAC?
2723          */
2724         for (pv = TAILQ_FIRST(&ppv->pv_list);
2725                 pv;
2726                 pv = TAILQ_NEXT(pv, pv_list)) {
2727
2728                 /*
2729                  * don't write protect pager mappings
2730                  */
2731                 if (!setem && bit == (PG_UWE|PG_KWE)) {
2732                         if (!pmap_track_modified(pv->pv_va))
2733                                 continue;
2734                 }
2735
2736 #if defined(PMAP_DIAGNOSTIC)
2737                 if (!pv->pv_pmap) {
2738                         printf("Null pmap (cb) at va: 0x%lx\n", pv->pv_va);
2739                         continue;
2740                 }
2741 #endif
2742
2743                 pte = pmap_lev3pte(pv->pv_pmap, pv->pv_va);
2744
2745                 changed = 0;
2746                 if (setem) {
2747                         *pte |= bit;
2748                         changed = 1;
2749                 } else {
2750                         pt_entry_t pbits = *pte;
2751                         if (pbits & bit) {
2752                                 changed = 1;
2753                                 *pte = pbits & ~bit;
2754                         }
2755                 }
2756                 if (changed)
2757                         pmap_invalidate_page(pv->pv_pmap, pv->pv_va);
2758         }
2759         splx(s);
2760 }
2761
2762 /*
2763  *      pmap_page_protect:
2764  *
2765  *      Lower the permission for all mappings to a given page.
2766  */
2767 void
2768 pmap_page_protect(vm_offset_t phys, vm_prot_t prot)
2769 {
2770         if ((prot & VM_PROT_WRITE) == 0) {
2771                 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2772                         pmap_changebit(phys, PG_KWE|PG_UWE, FALSE);
2773                 } else {
2774                         pmap_remove_all(phys);
2775                 }
2776         }
2777 }
2778
2779 vm_offset_t
2780 pmap_phys_address(ppn)
2781         int ppn;
2782 {
2783         return (alpha_ptob(ppn));
2784 }
2785
2786 /*
2787  *      pmap_ts_referenced:
2788  *
2789  *      Return the count of reference bits for a page, clearing all of them.
2790  *      
2791  */
2792 int
2793 pmap_ts_referenced(vm_offset_t pa)
2794 {
2795         pv_table_t *ppv;
2796
2797         if (!pmap_is_managed(pa))
2798                 return 0;
2799
2800         ppv = pa_to_pvh(pa);
2801
2802         if (ppv->pv_flags & PV_TABLE_REF) {
2803                 pmap_changebit(pa, PG_FOR|PG_FOE|PG_FOW, TRUE);
2804                 ppv->pv_flags &= ~PV_TABLE_REF;
2805                 return 1;
2806         }
2807
2808         return 0;
2809 }
2810
2811 /*
2812  *      pmap_is_modified:
2813  *
2814  *      Return whether or not the specified physical page was modified
2815  *      in any physical maps.
2816  */
2817 boolean_t
2818 pmap_is_modified(vm_offset_t pa)
2819 {
2820         pv_table_t *ppv;
2821
2822         if (!pmap_is_managed(pa))
2823                 return FALSE;
2824
2825         ppv = pa_to_pvh(pa);
2826
2827         return (ppv->pv_flags & PV_TABLE_MOD) != 0;
2828 }
2829
2830 /*
2831  *      Clear the modify bits on the specified physical page.
2832  */
2833 void
2834 pmap_clear_modify(vm_offset_t pa)
2835 {
2836         pv_table_t *ppv;
2837
2838         if (!pmap_is_managed(pa))
2839                 return;
2840
2841         ppv = pa_to_pvh(pa);
2842
2843         if (ppv->pv_flags & PV_TABLE_MOD) {
2844                 pmap_changebit(pa, PG_FOW, TRUE);
2845                 ppv->pv_flags &= ~PV_TABLE_MOD;
2846         }
2847 }
2848
2849 /*
2850  *      pmap_page_is_free:
2851  *
2852  *      Called when a page is freed to allow pmap to clean up
2853  *      any extra state associated with the page.  In this case
2854  *      clear modified/referenced bits.
2855  */
2856 void
2857 pmap_page_is_free(vm_page_t m)
2858 {
2859         pv_table_t *ppv;
2860
2861         ppv = pa_to_pvh(VM_PAGE_TO_PHYS(m));
2862         ppv->pv_flags = 0;
2863 }
2864
2865 /*
2866  *      pmap_clear_reference:
2867  *
2868  *      Clear the reference bit on the specified physical page.
2869  */
2870 void
2871 pmap_clear_reference(vm_offset_t pa)
2872 {
2873         pv_table_t *ppv;
2874
2875         if (!pmap_is_managed(pa))
2876                 return;
2877
2878         ppv = pa_to_pvh(pa);
2879
2880         if (ppv->pv_flags & PV_TABLE_REF) {
2881                 pmap_changebit(pa, PG_FOR|PG_FOE|PG_FOW, TRUE);
2882                 ppv->pv_flags &= ~PV_TABLE_REF;
2883         }
2884 }
2885
2886 /*
2887  * pmap_emulate_reference:
2888  *
2889  *      Emulate reference and/or modified bit hits.
2890  *      From NetBSD
2891  */
2892 void
2893 pmap_emulate_reference(struct proc *p, vm_offset_t v, int user, int write)
2894 {
2895         pt_entry_t faultoff, *pte;
2896         vm_offset_t pa;
2897         pv_table_t *ppv;
2898
2899         /*
2900          * Convert process and virtual address to physical address.
2901          */
2902         if (v >= VM_MIN_KERNEL_ADDRESS) {
2903                 if (user)
2904                         panic("pmap_emulate_reference: user ref to kernel");
2905                 pte = vtopte(v);
2906         } else {
2907 #ifdef DIAGNOSTIC
2908                 if (p == NULL)
2909                         panic("pmap_emulate_reference: bad proc");
2910                 if (p->p_vmspace == NULL)
2911                         panic("pmap_emulate_reference: bad p_vmspace");
2912 #endif
2913                 pte = pmap_lev3pte(p->p_vmspace->vm_map.pmap, v);
2914         }
2915 #ifdef DEBUG                            /* These checks are more expensive */
2916         if (!pmap_pte_v(pte))
2917                 panic("pmap_emulate_reference: invalid pte");
2918 #if 0
2919         /*
2920          * Can't do these, because cpu_fork and cpu_swapin call
2921          * pmap_emulate_reference(), and the bits aren't guaranteed,
2922          * for them...
2923          */
2924         if (write) {
2925                 if (!(*pte & (user ? PG_UWE : PG_UWE | PG_KWE)))
2926                         panic("pmap_emulate_reference: write but unwritable");
2927                 if (!(*pte & PG_FOW))
2928                         panic("pmap_emulate_reference: write but not FOW");
2929         } else {
2930                 if (!(*pte & (user ? PG_URE : PG_URE | PG_KRE)))
2931                         panic("pmap_emulate_reference: !write but unreadable");
2932                 if (!(*pte & (PG_FOR | PG_FOE)))
2933                         panic("pmap_emulate_reference: !write but not FOR|FOE");
2934         }
2935 #endif
2936         /* Other diagnostics? */
2937 #endif
2938         pa = pmap_pte_pa(pte);
2939
2940 #ifdef DIAGNOSTIC
2941         if ((*pte & PG_MANAGED) == 0)
2942                 panic("pmap_emulate_reference(%p, 0x%lx, %d, %d): pa 0x%lx not managed", p, v, user, write, pa);
2943 #endif
2944
2945         /*
2946          * Twiddle the appropriate bits to reflect the reference
2947          * and/or modification..
2948          *
2949          * The rules:
2950          *      (1) always mark page as used, and
2951          *      (2) if it was a write fault, mark page as modified.
2952          */
2953         ppv = pa_to_pvh(pa);
2954         ppv->pv_flags |= PV_TABLE_REF;
2955         faultoff = PG_FOR | PG_FOE;
2956         vm_page_flag_set(ppv->pv_vm_page, PG_REFERENCED);
2957         if (write) {
2958                 ppv->pv_flags |= PV_TABLE_MOD;
2959                 vm_page_dirty(ppv->pv_vm_page);
2960                 faultoff |= PG_FOW;
2961         }
2962         pmap_changebit(pa, faultoff, FALSE);
2963         if ((*pte & faultoff) != 0) {
2964 #if 1
2965                 /*
2966                  * XXX dfr - don't think its possible in our pmap
2967                  */
2968                 /*
2969                  * This is apparently normal.  Why? -- cgd
2970                  * XXX because was being called on unmanaged pages?
2971                  */
2972                 panic("warning: pmap_changebit didn't.");
2973 #endif
2974                 *pte &= ~faultoff;
2975                 ALPHA_TBIS(v);
2976         }
2977 }
2978
2979 /*
2980  * Miscellaneous support routines follow
2981  */
2982
2983 static void
2984 alpha_protection_init()
2985 {
2986         int prot, *kp, *up;
2987
2988         kp = protection_codes[0];
2989         up = protection_codes[1];
2990
2991         for (prot = 0; prot < 8; prot++) {
2992                 switch (prot) {
2993                 case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE:
2994                         *kp++ = PG_ASM;
2995                         *up++ = 0;
2996                         break;
2997                 case VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE:
2998                 case VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE:
2999                 case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE:
3000                         *kp++ = PG_ASM | PG_KRE;
3001                         *up++ = PG_URE | PG_KRE;
3002                         break;
3003                 case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE:
3004                         *kp++ = PG_ASM | PG_KWE;
3005                         *up++ = PG_UWE | PG_KWE;
3006                         break;
3007                 case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE:
3008                 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE:
3009                 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
3010                         *kp++ = PG_ASM | PG_KWE | PG_KRE;
3011                         *up++ = PG_UWE | PG_URE | PG_KWE | PG_KRE;
3012                         break;
3013                 }
3014         }
3015 }
3016
3017 /*
3018  * Map a set of physical memory pages into the kernel virtual
3019  * address space. Return a pointer to where it is mapped. This
3020  * routine is intended to be used for mapping device memory,
3021  * NOT real memory.
3022  */
3023 void *
3024 pmap_mapdev(pa, size)
3025         vm_offset_t pa;
3026         vm_size_t size;
3027 {
3028         return (void*) ALPHA_PHYS_TO_K0SEG(pa);
3029 }
3030
3031 /*
3032  * perform the pmap work for mincore
3033  */
3034 int
3035 pmap_mincore(pmap, addr)
3036         pmap_t pmap;
3037         vm_offset_t addr;
3038 {
3039         
3040         pt_entry_t *pte;
3041         vm_page_t m;
3042         int val = 0;
3043         
3044         pte = pmap_lev3pte(pmap, addr);
3045         if (pte == 0) {
3046                 return 0;
3047         }
3048
3049         if (pmap_pte_v(pte)) {
3050                 pv_table_t *ppv;
3051                 vm_offset_t pa;
3052
3053                 val = MINCORE_INCORE;
3054                 if ((*pte & PG_MANAGED) == 0)
3055                         return val;
3056
3057                 pa = pmap_pte_pa(pte);
3058
3059                 ppv = pa_to_pvh(pa);
3060                 m = ppv->pv_vm_page;
3061
3062                 /*
3063                  * Modified by us
3064                  */
3065                 if (ppv->pv_flags & PV_TABLE_MOD)
3066                         val |= MINCORE_MODIFIED|MINCORE_MODIFIED_OTHER;
3067                 /*
3068                  * Modified by someone
3069                  */
3070                 else if (m->dirty || pmap_is_modified(pa))
3071                         val |= MINCORE_MODIFIED_OTHER;
3072                 /*
3073                  * Referenced by us
3074                  */
3075                 if (ppv->pv_flags & PV_TABLE_REF)
3076                         val |= MINCORE_REFERENCED|MINCORE_REFERENCED_OTHER;
3077
3078                 /*
3079                  * Referenced by someone
3080                  */
3081                 else if ((m->flags & PG_REFERENCED) || pmap_ts_referenced(pa)) {
3082                         val |= MINCORE_REFERENCED_OTHER;
3083                         vm_page_flag_set(m, PG_REFERENCED);
3084                 }
3085         } 
3086         return val;
3087 }
3088
3089 void
3090 pmap_activate(struct proc *p)
3091 {
3092         pmap_t pmap;
3093
3094         pmap = vmspace_pmap(p->p_vmspace);
3095
3096         if (pmap_active && pmap != pmap_active) {
3097                 pmap_active->pm_active = 0;
3098                 pmap_active = 0;
3099         }
3100
3101         p->p_addr->u_pcb.pcb_hw.apcb_ptbr =
3102                 ALPHA_K0SEG_TO_PHYS((vm_offset_t) pmap->pm_lev1) >> PAGE_SHIFT;
3103
3104         if (pmap->pm_asngen != pmap_current_asngen)
3105                 pmap_get_asn(pmap);
3106
3107         pmap_active = pmap;
3108         pmap->pm_active = 1;    /* XXX use bitmap for SMP */
3109
3110         p->p_addr->u_pcb.pcb_hw.apcb_asn = pmap->pm_asn;
3111
3112         if (p == curproc) {
3113                 alpha_pal_swpctx((u_long)p->p_md.md_pcbpaddr);
3114         }
3115 }
3116
3117 void
3118 pmap_deactivate(struct proc *p)
3119 {
3120         pmap_t pmap;
3121         pmap = vmspace_pmap(p->p_vmspace);
3122         pmap->pm_active = 0;
3123         pmap_active = 0;
3124 }
3125
3126 vm_offset_t
3127 pmap_addr_hint(vm_object_t obj, vm_offset_t addr, vm_size_t size) {
3128
3129         return addr;
3130 }
3131
3132 #if 0
3133 #if defined(PMAP_DEBUG)
3134 pmap_pid_dump(int pid) {
3135         pmap_t pmap;
3136         struct proc *p;
3137         int npte = 0;
3138         int index;
3139         LIST_FOREACH(p, &allproc, p_list) {
3140                 if (p->p_pid != pid)
3141                         continue;
3142
3143                 if (p->p_vmspace) {
3144                         int i,j;
3145                         index = 0;
3146                         pmap = vmspace_pmap(p->p_vmspace);
3147                         for(i=0;i<1024;i++) {
3148                                 pd_entry_t *pde;
3149                                 pt_entry_t *pte;
3150                                 unsigned base = i << PDRSHIFT;
3151                                 
3152                                 pde = &pmap->pm_pdir[i];
3153                                 if (pde && pmap_pde_v(pde)) {
3154                                         for(j=0;j<1024;j++) {
3155                                                 unsigned va = base + (j << PAGE_SHIFT);
3156                                                 if (va >= (vm_offset_t) VM_MIN_KERNEL_ADDRESS) {
3157                                                         if (index) {
3158                                                                 index = 0;
3159                                                                 printf("\n");
3160                                                         }
3161                                                         return npte;
3162                                                 }
3163                                                 pte = pmap_pte_quick( pmap, va);
3164                                                 if (pte && pmap_pte_v(pte)) {
3165                                                         vm_offset_t pa;
3166                                                         vm_page_t m;
3167                                                         pa = *(int *)pte;
3168                                                         m = PHYS_TO_VM_PAGE((pa & PG_FRAME));
3169                                                         printf("va: 0x%x, pt: 0x%x, h: %d, w: %d, f: 0x%x",
3170                                                                 va, pa, m->hold_count, m->wire_count, m->flags);
3171                                                         npte++;
3172                                                         index++;
3173                                                         if (index >= 2) {
3174                                                                 index = 0;
3175                                                                 printf("\n");
3176                                                         } else {
3177                                                                 printf(" ");
3178                                                         }
3179                                                 }
3180                                         }
3181                                 }
3182                         }
3183                 }
3184         }
3185         return npte;
3186 }
3187 #endif
3188
3189 #if defined(DEBUG)
3190
3191 static void     pads __P((pmap_t pm));
3192 static void     pmap_pvdump __P((vm_offset_t pa));
3193
3194 /* print address space of pmap*/
3195 static void
3196 pads(pm)
3197         pmap_t pm;
3198 {
3199         int i, j;
3200         vm_offset_t va;
3201         pt_entry_t *ptep;
3202
3203         if (pm == kernel_pmap)
3204                 return;
3205         for (i = 0; i < 1024; i++)
3206                 if (pm->pm_pdir[i])
3207                         for (j = 0; j < 1024; j++) {
3208                                 va = (i << PDRSHIFT) + (j << PAGE_SHIFT);
3209                                 if (pm == kernel_pmap && va < KERNBASE)
3210                                         continue;
3211                                 if (pm != kernel_pmap && va > UPT_MAX_ADDRESS)
3212                                         continue;
3213                                 ptep = pmap_pte_quick(pm, va);
3214                                 if (pmap_pte_v(ptep))
3215                                         printf("%x:%x ", va, *(int *) ptep);
3216                         };
3217
3218 }
3219
3220 static void
3221 pmap_pvdump(pa)
3222         vm_offset_t pa;
3223 {
3224         pv_table_t *ppv;
3225         register pv_entry_t pv;
3226
3227         printf("pa %x", pa);
3228         ppv = pa_to_pvh(pa);
3229         for (pv = TAILQ_FIRST(&ppv->pv_list);
3230                 pv;
3231                 pv = TAILQ_NEXT(pv, pv_list)) {
3232 #ifdef used_to_be
3233                 printf(" -> pmap %x, va %x, flags %x",
3234                     pv->pv_pmap, pv->pv_va, pv->pv_flags);
3235 #endif
3236                 printf(" -> pmap %x, va %x",
3237                     pv->pv_pmap, pv->pv_va);
3238                 pads(pv->pv_pmap);
3239         }
3240         printf(" ");
3241 }
3242 #endif
3243 #endif