allocate segment tables out of a private submap that doesn't
[unix-history] / usr / src / sys / hp300 / hp300 / pmap.c
CommitLineData
8f961915 1/*
921517e8
KB
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
8f961915
KM
4 *
5 * This code is derived from software contributed to Berkeley by
4a4de5a4
KM
6 * the Systems Programming Group of the University of Utah Computer
7 * Science Department.
8f961915 8 *
4a4de5a4 9 * %sccs.include.redist.c%
8f961915 10 *
b55d9ecf 11 * @(#)pmap.c 8.5 (Berkeley) %G%
8f961915
KM
12 */
13
14/*
82043489
MH
15 * HP9000/300 series physical map management code.
16 *
17 * Supports:
18 * 68020 with HP MMU models 320, 350
19 * 68020 with 68551 MMU models 318, 319, 330 (all untested)
20 * 68030 with on-chip MMU models 340, 360, 370, 345, 375, 400
21 * 68040 with on-chip MMU models 380, 425, 433
22 *
23 * Notes:
8f961915 24 * Don't even pay lip service to multiprocessor support.
4bc66f7c 25 *
82043489
MH
26 * We assume TLB entries don't have process tags (except for the
27 * supervisor/user distinction) so we only invalidate TLB entries
28 * when changing mappings for the current (or kernel) pmap. This is
29 * technically not true for the 68551 but we flush the TLB on every
30 * context switch, so it effectively winds up that way.
31 *
32 * Bitwise and/or operations are significantly faster than bitfield
33 * references so we use them when accessing STE/PTEs in the pmap_pte_*
34 * macros. Note also that the two are not always equivalent; e.g.:
35 * (*(int *)pte & PG_PROT) [4] != pte->pg_prot [1]
36 * and a couple of routines that deal with protection and wiring take
37 * some shortcuts that assume the and/or definitions.
38 *
39 * This implementation will only work for PAGE_SIZE == NBPG
40 * (i.e. 4096 bytes).
8f961915
KM
41 */
42
43/*
44 * Manages physical address maps.
45 *
46 * In addition to hardware address maps, this
47 * module is called upon to provide software-use-only
48 * maps which may or may not be stored in the same
49 * form as hardware maps. These pseudo-maps are
50 * used to store intermediate results from copy
51 * operations to and from address spaces.
52 *
53 * Since the information managed by this module is
54 * also stored by the logical address mapping module,
55 * this module may throw away valid virtual-to-physical
56 * mappings at almost any time. However, invalidations
57 * of virtual-to-physical mappings must be done as
58 * requested.
59 *
60 * In order to cope with hardware architectures which
61 * make virtual-to-physical map invalidates expensive,
62 * this module may delay invalidate or reduced protection
63 * operations until such time as they are actually
64 * necessary. This module is given full information as
65 * to which processors are currently using which maps,
66 * and to when physical maps must be made correct.
67 */
68
38a01dbe
KB
69#include <sys/param.h>
70#include <sys/systm.h>
71#include <sys/proc.h>
72#include <sys/malloc.h>
73#include <sys/user.h>
8f961915 74
38a01dbe 75#include <hp300/hp300/pte.h>
8f961915 76
38a01dbe
KB
77#include <vm/vm.h>
78#include <vm/vm_kern.h>
79#include <vm/vm_page.h>
2059b854 80
38a01dbe 81#include <machine/cpu.h>
8f961915 82
82043489 83#ifdef PMAPSTATS
8f961915
KM
84struct {
85 int collectscans;
86 int collectpages;
87 int kpttotal;
88 int kptinuse;
89 int kptmaxuse;
90} kpt_stats;
91struct {
92 int kernel; /* entering kernel mapping */
93 int user; /* entering user mapping */
94 int ptpneeded; /* needed to allocate a PT page */
82043489 95 int nochange; /* no change at all */
8f961915
KM
96 int pwchange; /* no mapping change, just wiring or protection */
97 int wchange; /* no mapping change, just wiring */
82043489 98 int pchange; /* no mapping change, just protection */
8f961915
KM
99 int mchange; /* was mapped but mapping to different page */
100 int managed; /* a managed page */
101 int firstpv; /* first mapping for this PA */
102 int secondpv; /* second mapping for this PA */
103 int ci; /* cache inhibited */
104 int unmanaged; /* not a managed page */
105 int flushes; /* cache flushes */
106} enter_stats;
107struct {
108 int calls;
109 int removes;
110 int pvfirst;
111 int pvsearch;
112 int ptinvalid;
113 int uflushes;
114 int sflushes;
115} remove_stats;
9acfa6cd
MH
116struct {
117 int calls;
82043489 118 int changed;
9acfa6cd
MH
119 int alreadyro;
120 int alreadyrw;
121} protect_stats;
82043489
MH
122struct chgstats {
123 int setcalls;
124 int sethits;
125 int setmiss;
126 int clrcalls;
127 int clrhits;
128 int clrmiss;
129} changebit_stats[16];
130#endif
8f961915 131
82043489 132#ifdef DEBUG
8f961915
KM
133int debugmap = 0;
134int pmapdebug = 0x2000;
135#define PDB_FOLLOW 0x0001
136#define PDB_INIT 0x0002
137#define PDB_ENTER 0x0004
138#define PDB_REMOVE 0x0008
139#define PDB_CREATE 0x0010
140#define PDB_PTPAGE 0x0020
141#define PDB_CACHE 0x0040
142#define PDB_BITS 0x0080
143#define PDB_COLLECT 0x0100
144#define PDB_PROTECT 0x0200
145#define PDB_SEGTAB 0x0400
82043489 146#define PDB_MULTIMAP 0x0800
8f961915
KM
147#define PDB_PARANOIA 0x2000
148#define PDB_WIRING 0x4000
149#define PDB_PVDUMP 0x8000
150
82043489 151#ifdef HAVEVAC
8f961915
KM
152int pmapvacflush = 0;
153#define PVF_ENTER 0x01
154#define PVF_REMOVE 0x02
155#define PVF_PROTECT 0x04
156#define PVF_TOTAL 0x80
82043489 157#endif
4bc66f7c 158
9acfa6cd
MH
159#if defined(HP380)
160int dowriteback = 1; /* 68040: enable writeback caching */
161int dokwriteback = 1; /* 68040: enable writeback caching of kernel AS */
162#endif
163
4bc66f7c 164extern vm_offset_t pager_sva, pager_eva;
8f961915
KM
165#endif
166
167/*
168 * Get STEs and PTEs for user/kernel address space
169 */
9acfa6cd 170#if defined(HP380)
9acfa6cd
MH
171#define pmap_ste1(m, v) \
172 (&((m)->pm_stab[(vm_offset_t)(v) >> SG4_SHIFT1]))
173/* XXX assumes physically contiguous ST pages (if more than one) */
174#define pmap_ste2(m, v) \
175 (&((m)->pm_stab[(st_entry_t *)(*(u_int *)pmap_ste1(m, v) & SG4_ADDR1) \
176 - (m)->pm_stpa + (((v) & SG4_MASK2) >> SG4_SHIFT2)]))
82043489
MH
177#define pmap_ste(m, v) \
178 (&((m)->pm_stab[(vm_offset_t)(v) \
179 >> (mmutype == MMU_68040 ? SG4_SHIFT1 : SG_ISHIFT)]))
9acfa6cd
MH
180#define pmap_ste_v(m, v) \
181 (mmutype == MMU_68040 \
82043489
MH
182 ? ((*(int *)pmap_ste1(m, v) & SG_V) && \
183 (*(int *)pmap_ste2(m, v) & SG_V)) \
184 : (*(int *)pmap_ste(m, v) & SG_V))
9acfa6cd 185#else
82043489
MH
186#define pmap_ste(m, v) (&((m)->pm_stab[(vm_offset_t)(v) >> SG_ISHIFT]))
187#define pmap_ste_v(m, v) (*(int *)pmap_ste(m, v) & SG_V)
9acfa6cd 188#endif
8f961915 189
82043489 190#define pmap_pte(m, v) (&((m)->pm_ptab[(vm_offset_t)(v) >> PG_SHIFT]))
9acfa6cd 191#define pmap_pte_pa(pte) (*(int *)(pte) & PG_FRAME)
82043489
MH
192#define pmap_pte_w(pte) (*(int *)(pte) & PG_W)
193#define pmap_pte_ci(pte) (*(int *)(pte) & PG_CI)
194#define pmap_pte_m(pte) (*(int *)(pte) & PG_M)
195#define pmap_pte_u(pte) (*(int *)(pte) & PG_U)
196#define pmap_pte_prot(pte) (*(int *)(pte) & PG_PROT)
197#define pmap_pte_v(pte) (*(int *)(pte) & PG_V)
198
199#define pmap_pte_set_w(pte, v) \
200 if (v) *(int *)(pte) |= PG_W; else *(int *)(pte) &= ~PG_W
201#define pmap_pte_set_prot(pte, v) \
202 if (v) *(int *)(pte) |= PG_PROT; else *(int *)(pte) &= ~PG_PROT
203#define pmap_pte_w_chg(pte, nw) ((nw) ^ pmap_pte_w(pte))
204#define pmap_pte_prot_chg(pte, np) ((np) ^ pmap_pte_prot(pte))
8f961915
KM
205
206/*
207 * Given a map and a machine independent protection code,
82043489 208 * convert to an hp300 protection code.
8f961915
KM
209 */
210#define pte_prot(m, p) (protection_codes[p])
211int protection_codes[8];
212
213/*
214 * Kernel page table page management.
215 */
216struct kpt_page {
217 struct kpt_page *kpt_next; /* link on either used or free list */
218 vm_offset_t kpt_va; /* always valid kernel VA */
219 vm_offset_t kpt_pa; /* PA of this page (for speed) */
220};
221struct kpt_page *kpt_free_list, *kpt_used_list;
222struct kpt_page *kpt_pages;
223
224/*
225 * Kernel segment/page table and page table map.
226 * The page table map gives us a level of indirection we need to dynamically
227 * expand the page table. It is essentially a copy of the segment table
228 * with PTEs instead of STEs. All are initialized in locore at boot time.
229 * Sysmap will initially contain VM_KERNEL_PT_PAGES pages of PTEs.
230 * Segtabzero is an empty segment table which all processes share til they
231 * reference something.
232 */
233st_entry_t *Sysseg;
234pt_entry_t *Sysmap, *Sysptmap;
9acfa6cd 235st_entry_t *Segtabzero, *Segtabzeropa;
8f961915 236vm_size_t Sysptsize = VM_KERNEL_PT_PAGES;
8f961915
KM
237
238struct pmap kernel_pmap_store;
b55d9ecf 239vm_map_t st_map, pt_map;
8f961915
KM
240
241vm_offset_t avail_start; /* PA of first available physical page */
242vm_offset_t avail_end; /* PA of last available physical page */
243vm_size_t mem_size; /* memory size in bytes */
244vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss)*/
245vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */
246vm_offset_t vm_first_phys; /* PA of first managed page */
247vm_offset_t vm_last_phys; /* PA just past last managed page */
8f961915 248boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */
8f961915 249char *pmap_attributes; /* reference and modify bits */
82043489
MH
250#ifdef HAVEVAC
251int pmap_aliasmask; /* seperation at which VA aliasing ok */
252#endif
9acfa6cd 253#if defined(HP380)
82043489
MH
254int protostfree; /* prototype (default) free ST map */
255#endif
256
257/*
258 * Internal routines
259 */
260void pmap_remove_mapping __P((pmap_t, vm_offset_t, pt_entry_t *, int));
261boolean_t pmap_testbit __P((vm_offset_t, int));
262void pmap_changebit __P((vm_offset_t, int, boolean_t));
263void pmap_enter_ptpage __P((pmap_t, vm_offset_t));
264#ifdef DEBUG
265void pmap_pvdump __P((vm_offset_t));
266void pmap_check_wiring __P((char *, vm_offset_t));
9acfa6cd 267#endif
8f961915 268
82043489
MH
269/* pmap_remove_mapping flags */
270#define PRM_TFLUSH 1
271#define PRM_CFLUSH 2
8f961915 272
fd518746
WN
273/*
274 * Bootstrap memory allocator. This function allows for early dynamic
275 * memory allocation until the virtual memory system has been bootstrapped.
276 * After that point, either kmem_alloc or malloc should be used. This
277 * function works by stealing pages from the (to be) managed page pool,
278 * stealing virtual address space, then mapping the pages and zeroing them.
279 *
280 * It should be used from pmap_bootstrap till vm_page_startup, afterwards
281 * it cannot be used, and will generate a panic if tried. Note that this
282 * memory will never be freed, and in essence it is wired down.
283 */
284void *
8928c38a
KB
285pmap_bootstrap_alloc(size)
286 int size;
287{
fd518746 288 extern boolean_t vm_page_startup_initialized;
8928c38a 289 vm_offset_t val;
fd518746
WN
290
291 if (vm_page_startup_initialized)
292 panic("pmap_bootstrap_alloc: called after startup initialized");
293 size = round_page(size);
294 val = virtual_avail;
295
296 virtual_avail = pmap_map(virtual_avail, avail_start,
297 avail_start + size, VM_PROT_READ|VM_PROT_WRITE);
298 avail_start += size;
299
300 blkclr ((caddr_t) val, size);
301 return ((void *) val);
302}
303
8f961915
KM
304/*
305 * Initialize the pmap module.
306 * Called by vm_init, to initialize any structures that the pmap
307 * system needs to map virtual memory.
308 */
309void
310pmap_init(phys_start, phys_end)
311 vm_offset_t phys_start, phys_end;
312{
313 vm_offset_t addr, addr2;
314 vm_size_t npg, s;
315 int rv;
a1af79ae 316 extern char kstack[];
8f961915
KM
317
318#ifdef DEBUG
319 if (pmapdebug & PDB_FOLLOW)
320 printf("pmap_init(%x, %x)\n", phys_start, phys_end);
321#endif
322 /*
323 * Now that kernel map has been allocated, we can mark as
324 * unavailable regions which we have mapped in locore.
325 */
4bc66f7c 326 addr = (vm_offset_t) intiobase;
2059b854 327 (void) vm_map_find(kernel_map, NULL, (vm_offset_t) 0,
4bc66f7c
MH
328 &addr, hp300_ptob(IIOMAPSIZE+EIOMAPSIZE), FALSE);
329 if (addr != (vm_offset_t)intiobase)
8f961915
KM
330 goto bogons;
331 addr = (vm_offset_t) Sysmap;
332 vm_object_reference(kernel_object);
333 (void) vm_map_find(kernel_map, kernel_object, addr,
334 &addr, HP_MAX_PTSIZE, FALSE);
335 /*
336 * If this fails it is probably because the static portion of
337 * the kernel page table isn't big enough and we overran the
338 * page table map. Need to adjust pmap_size() in hp300_init.c.
339 */
340 if (addr != (vm_offset_t)Sysmap)
341 goto bogons;
342
a1af79ae 343 addr = (vm_offset_t) kstack;
8f961915
KM
344 vm_object_reference(kernel_object);
345 (void) vm_map_find(kernel_map, kernel_object, addr,
346 &addr, hp300_ptob(UPAGES), FALSE);
a1af79ae 347 if (addr != (vm_offset_t)kstack)
8f961915
KM
348bogons:
349 panic("pmap_init: bogons in the VM system!\n");
350
351#ifdef DEBUG
352 if (pmapdebug & PDB_INIT) {
353 printf("pmap_init: Sysseg %x, Sysmap %x, Sysptmap %x\n",
354 Sysseg, Sysmap, Sysptmap);
355 printf(" pstart %x, pend %x, vstart %x, vend %x\n",
356 avail_start, avail_end, virtual_avail, virtual_end);
357 }
358#endif
359
360 /*
361 * Allocate memory for random pmap data structures. Includes the
362 * initial segment table, pv_head_table and pmap_attributes.
363 */
364 npg = atop(phys_end - phys_start);
365 s = (vm_size_t) (HP_STSIZE + sizeof(struct pv_entry) * npg + npg);
366 s = round_page(s);
367 addr = (vm_offset_t) kmem_alloc(kernel_map, s);
368 Segtabzero = (st_entry_t *) addr;
9acfa6cd 369 Segtabzeropa = (st_entry_t *) pmap_extract(kernel_pmap, addr);
8f961915
KM
370 addr += HP_STSIZE;
371 pv_table = (pv_entry_t) addr;
372 addr += sizeof(struct pv_entry) * npg;
373 pmap_attributes = (char *) addr;
374#ifdef DEBUG
375 if (pmapdebug & PDB_INIT)
9acfa6cd
MH
376 printf("pmap_init: %x bytes: npg %x s0 %x(%x) tbl %x atr %x\n",
377 s, npg, Segtabzero, Segtabzeropa,
378 pv_table, pmap_attributes);
8f961915
KM
379#endif
380
381 /*
382 * Allocate physical memory for kernel PT pages and their management.
383 * We need 1 PT page per possible task plus some slop.
384 */
2059b854 385 npg = min(atop(HP_MAX_KPTSIZE), maxproc+16);
8f961915
KM
386 s = ptoa(npg) + round_page(npg * sizeof(struct kpt_page));
387
388 /*
389 * Verify that space will be allocated in region for which
390 * we already have kernel PT pages.
391 */
392 addr = 0;
2059b854 393 rv = vm_map_find(kernel_map, NULL, 0, &addr, s, TRUE);
8f961915
KM
394 if (rv != KERN_SUCCESS || addr + s >= (vm_offset_t)Sysmap)
395 panic("pmap_init: kernel PT too small");
396 vm_map_remove(kernel_map, addr, addr + s);
397
398 /*
399 * Now allocate the space and link the pages together to
400 * form the KPT free list.
401 */
402 addr = (vm_offset_t) kmem_alloc(kernel_map, s);
403 s = ptoa(npg);
404 addr2 = addr + s;
405 kpt_pages = &((struct kpt_page *)addr2)[npg];
406 kpt_free_list = (struct kpt_page *) 0;
407 do {
408 addr2 -= HP_PAGE_SIZE;
409 (--kpt_pages)->kpt_next = kpt_free_list;
410 kpt_free_list = kpt_pages;
411 kpt_pages->kpt_va = addr2;
412 kpt_pages->kpt_pa = pmap_extract(kernel_pmap, addr2);
413 } while (addr != addr2);
82043489 414#ifdef PMAPSTATS
8f961915 415 kpt_stats.kpttotal = atop(s);
82043489
MH
416#endif
417#ifdef DEBUG
8f961915
KM
418 if (pmapdebug & PDB_INIT)
419 printf("pmap_init: KPT: %d pages from %x to %x\n",
420 atop(s), addr, addr + s);
421#endif
422
b55d9ecf
MH
423 /*
424 * Allocate the segment table map
425 */
426 s = maxproc * HP_STSIZE;
427 st_map = kmem_suballoc(kernel_map, &addr, &addr2, s, TRUE);
428
8f961915
KM
429 /*
430 * Slightly modified version of kmem_suballoc() to get page table
431 * map where we want it.
432 */
433 addr = HP_PTBASE;
2059b854 434 s = min(HP_PTMAXSIZE, maxproc*HP_MAX_PTSIZE);
8f961915 435 addr2 = addr + s;
2059b854 436 rv = vm_map_find(kernel_map, NULL, 0, &addr, s, TRUE);
8f961915
KM
437 if (rv != KERN_SUCCESS)
438 panic("pmap_init: cannot allocate space for PT map");
439 pmap_reference(vm_map_pmap(kernel_map));
440 pt_map = vm_map_create(vm_map_pmap(kernel_map), addr, addr2, TRUE);
2059b854 441 if (pt_map == NULL)
8f961915
KM
442 panic("pmap_init: cannot create pt_map");
443 rv = vm_map_submap(kernel_map, addr, addr2, pt_map);
444 if (rv != KERN_SUCCESS)
445 panic("pmap_init: cannot map range to pt_map");
446#ifdef DEBUG
447 if (pmapdebug & PDB_INIT)
448 printf("pmap_init: pt_map [%x - %x)\n", addr, addr2);
449#endif
450
9acfa6cd
MH
451#if defined(HP380)
452 if (mmutype == MMU_68040) {
453 protostfree = ~l2tobm(0);
454 for (rv = MAXUL2SIZE; rv < sizeof(protostfree)*NBBY; rv++)
455 protostfree &= ~l2tobm(rv);
456 }
457#endif
458
8f961915
KM
459 /*
460 * Now it is safe to enable pv_table recording.
461 */
462 vm_first_phys = phys_start;
463 vm_last_phys = phys_end;
464 pmap_initialized = TRUE;
465}
466
467/*
468 * Used to map a range of physical addresses into kernel
469 * virtual address space.
470 *
471 * For now, VM is already on, we only need to map the
472 * specified memory.
473 */
474vm_offset_t
475pmap_map(virt, start, end, prot)
476 vm_offset_t virt;
477 vm_offset_t start;
478 vm_offset_t end;
479 int prot;
480{
481#ifdef DEBUG
482 if (pmapdebug & PDB_FOLLOW)
483 printf("pmap_map(%x, %x, %x, %x)\n", virt, start, end, prot);
484#endif
485 while (start < end) {
486 pmap_enter(kernel_pmap, virt, start, prot, FALSE);
487 virt += PAGE_SIZE;
488 start += PAGE_SIZE;
489 }
490 return(virt);
491}
492
493/*
494 * Create and return a physical map.
495 *
496 * If the size specified for the map
497 * is zero, the map is an actual physical
498 * map, and may be referenced by the
499 * hardware.
500 *
501 * If the size specified is non-zero,
502 * the map will be used in software only, and
503 * is bounded by that size.
504 */
505pmap_t
506pmap_create(size)
507 vm_size_t size;
508{
509 register pmap_t pmap;
510
511#ifdef DEBUG
512 if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
513 printf("pmap_create(%x)\n", size);
514#endif
515 /*
516 * Software use map does not need a pmap
517 */
518 if (size)
2059b854 519 return(NULL);
8f961915
KM
520
521 /* XXX: is it ok to wait here? */
522 pmap = (pmap_t) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK);
2059b854
MK
523#ifdef notifwewait
524 if (pmap == NULL)
8f961915 525 panic("pmap_create: cannot allocate a pmap");
2059b854
MK
526#endif
527 bzero(pmap, sizeof(*pmap));
528 pmap_pinit(pmap);
529 return (pmap);
530}
8f961915 531
2059b854
MK
532/*
533 * Initialize a preallocated and zeroed pmap structure,
534 * such as one in a vmspace structure.
535 */
536void
537pmap_pinit(pmap)
538 register struct pmap *pmap;
539{
540
541#ifdef DEBUG
542 if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
543 printf("pmap_pinit(%x)\n", pmap);
544#endif
8f961915
KM
545 /*
546 * No need to allocate page table space yet but we do need a
547 * valid segment table. Initially, we point everyone at the
548 * "null" segment table. On the first pmap_enter, a real
549 * segment table will be allocated.
550 */
8f961915 551 pmap->pm_stab = Segtabzero;
9acfa6cd
MH
552 pmap->pm_stpa = Segtabzeropa;
553#if defined(HP380)
554 if (mmutype == MMU_68040)
555 pmap->pm_stfree = protostfree;
556#endif
8f961915 557 pmap->pm_stchanged = TRUE;
8f961915
KM
558 pmap->pm_count = 1;
559 simple_lock_init(&pmap->pm_lock);
8f961915
KM
560}
561
562/*
563 * Retire the given physical map from service.
564 * Should only be called if the map contains
565 * no valid mappings.
566 */
567void
568pmap_destroy(pmap)
569 register pmap_t pmap;
570{
571 int count;
572
573#ifdef DEBUG
574 if (pmapdebug & PDB_FOLLOW)
575 printf("pmap_destroy(%x)\n", pmap);
576#endif
2059b854 577 if (pmap == NULL)
8f961915
KM
578 return;
579
580 simple_lock(&pmap->pm_lock);
581 count = --pmap->pm_count;
582 simple_unlock(&pmap->pm_lock);
2059b854
MK
583 if (count == 0) {
584 pmap_release(pmap);
585 free((caddr_t)pmap, M_VMPMAP);
586 }
587}
8f961915 588
2059b854
MK
589/*
590 * Release any resources held by the given physical map.
591 * Called when a pmap initialized by pmap_pinit is being released.
592 * Should only be called if the map contains no valid mappings.
593 */
594void
595pmap_release(pmap)
596 register struct pmap *pmap;
597{
598
599#ifdef DEBUG
600 if (pmapdebug & PDB_FOLLOW)
601 printf("pmap_release(%x)\n", pmap);
602#endif
603#ifdef notdef /* DIAGNOSTIC */
604 /* count would be 0 from pmap_destroy... */
605 simple_lock(&pmap->pm_lock);
606 if (pmap->pm_count != 1)
607 panic("pmap_release count");
608#endif
8f961915
KM
609 if (pmap->pm_ptab)
610 kmem_free_wakeup(pt_map, (vm_offset_t)pmap->pm_ptab,
611 HP_MAX_PTSIZE);
612 if (pmap->pm_stab != Segtabzero)
b55d9ecf
MH
613 kmem_free_wakeup(st_map, (vm_offset_t)pmap->pm_stab,
614 HP_STSIZE);
8f961915
KM
615}
616
617/*
618 * Add a reference to the specified pmap.
619 */
620void
621pmap_reference(pmap)
622 pmap_t pmap;
623{
624#ifdef DEBUG
625 if (pmapdebug & PDB_FOLLOW)
626 printf("pmap_reference(%x)\n", pmap);
627#endif
2059b854 628 if (pmap != NULL) {
8f961915
KM
629 simple_lock(&pmap->pm_lock);
630 pmap->pm_count++;
631 simple_unlock(&pmap->pm_lock);
632 }
633}
634
635/*
636 * Remove the given range of addresses from the specified map.
637 *
638 * It is assumed that the start and end are properly
639 * rounded to the page size.
640 */
641void
642pmap_remove(pmap, sva, eva)
643 register pmap_t pmap;
82043489 644 register vm_offset_t sva, eva;
8f961915 645{
82043489 646 register vm_offset_t nssva;
8f961915 647 register pt_entry_t *pte;
82043489
MH
648 boolean_t firstpage, needcflush;
649 int flags;
8f961915 650
82043489 651#ifdef DEBUG
8f961915
KM
652 if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT))
653 printf("pmap_remove(%x, %x, %x)\n", pmap, sva, eva);
654#endif
655
2059b854 656 if (pmap == NULL)
8f961915
KM
657 return;
658
82043489 659#ifdef PMAPSTATS
8f961915
KM
660 remove_stats.calls++;
661#endif
82043489
MH
662 firstpage = TRUE;
663 needcflush = FALSE;
664 flags = active_pmap(pmap) ? PRM_TFLUSH : 0;
665 while (sva < eva) {
666 nssva = hp300_trunc_seg(sva) + HP_SEG_SIZE;
667 if (nssva == 0 || nssva > eva)
668 nssva = eva;
8f961915 669 /*
82043489
MH
670 * If VA belongs to an unallocated segment,
671 * skip to the next segment boundary.
8f961915 672 */
82043489
MH
673 if (!pmap_ste_v(pmap, sva)) {
674 sva = nssva;
8f961915 675 continue;
8f961915 676 }
8f961915 677 /*
82043489 678 * Invalidate every valid mapping within this segment.
8f961915 679 */
82043489
MH
680 pte = pmap_pte(pmap, sva);
681 while (sva < nssva) {
682 if (pmap_pte_v(pte)) {
683#ifdef HAVEVAC
684 if (pmap_aliasmask) {
685 /*
686 * Purge kernel side of VAC to ensure
687 * we get the correct state of any
688 * hardware maintained bits.
689 */
690 if (firstpage) {
691 DCIS();
692#ifdef PMAPSTATS
693 remove_stats.sflushes++;
9acfa6cd 694#endif
82043489 695 }
8f961915 696 /*
82043489
MH
697 * Remember if we may need to
698 * flush the VAC due to a non-CI
699 * mapping.
8f961915 700 */
82043489
MH
701 if (!needcflush && !pmap_pte_ci(pte))
702 needcflush = TRUE;
703
8f961915 704 }
82043489
MH
705#endif
706 pmap_remove_mapping(pmap, sva, pte, flags);
707 firstpage = FALSE;
8f961915 708 }
82043489
MH
709 pte++;
710 sva += PAGE_SIZE;
8f961915 711 }
8f961915 712 }
82043489
MH
713 /*
714 * Didn't do anything, no need for cache flushes
715 */
716 if (firstpage)
717 return;
718#ifdef HAVEVAC
719 /*
720 * In a couple of cases, we don't need to worry about flushing
721 * the VAC:
722 * 1. if this is a kernel mapping,
723 * we have already done it
724 * 2. if it is a user mapping not for the current process,
725 * it won't be there
726 */
727 if (pmap_aliasmask &&
728 (pmap == kernel_pmap || pmap != curproc->p_vmspace->vm_map.pmap))
729 needcflush = FALSE;
8f961915 730#ifdef DEBUG
82043489 731 if (pmap_aliasmask && (pmapvacflush & PVF_REMOVE)) {
8f961915
KM
732 if (pmapvacflush & PVF_TOTAL)
733 DCIA();
734 else if (pmap == kernel_pmap)
735 DCIS();
736 else
737 DCIU();
82043489 738 } else
8f961915 739#endif
82043489 740 if (needcflush) {
8f961915
KM
741 if (pmap == kernel_pmap) {
742 DCIS();
82043489 743#ifdef PMAPSTATS
8f961915
KM
744 remove_stats.sflushes++;
745#endif
746 } else {
747 DCIU();
82043489 748#ifdef PMAPSTATS
8f961915
KM
749 remove_stats.uflushes++;
750#endif
751 }
752 }
82043489 753#endif
8f961915
KM
754}
755
756/*
4bc66f7c
MH
757 * pmap_page_protect:
758 *
759 * Lower the permission for all mappings to a given page.
8f961915
KM
760 */
761void
4bc66f7c
MH
762pmap_page_protect(pa, prot)
763 vm_offset_t pa;
764 vm_prot_t prot;
8f961915
KM
765{
766 register pv_entry_t pv;
767 int s;
768
769#ifdef DEBUG
4bc66f7c
MH
770 if ((pmapdebug & (PDB_FOLLOW|PDB_PROTECT)) ||
771 prot == VM_PROT_NONE && (pmapdebug & PDB_REMOVE))
772 printf("pmap_page_protect(%x, %x)\n", pa, prot);
8f961915 773#endif
8f961915
KM
774 if (pa < vm_first_phys || pa >= vm_last_phys)
775 return;
776
4bc66f7c 777 switch (prot) {
82043489 778 case VM_PROT_READ|VM_PROT_WRITE:
4bc66f7c 779 case VM_PROT_ALL:
599b6bd7 780 return;
4bc66f7c
MH
781 /* copy_on_write */
782 case VM_PROT_READ:
783 case VM_PROT_READ|VM_PROT_EXECUTE:
784 pmap_changebit(pa, PG_RO, TRUE);
599b6bd7 785 return;
4bc66f7c
MH
786 /* remove_all */
787 default:
599b6bd7
MH
788 break;
789 }
790 pv = pa_to_pvh(pa);
791 s = splimp();
792 while (pv->pv_pmap != NULL) {
793 register pt_entry_t *pte;
794
795 pte = pmap_pte(pv->pv_pmap, pv->pv_va);
8f961915 796#ifdef DEBUG
599b6bd7
MH
797 if (!pmap_ste_v(pv->pv_pmap, pv->pv_va) ||
798 pmap_pte_pa(pte) != pa)
799 panic("pmap_page_protect: bad mapping");
8f961915 800#endif
599b6bd7 801 if (!pmap_pte_w(pte))
82043489 802 pmap_remove_mapping(pv->pv_pmap, pv->pv_va,
599b6bd7
MH
803 pte, PRM_TFLUSH|PRM_CFLUSH);
804 else {
805 pv = pv->pv_next;
806#ifdef DEBUG
807 if (pmapdebug & PDB_PARANOIA)
808 printf("%s wired mapping for %x not removed\n",
809 "pmap_page_protect:", pa);
810#endif
4bc66f7c 811 }
8f961915 812 }
599b6bd7 813 splx(s);
8f961915
KM
814}
815
816/*
817 * Set the physical protection on the
818 * specified range of this map as requested.
819 */
820void
821pmap_protect(pmap, sva, eva, prot)
822 register pmap_t pmap;
82043489
MH
823 register vm_offset_t sva, eva;
824 vm_prot_t prot;
8f961915 825{
82043489 826 register vm_offset_t nssva;
8f961915 827 register pt_entry_t *pte;
82043489
MH
828 boolean_t firstpage, needtflush;
829 int isro;
8f961915
KM
830
831#ifdef DEBUG
832 if (pmapdebug & (PDB_FOLLOW|PDB_PROTECT))
833 printf("pmap_protect(%x, %x, %x, %x)\n", pmap, sva, eva, prot);
834#endif
82043489 835
2059b854 836 if (pmap == NULL)
8f961915
KM
837 return;
838
82043489
MH
839#ifdef PMAPSTATS
840 protect_stats.calls++;
841#endif
8f961915
KM
842 if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
843 pmap_remove(pmap, sva, eva);
844 return;
845 }
846 if (prot & VM_PROT_WRITE)
847 return;
848
82043489
MH
849 isro = pte_prot(pmap, prot);
850 needtflush = active_pmap(pmap);
851 firstpage = TRUE;
852 while (sva < eva) {
853 nssva = hp300_trunc_seg(sva) + HP_SEG_SIZE;
854 if (nssva == 0 || nssva > eva)
855 nssva = eva;
8f961915 856 /*
82043489
MH
857 * If VA belongs to an unallocated segment,
858 * skip to the next segment boundary.
8f961915 859 */
82043489
MH
860 if (!pmap_ste_v(pmap, sva)) {
861 sva = nssva;
8f961915
KM
862 continue;
863 }
864 /*
82043489
MH
865 * Change protection on mapping if it is valid and doesn't
866 * already have the correct protection.
8f961915 867 */
82043489
MH
868 pte = pmap_pte(pmap, sva);
869 while (sva < nssva) {
870 if (pmap_pte_v(pte) && pmap_pte_prot_chg(pte, isro)) {
871#ifdef HAVEVAC
9acfa6cd 872 /*
82043489
MH
873 * Purge kernel side of VAC to ensure we
874 * get the correct state of any hardware
875 * maintained bits.
876 *
877 * XXX do we need to clear the VAC in
878 * general to reflect the new protection?
9acfa6cd 879 */
82043489
MH
880 if (firstpage && pmap_aliasmask)
881 DCIS();
882#endif
9acfa6cd 883#if defined(HP380)
82043489
MH
884 /*
885 * Clear caches if making RO (see section
886 * "7.3 Cache Coherency" in the manual).
887 */
888 if (isro && mmutype == MMU_68040) {
9acfa6cd
MH
889 vm_offset_t pa = pmap_pte_pa(pte);
890
82043489
MH
891 DCFP(pa);
892 ICPP(pa);
9acfa6cd
MH
893 }
894#endif
82043489
MH
895 pmap_pte_set_prot(pte, isro);
896 if (needtflush)
897 TBIS(sva);
898#ifdef PMAPSTATS
899 protect_stats.changed++;
900#endif
901 firstpage = FALSE;
902 }
903#ifdef PMAPSTATS
904 else if (pmap_pte_v(pte)) {
905 if (isro)
9acfa6cd 906 protect_stats.alreadyro++;
82043489 907 else
9acfa6cd 908 protect_stats.alreadyrw++;
9acfa6cd 909 }
9acfa6cd 910#endif
82043489
MH
911 pte++;
912 sva += PAGE_SIZE;
913 }
8f961915 914 }
82043489
MH
915#if defined(HAVEVAC) && defined(DEBUG)
916 if (pmap_aliasmask && (pmapvacflush & PVF_PROTECT)) {
8f961915
KM
917 if (pmapvacflush & PVF_TOTAL)
918 DCIA();
919 else if (pmap == kernel_pmap)
920 DCIS();
921 else
922 DCIU();
923 }
924#endif
925}
926
927/*
928 * Insert the given physical page (p) at
929 * the specified virtual address (v) in the
930 * target physical map with the protection requested.
931 *
932 * If specified, the page will be wired down, meaning
933 * that the related pte can not be reclaimed.
934 *
935 * NB: This is the only routine which MAY NOT lazy-evaluate
936 * or lose information. That is, this routine must actually
937 * insert this page into the given map NOW.
938 */
939void
940pmap_enter(pmap, va, pa, prot, wired)
941 register pmap_t pmap;
942 vm_offset_t va;
943 register vm_offset_t pa;
944 vm_prot_t prot;
945 boolean_t wired;
946{
947 register pt_entry_t *pte;
9acfa6cd 948 register int npte;
8f961915
KM
949 vm_offset_t opa;
950 boolean_t cacheable = TRUE;
951 boolean_t checkpv = TRUE;
952
953#ifdef DEBUG
954 if (pmapdebug & (PDB_FOLLOW|PDB_ENTER))
955 printf("pmap_enter(%x, %x, %x, %x, %x)\n",
956 pmap, va, pa, prot, wired);
957#endif
2059b854 958 if (pmap == NULL)
8f961915
KM
959 return;
960
82043489 961#ifdef PMAPSTATS
8f961915
KM
962 if (pmap == kernel_pmap)
963 enter_stats.kernel++;
964 else
965 enter_stats.user++;
966#endif
967 /*
968 * For user mapping, allocate kernel VM resources if necessary.
969 */
2059b854 970 if (pmap->pm_ptab == NULL)
8f961915
KM
971 pmap->pm_ptab = (pt_entry_t *)
972 kmem_alloc_wait(pt_map, HP_MAX_PTSIZE);
973
974 /*
975 * Segment table entry not valid, we need a new PT page
976 */
9acfa6cd 977 if (!pmap_ste_v(pmap, va))
8f961915
KM
978 pmap_enter_ptpage(pmap, va);
979
82043489 980 pa = hp300_trunc_page(pa);
8f961915
KM
981 pte = pmap_pte(pmap, va);
982 opa = pmap_pte_pa(pte);
983#ifdef DEBUG
984 if (pmapdebug & PDB_ENTER)
985 printf("enter: pte %x, *pte %x\n", pte, *(int *)pte);
986#endif
987
988 /*
989 * Mapping has not changed, must be protection or wiring change.
990 */
991 if (opa == pa) {
82043489 992#ifdef PMAPSTATS
8f961915
KM
993 enter_stats.pwchange++;
994#endif
995 /*
996 * Wiring change, just update stats.
997 * We don't worry about wiring PT pages as they remain
998 * resident as long as there are valid mappings in them.
999 * Hence, if a user page is wired, the PT page will be also.
1000 */
82043489 1001 if (pmap_pte_w_chg(pte, wired ? PG_W : 0)) {
8f961915
KM
1002#ifdef DEBUG
1003 if (pmapdebug & PDB_ENTER)
1004 printf("enter: wiring change -> %x\n", wired);
1005#endif
1006 if (wired)
1007 pmap->pm_stats.wired_count++;
1008 else
1009 pmap->pm_stats.wired_count--;
82043489
MH
1010#ifdef PMAPSTATS
1011 if (pmap_pte_prot(pte) == pte_prot(pmap, prot))
1012 enter_stats.wchange++;
8f961915
KM
1013#endif
1014 }
82043489
MH
1015#ifdef PMAPSTATS
1016 else if (pmap_pte_prot(pte) != pte_prot(pmap, prot))
1017 enter_stats.pchange++;
1018 else
1019 enter_stats.nochange++;
1020#endif
8f961915
KM
1021 /*
1022 * Retain cache inhibition status
1023 */
1024 checkpv = FALSE;
1025 if (pmap_pte_ci(pte))
1026 cacheable = FALSE;
1027 goto validate;
1028 }
1029
1030 /*
1031 * Mapping has changed, invalidate old range and fall through to
1032 * handle validating new mapping.
1033 */
1034 if (opa) {
1035#ifdef DEBUG
1036 if (pmapdebug & PDB_ENTER)
1037 printf("enter: removing old mapping %x\n", va);
1038#endif
82043489
MH
1039 pmap_remove_mapping(pmap, va, pte, PRM_TFLUSH|PRM_CFLUSH);
1040#ifdef PMAPSTATS
8f961915
KM
1041 enter_stats.mchange++;
1042#endif
1043 }
1044
1045 /*
1046 * If this is a new user mapping, increment the wiring count
1047 * on this PT page. PT pages are wired down as long as there
1048 * is a valid mapping in the page.
1049 */
1050 if (pmap != kernel_pmap)
ab614754
MH
1051 (void) vm_map_pageable(pt_map, trunc_page(pte),
1052 round_page(pte+1), FALSE);
8f961915
KM
1053
1054 /*
1055 * Enter on the PV list if part of our managed memory
1056 * Note that we raise IPL while manipulating pv_table
1057 * since pmap_enter can be called at interrupt time.
1058 */
1059 if (pa >= vm_first_phys && pa < vm_last_phys) {
1060 register pv_entry_t pv, npv;
1061 int s;
1062
82043489 1063#ifdef PMAPSTATS
8f961915
KM
1064 enter_stats.managed++;
1065#endif
1066 pv = pa_to_pvh(pa);
1067 s = splimp();
1068#ifdef DEBUG
1069 if (pmapdebug & PDB_ENTER)
1070 printf("enter: pv at %x: %x/%x/%x\n",
1071 pv, pv->pv_va, pv->pv_pmap, pv->pv_next);
1072#endif
1073 /*
1074 * No entries yet, use header as the first entry
1075 */
2059b854 1076 if (pv->pv_pmap == NULL) {
82043489 1077#ifdef PMAPSTATS
8f961915
KM
1078 enter_stats.firstpv++;
1079#endif
1080 pv->pv_va = va;
1081 pv->pv_pmap = pmap;
2059b854
MK
1082 pv->pv_next = NULL;
1083 pv->pv_ptste = NULL;
1084 pv->pv_ptpmap = NULL;
8f961915
KM
1085 pv->pv_flags = 0;
1086 }
1087 /*
1088 * There is at least one other VA mapping this page.
1089 * Place this entry after the header.
1090 */
1091 else {
1092#ifdef DEBUG
1093 for (npv = pv; npv; npv = npv->pv_next)
1094 if (pmap == npv->pv_pmap && va == npv->pv_va)
1095 panic("pmap_enter: already in pv_tab");
1096#endif
1097 npv = (pv_entry_t)
1098 malloc(sizeof *npv, M_VMPVENT, M_NOWAIT);
1099 npv->pv_va = va;
1100 npv->pv_pmap = pmap;
1101 npv->pv_next = pv->pv_next;
2059b854
MK
1102 npv->pv_ptste = NULL;
1103 npv->pv_ptpmap = NULL;
82043489 1104 npv->pv_flags = 0;
8f961915 1105 pv->pv_next = npv;
82043489 1106#ifdef PMAPSTATS
8f961915
KM
1107 if (!npv->pv_next)
1108 enter_stats.secondpv++;
1109#endif
82043489 1110#ifdef HAVEVAC
8f961915
KM
1111 /*
1112 * Since there is another logical mapping for the
1113 * same page we may need to cache-inhibit the
1114 * descriptors on those CPUs with external VACs.
1115 * We don't need to CI if:
1116 *
1117 * - No two mappings belong to the same user pmaps.
1118 * Since the cache is flushed on context switches
1119 * there is no problem between user processes.
1120 *
1121 * - Mappings within a single pmap are a certain
1122 * magic distance apart. VAs at these appropriate
1123 * boundaries map to the same cache entries or
1124 * otherwise don't conflict.
1125 *
1126 * To keep it simple, we only check for these special
1127 * cases if there are only two mappings, otherwise we
1128 * punt and always CI.
1129 *
1130 * Note that there are no aliasing problems with the
1131 * on-chip data-cache when the WA bit is set.
1132 */
1133 if (pmap_aliasmask) {
1134 if (pv->pv_flags & PV_CI) {
1135#ifdef DEBUG
1136 if (pmapdebug & PDB_CACHE)
1137 printf("enter: pa %x already CI'ed\n",
1138 pa);
1139#endif
1140 checkpv = cacheable = FALSE;
1141 } else if (npv->pv_next ||
1142 ((pmap == pv->pv_pmap ||
1143 pmap == kernel_pmap ||
1144 pv->pv_pmap == kernel_pmap) &&
1145 ((pv->pv_va & pmap_aliasmask) !=
1146 (va & pmap_aliasmask)))) {
1147#ifdef DEBUG
1148 if (pmapdebug & PDB_CACHE)
1149 printf("enter: pa %x CI'ing all\n",
1150 pa);
1151#endif
1152 cacheable = FALSE;
1153 pv->pv_flags |= PV_CI;
82043489 1154#ifdef PMAPSTATS
8f961915
KM
1155 enter_stats.ci++;
1156#endif
1157 }
1158 }
82043489 1159#endif
8f961915
KM
1160 }
1161 splx(s);
1162 }
1163 /*
1164 * Assumption: if it is not part of our managed memory
1165 * then it must be device memory which may be volitile.
1166 */
1167 else if (pmap_initialized) {
1168 checkpv = cacheable = FALSE;
82043489 1169#ifdef PMAPSTATS
8f961915
KM
1170 enter_stats.unmanaged++;
1171#endif
1172 }
1173
1174 /*
1175 * Increment counters
1176 */
1177 pmap->pm_stats.resident_count++;
1178 if (wired)
1179 pmap->pm_stats.wired_count++;
1180
1181validate:
82043489 1182#ifdef HAVEVAC
8f961915 1183 /*
9acfa6cd
MH
1184 * Purge kernel side of VAC to ensure we get correct state
1185 * of HW bits so we don't clobber them.
8f961915
KM
1186 */
1187 if (pmap_aliasmask)
1188 DCIS();
82043489 1189#endif
8f961915 1190 /*
82043489 1191 * Build the new PTE.
8f961915 1192 */
82043489 1193 npte = pa | pte_prot(pmap, prot) | (*(int *)pte & (PG_M|PG_U)) | PG_V;
8f961915
KM
1194 if (wired)
1195 npte |= PG_W;
1196 if (!checkpv && !cacheable)
1197 npte |= PG_CI;
9acfa6cd
MH
1198#if defined(HP380)
1199 if (mmutype == MMU_68040 && (npte & (PG_PROT|PG_CI)) == PG_RW)
1200#ifdef DEBUG
1201 if (dowriteback && (dokwriteback || pmap != kernel_pmap))
1202#endif
1203 npte |= PG_CCB;
1204#endif
8f961915
KM
1205#ifdef DEBUG
1206 if (pmapdebug & PDB_ENTER)
1207 printf("enter: new pte value %x\n", npte);
1208#endif
82043489
MH
1209 /*
1210 * Remember if this was a wiring-only change.
1211 * If so, we need not flush the TLB and caches.
1212 */
1213 wired = ((*(int *)pte ^ npte) == PG_W);
9acfa6cd 1214#if defined(HP380)
82043489 1215 if (mmutype == MMU_68040 && !wired) {
9acfa6cd
MH
1216 DCFP(pa);
1217 ICPP(pa);
1218 }
1219#endif
1220 *(int *)pte = npte;
82043489
MH
1221 if (!wired && active_pmap(pmap))
1222 TBIS(va);
1223#ifdef HAVEVAC
8f961915
KM
1224 /*
1225 * The following is executed if we are entering a second
1226 * (or greater) mapping for a physical page and the mappings
1227 * may create an aliasing problem. In this case we must
1228 * cache inhibit the descriptors involved and flush any
1229 * external VAC.
1230 */
1231 if (checkpv && !cacheable) {
1232 pmap_changebit(pa, PG_CI, TRUE);
1233 DCIA();
82043489 1234#ifdef PMAPSTATS
8f961915
KM
1235 enter_stats.flushes++;
1236#endif
1237#ifdef DEBUG
1238 if ((pmapdebug & (PDB_CACHE|PDB_PVDUMP)) ==
1239 (PDB_CACHE|PDB_PVDUMP))
1240 pmap_pvdump(pa);
1241#endif
1242 }
1243#ifdef DEBUG
1244 else if (pmapvacflush & PVF_ENTER) {
1245 if (pmapvacflush & PVF_TOTAL)
1246 DCIA();
1247 else if (pmap == kernel_pmap)
1248 DCIS();
1249 else
1250 DCIU();
1251 }
9acfa6cd 1252#endif
82043489
MH
1253#endif
1254#ifdef DEBUG
1255 if ((pmapdebug & PDB_WIRING) && pmap != kernel_pmap)
8f961915 1256 pmap_check_wiring("enter", trunc_page(pmap_pte(pmap, va)));
8f961915
KM
1257#endif
1258}
1259
1260/*
1261 * Routine: pmap_change_wiring
1262 * Function: Change the wiring attribute for a map/virtual-address
1263 * pair.
1264 * In/out conditions:
1265 * The mapping must already exist in the pmap.
1266 */
1267void
1268pmap_change_wiring(pmap, va, wired)
1269 register pmap_t pmap;
1270 vm_offset_t va;
1271 boolean_t wired;
1272{
1273 register pt_entry_t *pte;
8f961915
KM
1274
1275#ifdef DEBUG
1276 if (pmapdebug & PDB_FOLLOW)
1277 printf("pmap_change_wiring(%x, %x, %x)\n", pmap, va, wired);
1278#endif
2059b854 1279 if (pmap == NULL)
8f961915
KM
1280 return;
1281
1282 pte = pmap_pte(pmap, va);
1283#ifdef DEBUG
1284 /*
1285 * Page table page is not allocated.
1286 * Should this ever happen? Ignore it for now,
1287 * we don't want to force allocation of unnecessary PTE pages.
1288 */
9acfa6cd 1289 if (!pmap_ste_v(pmap, va)) {
8f961915
KM
1290 if (pmapdebug & PDB_PARANOIA)
1291 printf("pmap_change_wiring: invalid STE for %x\n", va);
1292 return;
1293 }
1294 /*
1295 * Page not valid. Should this ever happen?
1296 * Just continue and change wiring anyway.
1297 */
1298 if (!pmap_pte_v(pte)) {
1299 if (pmapdebug & PDB_PARANOIA)
1300 printf("pmap_change_wiring: invalid PTE for %x\n", va);
1301 }
1302#endif
82043489
MH
1303 /*
1304 * If wiring actually changed (always?) set the wire bit and
1305 * update the wire count. Note that wiring is not a hardware
1306 * characteristic so there is no need to invalidate the TLB.
1307 */
1308 if (pmap_pte_w_chg(pte, wired ? PG_W : 0)) {
1309 pmap_pte_set_w(pte, wired);
8f961915
KM
1310 if (wired)
1311 pmap->pm_stats.wired_count++;
1312 else
1313 pmap->pm_stats.wired_count--;
1314 }
8f961915
KM
1315}
1316
1317/*
1318 * Routine: pmap_extract
1319 * Function:
1320 * Extract the physical page address associated
1321 * with the given map/virtual_address pair.
1322 */
1323
1324vm_offset_t
1325pmap_extract(pmap, va)
1326 register pmap_t pmap;
1327 vm_offset_t va;
1328{
1329 register vm_offset_t pa;
1330
1331#ifdef DEBUG
1332 if (pmapdebug & PDB_FOLLOW)
1333 printf("pmap_extract(%x, %x) -> ", pmap, va);
1334#endif
1335 pa = 0;
9acfa6cd 1336 if (pmap && pmap_ste_v(pmap, va))
8f961915
KM
1337 pa = *(int *)pmap_pte(pmap, va);
1338 if (pa)
1339 pa = (pa & PG_FRAME) | (va & ~PG_FRAME);
1340#ifdef DEBUG
1341 if (pmapdebug & PDB_FOLLOW)
1342 printf("%x\n", pa);
1343#endif
1344 return(pa);
1345}
1346
1347/*
1348 * Copy the range specified by src_addr/len
1349 * from the source map to the range dst_addr/len
1350 * in the destination map.
1351 *
1352 * This routine is only advisory and need not do anything.
1353 */
1354void pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr)
1355 pmap_t dst_pmap;
1356 pmap_t src_pmap;
1357 vm_offset_t dst_addr;
1358 vm_size_t len;
1359 vm_offset_t src_addr;
1360{
1361#ifdef DEBUG
1362 if (pmapdebug & PDB_FOLLOW)
1363 printf("pmap_copy(%x, %x, %x, %x, %x)\n",
1364 dst_pmap, src_pmap, dst_addr, len, src_addr);
1365#endif
1366}
1367
1368/*
1369 * Require that all active physical maps contain no
1370 * incorrect entries NOW. [This update includes
1371 * forcing updates of any address map caching.]
1372 *
1373 * Generally used to insure that a thread about
1374 * to run will see a semantically correct world.
1375 */
1376void pmap_update()
1377{
1378#ifdef DEBUG
1379 if (pmapdebug & PDB_FOLLOW)
1380 printf("pmap_update()\n");
1381#endif
1382 TBIA();
1383}
1384
1385/*
1386 * Routine: pmap_collect
1387 * Function:
1388 * Garbage collects the physical map system for
1389 * pages which are no longer used.
1390 * Success need not be guaranteed -- that is, there
1391 * may well be pages which are not referenced, but
1392 * others may be collected.
1393 * Usage:
1394 * Called by the pageout daemon when pages are scarce.
1395 */
1396void
1397pmap_collect(pmap)
1398 pmap_t pmap;
1399{
1400 register vm_offset_t pa;
1401 register pv_entry_t pv;
1402 register int *pte;
1403 vm_offset_t kpa;
1404 int s;
1405
1406#ifdef DEBUG
1407 int *ste;
1408 int opmapdebug;
1409#endif
1410 if (pmap != kernel_pmap)
1411 return;
1412
1413#ifdef DEBUG
1414 if (pmapdebug & PDB_FOLLOW)
1415 printf("pmap_collect(%x)\n", pmap);
82043489
MH
1416#endif
1417#ifdef PMAPSTATS
8f961915
KM
1418 kpt_stats.collectscans++;
1419#endif
1420 s = splimp();
1421 for (pa = vm_first_phys; pa < vm_last_phys; pa += PAGE_SIZE) {
1422 register struct kpt_page *kpt, **pkpt;
1423
1424 /*
1425 * Locate physical pages which are being used as kernel
1426 * page table pages.
1427 */
1428 pv = pa_to_pvh(pa);
1429 if (pv->pv_pmap != kernel_pmap || !(pv->pv_flags & PV_PTPAGE))
1430 continue;
1431 do {
1432 if (pv->pv_ptste && pv->pv_ptpmap == kernel_pmap)
1433 break;
1434 } while (pv = pv->pv_next);
2059b854 1435 if (pv == NULL)
8f961915
KM
1436 continue;
1437#ifdef DEBUG
1438 if (pv->pv_va < (vm_offset_t)Sysmap ||
1439 pv->pv_va >= (vm_offset_t)Sysmap + HP_MAX_PTSIZE)
1440 printf("collect: kernel PT VA out of range\n");
1441 else
1442 goto ok;
1443 pmap_pvdump(pa);
1444 continue;
1445ok:
1446#endif
1447 pte = (int *)(pv->pv_va + HP_PAGE_SIZE);
1448 while (--pte >= (int *)pv->pv_va && *pte == PG_NV)
1449 ;
1450 if (pte >= (int *)pv->pv_va)
1451 continue;
1452
1453#ifdef DEBUG
1454 if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT)) {
1455 printf("collect: freeing KPT page at %x (ste %x@%x)\n",
1456 pv->pv_va, *(int *)pv->pv_ptste, pv->pv_ptste);
1457 opmapdebug = pmapdebug;
1458 pmapdebug |= PDB_PTPAGE;
1459 }
1460
1461 ste = (int *)pv->pv_ptste;
1462#endif
1463 /*
1464 * If all entries were invalid we can remove the page.
82043489
MH
1465 * We call pmap_remove_entry to take care of invalidating
1466 * ST and Sysptmap entries.
8f961915
KM
1467 */
1468 kpa = pmap_extract(pmap, pv->pv_va);
82043489
MH
1469 pmap_remove_mapping(pmap, pv->pv_va, PT_ENTRY_NULL,
1470 PRM_TFLUSH|PRM_CFLUSH);
8f961915
KM
1471 /*
1472 * Use the physical address to locate the original
1473 * (kmem_alloc assigned) address for the page and put
1474 * that page back on the free list.
1475 */
1476 for (pkpt = &kpt_used_list, kpt = *pkpt;
1477 kpt != (struct kpt_page *)0;
1478 pkpt = &kpt->kpt_next, kpt = *pkpt)
1479 if (kpt->kpt_pa == kpa)
1480 break;
1481#ifdef DEBUG
1482 if (kpt == (struct kpt_page *)0)
1483 panic("pmap_collect: lost a KPT page");
1484 if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT))
1485 printf("collect: %x (%x) to free list\n",
1486 kpt->kpt_va, kpa);
1487#endif
1488 *pkpt = kpt->kpt_next;
1489 kpt->kpt_next = kpt_free_list;
1490 kpt_free_list = kpt;
82043489 1491#ifdef PMAPSTATS
8f961915
KM
1492 kpt_stats.kptinuse--;
1493 kpt_stats.collectpages++;
82043489
MH
1494#endif
1495#ifdef DEBUG
8f961915
KM
1496 if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT))
1497 pmapdebug = opmapdebug;
1498
1499 if (*ste)
1500 printf("collect: kernel STE at %x still valid (%x)\n",
1501 ste, *ste);
1502 ste = (int *)&Sysptmap[(st_entry_t *)ste-pmap_ste(kernel_pmap, 0)];
1503 if (*ste)
1504 printf("collect: kernel PTmap at %x still valid (%x)\n",
1505 ste, *ste);
1506#endif
1507 }
1508 splx(s);
1509}
1510
1511void
1512pmap_activate(pmap, pcbp)
1513 register pmap_t pmap;
1514 struct pcb *pcbp;
1515{
1516#ifdef DEBUG
1517 if (pmapdebug & (PDB_FOLLOW|PDB_SEGTAB))
1518 printf("pmap_activate(%x, %x)\n", pmap, pcbp);
1519#endif
2059b854 1520 PMAP_ACTIVATE(pmap, pcbp, pmap == curproc->p_vmspace->vm_map.pmap);
8f961915
KM
1521}
1522
8f961915
KM
1523/*
1524 * pmap_zero_page zeros the specified (machine independent)
1525 * page by mapping the page into virtual memory and using
1526 * bzero to clear its contents, one machine dependent page
1527 * at a time.
9acfa6cd
MH
1528 *
1529 * XXX this is a bad implementation for virtual cache machines
1530 * (320/350) because pmap_enter doesn't cache-inhibit the temporary
1531 * kernel mapping and we wind up with data cached for that KVA.
1532 * It is probably a win for physical cache machines (370/380)
1533 * as the cache loading is not wasted.
8f961915 1534 */
21b1e496 1535void
8f961915 1536pmap_zero_page(phys)
9acfa6cd 1537 vm_offset_t phys;
8f961915 1538{
9acfa6cd
MH
1539 register vm_offset_t kva;
1540 extern caddr_t CADDR1;
8f961915
KM
1541
1542#ifdef DEBUG
1543 if (pmapdebug & PDB_FOLLOW)
1544 printf("pmap_zero_page(%x)\n", phys);
1545#endif
9acfa6cd 1546 kva = (vm_offset_t) CADDR1;
9acfa6cd
MH
1547 pmap_enter(kernel_pmap, kva, phys, VM_PROT_READ|VM_PROT_WRITE, TRUE);
1548 bzero((caddr_t)kva, HP_PAGE_SIZE);
82043489
MH
1549 pmap_remove_mapping(kernel_pmap, kva, PT_ENTRY_NULL,
1550 PRM_TFLUSH|PRM_CFLUSH);
8f961915
KM
1551}
1552
1553/*
1554 * pmap_copy_page copies the specified (machine independent)
1555 * page by mapping the page into virtual memory and using
1556 * bcopy to copy the page, one machine dependent page at a
1557 * time.
9acfa6cd
MH
1558 *
1559 *
1560 * XXX this is a bad implementation for virtual cache machines
1561 * (320/350) because pmap_enter doesn't cache-inhibit the temporary
1562 * kernel mapping and we wind up with data cached for that KVA.
1563 * It is probably a win for physical cache machines (370/380)
1564 * as the cache loading is not wasted.
8f961915 1565 */
21b1e496 1566void
8f961915 1567pmap_copy_page(src, dst)
9acfa6cd 1568 vm_offset_t src, dst;
8f961915 1569{
9acfa6cd
MH
1570 register vm_offset_t skva, dkva;
1571 extern caddr_t CADDR1, CADDR2;
8f961915
KM
1572
1573#ifdef DEBUG
1574 if (pmapdebug & PDB_FOLLOW)
1575 printf("pmap_copy_page(%x, %x)\n", src, dst);
1576#endif
9acfa6cd
MH
1577 skva = (vm_offset_t) CADDR1;
1578 dkva = (vm_offset_t) CADDR2;
9acfa6cd
MH
1579 pmap_enter(kernel_pmap, skva, src, VM_PROT_READ, TRUE);
1580 pmap_enter(kernel_pmap, dkva, dst, VM_PROT_READ|VM_PROT_WRITE, TRUE);
9b0c8a0d 1581 copypage((caddr_t)skva, (caddr_t)dkva);
9acfa6cd
MH
1582 /* CADDR1 and CADDR2 are virtually contiguous */
1583 pmap_remove(kernel_pmap, skva, skva+2*PAGE_SIZE);
9acfa6cd 1584}
8f961915
KM
1585
1586/*
1587 * Routine: pmap_pageable
1588 * Function:
1589 * Make the specified pages (by pmap, offset)
1590 * pageable (or not) as requested.
1591 *
1592 * A page which is not pageable may not take
1593 * a fault; therefore, its page table entry
1594 * must remain valid for the duration.
1595 *
1596 * This routine is merely advisory; pmap_enter
1597 * will specify that these pages are to be wired
1598 * down (or not) as appropriate.
1599 */
21b1e496 1600void
8f961915
KM
1601pmap_pageable(pmap, sva, eva, pageable)
1602 pmap_t pmap;
1603 vm_offset_t sva, eva;
1604 boolean_t pageable;
1605{
1606#ifdef DEBUG
1607 if (pmapdebug & PDB_FOLLOW)
1608 printf("pmap_pageable(%x, %x, %x, %x)\n",
1609 pmap, sva, eva, pageable);
1610#endif
1611 /*
1612 * If we are making a PT page pageable then all valid
1613 * mappings must be gone from that page. Hence it should
1614 * be all zeros and there is no need to clean it.
1615 * Assumptions:
1616 * - we are called with only one page at a time
1617 * - PT pages have only one pv_table entry
1618 */
1619 if (pmap == kernel_pmap && pageable && sva + PAGE_SIZE == eva) {
1620 register pv_entry_t pv;
1621 register vm_offset_t pa;
1622
1623#ifdef DEBUG
1624 if ((pmapdebug & (PDB_FOLLOW|PDB_PTPAGE)) == PDB_PTPAGE)
1625 printf("pmap_pageable(%x, %x, %x, %x)\n",
1626 pmap, sva, eva, pageable);
1627#endif
9acfa6cd 1628 if (!pmap_ste_v(pmap, sva))
8f961915
KM
1629 return;
1630 pa = pmap_pte_pa(pmap_pte(pmap, sva));
1631 if (pa < vm_first_phys || pa >= vm_last_phys)
1632 return;
1633 pv = pa_to_pvh(pa);
2059b854 1634 if (pv->pv_ptste == NULL)
8f961915
KM
1635 return;
1636#ifdef DEBUG
1637 if (pv->pv_va != sva || pv->pv_next) {
1638 printf("pmap_pageable: bad PT page va %x next %x\n",
1639 pv->pv_va, pv->pv_next);
1640 return;
1641 }
1642#endif
1643 /*
1644 * Mark it unmodified to avoid pageout
1645 */
2059b854 1646 pmap_changebit(pa, PG_M, FALSE);
8f961915 1647#ifdef DEBUG
599b6bd7
MH
1648 if ((PHYS_TO_VM_PAGE(pa)->flags & PG_CLEAN) == 0) {
1649 printf("pa %x: flags=%x: not clean\n",
1650 pa, PHYS_TO_VM_PAGE(pa)->flags);
1651 PHYS_TO_VM_PAGE(pa)->flags |= PG_CLEAN;
1652 }
8f961915
KM
1653 if (pmapdebug & PDB_PTPAGE)
1654 printf("pmap_pageable: PT page %x(%x) unmodified\n",
1655 sva, *(int *)pmap_pte(pmap, sva));
1656 if (pmapdebug & PDB_WIRING)
1657 pmap_check_wiring("pageable", sva);
1658#endif
1659 }
1660}
1661
1662/*
1663 * Clear the modify bits on the specified physical page.
1664 */
1665
1666void
1667pmap_clear_modify(pa)
1668 vm_offset_t pa;
1669{
1670#ifdef DEBUG
1671 if (pmapdebug & PDB_FOLLOW)
1672 printf("pmap_clear_modify(%x)\n", pa);
1673#endif
1674 pmap_changebit(pa, PG_M, FALSE);
1675}
1676
1677/*
1678 * pmap_clear_reference:
1679 *
1680 * Clear the reference bit on the specified physical page.
1681 */
1682
1683void pmap_clear_reference(pa)
1684 vm_offset_t pa;
1685{
1686#ifdef DEBUG
1687 if (pmapdebug & PDB_FOLLOW)
1688 printf("pmap_clear_reference(%x)\n", pa);
1689#endif
1690 pmap_changebit(pa, PG_U, FALSE);
1691}
1692
1693/*
1694 * pmap_is_referenced:
1695 *
1696 * Return whether or not the specified physical page is referenced
1697 * by any physical maps.
1698 */
1699
1700boolean_t
1701pmap_is_referenced(pa)
1702 vm_offset_t pa;
1703{
1704#ifdef DEBUG
1705 if (pmapdebug & PDB_FOLLOW) {
1706 boolean_t rv = pmap_testbit(pa, PG_U);
1707 printf("pmap_is_referenced(%x) -> %c\n", pa, "FT"[rv]);
1708 return(rv);
1709 }
1710#endif
1711 return(pmap_testbit(pa, PG_U));
1712}
1713
1714/*
1715 * pmap_is_modified:
1716 *
1717 * Return whether or not the specified physical page is modified
1718 * by any physical maps.
1719 */
1720
1721boolean_t
1722pmap_is_modified(pa)
1723 vm_offset_t pa;
1724{
1725#ifdef DEBUG
1726 if (pmapdebug & PDB_FOLLOW) {
1727 boolean_t rv = pmap_testbit(pa, PG_M);
1728 printf("pmap_is_modified(%x) -> %c\n", pa, "FT"[rv]);
1729 return(rv);
1730 }
1731#endif
1732 return(pmap_testbit(pa, PG_M));
1733}
1734
1735vm_offset_t
1736pmap_phys_address(ppn)
1737 int ppn;
1738{
1739 return(hp300_ptob(ppn));
1740}
1741
82043489
MH
1742#ifdef HPUXCOMPAT
1743/*
1744 * 'PUX hack for dealing with the so called multi-mapped address space.
1745 * The first 256mb is mapped in at every 256mb region from 0x10000000
1746 * up to 0xF0000000. This allows for 15 bits of tag information.
1747 *
1748 * We implement this at the segment table level, the machine independent
1749 * VM knows nothing about it.
1750 */
1751pmap_mapmulti(pmap, va)
1752 pmap_t pmap;
1753 vm_offset_t va;
1754{
1755 int *ste, *bste;
1756
1757#ifdef DEBUG
1758 if (pmapdebug & PDB_MULTIMAP) {
1759 ste = (int *)pmap_ste(pmap, HPMMBASEADDR(va));
1760 printf("pmap_mapmulti(%x, %x): bste %x(%x)",
1761 pmap, va, ste, *ste);
1762 ste = (int *)pmap_ste(pmap, va);
1763 printf(" ste %x(%x)\n", ste, *ste);
1764 }
1765#endif
1766 bste = (int *) pmap_ste(pmap, HPMMBASEADDR(va));
1767 ste = (int *) pmap_ste(pmap, va);
1768 if (*ste == SG_NV && (*bste & SG_V)) {
1769 *ste = *bste;
1770 TBIAU();
1771 return (KERN_SUCCESS);
1772 }
1773 return (KERN_INVALID_ADDRESS);
1774}
1775#endif
1776
8f961915
KM
1777/*
1778 * Miscellaneous support routines follow
1779 */
1780
82043489
MH
1781/*
1782 * Invalidate a single page denoted by pmap/va.
1783 * If (pte != NULL), it is the already computed PTE for the page.
1784 * If (flags & PRM_TFLUSH), we must invalidate any TLB information.
1785 * If (flags & PRM_CFLUSH), we must flush/invalidate any cache information.
1786 */
1787/* static */
1788void
1789pmap_remove_mapping(pmap, va, pte, flags)
1790 register pmap_t pmap;
1791 register vm_offset_t va;
1792 register pt_entry_t *pte;
1793 int flags;
1794{
1795 register vm_offset_t pa;
1796 register pv_entry_t pv, npv;
1797 pmap_t ptpmap;
1798 int *ste, s, bits;
1799#ifdef DEBUG
1800 pt_entry_t opte;
1801
1802 if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT))
1803 printf("pmap_remove_mapping(%x, %x, %x, %x)\n",
1804 pmap, va, pte, flags);
1805#endif
1806
1807 /*
1808 * PTE not provided, compute it from pmap and va.
1809 */
1810 if (pte == PT_ENTRY_NULL) {
1811 pte = pmap_pte(pmap, va);
1812 if (*(int *)pte == PG_NV)
1813 return;
1814 }
1815#ifdef HAVEVAC
1816 if (pmap_aliasmask && (flags & PRM_CFLUSH)) {
1817 /*
1818 * Purge kernel side of VAC to ensure we get the correct
1819 * state of any hardware maintained bits.
1820 */
1821 DCIS();
1822#ifdef PMAPSTATS
1823 remove_stats.sflushes++;
1824#endif
1825 /*
1826 * If this is a non-CI user mapping for the current process,
1827 * flush the VAC. Note that the kernel side was flushed
1828 * above so we don't worry about non-CI kernel mappings.
1829 */
1830 if (pmap == curproc->p_vmspace->vm_map.pmap &&
1831 !pmap_pte_ci(pte)) {
1832 DCIU();
1833#ifdef PMAPSTATS
1834 remove_stats.uflushes++;
1835#endif
1836 }
1837 }
1838#endif
1839 pa = pmap_pte_pa(pte);
1840#ifdef DEBUG
1841 opte = *pte;
1842#endif
1843#ifdef PMAPSTATS
1844 remove_stats.removes++;
1845#endif
1846 /*
1847 * Update statistics
1848 */
1849 if (pmap_pte_w(pte))
1850 pmap->pm_stats.wired_count--;
1851 pmap->pm_stats.resident_count--;
1852
1853 /*
1854 * Invalidate the PTE after saving the reference modify info.
1855 */
1856#ifdef DEBUG
1857 if (pmapdebug & PDB_REMOVE)
1858 printf("remove: invalidating pte at %x\n", pte);
1859#endif
1860 bits = *(int *)pte & (PG_U|PG_M);
1861 *(int *)pte = PG_NV;
1862 if ((flags & PRM_TFLUSH) && active_pmap(pmap))
1863 TBIS(va);
1864 /*
1865 * For user mappings decrement the wiring count on
1866 * the PT page. We do this after the PTE has been
1867 * invalidated because vm_map_pageable winds up in
1868 * pmap_pageable which clears the modify bit for the
1869 * PT page.
1870 */
1871 if (pmap != kernel_pmap) {
ab614754
MH
1872 (void) vm_map_pageable(pt_map, trunc_page(pte),
1873 round_page(pte+1), TRUE);
82043489
MH
1874#ifdef DEBUG
1875 if (pmapdebug & PDB_WIRING)
1876 pmap_check_wiring("remove", trunc_page(pte));
1877#endif
1878 }
1879 /*
1880 * If this isn't a managed page, we are all done.
1881 */
1882 if (pa < vm_first_phys || pa >= vm_last_phys)
1883 return;
1884 /*
1885 * Otherwise remove it from the PV table
1886 * (raise IPL since we may be called at interrupt time).
1887 */
1888 pv = pa_to_pvh(pa);
1889 ste = (int *)0;
1890 s = splimp();
1891 /*
1892 * If it is the first entry on the list, it is actually
1893 * in the header and we must copy the following entry up
1894 * to the header. Otherwise we must search the list for
1895 * the entry. In either case we free the now unused entry.
1896 */
1897 if (pmap == pv->pv_pmap && va == pv->pv_va) {
1898 ste = (int *)pv->pv_ptste;
1899 ptpmap = pv->pv_ptpmap;
1900 npv = pv->pv_next;
1901 if (npv) {
1902 npv->pv_flags = pv->pv_flags;
1903 *pv = *npv;
1904 free((caddr_t)npv, M_VMPVENT);
1905 } else
1906 pv->pv_pmap = NULL;
1907#ifdef PMAPSTATS
1908 remove_stats.pvfirst++;
1909#endif
1910 } else {
1911 for (npv = pv->pv_next; npv; npv = npv->pv_next) {
1912#ifdef PMAPSTATS
1913 remove_stats.pvsearch++;
1914#endif
1915 if (pmap == npv->pv_pmap && va == npv->pv_va)
1916 break;
1917 pv = npv;
1918 }
1919#ifdef DEBUG
1920 if (npv == NULL)
1921 panic("pmap_remove: PA not in pv_tab");
1922#endif
1923 ste = (int *)npv->pv_ptste;
1924 ptpmap = npv->pv_ptpmap;
1925 pv->pv_next = npv->pv_next;
1926 free((caddr_t)npv, M_VMPVENT);
1927 pv = pa_to_pvh(pa);
1928 }
1929#ifdef HAVEVAC
1930 /*
1931 * If only one mapping left we no longer need to cache inhibit
1932 */
1933 if (pmap_aliasmask &&
1934 pv->pv_pmap && pv->pv_next == NULL && (pv->pv_flags & PV_CI)) {
1935#ifdef DEBUG
1936 if (pmapdebug & PDB_CACHE)
1937 printf("remove: clearing CI for pa %x\n", pa);
1938#endif
1939 pv->pv_flags &= ~PV_CI;
1940 pmap_changebit(pa, PG_CI, FALSE);
1941#ifdef DEBUG
1942 if ((pmapdebug & (PDB_CACHE|PDB_PVDUMP)) ==
1943 (PDB_CACHE|PDB_PVDUMP))
1944 pmap_pvdump(pa);
1945#endif
1946 }
1947#endif
1948 /*
1949 * If this was a PT page we must also remove the
1950 * mapping from the associated segment table.
1951 */
1952 if (ste) {
1953#ifdef PMAPSTATS
1954 remove_stats.ptinvalid++;
1955#endif
1956#ifdef DEBUG
1957 if (pmapdebug & (PDB_REMOVE|PDB_PTPAGE))
1958 printf("remove: ste was %x@%x pte was %x@%x\n",
1959 *ste, ste, *(int *)&opte, pmap_pte(pmap, va));
1960#endif
1961#if defined(HP380)
1962 if (mmutype == MMU_68040) {
1963 int *este = &ste[NPTEPG/SG4_LEV3SIZE];
1964
1965 while (ste < este)
1966 *ste++ = SG_NV;
1967#ifdef DEBUG
1968 ste -= NPTEPG/SG4_LEV3SIZE;
1969#endif
1970 } else
1971#endif
1972 *ste = SG_NV;
1973 /*
1974 * If it was a user PT page, we decrement the
1975 * reference count on the segment table as well,
1976 * freeing it if it is now empty.
1977 */
1978 if (ptpmap != kernel_pmap) {
1979#ifdef DEBUG
1980 if (pmapdebug & (PDB_REMOVE|PDB_SEGTAB))
1981 printf("remove: stab %x, refcnt %d\n",
1982 ptpmap->pm_stab, ptpmap->pm_sref - 1);
1983 if ((pmapdebug & PDB_PARANOIA) &&
1984 ptpmap->pm_stab != (st_entry_t *)trunc_page(ste))
1985 panic("remove: bogus ste");
1986#endif
1987 if (--(ptpmap->pm_sref) == 0) {
1988#ifdef DEBUG
1989 if (pmapdebug&(PDB_REMOVE|PDB_SEGTAB))
1990 printf("remove: free stab %x\n",
1991 ptpmap->pm_stab);
1992#endif
b55d9ecf
MH
1993 kmem_free_wakeup(st_map,
1994 (vm_offset_t)ptpmap->pm_stab,
1995 HP_STSIZE);
82043489
MH
1996 ptpmap->pm_stab = Segtabzero;
1997 ptpmap->pm_stpa = Segtabzeropa;
1998#if defined(HP380)
1999 if (mmutype == MMU_68040)
2000 ptpmap->pm_stfree = protostfree;
2001#endif
2002 ptpmap->pm_stchanged = TRUE;
2003 /*
2004 * XXX may have changed segment table
2005 * pointer for current process so
2006 * update now to reload hardware.
2007 */
2008 if (ptpmap == curproc->p_vmspace->vm_map.pmap)
2009 PMAP_ACTIVATE(ptpmap,
2010 (struct pcb *)curproc->p_addr, 1);
2011 }
599b6bd7
MH
2012#ifdef DEBUG
2013 else if (ptpmap->pm_sref < 0)
2014 panic("remove: sref < 0");
2015#endif
82043489
MH
2016 }
2017#if 0
2018 /*
2019 * XXX this should be unnecessary as we have been
2020 * flushing individual mappings as we go.
2021 */
2022 if (ptpmap == kernel_pmap)
2023 TBIAS();
2024 else
2025 TBIAU();
2026#endif
2027 pv->pv_flags &= ~PV_PTPAGE;
2028 ptpmap->pm_ptpages--;
2029 }
2030 /*
2031 * Update saved attributes for managed page
2032 */
2033 pmap_attributes[pa_index(pa)] |= bits;
2034 splx(s);
2035}
2036
8f961915
KM
2037/* static */
2038boolean_t
2039pmap_testbit(pa, bit)
2040 register vm_offset_t pa;
2041 int bit;
2042{
2043 register pv_entry_t pv;
9acfa6cd 2044 register int *pte;
8f961915
KM
2045 int s;
2046
2047 if (pa < vm_first_phys || pa >= vm_last_phys)
2048 return(FALSE);
2049
2050 pv = pa_to_pvh(pa);
2051 s = splimp();
2052 /*
2053 * Check saved info first
2054 */
2055 if (pmap_attributes[pa_index(pa)] & bit) {
2056 splx(s);
2057 return(TRUE);
2058 }
82043489 2059#ifdef HAVEVAC
8f961915
KM
2060 /*
2061 * Flush VAC to get correct state of any hardware maintained bits.
2062 */
2063 if (pmap_aliasmask && (bit & (PG_U|PG_M)))
2064 DCIS();
82043489 2065#endif
8f961915
KM
2066 /*
2067 * Not found, check current mappings returning
2068 * immediately if found.
2069 */
2059b854 2070 if (pv->pv_pmap != NULL) {
8f961915
KM
2071 for (; pv; pv = pv->pv_next) {
2072 pte = (int *) pmap_pte(pv->pv_pmap, pv->pv_va);
9acfa6cd
MH
2073 if (*pte & bit) {
2074 splx(s);
2075 return(TRUE);
2076 }
8f961915
KM
2077 }
2078 }
2079 splx(s);
2080 return(FALSE);
2081}
2082
2083/* static */
82043489 2084void
8f961915
KM
2085pmap_changebit(pa, bit, setem)
2086 register vm_offset_t pa;
2087 int bit;
2088 boolean_t setem;
2089{
2090 register pv_entry_t pv;
9acfa6cd 2091 register int *pte, npte;
8f961915
KM
2092 vm_offset_t va;
2093 int s;
2094 boolean_t firstpage = TRUE;
82043489
MH
2095#ifdef PMAPSTATS
2096 struct chgstats *chgp;
2097#endif
8f961915
KM
2098
2099#ifdef DEBUG
2100 if (pmapdebug & PDB_BITS)
2101 printf("pmap_changebit(%x, %x, %s)\n",
2102 pa, bit, setem ? "set" : "clear");
2103#endif
2104 if (pa < vm_first_phys || pa >= vm_last_phys)
2105 return;
2106
82043489
MH
2107#ifdef PMAPSTATS
2108 chgp = &changebit_stats[(bit>>2)-1];
2109 if (setem)
2110 chgp->setcalls++;
2111 else
2112 chgp->clrcalls++;
2113#endif
8f961915
KM
2114 pv = pa_to_pvh(pa);
2115 s = splimp();
2116 /*
2117 * Clear saved attributes (modify, reference)
2118 */
2119 if (!setem)
2120 pmap_attributes[pa_index(pa)] &= ~bit;
2121 /*
2122 * Loop over all current mappings setting/clearing as appropos
2123 * If setting RO do we need to clear the VAC?
2124 */
2059b854 2125 if (pv->pv_pmap != NULL) {
8f961915
KM
2126#ifdef DEBUG
2127 int toflush = 0;
2128#endif
2129 for (; pv; pv = pv->pv_next) {
2130#ifdef DEBUG
2131 toflush |= (pv->pv_pmap == kernel_pmap) ? 2 : 1;
2132#endif
2133 va = pv->pv_va;
4bc66f7c
MH
2134
2135 /*
2136 * XXX don't write protect pager mappings
2137 */
2138 if (bit == PG_RO) {
2139 extern vm_offset_t pager_sva, pager_eva;
2140
2141 if (va >= pager_sva && va < pager_eva)
2142 continue;
2143 }
2144
8f961915 2145 pte = (int *) pmap_pte(pv->pv_pmap, va);
82043489 2146#ifdef HAVEVAC
8f961915
KM
2147 /*
2148 * Flush VAC to ensure we get correct state of HW bits
2149 * so we don't clobber them.
2150 */
2151 if (firstpage && pmap_aliasmask) {
2152 firstpage = FALSE;
2153 DCIS();
2154 }
82043489 2155#endif
9acfa6cd
MH
2156 if (setem)
2157 npte = *pte | bit;
2158 else
2159 npte = *pte & ~bit;
2160 if (*pte != npte) {
82043489
MH
2161#if defined(HP380)
2162 /*
2163 * If we are changing caching status or
2164 * protection make sure the caches are
2165 * flushed (but only once).
2166 */
2167 if (firstpage && mmutype == MMU_68040 &&
2168 (bit == PG_RO && setem ||
2169 (bit & PG_CMASK))) {
2170 firstpage = FALSE;
2171 DCFP(pa);
2172 ICPP(pa);
2173 }
2174#endif
9acfa6cd 2175 *pte = npte;
82043489
MH
2176 if (active_pmap(pv->pv_pmap))
2177 TBIS(va);
2178#ifdef PMAPSTATS
2179 if (setem)
2180 chgp->sethits++;
2181 else
2182 chgp->clrhits++;
2183#endif
2184 }
2185#ifdef PMAPSTATS
2186 else {
2187 if (setem)
2188 chgp->setmiss++;
2189 else
2190 chgp->clrmiss++;
9acfa6cd
MH
2191 }
2192#endif
8f961915 2193 }
82043489 2194#if defined(HAVEVAC) && defined(DEBUG)
8f961915
KM
2195 if (setem && bit == PG_RO && (pmapvacflush & PVF_PROTECT)) {
2196 if ((pmapvacflush & PVF_TOTAL) || toflush == 3)
2197 DCIA();
2198 else if (toflush == 2)
2199 DCIS();
2200 else
2201 DCIU();
2202 }
2203#endif
2204 }
2205 splx(s);
2206}
2207
2208/* static */
2209void
2210pmap_enter_ptpage(pmap, va)
2211 register pmap_t pmap;
2212 register vm_offset_t va;
2213{
2214 register vm_offset_t ptpa;
2215 register pv_entry_t pv;
2216 st_entry_t *ste;
2217 int s;
2218
2219#ifdef DEBUG
2220 if (pmapdebug & (PDB_FOLLOW|PDB_ENTER|PDB_PTPAGE))
2221 printf("pmap_enter_ptpage: pmap %x, va %x\n", pmap, va);
82043489
MH
2222#endif
2223#ifdef PMAPSTATS
8f961915
KM
2224 enter_stats.ptpneeded++;
2225#endif
2226 /*
2227 * Allocate a segment table if necessary. Note that it is allocated
b55d9ecf 2228 * from a private map and not pt_map. This keeps user page tables
8f961915
KM
2229 * aligned on segment boundaries in the kernel address space.
2230 * The segment table is wired down. It will be freed whenever the
2231 * reference count drops to zero.
2232 */
2233 if (pmap->pm_stab == Segtabzero) {
2234 pmap->pm_stab = (st_entry_t *)
b55d9ecf 2235 kmem_alloc(st_map, HP_STSIZE);
9acfa6cd
MH
2236 pmap->pm_stpa = (st_entry_t *)
2237 pmap_extract(kernel_pmap, (vm_offset_t)pmap->pm_stab);
2238#if defined(HP380)
2239 if (mmutype == MMU_68040) {
2240#ifdef DEBUG
2241 if (dowriteback && dokwriteback)
2242#endif
2243 pmap_changebit((vm_offset_t)pmap->pm_stab, PG_CCB, 0);
2244 pmap->pm_stfree = protostfree;
2245 }
2246#endif
8f961915
KM
2247 pmap->pm_stchanged = TRUE;
2248 /*
2249 * XXX may have changed segment table pointer for current
2250 * process so update now to reload hardware.
2251 */
2059b854
MK
2252 if (pmap == curproc->p_vmspace->vm_map.pmap)
2253 PMAP_ACTIVATE(pmap, (struct pcb *)curproc->p_addr, 1);
8f961915
KM
2254#ifdef DEBUG
2255 if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB))
9acfa6cd
MH
2256 printf("enter: pmap %x stab %x(%x)\n",
2257 pmap, pmap->pm_stab, pmap->pm_stpa);
8f961915
KM
2258#endif
2259 }
2260
2261 ste = pmap_ste(pmap, va);
9acfa6cd
MH
2262#if defined(HP380)
2263 /*
2264 * Allocate level 2 descriptor block if necessary
2265 */
2266 if (mmutype == MMU_68040) {
2267 if (!ste->sg_v) {
2268 int ix;
2269 caddr_t addr;
2270
2271 ix = bmtol2(pmap->pm_stfree);
2272 if (ix == -1)
2273 panic("enter: out of address space"); /* XXX */
2274 pmap->pm_stfree &= ~l2tobm(ix);
2275 addr = (caddr_t)&pmap->pm_stab[ix*SG4_LEV2SIZE];
2276 bzero(addr, SG4_LEV2SIZE*sizeof(st_entry_t));
2277 addr = (caddr_t)&pmap->pm_stpa[ix*SG4_LEV2SIZE];
2278 *(int *)ste = (u_int)addr | SG_RW | SG_U | SG_V;
2279#ifdef DEBUG
2280 if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB))
2281 printf("enter: alloc ste2 %d(%x)\n", ix, addr);
2282#endif
2283 }
2284 ste = pmap_ste2(pmap, va);
2285 /*
2286 * Since a level 2 descriptor maps a block of SG4_LEV3SIZE
2287 * level 3 descriptors, we need a chunk of NPTEPG/SG4_LEV3SIZE
2288 * (16) such descriptors (NBPG/SG4_LEV3SIZE bytes) to map a
2289 * PT page--the unit of allocation. We set `ste' to point
2290 * to the first entry of that chunk which is validated in its
2291 * entirety below.
2292 */
2293 ste = (st_entry_t *)((int)ste & ~(NBPG/SG4_LEV3SIZE-1));
2294#ifdef DEBUG
2295 if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB))
2296 printf("enter: ste2 %x (%x)\n",
2297 pmap_ste2(pmap, va), ste);
2298#endif
2299 }
2300#endif
8f961915
KM
2301 va = trunc_page((vm_offset_t)pmap_pte(pmap, va));
2302
2303 /*
2304 * In the kernel we allocate a page from the kernel PT page
2305 * free list and map it into the kernel page table map (via
2306 * pmap_enter).
2307 */
2308 if (pmap == kernel_pmap) {
2309 register struct kpt_page *kpt;
2310
2311 s = splimp();
2312 if ((kpt = kpt_free_list) == (struct kpt_page *)0) {
2313 /*
2314 * No PT pages available.
2315 * Try once to free up unused ones.
2316 */
2317#ifdef DEBUG
2318 if (pmapdebug & PDB_COLLECT)
2319 printf("enter: no KPT pages, collecting...\n");
2320#endif
2321 pmap_collect(kernel_pmap);
2322 if ((kpt = kpt_free_list) == (struct kpt_page *)0)
2323 panic("pmap_enter_ptpage: can't get KPT page");
2324 }
82043489 2325#ifdef PMAPSTATS
8f961915
KM
2326 if (++kpt_stats.kptinuse > kpt_stats.kptmaxuse)
2327 kpt_stats.kptmaxuse = kpt_stats.kptinuse;
2328#endif
2329 kpt_free_list = kpt->kpt_next;
2330 kpt->kpt_next = kpt_used_list;
2331 kpt_used_list = kpt;
2332 ptpa = kpt->kpt_pa;
cb6a4b59 2333 bzero((caddr_t)kpt->kpt_va, HP_PAGE_SIZE);
8f961915
KM
2334 pmap_enter(pmap, va, ptpa, VM_PROT_DEFAULT, TRUE);
2335#ifdef DEBUG
9acfa6cd
MH
2336 if (pmapdebug & (PDB_ENTER|PDB_PTPAGE)) {
2337 int ix = pmap_ste(pmap, va) - pmap_ste(pmap, 0);
2338
8f961915 2339 printf("enter: add &Sysptmap[%d]: %x (KPT page %x)\n",
9acfa6cd
MH
2340 ix, *(int *)&Sysptmap[ix], kpt->kpt_va);
2341 }
8f961915
KM
2342#endif
2343 splx(s);
2344 }
2345 /*
2346 * For user processes we just simulate a fault on that location
2347 * letting the VM system allocate a zero-filled page.
2348 */
2349 else {
2350#ifdef DEBUG
2351 if (pmapdebug & (PDB_ENTER|PDB_PTPAGE))
2352 printf("enter: about to fault UPT pg at %x\n", va);
ab614754 2353#endif
9acfa6cd
MH
2354 s = vm_fault(pt_map, va, VM_PROT_READ|VM_PROT_WRITE, FALSE);
2355 if (s != KERN_SUCCESS) {
2356 printf("vm_fault(pt_map, %x, RW, 0) -> %d\n", va, s);
2357 panic("pmap_enter: vm_fault failed");
2358 }
8f961915 2359 ptpa = pmap_extract(kernel_pmap, va);
ab614754
MH
2360 /*
2361 * Mark the page clean now to avoid its pageout (and
2362 * hence creation of a pager) between now and when it
2363 * is wired; i.e. while it is on a paging queue.
2364 */
2365 PHYS_TO_VM_PAGE(ptpa)->flags |= PG_CLEAN;
8f961915 2366#ifdef DEBUG
2cbf9af3 2367 PHYS_TO_VM_PAGE(ptpa)->flags |= PG_PTPAGE;
8f961915
KM
2368#endif
2369 }
9acfa6cd
MH
2370#if defined(HP380)
2371 /*
2372 * Turn off copyback caching of page table pages,
2373 * could get ugly otherwise.
2374 */
2375#ifdef DEBUG
2376 if (dowriteback && dokwriteback)
2377#endif
2378 if (mmutype == MMU_68040) {
2379 int *pte = (int *)pmap_pte(kernel_pmap, va);
2380#ifdef DEBUG
2381 if ((pmapdebug & PDB_PARANOIA) && (*pte & PG_CCB) == 0)
2382 printf("%s PT no CCB: kva=%x ptpa=%x pte@%x=%x\n",
2383 pmap == kernel_pmap ? "Kernel" : "User",
2384 va, ptpa, pte, *pte);
2385#endif
2386 pmap_changebit(ptpa, PG_CCB, 0);
2387 }
2388#endif
8f961915
KM
2389 /*
2390 * Locate the PV entry in the kernel for this PT page and
2391 * record the STE address. This is so that we can invalidate
2392 * the STE when we remove the mapping for the page.
2393 */
2394 pv = pa_to_pvh(ptpa);
2395 s = splimp();
2396 if (pv) {
2397 pv->pv_flags |= PV_PTPAGE;
2398 do {
2399 if (pv->pv_pmap == kernel_pmap && pv->pv_va == va)
2400 break;
2401 } while (pv = pv->pv_next);
2402 }
2403#ifdef DEBUG
2059b854 2404 if (pv == NULL)
8f961915
KM
2405 panic("pmap_enter_ptpage: PT page not entered");
2406#endif
2407 pv->pv_ptste = ste;
2408 pv->pv_ptpmap = pmap;
2409#ifdef DEBUG
2410 if (pmapdebug & (PDB_ENTER|PDB_PTPAGE))
2411 printf("enter: new PT page at PA %x, ste at %x\n", ptpa, ste);
2412#endif
2413
2414 /*
2415 * Map the new PT page into the segment table.
2416 * Also increment the reference count on the segment table if this
2417 * was a user page table page. Note that we don't use vm_map_pageable
2418 * to keep the count like we do for PT pages, this is mostly because
2419 * it would be difficult to identify ST pages in pmap_pageable to
2420 * release them. We also avoid the overhead of vm_map_pageable.
2421 */
9acfa6cd
MH
2422#if defined(HP380)
2423 if (mmutype == MMU_68040) {
2424 st_entry_t *este;
2425
2426 for (este = &ste[NPTEPG/SG4_LEV3SIZE]; ste < este; ste++) {
2427 *(int *)ste = ptpa | SG_U | SG_RW | SG_V;
2428 ptpa += SG4_LEV3SIZE * sizeof(st_entry_t);
2429 }
2430 } else
2431#endif
8f961915
KM
2432 *(int *)ste = (ptpa & SG_FRAME) | SG_RW | SG_V;
2433 if (pmap != kernel_pmap) {
2434 pmap->pm_sref++;
2435#ifdef DEBUG
2436 if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB))
2437 printf("enter: stab %x refcnt %d\n",
2438 pmap->pm_stab, pmap->pm_sref);
2439#endif
2440 }
82043489 2441#if 0
8f961915
KM
2442 /*
2443 * Flush stale TLB info.
2444 */
2445 if (pmap == kernel_pmap)
2446 TBIAS();
2447 else
2448 TBIAU();
82043489 2449#endif
8f961915
KM
2450 pmap->pm_ptpages++;
2451 splx(s);
2452}
2453
2454#ifdef DEBUG
82043489
MH
2455/* static */
2456void
8f961915
KM
2457pmap_pvdump(pa)
2458 vm_offset_t pa;
2459{
2460 register pv_entry_t pv;
2461
2462 printf("pa %x", pa);
2463 for (pv = pa_to_pvh(pa); pv; pv = pv->pv_next)
2464 printf(" -> pmap %x, va %x, ptste %x, ptpmap %x, flags %x",
2465 pv->pv_pmap, pv->pv_va, pv->pv_ptste, pv->pv_ptpmap,
2466 pv->pv_flags);
2467 printf("\n");
2468}
2469
82043489
MH
2470/* static */
2471void
8f961915
KM
2472pmap_check_wiring(str, va)
2473 char *str;
2474 vm_offset_t va;
2475{
2476 vm_map_entry_t entry;
2477 register int count, *pte;
2478
2479 va = trunc_page(va);
9acfa6cd 2480 if (!pmap_ste_v(kernel_pmap, va) ||
8f961915
KM
2481 !pmap_pte_v(pmap_pte(kernel_pmap, va)))
2482 return;
2483
2484 if (!vm_map_lookup_entry(pt_map, va, &entry)) {
2485 printf("wired_check: entry for %x not found\n", va);
2486 return;
2487 }
2488 count = 0;
2489 for (pte = (int *)va; pte < (int *)(va+PAGE_SIZE); pte++)
2490 if (*pte)
2491 count++;
2492 if (entry->wired_count != count)
2493 printf("*%s*: %x: w%d/a%d\n",
2494 str, va, entry->wired_count, count);
2495}
2496#endif