summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorart <art@openbsd.org>2000-11-09 13:57:34 +0000
committerart <art@openbsd.org>2000-11-09 13:57:34 +0000
commitbd6e9ca986f28d736414aa2f0528b1cda7f6e888 (patch)
tree7389c30f505618edc790b32d0aa78c8d09fee365
parentzap dead files. (diff)
downloadwireguard-openbsd-bd6e9ca986f28d736414aa2f0528b1cda7f6e888.tar.xz
wireguard-openbsd-bd6e9ca986f28d736414aa2f0528b1cda7f6e888.zip
zap old file.
-rw-r--r--sys/arch/alpha/alpha/pmap.old.c2286
1 files changed, 0 insertions, 2286 deletions
diff --git a/sys/arch/alpha/alpha/pmap.old.c b/sys/arch/alpha/alpha/pmap.old.c
deleted file mode 100644
index 4e8ade0cd7e..00000000000
--- a/sys/arch/alpha/alpha/pmap.old.c
+++ /dev/null
@@ -1,2286 +0,0 @@
-/* $OpenBSD: pmap.old.c,v 1.7 2000/06/08 11:57:21 art Exp $ */
-/* $NetBSD: pmap.old.c,v 1.14 1996/11/13 21:13:10 cgd Exp $ */
-
-/*
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * the Systems Programming Group of the University of Utah Computer
- * Science Department.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)pmap.c 8.6 (Berkeley) 5/27/94
- */
-
-#ifdef XXX
-/*
- * HP9000/300 series physical map management code.
- *
- * Supports:
- * 68020 with HP MMU models 320, 350
- * 68020 with 68551 MMU models 318, 319, 330 (all untested)
- * 68030 with on-chip MMU models 340, 360, 370, 345, 375, 400
- * 68040 with on-chip MMU models 380, 425, 433
- *
- * Notes:
- * Don't even pay lip service to multiprocessor support.
- *
- * We assume TLB entries don't have process tags (except for the
- * supervisor/user distinction) so we only invalidate TLB entries
- * when changing mappings for the current (or kernel) pmap. This is
- * technically not true for the 68551 but we flush the TLB on every
- * context switch, so it effectively winds up that way.
- *
- * Bitwise and/or operations are significantly faster than bitfield
- * references so we use them when accessing STE/PTEs in the pmap_pte_*
- * macros. Note also that the two are not always equivalent; e.g.:
- * (*(int *)pte & PG_PROT) [4] != pte->pg_prot [1]
- * and a couple of routines that deal with protection and wiring take
- * some shortcuts that assume the and/or definitions.
- *
- * This implementation will only work for PAGE_SIZE == NBPG
- * (i.e. 4096 bytes).
- */
-#endif
-
-/*
- * Manages physical address maps.
- *
- * In addition to hardware address maps, this
- * module is called upon to provide software-use-only
- * maps which may or may not be stored in the same
- * form as hardware maps. These pseudo-maps are
- * used to store intermediate results from copy
- * operations to and from address spaces.
- *
- * Since the information managed by this module is
- * also stored by the logical address mapping module,
- * this module may throw away valid virtual-to-physical
- * mappings at almost any time. However, invalidations
- * of virtual-to-physical mappings must be done as
- * requested.
- *
- * In order to cope with hardware architectures which
- * make virtual-to-physical map invalidates expensive,
- * this module may delay invalidate or reduced protection
- * operations until such time as they are actually
- * necessary. This module is given full information as
- * to which processors are currently using which maps,
- * and to when physical maps must be made correct.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/malloc.h>
-#include <sys/user.h>
-#include <sys/buf.h>
-#ifdef SYSVSHM
-#include <sys/shm.h>
-#endif
-
-#include <vm/vm.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_page.h>
-
-#include <machine/cpu.h>
-
-#ifdef PMAPSTATS
-struct {
- int collectscans;
- int collectpages;
- int kpttotal;
- int kptinuse;
- int kptmaxuse;
-} kpt_stats;
-struct {
- int kernel; /* entering kernel mapping */
- int user; /* entering user mapping */
- int ptpneeded; /* needed to allocate a PT page */
- int nochange; /* no change at all */
- int pwchange; /* no mapping change, just wiring or protection */
- int wchange; /* no mapping change, just wiring */
- int pchange; /* no mapping change, just protection */
- int mchange; /* was mapped but mapping to different page */
- int managed; /* a managed page */
- int firstpv; /* first mapping for this PA */
- int secondpv; /* second mapping for this PA */
- int ci; /* cache inhibited */
- int unmanaged; /* not a managed page */
- int flushes; /* cache flushes */
-} enter_stats;
-struct {
- int calls;
- int removes;
- int pvfirst;
- int pvsearch;
- int ptinvalid;
- int uflushes;
- int sflushes;
-} remove_stats;
-struct {
- int calls;
- int changed;
- int alreadyro;
- int alreadyrw;
-} protect_stats;
-struct chgstats {
- int setcalls;
- int sethits;
- int setmiss;
- int clrcalls;
- int clrhits;
- int clrmiss;
-} changebit_stats[16];
-#endif
-
-#ifdef DEBUG
-#define PDB_FOLLOW 0x0001
-#define PDB_INIT 0x0002
-#define PDB_ENTER 0x0004
-#define PDB_REMOVE 0x0008
-#define PDB_CREATE 0x0010
-#define PDB_PTPAGE 0x0020
-#define PDB_CACHE 0x0040
-#define PDB_BITS 0x0080
-#define PDB_COLLECT 0x0100
-#define PDB_PROTECT 0x0200
-#define PDB_SEGTAB 0x0400
-#define PDB_MULTIMAP 0x0800
-#define PDB_BOOTSTRAP 0x1000
-#define PDB_PARANOIA 0x2000
-#define PDB_WIRING 0x4000
-#define PDB_PVDUMP 0x8000
-
-int debugmap = 0;
-int pmapdebug = PDB_PARANOIA;
-extern vm_offset_t pager_sva, pager_eva;
-#endif
-
-/*
- * Get STEs and PTEs for user/kernel address space
- */
-#define pmap_ste(m, v) (&((m)->pm_stab[vatoste((vm_offset_t)(v))]))
-#define pmap_ste_v(m, v) (*pmap_ste(m, v) & PG_V)
-
-#define pmap_pte(m, v) \
- (&((m)->pm_ptab[NPTEPG * vatoste((vm_offset_t)(v)) + \
- vatopte((vm_offset_t)(v))]))
-#define pmap_pte_pa(pte) (PG_PFNUM(*(pte)) << PGSHIFT)
-#define pmap_pte_prot(pte) (*(pte) & PG_PROT)
-#define pmap_pte_w(pte) (*(pte) & PG_WIRED)
-#define pmap_pte_v(pte) (*(pte) & PG_V)
-
-#define pmap_pte_set_w(pte, v) \
- if (v) *(u_long *)(pte) |= PG_WIRED; else *(u_long *)(pte) &= ~PG_WIRED
-#define pmap_pte_w_chg(pte, nw) ((nw) ^ pmap_pte_w(pte))
-
-#define pmap_pte_set_prot(pte, np) { *(pte) &= ~PG_PROT ; *(pte) |= (np); }
-#define pmap_pte_prot_chg(pte, np) ((np) ^ pmap_pte_prot(pte))
-
-
-/*
- * Given a map and a machine independent protection code,
- * convert to an hp300 protection code.
- */
-#define pte_prot(m, p) (protection_codes[m == pmap_kernel() ? 0 : 1][p])
-int protection_codes[2][8];
-
-/*
- * Kernel page table page management.
- */
-struct kpt_page {
- struct kpt_page *kpt_next; /* link on either used or free list */
- vm_offset_t kpt_va; /* always valid kernel VA */
- vm_offset_t kpt_pa; /* PA of this page (for speed) */
-};
-struct kpt_page *kpt_free_list, *kpt_used_list;
-struct kpt_page *kpt_pages;
-
-/*
- * The Alpha's level-1 page table.
- */
-pt_entry_t *Lev1map;
-
-/*
- * Kernel segment/page table and page table map.
- * The page table map gives us a level of indirection we need to dynamically
- * expand the page table. It is essentially a copy of the segment table
- * with PTEs instead of STEs. All are initialized in locore at boot time.
- * Segtabzero is an empty segment table which all processes share til they
- * reference something.
- */
-pt_entry_t *Sysptmap;
-pt_entry_t *Sysmap;
-vm_size_t Sysptmapsize, Sysmapsize;
-pt_entry_t *Segtabzero, Segtabzeropte;
-
-struct pmap kernel_pmap_store;
-vm_map_t st_map, pt_map;
-
-vm_offset_t avail_start; /* PA of first available physical page */
-vm_offset_t avail_end; /* PA of last available physical page */
-vm_size_t mem_size; /* memory size in bytes */
-vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss)*/
-vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */
-vm_offset_t vm_first_phys; /* PA of first managed page */
-vm_offset_t vm_last_phys; /* PA just past last managed page */
-boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */
-char *pmap_attributes; /* reference and modify bits */
-
-/*
- * Internal routines
- */
-void alpha_protection_init __P((void));
-void pmap_remove_mapping __P((pmap_t, vm_offset_t, pt_entry_t *, int));
-void pmap_changebit __P((vm_offset_t, u_long, boolean_t));
-void pmap_enter_ptpage __P((pmap_t, vm_offset_t));
-#ifdef DEBUG
-void pmap_pvdump __P((vm_offset_t));
-void pmap_check_wiring __P((char *, vm_offset_t));
-#endif
-
-#define PAGE_IS_MANAGED(pa) ((pa) >= vm_first_phys && (pa) < vm_last_phys)
-
-/* pmap_remove_mapping flags */
-#define PRM_TFLUSH 1
-#define PRM_CFLUSH 2
-
-/*
- * pmap_bootstrap:
- * Bootstrap the system to run with virtual memory.
- * firstaddr is the first unused kseg0 address (not page aligned).
- */
-void
-pmap_bootstrap(firstaddr, ptaddr)
- vm_offset_t firstaddr;
- vm_offset_t ptaddr;
-{
- register int i;
- vm_offset_t start;
- pt_entry_t pte;
- extern int firstusablepage, lastusablepage;
-
-#ifdef DEBUG
- if (pmapdebug & (PDB_FOLLOW|PDB_BOOTSTRAP))
- printf("pmap_bootstrap(0x%lx, 0x%lx)\n", firstaddr, ptaddr);
-#endif
-
- /* must be page aligned */
- start = firstaddr = alpha_round_page(firstaddr);
-
-#define valloc(name, type, num) \
- (name) = (type *)firstaddr; \
- firstaddr = ALIGN((vm_offset_t)((name)+(num)))
-
- /*
- * Allocate an empty prototype segment map for processes.
- * This will be used until processes get their own.
- */
- valloc(Segtabzero, pt_entry_t, NPTEPG);
- Segtabzeropte = (ALPHA_K0SEG_TO_PHYS((vm_offset_t)Segtabzero) >> PGSHIFT) << PG_SHIFT;
- Segtabzeropte |= PG_V | PG_KRE | PG_KWE | PG_WIRED;
-
- /*
- * Figure out how many PTE's are necessary to map the kernel.
- * The '512' comes from PAGER_MAP_SIZE in vm_pager_init().
- * This should be kept in sync.
- * We also reserve space for kmem_alloc_pageable() for vm_fork().
- */
- Sysmapsize = (VM_KMEM_SIZE + VM_MBUF_SIZE + VM_PHYS_SIZE +
- nbuf * MAXBSIZE + 16 * NCARGS) / NBPG + 512 + 256;
- Sysmapsize += maxproc * (btoc(ALPHA_STSIZE) + btoc(ALPHA_MAX_PTSIZE));
-
-#ifdef SYSVSHM
- Sysmapsize += shminfo.shmall;
-#endif
- Sysmapsize = roundup(Sysmapsize, NPTEPG);
-
- /*
- * Allocate a level 1 PTE table for the kernel.
- * This is always one page long.
- * IF THIS IS NOT A MULTIPLE OF NBPG, ALL WILL GO TO HELL.
- */
- valloc(Lev1map, pt_entry_t, NPTEPG);
-
- /*
- * Allocate a level 2 PTE table for the kernel.
- * These must map all of the level3 PTEs.
- * IF THIS IS NOT A MULTIPLE OF NBPG, ALL WILL GO TO HELL.
- */
- Sysptmapsize = roundup(howmany(Sysmapsize, NPTEPG), NPTEPG);
- valloc(Sysptmap, pt_entry_t, Sysptmapsize);
- pmap_kernel()->pm_stab = Sysptmap;
-
- /*
- * Allocate a level 3 PTE table for the kernel.
- * Contains Sysmapsize PTEs.
- */
- valloc(Sysmap, pt_entry_t, Sysmapsize);
- pmap_kernel()->pm_ptab = Sysmap;
-
- /*
- * Allocate memory for page attributes.
- * allocates a few more entries than we need, but that's safe.
- */
- valloc(pmap_attributes, char, 1 + lastusablepage - firstusablepage);
-
- /*
- * Allocate memory for pv_table.
- * This will allocate more entries than we really need.
- * We could do this in pmap_init when we know the actual
- * phys_start and phys_end but its better to use kseg0 addresses
- * rather than kernel virtual addresses mapped through the TLB.
- */
- i = 1 + lastusablepage - alpha_btop(ALPHA_K0SEG_TO_PHYS(firstaddr));
- valloc(pv_table, struct pv_entry, i);
-
- /*
- * Clear allocated memory.
- */
- firstaddr = alpha_round_page(firstaddr);
- bzero((caddr_t)start, firstaddr - start);
-
- /*
- * Set up level 1 page table
- */
-
- /* First, copy mappings for things below VM_MIN_KERNEL_ADDRESS */
- bcopy((caddr_t)ptaddr, Lev1map,
- kvtol1pte(VM_MIN_KERNEL_ADDRESS) * sizeof Lev1map[0]);
-
- /* Second, map all of the level 2 pte pages */
- for (i = 0; i < howmany(Sysptmapsize, NPTEPG); i++) {
- pte = (ALPHA_K0SEG_TO_PHYS(((vm_offset_t)Sysptmap) + (i*PAGE_SIZE)) >> PGSHIFT)
- << PG_SHIFT;
- pte |= PG_V | PG_ASM | PG_KRE | PG_KWE | PG_WIRED;
- Lev1map[kvtol1pte(VM_MIN_KERNEL_ADDRESS +
- (i*PAGE_SIZE*NPTEPG*NPTEPG))] = pte;
- }
-
- /* Finally, map the virtual page table */
- pte = (ALPHA_K0SEG_TO_PHYS((vm_offset_t)Lev1map) >> PGSHIFT) << PG_SHIFT;
- pte |= PG_V | PG_KRE | PG_KWE; /* NOTE NO ASM */
- Lev1map[kvtol1pte(VPTBASE)] = pte;
-
- /*
- * Set up level 2 page table.
- */
- /* Map all of the level 3 pte pages */
- for (i = 0; i < howmany(Sysmapsize, NPTEPG); i++) {
- pte = (ALPHA_K0SEG_TO_PHYS(((vm_offset_t)Sysmap)+(i*PAGE_SIZE)) >> PGSHIFT)
- << PG_SHIFT;
- pte |= PG_V | PG_ASM | PG_KRE | PG_KWE | PG_WIRED;
- Sysptmap[vatoste(VM_MIN_KERNEL_ADDRESS+
- (i*PAGE_SIZE*NPTEPG))] = pte;
- }
-
- /*
- * Set up level three page table (Sysmap)
- */
- /* Nothing to do; it's already zero'd */
-
- avail_start = ALPHA_K0SEG_TO_PHYS(firstaddr);
-#if 1
- avail_end = alpha_ptob(lastusablepage + 1);
- mem_size = avail_end - avail_start;
-#else
- /* XXX why not lastusablepage + 1, & not include NBPG in mem_size? */
- avail_end = alpha_ptob(lastusablepage);
- mem_size = NBPG + avail_end - avail_start;
-#endif
-#if 0
- printf("avail_start = 0x%lx\n", avail_start);
- printf("avail_end = 0x%lx\n", avail_end);
- printf("mem_size = 0x%lx\n", mem_size);
-#endif
-
- virtual_avail = VM_MIN_KERNEL_ADDRESS;
- virtual_end = VM_MIN_KERNEL_ADDRESS + Sysmapsize * NBPG;
-
- simple_lock_init(&pmap_kernel()->pm_lock);
- pmap_kernel()->pm_count = 1;
-
- /*
- * Set up curproc's (i.e. proc 0's) PCB such that the ptbr
- * points to the right place.
- */
- curproc->p_addr->u_pcb.pcb_hw.apcb_ptbr = ALPHA_K0SEG_TO_PHYS((vm_offset_t)Lev1map) >> PGSHIFT;
-}
-
-/*
- * Unmap the PROM mappings. PROM mappings are kept around
- * by pmap_bootstrap, so we can still use the prom's printf.
- * Basically, blow away all mappings in the level one PTE
- * table below VM_MIN_KERNEL_ADDRESS. The Virtual Page Table
- * Is at the end of virtual space, so it's safe.
- */
-void
-pmap_unmap_prom()
-{
- extern int prom_mapped;
- extern pt_entry_t *rom_ptep, rom_pte;
-
-#ifdef DEBUG
- if (pmapdebug & (PDB_FOLLOW|PDB_BOOTSTRAP))
- printf("pmap_unmap_prom\n");
-#endif
-
- /* XXX save old pte so that we can remap prom if necessary */
- rom_ptep = &Lev1map[0]; /* XXX */
- rom_pte = *rom_ptep & ~PG_ASM; /* XXX */
-
- /* Mark all mappings before VM_MIN_KERNEL_ADDRESS as invalid. */
- bzero(Lev1map, kvtol1pte(VM_MIN_KERNEL_ADDRESS) * sizeof Lev1map[0]);
- prom_mapped = 0;
- ALPHA_TBIA();
-}
-
-/*
- * Bootstrap memory allocator. This function allows for early dynamic
- * memory allocation until the virtual memory system has been bootstrapped.
- * After that point, either kmem_alloc or malloc should be used. This
- * function works by stealing pages from the (to be) managed page pool,
- * stealing virtual address space, then implicitly mapping the pages
- * (by using their k0seg addresses) and zeroing them.
- *
- * It should be used from pmap_bootstrap till vm_page_startup, afterwards
- * it cannot be used, and will generate a panic if tried. Note that this
- * memory will never be freed, and in essence it is wired down.
- */
-void *
-pmap_bootstrap_alloc(size)
- int size;
-{
- vm_offset_t val;
- extern boolean_t vm_page_startup_initialized;
-
-#ifdef DEBUG
- if (pmapdebug & (PDB_FOLLOW|PDB_BOOTSTRAP))
- printf("pmap_bootstrap_alloc(%x)\n", size);
-#endif
- if (vm_page_startup_initialized)
- panic("pmap_bootstrap_alloc: called after startup initialized");
-
- val = ALPHA_PHYS_TO_K0SEG(avail_start);
- size = round_page(size);
- avail_start += size;
-
- bzero((caddr_t)val, size);
- return ((void *)val);
-}
-
-/*
- * Initialize the pmap module.
- * Called by vm_init, to initialize any structures that the pmap
- * system needs to map virtual memory.
- */
-void
-pmap_init(phys_start, phys_end)
- vm_offset_t phys_start, phys_end;
-{
- vm_offset_t addr, addr2;
- vm_size_t s;
-
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("pmap_init(%lx, %lx)\n", phys_start, phys_end);
-#endif
-
- /* initialize protection array */
- alpha_protection_init();
-
- /*
- * Allocate the segment table map
- */
- s = maxproc * ALPHA_STSIZE;
- st_map = kmem_suballoc(kernel_map, &addr, &addr2, s, TRUE);
-
- /*
- * Allocate the page table map
- */
- s = maxproc * ALPHA_MAX_PTSIZE; /* XXX limit it */
- pt_map = kmem_suballoc(kernel_map, &addr, &addr2, s, TRUE);
-
- /*
- * Now it is safe to enable pv_table recording.
- */
- vm_first_phys = phys_start;
- vm_last_phys = phys_end;
-#if 0
- printf("vm_first_phys = 0x%lx\n", vm_first_phys);
- printf("vm_last_phys = 0x%lx\n", vm_last_phys);
-#endif
- pmap_initialized = TRUE;
-}
-
-#if 0
-/*
- * Used to map a range of physical addresses into kernel
- * virtual address space.
- *
- * For now, VM is already on, we only need to map the
- * specified memory.
- */
-vm_offset_t
-pmap_map(virt, start, end, prot)
- vm_offset_t virt;
- vm_offset_t start;
- vm_offset_t end;
- int prot;
-{
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("pmap_map(%lx, %lx, %lx, %x)\n", virt, start, end, prot);
-#endif
- while (start < end) {
- pmap_enter(pmap_kernel(), virt, start, prot, FALSE, 0);
- virt += PAGE_SIZE;
- start += PAGE_SIZE;
- }
- return(virt);
-}
-#endif
-
-/*
- * Create and return a physical map.
- *
- * If the size specified for the map
- * is zero, the map is an actual physical
- * map, and may be referenced by the
- * hardware.
- *
- * If the size specified is non-zero,
- * the map will be used in software only, and
- * is bounded by that size.
- */
-pmap_t
-pmap_create(size)
- vm_size_t size;
-{
- register pmap_t pmap;
-
-#ifdef DEBUG
- if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
- printf("pmap_create(%lx)\n", size);
-#endif
- /*
- * Software use map does not need a pmap
- */
- if (size)
- return(NULL);
-
- /* XXX: is it ok to wait here? */
- pmap = (pmap_t) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK);
-#ifdef notifwewait
- if (pmap == NULL)
- panic("pmap_create: cannot allocate a pmap");
-#endif
- bzero(pmap, sizeof(*pmap));
- pmap_pinit(pmap);
- return (pmap);
-}
-
-/*
- * Initialize a preallocated and zeroed pmap structure,
- * such as one in a vmspace structure.
- */
-void
-pmap_pinit(pmap)
- register struct pmap *pmap;
-{
-
-#ifdef DEBUG
- if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
- printf("pmap_pinit(%p)\n", pmap);
-#endif
- /*
- * No need to allocate page table space yet but we do need a
- * valid segment table. Initially, we point everyone at the
- * "null" segment table. On the first pmap_enter, a real
- * segment table will be allocated.
- */
- pmap->pm_stab = Segtabzero;
- pmap->pm_stpte = Segtabzeropte;
- pmap->pm_stchanged = TRUE;
- pmap->pm_count = 1;
- simple_lock_init(&pmap->pm_lock);
-}
-
-/*
- * Retire the given physical map from service.
- * Should only be called if the map contains
- * no valid mappings.
- */
-void
-pmap_destroy(pmap)
- register pmap_t pmap;
-{
- int count;
-
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("pmap_destroy(%p)\n", pmap);
-#endif
- if (pmap == NULL)
- return;
-
- simple_lock(&pmap->pm_lock);
- count = --pmap->pm_count;
- simple_unlock(&pmap->pm_lock);
- if (count == 0) {
- pmap_release(pmap);
- free((caddr_t)pmap, M_VMPMAP);
- }
-}
-
-/*
- * Release any resources held by the given physical map.
- * Called when a pmap initialized by pmap_pinit is being released.
- * Should only be called if the map contains no valid mappings.
- */
-void
-pmap_release(pmap)
- register struct pmap *pmap;
-{
-
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("pmap_release(%p)\n", pmap);
-#endif
-#ifdef notdef /* DIAGNOSTIC */
- /* count would be 0 from pmap_destroy... */
- simple_lock(&pmap->pm_lock);
- if (pmap->pm_count != 1)
- panic("pmap_release count");
-#endif
- if (pmap->pm_ptab)
- kmem_free_wakeup(pt_map, (vm_offset_t)pmap->pm_ptab,
- ALPHA_MAX_PTSIZE);
- if (pmap->pm_stab != Segtabzero)
- kmem_free_wakeup(st_map, (vm_offset_t)pmap->pm_stab,
- ALPHA_STSIZE);
-}
-
-/*
- * Add a reference to the specified pmap.
- */
-void
-pmap_reference(pmap)
- pmap_t pmap;
-{
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("pmap_reference(%p)\n", pmap);
-#endif
- if (pmap != NULL) {
- simple_lock(&pmap->pm_lock);
- pmap->pm_count++;
- simple_unlock(&pmap->pm_lock);
- }
-}
-
-/*
- * Remove the given range of addresses from the specified map.
- *
- * It is assumed that the start and end are properly
- * rounded to the page size.
- */
-void
-pmap_remove(pmap, sva, eva)
- register pmap_t pmap;
- register vm_offset_t sva, eva;
-{
- register vm_offset_t nssva;
- register pt_entry_t *pte;
- boolean_t firstpage, needcflush;
- int flags;
-
-#ifdef DEBUG
- if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT))
- printf("pmap_remove(%p, %lx, %lx)\n", pmap, sva, eva);
-#endif
-
- if (pmap == NULL)
- return;
-
-#ifdef PMAPSTATS
- remove_stats.calls++;
-#endif
- firstpage = TRUE;
- needcflush = FALSE;
- flags = active_pmap(pmap) ? PRM_TFLUSH : 0;
- while (sva < eva) {
- nssva = alpha_trunc_seg(sva) + ALPHA_SEG_SIZE;
- if (nssva == 0 || nssva > eva)
- nssva = eva;
- /*
- * If VA belongs to an unallocated segment,
- * skip to the next segment boundary.
- */
- if (!pmap_ste_v(pmap, sva)) {
- sva = nssva;
- continue;
- }
- /*
- * Invalidate every valid mapping within this segment.
- */
- pte = pmap_pte(pmap, sva);
- while (sva < nssva) {
- if (pmap_pte_v(pte)) {
- pmap_remove_mapping(pmap, sva, pte, flags);
- firstpage = FALSE;
- }
- pte++;
- sva += PAGE_SIZE;
- }
- }
- /*
- * Didn't do anything, no need for cache flushes
- */
- if (firstpage)
- return;
-}
-
-/*
- * pmap_page_protect:
- *
- * Lower the permission for all mappings to a given page.
- */
-void
-pmap_page_protect(pa, prot)
- vm_offset_t pa;
- vm_prot_t prot;
-{
- register pv_entry_t pv;
- int s;
-
-#ifdef DEBUG
- if ((pmapdebug & (PDB_FOLLOW|PDB_PROTECT)) ||
- (prot == VM_PROT_NONE && (pmapdebug & PDB_REMOVE)))
- printf("pmap_page_protect(%lx, %x)\n", pa, prot);
-#endif
- if (!PAGE_IS_MANAGED(pa))
- return;
-
- switch (prot) {
- case VM_PROT_READ|VM_PROT_WRITE:
- case VM_PROT_ALL:
- return;
- /* copy_on_write */
- case VM_PROT_READ:
- case VM_PROT_READ|VM_PROT_EXECUTE:
-/* XXX */ pmap_changebit(pa, PG_KWE | PG_UWE, FALSE);
- return;
- /* remove_all */
- default:
- break;
- }
- pv = pa_to_pvh(pa);
- s = splimp();
- while (pv->pv_pmap != NULL) {
- register pt_entry_t *pte;
-
- pte = pmap_pte(pv->pv_pmap, pv->pv_va);
-#ifdef DEBUG
- if (!pmap_ste_v(pv->pv_pmap, pv->pv_va) ||
- pmap_pte_pa(pte) != pa)
- panic("pmap_page_protect: bad mapping");
-#endif
- if (!pmap_pte_w(pte))
- pmap_remove_mapping(pv->pv_pmap, pv->pv_va,
- pte, PRM_TFLUSH|PRM_CFLUSH);
- else {
- pv = pv->pv_next;
-#ifdef DEBUG
- if (pmapdebug & PDB_PARANOIA)
- printf("%s wired mapping for %lx not removed\n",
- "pmap_page_protect:", pa);
-#endif
- }
- }
- splx(s);
-}
-
-/*
- * Set the physical protection on the
- * specified range of this map as requested.
- */
-void
-pmap_protect(pmap, sva, eva, prot)
- register pmap_t pmap;
- register vm_offset_t sva, eva;
- vm_prot_t prot;
-{
- register vm_offset_t nssva;
- register pt_entry_t *pte, bits;
- boolean_t firstpage, needtflush;
-
-#ifdef DEBUG
- if (pmapdebug & (PDB_FOLLOW|PDB_PROTECT))
- printf("pmap_protect(%p, %lx, %lx, %x)\n", pmap, sva, eva, prot);
-#endif
-
- if (pmap == NULL)
- return;
-
-#ifdef PMAPSTATS
- protect_stats.calls++;
-#endif
- if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
- pmap_remove(pmap, sva, eva);
- return;
- }
- if (prot & VM_PROT_WRITE)
- return;
-
- bits = pte_prot(pmap, prot);
- needtflush = active_pmap(pmap);
- firstpage = TRUE;
- while (sva < eva) {
- nssva = alpha_trunc_seg(sva) + ALPHA_SEG_SIZE;
- if (nssva == 0 || nssva > eva)
- nssva = eva;
- /*
- * If VA belongs to an unallocated segment,
- * skip to the next segment boundary.
- */
- if (!pmap_ste_v(pmap, sva)) {
- sva = nssva;
- continue;
- }
- /*
- * Change protection on mapping if it is valid and doesn't
- * already have the correct protection.
- */
- pte = pmap_pte(pmap, sva);
- while (sva < nssva) {
- if (pmap_pte_v(pte) && pmap_pte_prot_chg(pte, bits)) {
- pmap_pte_set_prot(pte, bits);
- if (needtflush)
- ALPHA_TBIS(sva);
-#ifdef PMAPSTATS
- protect_stats.changed++;
-#endif
- firstpage = FALSE;
- }
-#ifdef PMAPSTATS
- else if (pmap_pte_v(pte)) {
- if (isro)
- protect_stats.alreadyro++;
- else
- protect_stats.alreadyrw++;
- }
-#endif
- pte++;
- sva += PAGE_SIZE;
- }
- }
-}
-
-/*
- * Insert the given physical page (p) at
- * the specified virtual address (v) in the
- * target physical map with the protection requested.
- *
- * If specified, the page will be wired down, meaning
- * that the related pte can not be reclaimed.
- *
- * NB: This is the only routine which MAY NOT lazy-evaluate
- * or lose information. That is, this routine must actually
- * insert this page into the given map NOW.
- */
-void
-pmap_enter(pmap, va, pa, prot, wired, access_type)
- register pmap_t pmap;
- vm_offset_t va;
- register vm_offset_t pa;
- vm_prot_t prot;
- boolean_t wired;
- vm_prot_t access_type;
-{
- register pt_entry_t *pte;
- register pt_entry_t npte;
- vm_offset_t opa;
- boolean_t checkpv = TRUE;
-
-#ifdef DEBUG
- if (pmapdebug & (PDB_FOLLOW|PDB_ENTER))
- printf("pmap_enter(%p, %lx, %lx, %x, %x)\n",
- pmap, va, pa, prot, wired);
-#endif
- if (pmap == NULL)
- return;
-
-#ifdef PMAPSTATS
- if (pmap == pmap_kernel())
- enter_stats.kernel++;
- else
- enter_stats.user++;
-#endif
- /*
- * For user mapping, allocate kernel VM resources if necessary.
- */
- if (pmap->pm_ptab == NULL)
- pmap->pm_ptab = (pt_entry_t *)
- kmem_alloc_wait(pt_map, ALPHA_MAX_PTSIZE);
- /*
- * Segment table entry not valid, we need a new PT page
- */
- if (!pmap_ste_v(pmap, va))
- pmap_enter_ptpage(pmap, va);
-
- pa = alpha_trunc_page(pa);
- pte = pmap_pte(pmap, va);
- opa = pmap_pte_pa(pte);
-#ifdef DEBUG
- if (pmapdebug & PDB_ENTER)
- printf("enter: pte %p, *pte %lx\n", pte, *pte);
-#endif
-
- /*
- * Mapping has not changed, must be protection or wiring change.
- */
- if (opa == pa) {
-#ifdef PMAPSTATS
- enter_stats.pwchange++;
-#endif
- /*
- * Wiring change, just update stats.
- * We don't worry about wiring PT pages as they remain
- * resident as long as there are valid mappings in them.
- * Hence, if a user page is wired, the PT page will be also.
- */
- if (pmap_pte_w_chg(pte, wired ? PG_WIRED : 0)) {
-#ifdef DEBUG
- if (pmapdebug & PDB_ENTER)
- printf("enter: wiring change -> %x\n", wired);
-#endif
- if (wired)
- pmap->pm_stats.wired_count++;
- else
- pmap->pm_stats.wired_count--;
-#ifdef PMAPSTATS
- if (pmap_pte_prot(pte) == pte_prot(pmap, prot))
- enter_stats.wchange++;
-#endif
- }
-#ifdef PMAPSTATS
- else if (pmap_pte_prot(pte) != pte_prot(pmap, prot))
- enter_stats.pchange++;
- else
- enter_stats.nochange++;
-#endif
- /*
- * Retain cache inhibition status
- */
- checkpv = FALSE;
- goto validate;
- }
-
- /*
- * Mapping has changed, invalidate old range and fall through to
- * handle validating new mapping.
- */
- if (opa) {
-#ifdef DEBUG
- if (pmapdebug & PDB_ENTER)
- printf("enter: removing old mapping %lx\n", va);
-#endif
- pmap_remove_mapping(pmap, va, pte, PRM_TFLUSH|PRM_CFLUSH);
-#ifdef PMAPSTATS
- enter_stats.mchange++;
-#endif
- }
-
- /*
- * If this is a new user mapping, increment the wiring count
- * on this PT page. PT pages are wired down as long as there
- * is a valid mapping in the page.
- */
- if (pmap != pmap_kernel())
- (void) vm_map_pageable(pt_map, trunc_page(pte),
- round_page(pte+1), FALSE);
-
- /*
- * Enter on the PV list if part of our managed memory
- * Note that we raise IPL while manipulating pv_table
- * since pmap_enter can be called at interrupt time.
- */
- if (PAGE_IS_MANAGED(pa)) {
- register pv_entry_t pv, npv;
- int s;
-
-#ifdef PMAPSTATS
- enter_stats.managed++;
-#endif
- pv = pa_to_pvh(pa);
- s = splimp();
-#ifdef DEBUG
- if (pmapdebug & PDB_ENTER)
- printf("enter: pv at %p: %lx/%p/%p\n",
- pv, pv->pv_va, pv->pv_pmap, pv->pv_next);
-#endif
- /*
- * No entries yet, use header as the first entry
- */
- if (pv->pv_pmap == NULL) {
-#ifdef PMAPSTATS
- enter_stats.firstpv++;
-#endif
- pv->pv_va = va;
- pv->pv_pmap = pmap;
- pv->pv_next = NULL;
- pv->pv_ptpte = NULL;
- pv->pv_ptpmap = NULL;
- pv->pv_flags = 0;
- }
- /*
- * There is at least one other VA mapping this page.
- * Place this entry after the header.
- */
- else {
-#ifdef DEBUG
- for (npv = pv; npv; npv = npv->pv_next)
- if (pmap == npv->pv_pmap && va == npv->pv_va)
- panic("pmap_enter: already in pv_tab");
-#endif
- npv = (pv_entry_t)
- malloc(sizeof *npv, M_VMPVENT, M_NOWAIT);
- npv->pv_va = va;
- npv->pv_pmap = pmap;
- npv->pv_next = pv->pv_next;
- npv->pv_ptpte = NULL;
- npv->pv_ptpmap = NULL;
- npv->pv_flags = 0;
- pv->pv_next = npv;
-#ifdef PMAPSTATS
- if (!npv->pv_next)
- enter_stats.secondpv++;
-#endif
- }
- splx(s);
- }
- /*
- * Assumption: if it is not part of our managed memory
- * then it must be device memory which may be volitile.
- */
- else if (pmap_initialized) {
- checkpv = FALSE;
-#ifdef PMAPSTATS
- enter_stats.unmanaged++;
-#endif
- }
-
- /*
- * Increment counters
- */
- pmap->pm_stats.resident_count++;
- if (wired)
- pmap->pm_stats.wired_count++;
-
-validate:
- /*
- * Build the new PTE.
- */
- npte = ((pa >> PGSHIFT) << PG_SHIFT) | pte_prot(pmap, prot) | PG_V;
- if (PAGE_IS_MANAGED(pa)) {
- if ((pmap_attributes[pa_index(pa)] & PMAP_ATTR_REF) == 0)
- npte |= PG_FOR | PG_FOW | PG_FOE;
- else if ((pmap_attributes[pa_index(pa)] & PMAP_ATTR_MOD) == 0)
- npte |= PG_FOW;
- }
- if (wired)
- npte |= PG_WIRED;
-#ifdef DEBUG
- if (pmapdebug & PDB_ENTER)
- printf("enter: new pte value %lx\n", npte);
-#endif
- /*
- * Remember if this was a wiring-only change.
- * If so, we need not flush the TLB and caches.
- */
- wired = ((*pte ^ npte) == PG_WIRED);
- *pte = npte;
- if (!wired && active_pmap(pmap))
- ALPHA_TBIS(va);
-#ifdef DEBUG
- if ((pmapdebug & PDB_WIRING) && pmap != pmap_kernel())
- pmap_check_wiring("enter", trunc_page(pmap_pte(pmap, va)));
-#endif
-}
-
-/*
- * Routine: pmap_change_wiring
- * Function: Change the wiring attribute for a map/virtual-address
- * pair.
- * In/out conditions:
- * The mapping must already exist in the pmap.
- */
-void
-pmap_change_wiring(pmap, va, wired)
- register pmap_t pmap;
- vm_offset_t va;
- boolean_t wired;
-{
- register pt_entry_t *pte;
-
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("pmap_change_wiring(%p, %lx, %x)\n", pmap, va, wired);
-#endif
- if (pmap == NULL)
- return;
-
- pte = pmap_pte(pmap, va);
-#ifdef DEBUG
- /*
- * Page table page is not allocated.
- * Should this ever happen? Ignore it for now,
- * we don't want to force allocation of unnecessary PTE pages.
- */
- if (!pmap_ste_v(pmap, va)) {
- if (pmapdebug & PDB_PARANOIA)
- printf("pmap_change_wiring: invalid STE for %lx\n", va);
- return;
- }
- /*
- * Page not valid. Should this ever happen?
- * Just continue and change wiring anyway.
- */
- if (!pmap_pte_v(pte)) {
- if (pmapdebug & PDB_PARANOIA)
- printf("pmap_change_wiring: invalid PTE for %lx\n", va);
- }
-#endif
- /*
- * If wiring actually changed (always?) set the wire bit and
- * update the wire count. Note that wiring is not a hardware
- * characteristic so there is no need to invalidate the TLB.
- */
- if (pmap_pte_w_chg(pte, wired ? PG_WIRED : 0)) {
- pmap_pte_set_w(pte, wired);
- if (wired)
- pmap->pm_stats.wired_count++;
- else
- pmap->pm_stats.wired_count--;
- }
-}
-
-/*
- * Routine: pmap_extract
- * Function:
- * Extract the physical page address associated
- * with the given map/virtual_address pair.
- */
-
-vm_offset_t
-pmap_extract(pmap, va)
- register pmap_t pmap;
- vm_offset_t va;
-{
- pt_entry_t pte;
- register vm_offset_t pa;
-
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("pmap_extract(%p, %lx) -> ", pmap, va);
-#endif
- pa = 0;
- if (pmap && pmap_ste_v(pmap, va)) {
- pte = *pmap_pte(pmap, va);
- if (pte & PG_V)
- pa = ctob(PG_PFNUM(pte)) | (va & PGOFSET);
- }
-
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("%lx\n", pa);
-#endif
- return(pa);
-}
-
-/*
- * Copy the range specified by src_addr/len
- * from the source map to the range dst_addr/len
- * in the destination map.
- *
- * This routine is only advisory and need not do anything.
- */
-void pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr)
- pmap_t dst_pmap;
- pmap_t src_pmap;
- vm_offset_t dst_addr;
- vm_size_t len;
- vm_offset_t src_addr;
-{
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("pmap_copy(%p, %p, %lx, %lx, %lx)\n",
- dst_pmap, src_pmap, dst_addr, len, src_addr);
-#endif
-}
-
-/*
- * Require that all active physical maps contain no
- * incorrect entries NOW. [This update includes
- * forcing updates of any address map caching.]
- *
- * Generally used to insure that a thread about
- * to run will see a semantically correct world.
- */
-void pmap_update()
-{
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("pmap_update()\n");
-#endif
- ALPHA_TBIA();
-}
-
-/*
- * Routine: pmap_collect
- * Function:
- * Garbage collects the physical map system for
- * pages which are no longer used.
- * Success need not be guaranteed -- that is, there
- * may well be pages which are not referenced, but
- * others may be collected.
- * Usage:
- * Called by the pageout daemon when pages are scarce.
- */
-void
-pmap_collect(pmap)
- pmap_t pmap;
-{
- register vm_offset_t pa;
- register pv_entry_t pv;
- register pt_entry_t *pte;
- vm_offset_t kpa;
- int s;
-
-#ifdef DEBUG
- pt_entry_t *ste;
- int opmapdebug = 0;
-#endif
- if (pmap != pmap_kernel())
- return;
-
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("pmap_collect(%p)\n", pmap);
-#endif
-#ifdef PMAPSTATS
- kpt_stats.collectscans++;
-#endif
- s = splimp();
- for (pa = vm_first_phys; pa < vm_last_phys; pa += PAGE_SIZE) {
- register struct kpt_page *kpt, **pkpt;
-
- /*
- * Locate physical pages which are being used as kernel
- * page table pages.
- */
- pv = pa_to_pvh(pa);
- if (pv->pv_pmap != pmap_kernel() || !(pv->pv_flags & PV_PTPAGE))
- continue;
- do {
- if (pv->pv_ptpte && pv->pv_ptpmap == pmap_kernel())
- break;
- } while ((pv = pv->pv_next) != NULL);
- if (pv == NULL)
- continue;
-#ifdef DEBUG
- if (pv->pv_va < (vm_offset_t)Sysmap ||
- pv->pv_va >= (vm_offset_t)Sysmap + ALPHA_MAX_PTSIZE)
- printf("collect: kernel PT VA out of range\n");
- else
- goto ok;
- pmap_pvdump(pa);
- continue;
-ok:
-#endif
- pte = (pt_entry_t *)(pv->pv_va + ALPHA_PAGE_SIZE);
- while (--pte >= (pt_entry_t *)pv->pv_va && *pte == PG_NV)
- ;
- if (pte >= (pt_entry_t *)pv->pv_va)
- continue;
-
-#ifdef DEBUG
- if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT)) {
- printf("collect: freeing KPT page at %lx (ste %lx@%p)\n",
- pv->pv_va, *pv->pv_ptpte, pv->pv_ptpte);
- opmapdebug = pmapdebug;
- pmapdebug |= PDB_PTPAGE;
- }
-
- ste = pv->pv_ptpte;
-#endif
- /*
- * If all entries were invalid we can remove the page.
- * We call pmap_remove_entry to take care of invalidating
- * ST and Sysptmap entries.
- */
- kpa = pmap_extract(pmap, pv->pv_va);
- pmap_remove_mapping(pmap, pv->pv_va, PT_ENTRY_NULL,
- PRM_TFLUSH|PRM_CFLUSH);
- /*
- * Use the physical address to locate the original
- * (kmem_alloc assigned) address for the page and put
- * that page back on the free list.
- */
- for (pkpt = &kpt_used_list, kpt = *pkpt;
- kpt != (struct kpt_page *)0;
- pkpt = &kpt->kpt_next, kpt = *pkpt)
- if (kpt->kpt_pa == kpa)
- break;
-#ifdef DEBUG
- if (kpt == (struct kpt_page *)0)
- panic("pmap_collect: lost a KPT page");
- if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT))
- printf("collect: %lx (%lx) to free list\n",
- kpt->kpt_va, kpa);
-#endif
- *pkpt = kpt->kpt_next;
- kpt->kpt_next = kpt_free_list;
- kpt_free_list = kpt;
-#ifdef PMAPSTATS
- kpt_stats.kptinuse--;
- kpt_stats.collectpages++;
-#endif
-#ifdef DEBUG
- if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT))
- pmapdebug = opmapdebug;
-
- if (*ste)
- printf("collect: kernel STE at %p still valid (%lx)\n",
- ste, *ste);
- ste = &Sysptmap[(pt_entry_t *)ste-pmap_ste(pmap_kernel(), 0)];
- if (*ste)
- printf("collect: kernel PTmap at %p still valid (%lx)\n",
- ste, *ste);
-#endif
- }
- splx(s);
-}
-
-void
-pmap_activate(pmap)
- register pmap_t pmap;
-{
- int iscurproc;
-
-#ifdef DEBUG
- if (pmapdebug & (PDB_FOLLOW|PDB_SEGTAB))
- printf("pmap_activate(%p)\n", pmap);
-#endif
-
- iscurproc = curproc != NULL && pmap == curproc->p_vmspace->vm_map.pmap;
- PMAP_ACTIVATE(pmap, iscurproc);
-}
-
-/*
- * pmap_zero_page zeros the specified (machine independent)
- * page by mapping the page into virtual memory and using
- * bzero to clear its contents, one machine dependent page
- * at a time.
- */
-void
-pmap_zero_page(phys)
- vm_offset_t phys;
-{
- caddr_t p;
-
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("pmap_zero_page(%lx)\n", phys);
-#endif
- p = (caddr_t)ALPHA_PHYS_TO_K0SEG(phys);
- bzero(p, PAGE_SIZE);
-}
-
-/*
- * pmap_copy_page copies the specified (machine independent)
- * page by mapping the page into virtual memory and using
- * bcopy to copy the page, one machine dependent page at a
- * time.
- */
-void
-pmap_copy_page(src, dst)
- vm_offset_t src, dst;
-{
- caddr_t s, d;
-
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("pmap_copy_page(%lx, %lx)\n", src, dst);
-#endif
- s = (caddr_t)ALPHA_PHYS_TO_K0SEG(src);
- d = (caddr_t)ALPHA_PHYS_TO_K0SEG(dst);
- bcopy(s, d, PAGE_SIZE);
-}
-
-/*
- * Routine: pmap_pageable
- * Function:
- * Make the specified pages (by pmap, offset)
- * pageable (or not) as requested.
- *
- * A page which is not pageable may not take
- * a fault; therefore, its page table entry
- * must remain valid for the duration.
- *
- * This routine is merely advisory; pmap_enter
- * will specify that these pages are to be wired
- * down (or not) as appropriate.
- */
-void
-pmap_pageable(pmap, sva, eva, pageable)
- pmap_t pmap;
- vm_offset_t sva, eva;
- boolean_t pageable;
-{
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("pmap_pageable(%p, %lx, %lx, %x)\n",
- pmap, sva, eva, pageable);
-#endif
- /*
- * If we are making a PT page pageable then all valid
- * mappings must be gone from that page. Hence it should
- * be all zeros and there is no need to clean it.
- * Assumptions:
- * - we are called with only one page at a time
- * - PT pages have only one pv_table entry
- */
- if (pmap == pmap_kernel() && pageable && sva + PAGE_SIZE == eva) {
- register pv_entry_t pv;
- register vm_offset_t pa;
-
-#ifdef DEBUG
- if ((pmapdebug & (PDB_FOLLOW|PDB_PTPAGE)) == PDB_PTPAGE)
- printf("pmap_pageable(%p, %lx, %lx, %x)\n",
- pmap, sva, eva, pageable);
-#endif
- if (!pmap_ste_v(pmap, sva))
- return;
- pa = pmap_pte_pa(pmap_pte(pmap, sva));
- if (!PAGE_IS_MANAGED(pa))
- return;
- pv = pa_to_pvh(pa);
- if (pv->pv_ptpte == NULL)
- return;
-#ifdef DEBUG
- if (pv->pv_va != sva || pv->pv_next) {
- printf("pmap_pageable: bad PT page va %lx next %p\n",
- pv->pv_va, pv->pv_next);
- return;
- }
-#endif
- /*
- * Mark it unmodified to avoid pageout
- */
- pmap_clear_modify(pa);
-#ifdef DEBUG
- if ((PHYS_TO_VM_PAGE(pa)->flags & PG_CLEAN) == 0) {
- printf("pa %lx: flags=%x: not clean\n",
- pa, PHYS_TO_VM_PAGE(pa)->flags);
- PHYS_TO_VM_PAGE(pa)->flags |= PG_CLEAN;
- }
- if (pmapdebug & PDB_PTPAGE)
- printf("pmap_pageable: PT page %lx(%lx) unmodified\n",
- sva, *pmap_pte(pmap, sva));
- if (pmapdebug & PDB_WIRING)
- pmap_check_wiring("pageable", sva);
-#endif
- }
-}
-
-/*
- * Clear the modify bits on the specified physical page.
- */
-
-void
-pmap_clear_modify(pa)
- vm_offset_t pa;
-{
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("pmap_clear_modify(%lx)\n", pa);
-#endif
- if (!PAGE_IS_MANAGED(pa)) /* XXX why not panic? */
- return;
- if ((pmap_attributes[pa_index(pa)] & PMAP_ATTR_MOD) != 0) {
- pmap_changebit(pa, PG_FOW, TRUE);
- pmap_attributes[pa_index(pa)] &= ~PMAP_ATTR_MOD;
- }
-}
-
-/*
- * pmap_clear_reference:
- *
- * Clear the reference bit on the specified physical page.
- */
-
-void pmap_clear_reference(pa)
- vm_offset_t pa;
-{
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("pmap_clear_reference(%lx)\n", pa);
-#endif
- if (!PAGE_IS_MANAGED(pa)) /* XXX why not panic? */
- return;
- if ((pmap_attributes[pa_index(pa)] & PMAP_ATTR_REF) != 0) {
- pmap_changebit(pa, PG_FOR | PG_FOW | PG_FOE, TRUE);
- pmap_attributes[pa_index(pa)] &= ~PMAP_ATTR_REF;
- }
-}
-
-/*
- * pmap_is_referenced:
- *
- * Return whether or not the specified physical page is referenced
- * by any physical maps.
- */
-
-boolean_t
-pmap_is_referenced(pa)
- vm_offset_t pa;
-{
- boolean_t rv;
-
- if (!PAGE_IS_MANAGED(pa)) /* XXX why not panic? */
- return 0;
- rv = (pmap_attributes[pa_index(pa)] & PMAP_ATTR_REF) != 0;
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW) {
- printf("pmap_is_referenced(%lx) -> %c\n", pa, "FT"[rv]);
- }
-#endif
- return rv;
-}
-
-/*
- * pmap_is_modified:
- *
- * Return whether or not the specified physical page is modified
- * by any physical maps.
- */
-
-boolean_t
-pmap_is_modified(pa)
- vm_offset_t pa;
-{
- boolean_t rv;
-
- if (!PAGE_IS_MANAGED(pa)) /* XXX why not panic? */
- return 0;
- rv = (pmap_attributes[pa_index(pa)] & PMAP_ATTR_MOD) != 0;
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW) {
- printf("pmap_is_modified(%lx) -> %c\n", pa, "FT"[rv]);
- }
-#endif
- return rv;
-}
-
-vm_offset_t
-pmap_phys_address(ppn)
- int ppn;
-{
- return(alpha_ptob(ppn));
-}
-
-/*
- * Miscellaneous support routines follow
- */
-
-/*
- * Initialize Alpha protection code array.
- */
-/* static */
-void
-alpha_protection_init()
-{
- int prot, *kp, *up;
-
- kp = protection_codes[0];
- up = protection_codes[1];
-
- for (prot = 0; prot < 8; prot++) {
- switch (prot) {
- case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE:
- *kp++ = PG_ASM;
- *up++ = 0;
- break;
- case VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE:
- case VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE:
- case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE:
- *kp++ = PG_ASM | PG_KRE;
- *up++ = PG_URE | PG_KRE;
- break;
- case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE:
- *kp++ = PG_ASM | PG_KWE;
- *up++ = PG_UWE | PG_KWE;
- break;
- case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE:
- case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE:
- case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
- *kp++ = PG_ASM | PG_KWE | PG_KRE;
- *up++ = PG_UWE | PG_URE | PG_KWE | PG_KRE;
- break;
- }
- }
-}
-
-/*
- * Invalidate a single page denoted by pmap/va.
- * If (pte != NULL), it is the already computed PTE for the page.
- * If (flags & PRM_TFLUSH), we must invalidate any TLB information.
- * If (flags & PRM_CFLUSH), we must flush/invalidate any cache information.
- */
-/* static */
-void
-pmap_remove_mapping(pmap, va, pte, flags)
- register pmap_t pmap;
- register vm_offset_t va;
- register pt_entry_t *pte;
- int flags;
-{
- register vm_offset_t pa;
- register pv_entry_t pv, npv;
- pmap_t ptpmap;
- pt_entry_t *ste;
- int s;
-#ifdef DEBUG
- pt_entry_t opte;
-
- if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT))
- printf("pmap_remove_mapping(%p, %lx, %p, %x)\n",
- pmap, va, pte, flags);
-#endif
-
- /*
- * PTE not provided, compute it from pmap and va.
- */
- if (pte == PT_ENTRY_NULL) {
- pte = pmap_pte(pmap, va);
- if (*pte == PG_NV)
- return;
- }
- pa = pmap_pte_pa(pte);
-#ifdef DEBUG
- opte = *pte;
-#endif
-#ifdef PMAPSTATS
- remove_stats.removes++;
-#endif
- /*
- * Update statistics
- */
- if (pmap_pte_w(pte))
- pmap->pm_stats.wired_count--;
- pmap->pm_stats.resident_count--;
-
- /*
- * Invalidate the PTE after saving the reference modify info.
- */
-#ifdef DEBUG
- if (pmapdebug & PDB_REMOVE)
- printf("remove: invalidating pte at %p\n", pte);
-#endif
- *pte = PG_NV;
- if ((flags & PRM_TFLUSH) && active_pmap(pmap))
- ALPHA_TBIS(va);
- /*
- * For user mappings decrement the wiring count on
- * the PT page. We do this after the PTE has been
- * invalidated because vm_map_pageable winds up in
- * pmap_pageable which clears the modify bit for the
- * PT page.
- */
- if (pmap != pmap_kernel()) {
- (void) vm_map_pageable(pt_map, trunc_page(pte),
- round_page(pte+1), TRUE);
-#ifdef DEBUG
- if (pmapdebug & PDB_WIRING)
- pmap_check_wiring("remove", trunc_page(pte));
-#endif
- }
- /*
- * If this isn't a managed page, we are all done.
- */
- if (!PAGE_IS_MANAGED(pa))
- return;
- /*
- * Otherwise remove it from the PV table
- * (raise IPL since we may be called at interrupt time).
- */
- pv = pa_to_pvh(pa);
- ste = NULL;
- s = splimp();
- /*
- * If it is the first entry on the list, it is actually
- * in the header and we must copy the following entry up
- * to the header. Otherwise we must search the list for
- * the entry. In either case we free the now unused entry.
- */
- if (pmap == pv->pv_pmap && va == pv->pv_va) {
- ste = pv->pv_ptpte;
- ptpmap = pv->pv_ptpmap;
- npv = pv->pv_next;
- if (npv) {
- npv->pv_flags = pv->pv_flags;
- *pv = *npv;
- free((caddr_t)npv, M_VMPVENT);
- } else
- pv->pv_pmap = NULL;
-#ifdef PMAPSTATS
- remove_stats.pvfirst++;
-#endif
- } else {
- for (npv = pv->pv_next; npv; npv = npv->pv_next) {
-#ifdef PMAPSTATS
- remove_stats.pvsearch++;
-#endif
- if (pmap == npv->pv_pmap && va == npv->pv_va)
- break;
- pv = npv;
- }
-#ifdef DEBUG
- if (npv == NULL)
- panic("pmap_remove: PA not in pv_tab");
-#endif
- ste = npv->pv_ptpte;
- ptpmap = npv->pv_ptpmap;
- pv->pv_next = npv->pv_next;
- free((caddr_t)npv, M_VMPVENT);
- pv = pa_to_pvh(pa);
- }
- /*
- * If this was a PT page we must also remove the
- * mapping from the associated segment table.
- */
- if (ste) {
-#ifdef PMAPSTATS
- remove_stats.ptinvalid++;
-#endif
-#ifdef DEBUG
- if (pmapdebug & (PDB_REMOVE|PDB_PTPAGE))
- printf("remove: ste was %lx@%p pte was %lx@%p\n",
- *ste, ste, opte, pmap_pte(pmap, va));
-#endif
- *ste = PG_NV;
- /*
- * If it was a user PT page, we decrement the
- * reference count on the segment table as well,
- * freeing it if it is now empty.
- */
- if (ptpmap != pmap_kernel()) {
-#ifdef DEBUG
- if (pmapdebug & (PDB_REMOVE|PDB_SEGTAB))
- printf("remove: stab %p, refcnt %d\n",
- ptpmap->pm_stab, ptpmap->pm_sref - 1);
- if ((pmapdebug & PDB_PARANOIA) &&
- ptpmap->pm_stab != (pt_entry_t *)trunc_page(ste))
- panic("remove: bogus ste");
-#endif
- if (--(ptpmap->pm_sref) == 0) {
-#ifdef DEBUG
- if (pmapdebug&(PDB_REMOVE|PDB_SEGTAB))
- printf("remove: free stab %p\n",
- ptpmap->pm_stab);
-#endif
- kmem_free_wakeup(st_map,
- (vm_offset_t)ptpmap->pm_stab,
- ALPHA_STSIZE);
- ptpmap->pm_stab = Segtabzero;
- ptpmap->pm_stpte = Segtabzeropte;
- ptpmap->pm_stchanged = TRUE;
- /*
- * XXX may have changed segment table
- * pointer for current process so
- * update now to reload hardware.
- * (curproc may be NULL if exiting.)
- */
- if (curproc != NULL &&
- ptpmap == curproc->p_vmspace->vm_map.pmap)
- PMAP_ACTIVATE(ptpmap, 1);
- }
-#ifdef DEBUG
- else if (ptpmap->pm_sref < 0)
- panic("remove: sref < 0");
-#endif
- }
-#if 0
- /*
- * XXX this should be unnecessary as we have been
- * flushing individual mappings as we go.
- */
- if (ptpmap == pmap_kernel())
- ALPHA_TBIAS();
- else
- ALPHA_TBIAU();
-#endif
- pv->pv_flags &= ~PV_PTPAGE;
- ptpmap->pm_ptpages--;
- }
- splx(s);
-}
-
-/* static */
-void
-pmap_changebit(pa, bit, setem)
- register vm_offset_t pa;
- u_long bit;
- boolean_t setem;
-{
- register pv_entry_t pv;
- register pt_entry_t *pte, npte;
- vm_offset_t va;
- int s;
-#ifdef PMAPSTATS
- struct chgstats *chgp;
-#endif
-
-#ifdef DEBUG
- if (pmapdebug & PDB_BITS)
- printf("pmap_changebit(%lx, %lx, %s)\n",
- pa, bit, setem ? "set" : "clear");
-#endif
- if (!PAGE_IS_MANAGED(pa))
- return;
-
-#ifdef PMAPSTATS
- chgp = &changebit_stats[(bit>>2)-1];
- if (setem)
- chgp->setcalls++;
- else
- chgp->clrcalls++;
-#endif
- pv = pa_to_pvh(pa);
- s = splimp();
- /*
- * Loop over all current mappings setting/clearing as appropos
- * If setting RO do we need to clear the VAC?
- */
- if (pv->pv_pmap != NULL) {
-#ifdef DEBUG
- int toflush = 0;
-#endif
- for (; pv; pv = pv->pv_next) {
-#ifdef DEBUG
- toflush |= (pv->pv_pmap == pmap_kernel()) ? 2 : 1;
-#endif
- va = pv->pv_va;
-
- /*
- * XXX don't write protect pager mappings
- */
-/* XXX */ if (bit == (PG_UWE | PG_KWE)) {
- extern vm_offset_t pager_sva, pager_eva;
-
- if (va >= pager_sva && va < pager_eva)
- continue;
- }
-
- pte = pmap_pte(pv->pv_pmap, va);
- if (setem)
- npte = *pte | bit;
- else
- npte = *pte & ~bit;
- if (*pte != npte) {
- *pte = npte;
- if (active_pmap(pv->pv_pmap))
- ALPHA_TBIS(va);
-#ifdef PMAPSTATS
- if (setem)
- chgp->sethits++;
- else
- chgp->clrhits++;
-#endif
- }
-#ifdef PMAPSTATS
- else {
- if (setem)
- chgp->setmiss++;
- else
- chgp->clrmiss++;
- }
-#endif
- }
- }
- splx(s);
-}
-
-/* static */
-void
-pmap_enter_ptpage(pmap, va)
- register pmap_t pmap;
- register vm_offset_t va;
-{
- register vm_offset_t ptpa;
- register pv_entry_t pv;
- pt_entry_t *ste;
- int s;
-
-#ifdef DEBUG
- if (pmapdebug & (PDB_FOLLOW|PDB_ENTER|PDB_PTPAGE))
- printf("pmap_enter_ptpage: pmap %p, va %lx\n", pmap, va);
-#endif
-#ifdef PMAPSTATS
- enter_stats.ptpneeded++;
-#endif
- /*
- * Allocate a segment table if necessary. Note that it is allocated
- * from a private map and not pt_map. This keeps user page tables
- * aligned on segment boundaries in the kernel address space.
- * The segment table is wired down. It will be freed whenever the
- * reference count drops to zero.
- */
- if (pmap->pm_stab == Segtabzero) {
- pmap->pm_stab = (pt_entry_t *)
- kmem_alloc(st_map, ALPHA_STSIZE);
- pmap->pm_stpte = *kvtopte(pmap->pm_stab);
- pmap->pm_stchanged = TRUE;
- /*
- * XXX may have changed segment table pointer for current
- * process so update now to reload hardware.
- */
- if (pmap == curproc->p_vmspace->vm_map.pmap)
- PMAP_ACTIVATE(pmap, 1);
-#ifdef DEBUG
- if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB))
- printf("enter: pmap %p stab %p(%lx)\n",
- pmap, pmap->pm_stab, pmap->pm_stpte);
-#endif
- }
-
- ste = pmap_ste(pmap, va);
- va = trunc_page((vm_offset_t)pmap_pte(pmap, va));
-
- /*
- * In the kernel we allocate a page from the kernel PT page
- * free list and map it into the kernel page table map (via
- * pmap_enter).
- */
- if (pmap == pmap_kernel()) {
- register struct kpt_page *kpt;
-
- s = splimp();
- if ((kpt = kpt_free_list) == (struct kpt_page *)0) {
- /*
- * No PT pages available.
- * Try once to free up unused ones.
- */
-#ifdef DEBUG
- if (pmapdebug & PDB_COLLECT)
- printf("enter: no KPT pages, collecting...\n");
-#endif
- pmap_collect(pmap_kernel());
- if ((kpt = kpt_free_list) == (struct kpt_page *)0)
- panic("pmap_enter_ptpage: can't get KPT page");
- }
-#ifdef PMAPSTATS
- if (++kpt_stats.kptinuse > kpt_stats.kptmaxuse)
- kpt_stats.kptmaxuse = kpt_stats.kptinuse;
-#endif
- kpt_free_list = kpt->kpt_next;
- kpt->kpt_next = kpt_used_list;
- kpt_used_list = kpt;
- ptpa = kpt->kpt_pa;
- bzero((caddr_t)kpt->kpt_va, ALPHA_PAGE_SIZE);
- pmap_enter(pmap, va, ptpa, VM_PROT_DEFAULT, TRUE, 0);
-#ifdef DEBUG
- if (pmapdebug & (PDB_ENTER|PDB_PTPAGE)) {
- int ix = pmap_ste(pmap, va) - pmap_ste(pmap, 0);
-
- printf("enter: add &Sysptmap[%d]: %lx (KPT page %lx)\n",
- ix, Sysptmap[ix], kpt->kpt_va);
- }
-#endif
- splx(s);
- }
- /*
- * For user processes we just simulate a fault on that location
- * letting the VM system allocate a zero-filled page.
- */
- else {
- /*
- * Count the segment table reference now so that we won't
- * lose the segment table when low on memory.
- */
- pmap->pm_sref++;
-#ifdef DEBUG
- if (pmapdebug & (PDB_ENTER|PDB_PTPAGE))
- printf("enter: about to fault UPT pg at %lx\n", va);
-#endif
- s = vm_fault(pt_map, va, VM_PROT_READ|VM_PROT_WRITE, FALSE);
- if (s != KERN_SUCCESS) {
- printf("vm_fault(pt_map, %lx, RW, 0) -> %d\n", va, s);
- panic("pmap_enter: vm_fault failed");
- }
- ptpa = pmap_extract(pmap_kernel(), va);
- /*
- * Mark the page clean now to avoid its pageout (and
- * hence creation of a pager) between now and when it
- * is wired; i.e. while it is on a paging queue.
- */
- PHYS_TO_VM_PAGE(ptpa)->flags |= PG_CLEAN;
-#ifdef DEBUG
- PHYS_TO_VM_PAGE(ptpa)->flags |= PG_PTPAGE;
-#endif
- }
- /*
- * Locate the PV entry in the kernel for this PT page and
- * record the STE address. This is so that we can invalidate
- * the STE when we remove the mapping for the page.
- */
- pv = pa_to_pvh(ptpa);
- s = splimp();
- if (pv) {
- pv->pv_flags |= PV_PTPAGE;
- do {
- if (pv->pv_pmap == pmap_kernel() && pv->pv_va == va)
- break;
- } while ((pv = pv->pv_next) != NULL);
- }
-#ifdef DEBUG
- if (pv == NULL)
- panic("pmap_enter_ptpage: PT page not entered");
-#endif
- pv->pv_ptpte = ste;
- pv->pv_ptpmap = pmap;
-#ifdef DEBUG
- if (pmapdebug & (PDB_ENTER|PDB_PTPAGE))
- printf("enter: new PT page at PA 0x%lx, ste at %p\n", ptpa, ste);
-#endif
-
- /*
- * Map the new PT page into the segment table.
- * Reference count on the user segment tables incremented above
- * to prevent race conditions. Note that we don't use vm_map_pageable
- * to keep the count like we do for PT pages, this is mostly because
- * it would be difficult to identify ST pages in pmap_pageable to
- * release them. We also avoid the overhead of vm_map_pageable.
- */
- *ste = ((ptpa >> PGSHIFT) << PG_SHIFT) | PG_KRE | PG_KWE | PG_V |
- (pmap == pmap_kernel() ? PG_ASM : 0);
- if (pmap != pmap_kernel()) {
-#ifdef DEBUG
- if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB))
- printf("enter: stab %p refcnt %d\n",
- pmap->pm_stab, pmap->pm_sref);
-#endif
- }
-#if 0
- /*
- * Flush stale TLB info.
- */
- if (pmap == pmap_kernel())
- ALPHA_TBIAS();
- else
- ALPHA_TBIAU();
-#endif
- pmap->pm_ptpages++;
- splx(s);
-}
-
-/*
- * Emulate reference and/or modified bit hits.
- */
-void
-pmap_emulate_reference(p, v, user, write)
- struct proc *p;
- vm_offset_t v;
- int user;
- int write;
-{
- pt_entry_t faultoff, *pte;
- vm_offset_t pa;
- char attr;
-
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("pmap_emulate_reference: %p, 0x%lx, %d, %d\n",
- p, v, user, write);
-#endif
-
- /*
- * Convert process and virtual address to physical address.
- */
- if (v >= VM_MIN_KERNEL_ADDRESS) {
- if (user)
- panic("pmap_emulate_reference: user ref to kernel");
- pte = kvtopte(v);
- } else {
-#ifdef DIAGNOSTIC
- if (p == NULL)
- panic("pmap_emulate_reference: bad proc");
- if (p->p_vmspace == NULL)
- panic("pmap_emulate_reference: bad p_vmspace");
-#endif
- pte = pmap_pte(p->p_vmspace->vm_map.pmap, v);
- }
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW) {
- printf("\tpte = %p, ", pte);
- printf("*pte = 0x%lx\n", *pte);
- }
-#endif
-#ifdef DEBUG /* These checks are more expensive */
- if (!pmap_pte_v(pte))
- panic("pmap_emulate_reference: invalid pte");
-#if 0
- /*
- * Can't do these, because cpu_fork and cpu_swapin call
- * pmap_emulate_reference(), and the bits aren't guaranteed,
- * for them...
- */
- if (write) {
- if (!(*pte & (user ? PG_UWE : PG_UWE | PG_KWE)))
- panic("pmap_emulate_reference: write but unwritable");
- if (!(*pte & PG_FOW))
- panic("pmap_emulate_reference: write but not FOW");
- } else {
- if (!(*pte & (user ? PG_URE : PG_URE | PG_KRE)))
- panic("pmap_emulate_reference: !write but unreadable");
- if (!(*pte & (PG_FOR | PG_FOE)))
- panic("pmap_emulate_reference: !write but not FOR|FOE");
- }
-#endif
- /* Other diagnostics? */
-#endif
- pa = pmap_pte_pa(pte);
-#ifdef DEBUG
- if (pmapdebug & PDB_FOLLOW)
- printf("\tpa = 0x%lx\n", pa);
-#endif
-#ifdef DIAGNOSTIC
- if (!PAGE_IS_MANAGED(pa))
- printf("WARNING: pmap_emulate_reference(%p, 0x%lx, %d, %d): pa 0x%lx not managed\n", p, v, user, write, pa);
-#endif
-
- /*
- * Twiddle the appropriate bits to reflect the reference
- * and/or modification..
- *
- * The rules:
- * (1) always mark page as used, and
- * (2) if it was a write fault, mark page as modified.
- */
- attr = PMAP_ATTR_REF;
- faultoff = PG_FOR | PG_FOE;
- if (write) {
- attr |= PMAP_ATTR_MOD;
- faultoff |= PG_FOW;
- }
- pmap_attributes[pa_index(pa)] |= attr;
- pmap_changebit(pa, faultoff, FALSE);
- if ((*pte & faultoff) != 0) {
-#if 0
- /*
- * This is apparently normal. Why? -- cgd
- * XXX because was being called on unmanaged pages?
- */
- printf("warning: pmap_changebit didn't.");
-#endif
- *pte &= ~faultoff;
- ALPHA_TBIS(v);
- }
-}
-
-#ifdef DEBUG
-/* static */
-void
-pmap_pvdump(pa)
- vm_offset_t pa;
-{
- register pv_entry_t pv;
-
- printf("pa %lx", pa);
- for (pv = pa_to_pvh(pa); pv; pv = pv->pv_next)
- printf(" -> pmap %p, va %lx, stpte %p, ptpmap %p, flags %x",
- pv->pv_pmap, pv->pv_va, pv->pv_ptpte, pv->pv_ptpmap,
- pv->pv_flags);
- printf("\n");
-}
-
-/* static */
-void
-pmap_check_wiring(str, va)
- char *str;
- vm_offset_t va;
-{
- vm_map_entry_t entry;
- pt_entry_t *pte;
- register int count;
-
- va = trunc_page(va);
- if (!pmap_ste_v(pmap_kernel(), va) ||
- !pmap_pte_v(pmap_pte(pmap_kernel(), va)))
- return;
-
- if (!vm_map_lookup_entry(pt_map, va, &entry)) {
- printf("wired_check: entry for %lx not found\n", va);
- return;
- }
- count = 0;
- for (pte = (pt_entry_t *)va; pte < (pt_entry_t *)(va+PAGE_SIZE); pte++)
- if (*pte)
- count++;
- if (entry->wired_count != count)
- printf("*%s*: %lx: w%d/a%d\n",
- str, va, entry->wired_count, count);
-}
-#endif
-
-vm_offset_t
-vtophys(vaddr)
- vm_offset_t vaddr;
-{
- vm_offset_t paddr;
-
- if (vaddr < ALPHA_K0SEG_BASE) {
- printf("vtophys: invalid vaddr 0x%lx", vaddr);
- paddr = vaddr;
- } else if (vaddr <= ALPHA_K0SEG_END)
- paddr = ALPHA_K0SEG_TO_PHYS(vaddr);
- else
- paddr = vatopa(vaddr);
-
-#if 0
- printf("vtophys(0x%lx) -> %lx\n", vaddr, paddr);
-#endif
-
- return (paddr);
-}