diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2002-02-22 22:45:35 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2002-02-22 22:45:35 +0000 |
commit | 58689227b203f959e5386aead56d74acf571f6d6 (patch) | |
tree | 0fe4a68a529bbff7009ac2da2fef67c789ac5750 /sys/arch/mvme68k | |
parent | 999f254bdd1f007fada89ad11fc0a375dc246c26 (diff) |
Switch mvme68k to pmap_motorola again.
68060 operation tested by deraadt@
Diffstat (limited to 'sys/arch/mvme68k')
-rw-r--r-- | sys/arch/mvme68k/conf/files.mvme68k | 4 | ||||
-rw-r--r-- | sys/arch/mvme68k/include/param.h | 21 | ||||
-rw-r--r-- | sys/arch/mvme68k/include/pmap.h | 158 | ||||
-rw-r--r-- | sys/arch/mvme68k/include/pte.h | 158 | ||||
-rw-r--r-- | sys/arch/mvme68k/mvme68k/pmap.c | 2403 | ||||
-rw-r--r-- | sys/arch/mvme68k/mvme68k/pmap_bootstrap.c | 39 |
6 files changed, 39 insertions, 2744 deletions
diff --git a/sys/arch/mvme68k/conf/files.mvme68k b/sys/arch/mvme68k/conf/files.mvme68k index e8801595ab7..f80864c825f 100644 --- a/sys/arch/mvme68k/conf/files.mvme68k +++ b/sys/arch/mvme68k/conf/files.mvme68k @@ -1,4 +1,4 @@ -# $OpenBSD: files.mvme68k,v 1.21 2001/12/20 19:02:29 miod Exp $ +# $OpenBSD: files.mvme68k,v 1.22 2002/02/22 22:45:30 miod Exp $ # config file for mvme68k @@ -115,7 +115,7 @@ file arch/mvme68k/mvme68k/disksubr.c file arch/mvme68k/mvme68k/dkbad.c file arch/mvme68k/mvme68k/machdep.c file arch/mvme68k/mvme68k/mem.c -file arch/mvme68k/mvme68k/pmap.c +file arch/m68k/m68k/pmap_motorola.c file arch/mvme68k/mvme68k/pmap_bootstrap.c file arch/mvme68k/mvme68k/sys_machdep.c file arch/mvme68k/mvme68k/trap.c diff --git a/sys/arch/mvme68k/include/param.h b/sys/arch/mvme68k/include/param.h index b3b64736ec6..a5bede421ac 100644 --- a/sys/arch/mvme68k/include/param.h +++ b/sys/arch/mvme68k/include/param.h @@ -1,4 +1,4 @@ -/* $OpenBSD: param.h,v 1.16 2001/12/20 19:02:29 miod Exp $ */ +/* $OpenBSD: param.h,v 1.17 2002/02/22 22:45:34 miod Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -57,12 +57,6 @@ #define PAGE_SIZE (1 << PAGE_SHIFT) #define PAGE_MASK (PAGE_SIZE - 1) -#define NPTEPG (NBPG/(sizeof (pt_entry_t))) - -#define SEGSHIFT 22 /* LOG2(NBSEG) */ -#define NBSEG (1 << SEGSHIFT) /* bytes/segment */ -#define SEGOFSET (NBSEG-1) /* byte offset into segment */ - #define KERNBASE 0x00000000 /* start of kernel virtual */ #define KERNTEXTOFF 0x00010000 /* start of kernel text */ @@ -92,17 +86,4 @@ #define DELAY(n) delay(n) #endif -#ifdef COMPAT_HPUX -/* - * Constants/macros for HPUX multiple mapping of user address space. - * Pages in the first 256Mb are mapped in at every 256Mb segment. - */ -#define HPMMMASK 0xF0000000 -#define ISHPMMADDR(v) \ - ((curproc->p_md.md_flags & MDP_HPUXMMAP) && \ - ((unsigned)(v) & HPMMMASK) && \ - ((unsigned)(v) & HPMMMASK) != HPMMMASK) -#define HPMMBASEADDR(v) \ - ((unsigned)(v) & ~HPMMMASK) -#endif #endif /* _MACHINE_PARAM_H_ */ diff --git a/sys/arch/mvme68k/include/pmap.h b/sys/arch/mvme68k/include/pmap.h index 2e873a725f9..9e32d5ed681 100644 --- a/sys/arch/mvme68k/include/pmap.h +++ b/sys/arch/mvme68k/include/pmap.h @@ -1,155 +1,13 @@ -/* $OpenBSD: pmap.h,v 1.10 2001/12/20 19:02:29 miod Exp $ */ +/* $OpenBSD: pmap.h,v 1.11 2002/02/22 22:45:34 miod Exp $ */ -/* - * Copyright (c) 1987 Carnegie-Mellon University - * 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.h 8.1 (Berkeley) 6/10/93 - */ +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ -#ifndef _MVME68K_PMAP_H_ -#define _MVME68K_PMAP_H_ - -#include <machine/pte.h> - -#if defined(M68040) -#define M68K_SEG_SIZE (mmutype == MMU_68040 ? 0x40000 : NBSEG) -#else -#define M68K_SEG_SIZE NBSEG -#endif - -/* - * Pmap stuff - */ -struct pmap { - pt_entry_t *pm_ptab; /* KVA of page table */ - st_entry_t *pm_stab; /* KVA of segment table */ - int pm_stfree; /* 040: free lev2 blocks */ - st_entry_t *pm_stpa; /* 040: ST phys addr */ - short pm_sref; /* segment table ref count */ - short pm_count; /* pmap reference count */ - struct simplelock pm_lock; /* lock on pmap */ - struct pmap_statistics pm_stats; /* pmap statistics */ - long pm_ptpages; /* more stats: PT pages */ -}; - -typedef struct pmap *pmap_t; - -/* - * On the 040 we keep track of which level 2 blocks are already in use - * with the pm_stfree mask. Bits are arranged from LSB (block 0) to MSB - * (block 31). For convenience, the level 1 table is considered to be - * block 0. - * - * MAX[KU]L2SIZE control how many pages of level 2 descriptors are allowed. - * for the kernel and users. 8 implies only the initial "segment table" - * page is used. WARNING: don't change MAXUL2SIZE unless you can allocate - * physically contiguous pages for the ST in pmap.c! - */ -#define MAXKL2SIZE 32 -#define MAXUL2SIZE 8 -#define l2tobm(n) (1 << (n)) -#define bmtol2(n) (ffs(n) - 1) - -/* - * Macros for speed - */ -#define PMAP_ACTIVATE(pmap, loadhw) \ -{ \ - if ((loadhw)) \ - loadustp(m68k_btop((vm_offset_t)(pmap)->pm_stpa)); \ -} - -/* - * For each vm_page_t, there is a list of all currently valid virtual - * mappings of that page. An entry is a pv_entry, the list is pv_table. - */ -struct pv_entry { - struct pv_entry *pv_next; /* next pv_entry */ - struct pmap *pv_pmap; /* pmap where mapping lies */ - vm_offset_t pv_va; /* virtual address for mapping */ - st_entry_t *pv_ptste; /* non-zero if VA maps a PT page */ - struct pmap *pv_ptpmap; /* if pv_ptste, pmap for PT page */ - int pv_flags; /* flags */ -}; - -#define PV_CI 0x01 /* header: all entries are cache inhibited */ -#define PV_PTPAGE 0x02 /* header: entry maps a page table page */ - -struct pv_page; - -struct pv_page_info { - TAILQ_ENTRY(pv_page) pgi_list; - struct pv_entry *pgi_freelist; - int pgi_nfree; -}; - -/* - * This is basically: - * ((NBPG - sizeof(struct pv_page_info)) / sizeof(struct pv_entry)) - */ -#define NPVPPG 170 - -struct pv_page { - struct pv_page_info pvp_pgi; - struct pv_entry pvp_pv[NPVPPG]; -}; +#include <m68k/pmap_motorola.h> #ifdef _KERNEL +void pmap_init_md __P((void)); +#define PMAP_INIT_MD() pmap_init_md() +#endif -extern struct pmap kernel_pmap_store; - -#define pmap_kernel() (&kernel_pmap_store) -#define active_pmap(pm) \ - ((pm) == pmap_kernel() || (pm) == curproc->p_vmspace->vm_map.pmap) -#define active_user_pmap(pm) \ - (curproc && \ - (pm) != pmap_kernel() && (pm) == curproc->p_vmspace->vm_map.pmap) - - -extern struct pv_entry *pv_table; /* array of entries, one per page */ - -#define pmap_page_index(pa) atop(pa - vm_first_phys) - -#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) -#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) -#define pmap_update(pmap) /* nothing */ - -extern pt_entry_t *Sysmap; -extern char *vmmap; /* map for mem, dumps, etc. */ -#endif /* _KERNEL */ - -#endif /* !_MVME68K_PMAP_H_ */ +#endif /* _MACHINE_PMAP_H_ */ diff --git a/sys/arch/mvme68k/include/pte.h b/sys/arch/mvme68k/include/pte.h index 78e9deb44c8..7d9b9ed582d 100644 --- a/sys/arch/mvme68k/include/pte.h +++ b/sys/arch/mvme68k/include/pte.h @@ -1,152 +1,14 @@ -/* $OpenBSD: pte.h,v 1.6 2001/12/20 19:02:29 miod Exp $ */ +/* $OpenBSD: pte.h,v 1.7 2002/02/22 22:45:34 miod Exp $ */ -/* - * Copyright (c) 1988 University of Utah. - * Copyright (c) 1982, 1986, 1990, 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. - * - * from: Utah $Hdr: pte.h 1.13 92/01/20$ - * - * @(#)pte.h 8.1 (Berkeley) 6/10/93 - */ +#ifndef _MACHINE_PTE_H_ +#define _MACHINE_PTE_H_ -#ifndef _MVME68K_PTE_H_ -#define _MVME68K_PTE_H_ +#include <m68k/pte_motorola.h> -/* - * m68k hardware segment/page table entries - */ +#define MACHINE_STSIZE M68K_STSIZE +#define MACHINE_MAX_PTSIZE M68K_MAX_PTSIZE +#define MACHINE_MAX_KPTSIZE M68K_MAX_KPTSIZE +#define MACHINE_PTBASE M68K_PTBASE +#define MACHINE_PTMAXSIZE M68K_PTMAXSIZE -#if 0 -struct ste { - unsigned int sg_pfnum:20; /* page table frame number */ - unsigned int :8; /* reserved at 0 */ - unsigned int :1; /* reserved at 1 */ - unsigned int sg_prot:1; /* write protect bit */ - unsigned int sg_v:2; /* valid bits */ -}; - -struct ste40 { - unsigned int sg_ptaddr:24; /* page table page addr */ - unsigned int :4; /* reserved at 0 */ - unsigned int sg_u; /* hardware modified (dirty) bit */ - unsigned int sg_prot:1; /* write protect bit */ - unsigned int sg_v:2; /* valid bits */ -}; - -struct pte { - unsigned int pg_pfnum:20; /* page frame number or 0 */ - unsigned int :3; - unsigned int pg_w:1; /* is wired */ - unsigned int :1; /* reserved at zero */ - unsigned int pg_ci:1; /* cache inhibit bit */ - unsigned int :1; /* reserved at zero */ - unsigned int pg_m:1; /* hardware modified (dirty) bit */ - unsigned int pg_u:1; /* hardware used (reference) bit */ - unsigned int pg_prot:1; /* write protect bit */ - unsigned int pg_v:2; /* valid bit */ -}; -#endif - -typedef int st_entry_t; /* segment table entry */ -typedef int pt_entry_t; /* Mach page table entry */ - -#define PT_ENTRY_NULL ((pt_entry_t *) 0) -#define ST_ENTRY_NULL ((st_entry_t *) 0) - -#define SG_V 0x00000002 /* segment is valid */ -#define SG_NV 0x00000000 -#define SG_PROT 0x00000004 /* access protection mask */ -#define SG_RO 0x00000004 -#define SG_RW 0x00000000 -#define SG_U 0x00000008 /* modified bit (68040) */ -#define SG_FRAME 0xfffff000 -#define SG_IMASK 0xffc00000 -#define SG_ISHIFT 22 -#define SG_PMASK 0x003ff000 -#define SG_PSHIFT 12 - -/* 68040 additions */ -#define SG4_MASK1 0xfe000000 -#define SG4_SHIFT1 25 -#define SG4_MASK2 0x01fc0000 -#define SG4_SHIFT2 18 -#define SG4_MASK3 0x0003f000 -#define SG4_SHIFT3 12 -#define SG4_ADDR1 0xfffffe00 -#define SG4_ADDR2 0xffffff00 -#define SG4_LEV1SIZE 128 -#define SG4_LEV2SIZE 128 -#define SG4_LEV3SIZE 64 - -#define PG_V 0x00000001 -#define PG_NV 0x00000000 -#define PG_PROT 0x00000004 -#define PG_U 0x00000008 -#define PG_M 0x00000010 -#define PG_W 0x00000100 -#define PG_RO 0x00000004 -#define PG_RW 0x00000000 -#define PG_FRAME 0xfffff000 -#define PG_CI 0x00000040 -#define PG_SHIFT 12 -#define PG_PFNUM(x) (((x) & PG_FRAME) >> PG_SHIFT) - -/* 68040 additions */ -#define PG_CMASK 0x00000060 /* cache mode mask */ -#define PG_CWT 0x00000000 /* writethrough caching */ -#define PG_CCB 0x00000020 /* copyback caching */ -#define PG_CIS 0x00000040 /* cache inhibited serialized */ -#define PG_CIN 0x00000060 /* cache inhibited nonserialized */ -#define PG_SO 0x00000080 /* supervisor only */ - -#define M68K_STSIZE (MAXUL2SIZE*SG4_LEV2SIZE*sizeof(st_entry_t)) - /* user process segment table size */ -#define M68K_MAX_PTSIZE 0x400000 /* max size of UPT */ -#define M68K_MAX_KPTSIZE 0x100000 /* max memory to allocate to KPT */ -#define M68K_PTBASE 0x10000000 /* UPT map base address */ -#define M68K_PTMAXSIZE 0x70000000 /* UPT map maximum size */ - -/* - * Kernel virtual address to page table entry and to physical address. - */ -#define kvtopte(va) \ - (&Sysmap[((unsigned)(va) - VM_MIN_KERNEL_ADDRESS) >> PGSHIFT]) -#define ptetokv(pt) \ - ((((pt_entry_t *)(pt) - Sysmap) << PGSHIFT) + VM_MIN_KERNEL_ADDRESS) -#define kvtophys(va) \ - ((kvtopte(va)->pg_pfnum << PGSHIFT) | ((int)(va) & PGOFSET)) - -#endif /* !_MVME68K_PTE_H_ */ +#endif /* _MACHINE_PTE_H_ */ diff --git a/sys/arch/mvme68k/mvme68k/pmap.c b/sys/arch/mvme68k/mvme68k/pmap.c deleted file mode 100644 index 7ef277f8f3e..00000000000 --- a/sys/arch/mvme68k/mvme68k/pmap.c +++ /dev/null @@ -1,2403 +0,0 @@ -/* $OpenBSD: pmap.c,v 1.37 2001/12/20 19:02:29 miod Exp $ */ - -/* - * Copyright (c) 1995 Theo de Raadt - * - * 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 under OpenBSD by - * Theo de Raadt for Willowglen Singapore. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - * 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 - */ - -/* - * m68k series physical map management code. - * - * Supports: - * XXX 68020 with 68551 MMU - * 68030 with on-chip MMU - * 68040 with on-chip MMU - * 68060 with on-chip MMU - * - * 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.: - * (*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). - */ - -/* - * 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 <machine/pte.h> - -#include <uvm/uvm_extern.h> -#include <uvm/uvm.h> - -#include <machine/cpu.h> - -#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_PARANOIA 0x2000 -#define PDB_WIRING 0x4000 -#define PDB_PVDUMP 0x8000 -#define PDB_ALL 0xFFFF - -int debugmap = 0; -int pmapdebug = PDB_PARANOIA; - -#if defined(M68040) || defined(M68060) -int dowriteback = 1; /* 68040: enable writeback caching */ -int dokwriteback = 1; /* 68040: enable writeback caching of kernel AS */ -#endif -#endif - -/* - * Get STEs and PTEs for user/kernel address space - */ -#if defined(M68040) || defined(M68060) -#define pmap_ste1(m, v) \ - (&((m)->pm_stab[(vm_offset_t)(v) >> SG4_SHIFT1])) -/* XXX assumes physically contiguous ST pages (if more than one) */ -#define pmap_ste2(m, v) \ - (&((m)->pm_stab[(st_entry_t *)(*(u_int *)pmap_ste1(m, v) & SG4_ADDR1) \ - - (m)->pm_stpa + (((v) & SG4_MASK2) >> SG4_SHIFT2)])) -#define pmap_ste(m, v) \ - (&((m)->pm_stab[(vm_offset_t)(v) \ - >> (mmutype <= MMU_68040 ? SG4_SHIFT1 : SG_ISHIFT)])) -#define pmap_ste_v(m, v) \ - (mmutype <= MMU_68040 \ - ? ((*pmap_ste1(m, v) & SG_V) && \ - (*pmap_ste2(m, v) & SG_V)) \ - : (*pmap_ste(m, v) & SG_V)) -#else -#define pmap_ste(m, v) (&((m)->pm_stab[(vm_offset_t)(v) >> SG_ISHIFT])) -#define pmap_ste_v(m, v) (*pmap_ste(m, v) & SG_V) -#endif - -#define pmap_pte(m, v) (&((m)->pm_ptab[(vm_offset_t)(v) >> PG_SHIFT])) -#define pmap_pte_pa(pte) (*(pte) & PG_FRAME) -#define pmap_pte_w(pte) (*(pte) & PG_W) -#define pmap_pte_ci(pte) (*(pte) & PG_CI) -#define pmap_pte_m(pte) (*(pte) & PG_M) -#define pmap_pte_u(pte) (*(pte) & PG_U) -#define pmap_pte_prot(pte) (*(pte) & PG_PROT) -#define pmap_pte_v(pte) (*(pte) & PG_V) - -#define pmap_pte_set_w(pte, v) \ - if (v) *(pte) |= PG_W; else *(pte) &= ~PG_W -#define pmap_pte_set_prot(pte, v) \ - if (v) *(pte) |= PG_PROT; else *(pte) &= ~PG_PROT -#define pmap_pte_w_chg(pte, nw) ((nw) ^ pmap_pte_w(pte)) -#define pmap_pte_prot_chg(pte, np) ((np) ^ pmap_pte_prot(pte)) - -/* - * Given a map and a machine independent protection code, - * convert to an m68k protection code. - */ -#define pte_prot(m, p) (protection_codes[p]) -int protection_codes[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; - -/* - * 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. - * Sysmap will initially contain VM_KERNEL_PT_PAGES pages of PTEs. - * Segtabzero is an empty segment table which all processes share til they - * reference something. - */ -st_entry_t *Sysseg; -pt_entry_t *Sysmap, *Sysptmap; -st_entry_t *Segtabzero, *Segtabzeropa; -vm_size_t Sysptsize = VM_KERNEL_PT_PAGES; - -struct pmap kernel_pmap_store; -struct vm_map *st_map, *pt_map; -struct vm_map st_map_store, pt_map_store; - -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) */ -int page_cnt; /* number of pages managed by VM system */ - -boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */ -struct pv_entry *pv_table; -char *pmap_attributes; /* reference and modify bits */ -TAILQ_HEAD(pv_page_list, pv_page) pv_page_freelist; -int pv_nfree; - -#if defined(M68040) || defined(M68060) -int protostfree; /* prototype (default) free ST map */ -#endif - -/* - * Internal routines - */ -void pmap_remove_mapping __P((pmap_t, vm_offset_t, pt_entry_t *, int)); -boolean_t pmap_testbit __P((vm_offset_t, int)); -void pmap_changebit __P((vm_offset_t, int, boolean_t)); -void pmap_enter_ptpage __P((pmap_t, vm_offset_t)); -void pmap_ptpage_addref __P((vaddr_t)); -int pmap_ptpage_delref __P((vaddr_t)); -void pmap_collect1 __P((pmap_t, vm_offset_t, vm_offset_t)); -void pmap_pinit __P((struct pmap *)); -void pmap_release __P((struct pmap *)); - - -#ifdef DEBUG -void pmap_pvdump __P((vm_offset_t)); -void pmap_check_wiring __P((char *, vm_offset_t)); -#endif - -/* pmap_remove_mapping flags */ -#define PRM_TFLUSH 1 -#define PRM_CFLUSH 2 -#define PRM_KEEPPTPAGE 4 - -#define PAGE_IS_MANAGED(pa) (pmap_initialized && \ - vm_physseg_find(atop((pa)), NULL) != -1) - -#define pa_to_pvh(pa) \ -({ \ - int bank_, pg_; \ - \ - bank_ = vm_physseg_find(atop((pa)), &pg_); \ - &vm_physmem[bank_].pmseg.pvent[pg_]; \ -}) - -#define pa_to_attribute(pa) \ -({ \ - int bank_, pg_; \ - \ - bank_ = vm_physseg_find(atop((pa)), &pg_); \ - &vm_physmem[bank_].pmseg.attrs[pg_]; \ -}) - -/* - * Routine: pmap_virtual_space - * - * Function: - * Report the range of available kernel virtual address - * space to the VM system during bootstrap. Called by - * vm_bootstrap_steal_memory(). - */ -void -pmap_virtual_space(vstartp, vendp) - vm_offset_t *vstartp, *vendp; -{ - - *vstartp = virtual_avail; - *vendp = virtual_end; -} - -/* - * Routine: pmap_init - * - * Function: - * Initialize the pmap module. - * Called by vm_init, to initialize any structures that the pmap - * system needs to map virtual memory. - */ -void -pmap_init() -{ - vm_offset_t addr, addr2; - vm_size_t s; - int rv; - int npages; - struct pv_entry *pv; - char *attr; - int bank; - - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_init()\n"); -#endif - /* - * Now that kernel map has been allocated, we can mark as - * unavailable regions which we have mapped in pmap_bootstrap(). - */ - addr = (vaddr_t) intiobase; - if (uvm_map(kernel_map, &addr, - m68k_ptob(iiomapsize+EIOMAPSIZE), - NULL, UVM_UNKNOWN_OFFSET, 0, - UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, - UVM_INH_NONE, UVM_ADV_RANDOM, - UVM_FLAG_FIXED))) - goto bogons; - addr = (vaddr_t) Sysmap; - if (uvm_map(kernel_map, &addr, M68K_MAX_PTSIZE, - NULL, UVM_UNKNOWN_OFFSET, 0, - UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, - UVM_INH_NONE, UVM_ADV_RANDOM, - UVM_FLAG_FIXED))) { - /* - * If this fails, it is probably because the static - * portion of the kernel page table isn't big enough - * and we overran the page table map. - */ - bogons: - panic("pmap_init: bogons in the VM system!\n"); - } - -#ifdef DEBUG - if (pmapdebug & PDB_INIT) { - printf("pmap_init: Sysseg %x, Sysmap %x, Sysptmap %x\n", - Sysseg, Sysmap, Sysptmap); - printf(" pstart %x, pend %x, vstart %x, vend %x\n", - avail_start, avail_end, virtual_avail, virtual_end); - } -#endif - - /* - * Allocate memory for random pmap data structures. Includes the - * initial segment table, pv_head_table and pmap_attributes. - */ - for (page_cnt = 0, bank = 0; bank < vm_nphysseg; bank++) - page_cnt += vm_physmem[bank].end - vm_physmem[bank].start; - s = M68K_STSIZE; /* Segtabzero */ - s += page_cnt * sizeof(struct pv_entry); /* pv table */ - s += page_cnt * sizeof(char); /* attribute table */ - s = round_page(s); - addr = uvm_km_zalloc(kernel_map, s); - if (addr == 0) - panic("pmap_init: can't allocate data structures"); - - Segtabzero = (st_entry_t *) addr; - pmap_extract(pmap_kernel(), addr, (paddr_t *)&Segtabzeropa); -#ifdef M68060 - if (mmutype == MMU_68060) { - addr2 = addr; - while (addr2 < addr + M68K_STSIZE) { - pmap_changebit(addr2, PG_CCB, 0); - pmap_changebit(addr2, PG_CI, 1); - addr2 += NBPG; - } - DCIS(); - } -#endif - addr += M68K_STSIZE; - - pv_table = (struct pv_entry *) addr; - addr += page_cnt * sizeof(struct pv_entry); - - pmap_attributes = (char *) addr; - -#ifdef DEBUG - if (pmapdebug & PDB_INIT) - printf("pmap_init: %lx bytes: page_cnt %x s0 %p(%p) " - "tbl %p atr %p\n", - s, page_cnt, Segtabzero, Segtabzeropa, - pv_table, pmap_attributes); -#endif - - /* - * Now that the pv and attribute tables have been allocated, - * assign them to the memory segments. - */ - pv = pv_table; - attr = pmap_attributes; - for (bank = 0; bank < vm_nphysseg; bank++) { - npages = vm_physmem[bank].end - vm_physmem[bank].start; - vm_physmem[bank].pmseg.pvent = pv; - vm_physmem[bank].pmseg.attrs = attr; - pv += npages; - attr += npages; - } - - /* - * Allocate physical memory for kernel PT pages and their management. - * We need 1 PT page per possible task plus some slop. - */ - npages = min(atop(M68K_MAX_KPTSIZE), maxproc+16); - s = ptoa(npages) + round_page(npages * sizeof(struct kpt_page)); - - /* - * Verify that space will be allocated in region for which - * we already have kernel PT pages. - */ - addr = 0; - rv = uvm_map(kernel_map, &addr, s, NULL, UVM_UNKNOWN_OFFSET, 0, - UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, - UVM_ADV_RANDOM, UVM_FLAG_NOMERGE)); - if (rv || (addr + s) >= (vaddr_t)Sysmap) - panic("pmap_init: kernel PT too small"); - uvm_unmap(kernel_map, addr, addr + s); - - /* - * Now allocate the space and link the pages together to - * form the KPT free list. - */ - addr = uvm_km_zalloc(kernel_map, s); - if (addr == 0) - panic("pmap_init: cannot allocate KPT free list"); - s = ptoa(npages); - addr2 = addr + s; - kpt_pages = &((struct kpt_page *)addr2)[npages]; - kpt_free_list = (struct kpt_page *) 0; - do { - addr2 -= NBPG; - (--kpt_pages)->kpt_next = kpt_free_list; - kpt_free_list = kpt_pages; - kpt_pages->kpt_va = addr2; - pmap_extract(pmap_kernel(), addr2, &kpt_pages->kpt_pa); -#ifdef M68060 - if (mmutype == MMU_68060) { - pmap_changebit(kpt_pages->kpt_pa, PG_CCB, 0); - pmap_changebit(kpt_pages->kpt_pa, PG_CI, 1); - DCIS(); - } -#endif - } while (addr != addr2); -#ifdef DEBUG - if (pmapdebug & PDB_INIT) - printf("pmap_init: KPT: %d pages from %x to %x\n", - atop(s), addr, addr + s); -#endif - - /* - * Allocate the segment table map - */ - s = maxproc * M68K_STSIZE; - st_map = uvm_km_suballoc(kernel_map, &addr, &addr2, s, 0, FALSE, - &st_map_store); - - /* - * Slightly modified version of kmem_suballoc() to get page table - * map where we want it. - */ - addr = M68K_PTBASE; - if ((M68K_PTMAXSIZE / M68K_MAX_PTSIZE) < maxproc) { - s = M68K_PTMAXSIZE; - /* - * XXX We don't want to hang when we run out of - * page tables, so we lower maxproc so that fork() - * will fail instead. Note that root could still raise - * this value via sysctl(2). - */ - maxproc = (M68K_PTMAXSIZE / M68K_MAX_PTSIZE); - } else - s = (maxproc * M68K_MAX_PTSIZE); - pt_map = uvm_km_suballoc(kernel_map, &addr, &addr2, s, VM_MAP_PAGEABLE, - TRUE, &pt_map_store); - -#if defined(M68040) || defined(M68060) - if (mmutype <= MMU_68040) { - protostfree = ~l2tobm(0); - for (rv = MAXUL2SIZE; rv < sizeof(protostfree)*NBBY; rv++) - protostfree &= ~l2tobm(rv); - } -#endif - - /* - * Now it is safe to enable pv_table recording. - */ - pmap_initialized = TRUE; -} - -struct pv_entry * -pmap_alloc_pv() -{ - struct pv_page *pvp; - struct pv_entry *pv; - int i; - - if (pv_nfree == 0) { - pvp = (struct pv_page *)uvm_km_zalloc(kernel_map, NBPG); - if (pvp == 0) - panic("pmap_alloc_pv: uvm_km_zalloc() failed"); - pvp->pvp_pgi.pgi_freelist = pv = &pvp->pvp_pv[1]; - for (i = NPVPPG - 2; i; i--, pv++) - pv->pv_next = pv + 1; - pv->pv_next = 0; - pv_nfree += pvp->pvp_pgi.pgi_nfree = NPVPPG - 1; - TAILQ_INSERT_HEAD(&pv_page_freelist, pvp, pvp_pgi.pgi_list); - pv = &pvp->pvp_pv[0]; - } else { - --pv_nfree; - pvp = pv_page_freelist.tqh_first; - if (--pvp->pvp_pgi.pgi_nfree == 0) { - TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list); - } - pv = pvp->pvp_pgi.pgi_freelist; -#ifdef DIAGNOSTIC - if (pv == 0) - panic("pmap_alloc_pv: pgi_nfree inconsistent"); -#endif - pvp->pvp_pgi.pgi_freelist = pv->pv_next; - } - return pv; -} - -void -pmap_free_pv(pv) - struct pv_entry *pv; -{ - register struct pv_page *pvp; - register int i; - - pvp = (struct pv_page *) trunc_page((vaddr_t)pv); - switch (++pvp->pvp_pgi.pgi_nfree) { - case 1: - TAILQ_INSERT_TAIL(&pv_page_freelist, pvp, pvp_pgi.pgi_list); - default: - pv->pv_next = pvp->pvp_pgi.pgi_freelist; - pvp->pvp_pgi.pgi_freelist = pv; - ++pv_nfree; - break; - case NPVPPG: - pv_nfree -= NPVPPG - 1; - TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list); - uvm_km_free(kernel_map, (vm_offset_t)pvp, NBPG); - break; - } -} - -void -pmap_collect_pv() -{ - struct pv_page_list pv_page_collectlist; - struct pv_page *pvp, *npvp; - struct pv_entry *ph, *ppv, *pv, *npv; - int s; - - TAILQ_INIT(&pv_page_collectlist); - - for (pvp = pv_page_freelist.tqh_first; pvp; pvp = npvp) { - if (pv_nfree < NPVPPG) - break; - npvp = pvp->pvp_pgi.pgi_list.tqe_next; - if (pvp->pvp_pgi.pgi_nfree > NPVPPG / 3) { - TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list); - TAILQ_INSERT_TAIL(&pv_page_collectlist, pvp, pvp_pgi.pgi_list); - pv_nfree -= pvp->pvp_pgi.pgi_nfree; - pvp->pvp_pgi.pgi_nfree = -1; - } - } - - if (pv_page_collectlist.tqh_first == 0) - return; - - for (ph = &pv_table[page_cnt - 1]; ph >= &pv_table[0]; ph--) { - if (ph->pv_pmap == 0) - continue; - s = splimp(); - for (ppv = ph; (pv = ppv->pv_next) != 0; ) { - pvp = (struct pv_page *) trunc_page((vaddr_t)pv); - if (pvp->pvp_pgi.pgi_nfree == -1) { - pvp = pv_page_freelist.tqh_first; - if (--pvp->pvp_pgi.pgi_nfree == 0) { - TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list); - } - npv = pvp->pvp_pgi.pgi_freelist; -#ifdef DIAGNOSTIC - if (npv == 0) - panic("pmap_collect_pv: pgi_nfree inconsistent"); -#endif - pvp->pvp_pgi.pgi_freelist = npv->pv_next; - *npv = *pv; - ppv->pv_next = npv; - ppv = npv; - } else - ppv = pv; - } - splx(s); - } - - for (pvp = pv_page_collectlist.tqh_first; pvp; pvp = npvp) { - npvp = pvp->pvp_pgi.pgi_list.tqe_next; - uvm_km_free(kernel_map, (vm_offset_t)pvp, NBPG); - } -} - -/* - * 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(va, spa, epa, prot) - vm_offset_t va, spa, epa; - int prot; -{ - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_map(%x, %x, %x, %x)\n", va, spa, epa, prot); -#endif - - while (spa < epa) { - pmap_enter(pmap_kernel(), va, spa, prot, prot); - va += NBPG; - spa += NBPG; - } - return (va); -} - -/* - * 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. - */ -struct pmap * -pmap_create(void) -{ - struct pmap *pmap; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_CREATE)) - printf("pmap_create(%x)\n", size); -#endif - - pmap = (struct pmap *) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK); - 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(%x)\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_stpa = Segtabzeropa; -#if defined(M68040) || defined(M68060) - if (mmutype <= MMU_68040) - pmap->pm_stfree = protostfree; -#endif - 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; - - if (pmap == NULL) - return; - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_destroy(%x)\n", pmap); -#endif - - 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(%x)\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) - uvm_km_free_wakeup(pt_map, (vm_offset_t)pmap->pm_ptab, - M68K_MAX_PTSIZE); - if (pmap->pm_stab != Segtabzero) - uvm_km_free_wakeup(st_map, (vm_offset_t)pmap->pm_stab, - M68K_STSIZE); -} - -/* - * Add a reference to the specified pmap. - */ -void -pmap_reference(pmap) - pmap_t pmap; -{ - - if (pmap == NULL) - return; - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_reference(%x)\n", pmap); -#endif - - simple_lock(&pmap->pm_lock); - pmap->pm_count++; - simple_unlock(&pmap->pm_lock); -} - -/* - * Mark that a processor is about to be used by a given pmap. - */ -void -pmap_activate(p) - struct proc *p; -{ - pmap_t pmap = p->p_vmspace->vm_map.pmap; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_SEGTAB)) - printf("pmap_activate(%p)\n", p); -#endif - - PMAP_ACTIVATE(pmap, p == curproc); -} - -void -pmap_deactivate(p) - struct proc *p; -{ -} - -/* - * 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(%x, %x, %x)\n", pmap, sva, eva); -#endif - - if (pmap == NULL) - return; - - firstpage = TRUE; - needcflush = FALSE; - flags = active_pmap(pmap) ? PRM_TFLUSH : 0; - while (sva < eva) { - nssva = m68k_trunc_seg(sva) + M68K_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 += NBPG; - } - } - /* - * 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(struct vm_page *pg, vm_prot_t prot) -{ - paddr_t pa = VM_PAGE_TO_PHYS(pg); - struct pv_entry *pv; - int s; - -#ifdef DEBUG - if ((pmapdebug & (PDB_FOLLOW|PDB_PROTECT)) || - prot == VM_PROT_NONE && (pmapdebug & PDB_REMOVE)) - printf("pmap_page_protect(%x, %x)\n", pa, prot); -#endif - if (PAGE_IS_MANAGED(pa) == 0) - 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: - pmap_changebit(pa, PG_RO, TRUE); - 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 %x 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; - boolean_t firstpage, needtflush; - int isro; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_PROTECT)) - printf("pmap_protect(%x, %x, %x, %x)\n", pmap, sva, eva, prot); -#endif - - if (pmap == NULL) - return; - - if ((prot & VM_PROT_READ) == VM_PROT_NONE) { - pmap_remove(pmap, sva, eva); - return; - } - if (prot & VM_PROT_WRITE) - return; - - isro = pte_prot(pmap, prot); - needtflush = active_pmap(pmap); - firstpage = TRUE; - while (sva < eva) { - nssva = m68k_trunc_seg(sva) + M68K_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, isro)) { -#if defined(M68040) || defined(M68060) - /* - * Clear caches if making RO (see section - * "7.3 Cache Coherency" in the manual). - */ - if (isro && mmutype <= MMU_68040) { - vm_offset_t pa = pmap_pte_pa(pte); - - DCFP(pa); - ICPP(pa); - } -#endif - pmap_pte_set_prot(pte, isro); - if (needtflush) - TBIS(sva); - firstpage = FALSE; - } - pte++; - sva += NBPG; - } - } -} - -/* - * 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. - */ - -int -pmap_enter(pmap, va, pa, prot, flags) - pmap_t pmap; - vaddr_t va; - paddr_t pa; - vm_prot_t prot; - int flags; -{ - register pt_entry_t *pte; - register int npte; - vm_offset_t opa; - boolean_t cacheable = TRUE; - boolean_t checkpv = TRUE; - boolean_t wired = (flags & PMAP_WIRED) != 0; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_ENTER)) - printf("pmap_enter(%x, %x, %x, %x, %x)\n", - pmap, va, pa, prot, flags); -#endif - - /* - * For user mapping, allocate kernel VM resources if necessary. - */ - if (pmap->pm_ptab == NULL) - pmap->pm_ptab = (pt_entry_t *) - uvm_km_valloc_wait(pt_map, M68K_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 = m68k_trunc_page(pa); - pte = pmap_pte(pmap, va); - opa = pmap_pte_pa(pte); -#ifdef DEBUG - if (pmapdebug & PDB_ENTER) - printf("enter: pte %x, *pte %x\n", pte, *pte); -#endif - - /* - * Mapping has not changed, must be protection or wiring change. - */ - if (opa == pa) { - /* - * 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_W : 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--; - } - /* - * Retain cache inhibition status - */ - checkpv = FALSE; - if (pmap_pte_ci(pte)) - cacheable = 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 %x\n", va); -#endif - pmap_remove_mapping(pmap, va, pte, - PRM_TFLUSH|PRM_CFLUSH|PRM_KEEPPTPAGE); - } - - /* - * 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()) { - pmap_ptpage_addref(trunc_page((vaddr_t)pte)); - } - - /* - * 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 struct pv_entry *pv, *npv; - int s; - - pv = pa_to_pvh(pa); - s = splimp(); -#ifdef DEBUG - if (pmapdebug & PDB_ENTER) - printf("enter: pv at %x: %x/%x/%x\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) { - pv->pv_va = va; - pv->pv_pmap = pmap; - pv->pv_next = NULL; - pv->pv_ptste = 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 = pmap_alloc_pv(); - npv->pv_va = va; - npv->pv_pmap = pmap; - npv->pv_next = pv->pv_next; - npv->pv_ptste = NULL; - npv->pv_ptpmap = NULL; - npv->pv_flags = 0; - pv->pv_next = npv; - } - 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 = cacheable = FALSE; - } - - /* - * Increment counters - */ - pmap->pm_stats.resident_count++; - if (wired) - pmap->pm_stats.wired_count++; - -validate: - /* - * Build the new PTE. - */ - npte = pa | pte_prot(pmap, prot) | (*pte & (PG_M|PG_U)) | PG_V; - if (wired) - npte |= PG_W; - - /* Don't cache if process can't take it, like SunOS ones. */ - if (mmutype <= MMU_68040 && pmap != pmap_kernel() && - (curproc->p_md.md_flags & MDP_UNCACHE_WX) && - (prot & VM_PROT_EXECUTE) && (prot & VM_PROT_WRITE)) - checkpv = cacheable = FALSE; - - if (!checkpv && !cacheable) - npte |= PG_CI; -#if defined(M68040) || defined(M68060) - if (mmutype <= MMU_68040 && (npte & (PG_PROT|PG_CI)) == PG_RW) -#ifdef DEBUG - if (dowriteback && (dokwriteback || pmap != pmap_kernel())) -#endif - npte |= PG_CCB; -#endif -#ifdef DEBUG - if (pmapdebug & PDB_ENTER) - printf("enter: new pte value %x\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_W); -#if defined(M68040) || defined(M68060) - if (mmutype <= MMU_68040 && !wired) { - DCFP(pa); - ICPP(pa); - } -#endif - *pte = npte; - if (!wired && active_pmap(pmap)) - TBIS(va); -#ifdef DEBUG - if ((pmapdebug & PDB_WIRING) && pmap != pmap_kernel()) - pmap_check_wiring("enter", trunc_page(pmap_pte(pmap, va))); -#endif - - return (0); -} - -/* - * Routine: pmap_unwire - * Function: Change the wiring attribute for a map/virtual-address - * pair. - * In/out conditions: - * The mapping must already exist in the pmap. - */ -void -pmap_unwire(pmap, va) - pmap_t pmap; - vm_offset_t va; -{ - pt_entry_t *pte; - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_unwire(%x, %x)\n", pmap, va); -#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_unwire: invalid STE for %x\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_unwire: invalid PTE for %x\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, 0)) { - pmap_pte_set_w(pte, 0); - pmap->pm_stats.wired_count--; - } -} - -/* - * Routine: pmap_extract - * Function: - * Extract the physical page address associated - * with the given map/virtual_address pair. - */ - -boolean_t -pmap_extract(pmap, va, pap) - pmap_t pmap; - vm_offset_t va; - paddr_t *pap; -{ - paddr_t pa; - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_extract(%x, %x) -> ", pmap, va); -#endif - if (pmap && pmap_ste_v(pmap, va)) - pa = *pmap_pte(pmap, va); - else - return (FALSE); - *pap = (pa & PG_FRAME) | (va & ~PG_FRAME); -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("%x\n", *pap); -#endif - return (TRUE); -} - -/* - * 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(%x, %x, %x, %x, %x)\n", - dst_pmap, src_pmap, dst_addr, len, src_addr); -#endif -} - -/* - * 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; -{ - int bank, s; - - if (pmap != pmap_kernel()) - return; - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_collect(%p)\n", pmap); -#endif - s = splimp(); - for (bank = 0; bank < vm_nphysseg; bank++) - pmap_collect1(pmap, ptoa(vm_physmem[bank].start), - ptoa(vm_physmem[bank].end)); - splx(s); - -#ifdef notyet - /* Go compact and garbage-collect the pv_table. */ - pmap_collect_pv(); -#endif -} - -/* - * Routine: pmap_collect1() - * - * Function: - * Helper function for pmap_collect(). Do the actual - * garbage-collection of range of physical addresses. - */ -void -pmap_collect1(pmap, startpa, endpa) - pmap_t pmap; - vm_offset_t startpa, endpa; -{ - vm_offset_t pa; - struct pv_entry *pv; - pt_entry_t *pte; - vm_offset_t kpa; -#ifdef DEBUG - st_entry_t *ste; - int opmapdebug = 0 /* XXX initialize to quiet gcc -Wall */; -#endif - - for (pa = startpa; pa < endpa; pa += NBPG) { - 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_ptste && pv->pv_ptpmap == pmap_kernel()) - break; - } while ((pv = pv->pv_next)); - if (pv == NULL) - continue; -#ifdef DEBUG1 - if (pv->pv_va < (vm_offset_t)Sysmap || - pv->pv_va >= (vm_offset_t)Sysmap + HP_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 + NBPG); - 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 %x@%p)\n", - pv->pv_va, *pv->pv_ptste, pv->pv_ptste); - opmapdebug = pmapdebug; - pmapdebug |= PDB_PTPAGE; - } - - ste = pv->pv_ptste; -#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. - */ - pmap_extract(pmap, pv->pv_va, &kpa); - 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 DEBUG - if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT)) - pmapdebug = opmapdebug; - - if (*ste != SG_NV) - printf("collect: kernel STE at %p still valid (%x)\n", - ste, *ste); - ste = &Sysptmap[ste - pmap_ste(pmap_kernel(), 0)]; - if (*ste != SG_NV) - printf("collect: kernel PTmap at %p still valid (%x)\n", - ste, *ste); -#endif - } -} - -/* - * 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. - * - * XXX this is a bad implementation for virtual cache machines - * (320/350) because pmap_enter doesn't cache-inhibit the temporary - * kernel mapping and we wind up with data cached for that KVA. - * It is probably a win for physical cache machines (370/380) - * as the cache loading is not wasted. - */ -void -pmap_zero_page(phys) - vm_offset_t phys; -{ - register vm_offset_t kva; - extern caddr_t CADDR1; - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_zero_page(%x)\n", phys); -#endif - kva = (vm_offset_t) CADDR1; - pmap_enter(pmap_kernel(), kva, phys, VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); - zeropage((caddr_t)kva); - pmap_remove_mapping(pmap_kernel(), kva, PT_ENTRY_NULL, - PRM_TFLUSH|PRM_CFLUSH); -} - -/* - * 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. - * - * - * XXX this is a bad implementation for virtual cache machines - * (320/350) because pmap_enter doesn't cache-inhibit the temporary - * kernel mapping and we wind up with data cached for that KVA. - * It is probably a win for physical cache machines (370/380) - * as the cache loading is not wasted. - */ -void -pmap_copy_page(src, dst) - vm_offset_t src, dst; -{ - register vm_offset_t skva, dkva; - extern caddr_t CADDR1, CADDR2; - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_copy_page(%x, %x)\n", src, dst); -#endif - skva = (vm_offset_t) CADDR1; - dkva = (vm_offset_t) CADDR2; - pmap_enter(pmap_kernel(), skva, src, VM_PROT_READ, VM_PROT_READ|PMAP_WIRED); - pmap_enter(pmap_kernel(), dkva, dst, VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); - copypage((caddr_t)skva, (caddr_t)dkva); - /* CADDR1 and CADDR2 are virtually contiguous */ - pmap_remove(pmap_kernel(), skva, skva + (2 * NBPG)); -} - -/* - * Clear the modify bits on the specified physical page. - */ - -boolean_t -pmap_clear_modify(struct vm_page *pg) -{ - paddr_t pa = VM_PAGE_TO_PHYS(pg); - boolean_t ret; - - ret = pmap_is_modified(pg); - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_clear_modify(%x)\n", pa); -#endif - pmap_changebit(pa, PG_M, FALSE); - - return (ret); -} - -/* - * pmap_clear_reference: - * - * Clear the reference bit on the specified physical page. - */ - -boolean_t -pmap_clear_reference(struct vm_page *pg) -{ - paddr_t pa = VM_PAGE_TO_PHYS(pg); - boolean_t ret; - - ret = pmap_is_referenced(pg); - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_clear_reference(%x)\n", pa); -#endif - pmap_changebit(pa, PG_U, FALSE); - - return (ret); -} - -/* - * pmap_is_referenced: - * - * Return whether or not the specified physical page is referenced - * by any physical maps. - */ - -boolean_t -pmap_is_referenced(struct vm_page *pg) -{ - paddr_t pa = VM_PAGE_TO_PHYS(pg); - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) { - boolean_t rv = pmap_testbit(pa, PG_U); - printf("pmap_is_referenced(%x) -> %c\n", pa, "FT"[rv]); - return(rv); - } -#endif - return(pmap_testbit(pa, PG_U)); -} - -/* - * pmap_is_modified: - * - * Return whether or not the specified physical page is modified - * by any physical maps. - */ - -boolean_t -pmap_is_modified(struct vm_page *pg) -{ - paddr_t pa = VM_PAGE_TO_PHYS(pg); -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) { - boolean_t rv = pmap_testbit(pa, PG_M); - printf("pmap_is_modified(%x) -> %c\n", pa, "FT"[rv]); - return(rv); - } -#endif - return(pmap_testbit(pa, PG_M)); -} - -vm_offset_t -pmap_phys_address(ppn) - int ppn; -{ - return(m68k_ptob(ppn)); -} - -#ifdef COMPAT_HPUX -/* - * 'PUX hack for dealing with the so called multi-mapped address space. - * The first 256mb is mapped in at every 256mb region from 0x10000000 - * up to 0xF0000000. This allows for 15 bits of tag information. - * - * We implement this at the segment table level, the machine independent - * VM knows nothing about it. - */ -pmap_mapmulti(pmap, va) - pmap_t pmap; - vm_offset_t va; -{ - st_entry_t *ste, *bste; - -#ifdef DEBUG - if (pmapdebug & PDB_MULTIMAP) { - ste = pmap_ste(pmap, HPMMBASEADDR(va)); - printf("pmap_mapmulti(%x, %x): bste %x(%x)", - pmap, va, ste, *ste); - ste = pmap_ste(pmap, va); - printf(" ste %x(%x)\n", ste, *ste); - } -#endif - bste = pmap_ste(pmap, HPMMBASEADDR(va)); - ste = pmap_ste(pmap, va); - if (*ste == SG_NV && (*bste & SG_V)) { - *ste = *bste; - TBIAU(); - return (0); - } - return (EFAULT); -} -#endif - -/* - * Miscellaneous support routines follow - */ - -/* - * 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. - * If (flags & PRM_KEEPPTPAGE), we don't free the page table page if the - * reference drops to zero. - */ -/* 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 struct pv_entry *pv, *npv; - pmap_t ptpmap; - st_entry_t *ste; - int s, bits; -#ifdef DEBUG - pt_entry_t opte; - - if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT)) - printf("pmap_remove_mapping(%x, %x, %x, %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 - /* - * 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 %x\n", pte); -#endif - bits = *pte & (PG_U|PG_M); - *pte = PG_NV; - if ((flags & PRM_TFLUSH) && active_pmap(pmap)) - 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()) { - vaddr_t ptpva = trunc_page((vaddr_t)pte); - int refs = pmap_ptpage_delref(ptpva); - - /* - * If reference count drops to 1, and we're not instructed - * to keep it around, free the PT page. - * - * Note: refcnt == 1 comes from the fact that we allocate - * the page with uvm_fault_wire(), which initially wires - * the page. The first reference we actually add causes - * the refcnt to be 2. - */ - if (refs == 1 && (flags & PRM_KEEPPTPAGE) == 0) { - struct pv_entry *pv; - paddr_t pa; - - pa = pmap_pte_pa(pmap_pte(pmap_kernel(), ptpva)); -#ifdef DIAGNOSTIC - if (PAGE_IS_MANAGED(pa) == 0) - panic("pmap_remove_mapping: unmanaged PT page"); -#endif - pv = pa_to_pvh(pa); -#ifdef DIAGNOSTIC - if (pv->pv_ptste == NULL) - panic("pmap_remove_mapping: ptste == NULL"); - if (pv->pv_pmap != pmap_kernel() || - pv->pv_va != ptpva || - pv->pv_next != NULL) - panic("pmap_remove_mapping: " - "bad PT page pmap %p, va 0x%lx, next %p", - pv->pv_pmap, pv->pv_va, pv->pv_next); -#endif - pmap_remove_mapping(pv->pv_pmap, pv->pv_va, - NULL, PRM_TFLUSH|PRM_CFLUSH); - uvm_pagefree(PHYS_TO_VM_PAGE(pa)); -#ifdef DEBUG - if (pmapdebug & (PDB_REMOVE|PDB_PTPAGE)) - printf("remove: PT page 0x%lx (0x%lx) freed\n", - ptpva, pa)); -#endif - } -#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) == 0) - return; - /* - * Otherwise remove it from the PV table - * (raise IPL since we may be called at interrupt time). - */ - pv = pa_to_pvh(pa); - ste = ST_ENTRY_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_ptste; - ptpmap = pv->pv_ptpmap; - npv = pv->pv_next; - if (npv) { - npv->pv_flags = pv->pv_flags; - *pv = *npv; - pmap_free_pv(npv); - } else - pv->pv_pmap = NULL; - } else { - for (npv = pv->pv_next; npv; npv = npv->pv_next) { - 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_ptste; - ptpmap = npv->pv_ptpmap; - pv->pv_next = npv->pv_next; - pmap_free_pv(npv); - 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 DEBUG - if (pmapdebug & (PDB_REMOVE|PDB_PTPAGE)) - printf("remove: ste was %x@%x pte was %x@%x\n", - *ste, ste, opte, pmap_pte(pmap, va)); -#endif -#if defined(M68040) || defined(M68060) - if (mmutype <= MMU_68040) { - st_entry_t *este = &ste[NPTEPG/SG4_LEV3SIZE]; - - while (ste < este) - *ste++ = SG_NV; -#ifdef DEBUG - ste -= NPTEPG/SG4_LEV3SIZE; -#endif - } else -#endif - *ste = SG_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 %x, refcnt %d\n", - ptpmap->pm_stab, ptpmap->pm_sref - 1); - if ((pmapdebug & PDB_PARANOIA) && - ptpmap->pm_stab != (st_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 %x\n", - ptpmap->pm_stab); -#endif - uvm_km_free_wakeup(st_map, - (vm_offset_t)ptpmap->pm_stab, - M68K_STSIZE); - ptpmap->pm_stab = Segtabzero; - ptpmap->pm_stpa = Segtabzeropa; -#if defined(M68040) || defined(M68060) - if (mmutype <= MMU_68040) - ptpmap->pm_stfree = protostfree; -#endif - /* - * XXX may have changed segment table - * pointer for current process so - * update now to reload hardware. - */ - if (active_user_pmap(ptpmap)) - 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()) - TBIAS(); - else - TBIAU(); -#endif - pv->pv_flags &= ~PV_PTPAGE; - ptpmap->pm_ptpages--; - } - /* - * Update saved attributes for managed page - */ - *pa_to_attribute(pa) |= bits; - splx(s); -} - -/* static */ -boolean_t -pmap_testbit(pa, bit) - register vm_offset_t pa; - int bit; -{ - register struct pv_entry *pv; - register pt_entry_t *pte; - int s; - - if (PAGE_IS_MANAGED(pa) == 0) - return(FALSE); - - pv = pa_to_pvh(pa); - s = splimp(); - /* - * Check saved info first - */ - if (*pa_to_attribute(pa) & bit) { - splx(s); - return(TRUE); - } - /* - * Not found, check current mappings returning - * immediately if found. - */ - if (pv->pv_pmap != NULL) { - for (; pv; pv = pv->pv_next) { - pte = pmap_pte(pv->pv_pmap, pv->pv_va); - if (*pte & bit) { - splx(s); - return(TRUE); - } - } - } - splx(s); - return(FALSE); -} - -/* static */ -void -pmap_changebit(pa, bit, setem) - register vm_offset_t pa; - int bit; - boolean_t setem; -{ - register struct pv_entry *pv; - register pt_entry_t *pte, npte; - vm_offset_t va; - int s; - boolean_t firstpage = TRUE; - -#ifdef DEBUG - if (pmapdebug & PDB_BITS) - printf("pmap_changebit(%x, %x, %s)\n", - pa, bit, setem ? "set" : "clear"); -#endif - if (PAGE_IS_MANAGED(pa) == 0) - return; - - pv = pa_to_pvh(pa); - s = splimp(); - /* - * Clear saved attributes (modify, reference) - */ - if (!setem) - *pa_to_attribute(pa) &= ~bit; - /* - * 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 - */ - if (bit == PG_RO) { - if (va >= uvm.pager_sva && va < uvm.pager_eva) - continue; - } - - pte = pmap_pte(pv->pv_pmap, va); - if (setem) - npte = *pte | bit; - else - npte = *pte & ~bit; - if (*pte != npte) { -#if defined(M68040) || defined(M68060) - /* - * If we are changing caching status or - * protection make sure the caches are - * flushed (but only once). - */ - if (firstpage && mmutype <= MMU_68040 && - (bit == PG_RO && setem || - (bit & PG_CMASK))) { - firstpage = FALSE; - DCFP(pa); - ICPP(pa); - } -#endif - *pte = npte; - if (active_pmap(pv->pv_pmap)) - TBIS(va); - } - } - } - splx(s); -} - -/* static */ -void -pmap_enter_ptpage(pmap, va) - register pmap_t pmap; - register vm_offset_t va; -{ - vm_offset_t ptpa; - register struct pv_entry *pv; -#ifdef M68060 - u_int stpa; -#endif - st_entry_t *ste; - int s; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_ENTER|PDB_PTPAGE)) - printf("pmap_enter_ptpage: pmap %x, va %x\n", pmap, va); -#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 = (st_entry_t *) - uvm_km_zalloc(st_map, M68K_STSIZE); - pmap_extract(pmap_kernel(), (vm_offset_t)pmap->pm_stab, - (paddr_t *)&pmap->pm_stpa); -#if defined(M68040) || defined(M68060) - if (mmutype <= MMU_68040) { -#ifdef DEBUG - if (dowriteback && dokwriteback) -#endif -#if defined(M68060) - stpa = (u_int)pmap->pm_stpa; - if (mmutype == MMU_68060) { - while (stpa < (u_int)pmap->pm_stpa + - M68K_STSIZE) { - pmap_changebit(stpa, PG_CCB, 0); - pmap_changebit(stpa, PG_CI, 1); - stpa += NBPG; - } - DCIS(); /* XXX */ - } - else -#endif - pmap_changebit((vm_offset_t)pmap->pm_stpa, PG_CCB, 0); - pmap->pm_stfree = protostfree; - } -#endif - /* - * XXX may have changed segment table pointer for current - * process so update now to reload hardware. - */ - if (active_user_pmap(pmap)) - PMAP_ACTIVATE(pmap, 1); -#ifdef DEBUG - if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB)) - printf("enter: pmap %x stab %x(%x)\n", - pmap, pmap->pm_stab, pmap->pm_stpa); -#endif - } - - ste = pmap_ste(pmap, va); -#if defined(M68040) || defined(M68060) - /* - * Allocate level 2 descriptor block if necessary - */ - if (mmutype <= MMU_68040) { - if (*ste == SG_NV) { - int ix; - caddr_t addr; - - ix = bmtol2(pmap->pm_stfree); - if (ix == -1) - panic("enter: out of address space"); /* XXX */ - pmap->pm_stfree &= ~l2tobm(ix); - addr = (caddr_t)&pmap->pm_stab[ix*SG4_LEV2SIZE]; - bzero(addr, SG4_LEV2SIZE*sizeof(st_entry_t)); - addr = (caddr_t)&pmap->pm_stpa[ix*SG4_LEV2SIZE]; - *ste = (u_int)addr | SG_RW | SG_U | SG_V; -#ifdef DEBUG - if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB)) - printf("enter: alloc ste2 %d(%x)\n", ix, addr); -#endif - } - ste = pmap_ste2(pmap, va); - /* - * Since a level 2 descriptor maps a block of SG4_LEV3SIZE - * level 3 descriptors, we need a chunk of NPTEPG/SG4_LEV3SIZE - * (16) such descriptors (NBPG/SG4_LEV3SIZE bytes) to map a - * PT page--the unit of allocation. We set `ste' to point - * to the first entry of that chunk which is validated in its - * entirety below. - */ - ste = (st_entry_t *)((int)ste & ~(NBPG/SG4_LEV3SIZE-1)); -#ifdef DEBUG - if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB)) - printf("enter: ste2 %x (%x)\n", - pmap_ste2(pmap, va), ste); -#endif - } -#endif - 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"); - } - 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, NBPG); - pmap_enter(pmap, va, ptpa, VM_PROT_DEFAULT, VM_PROT_DEFAULT|PMAP_WIRED); -#if defined(M68060) - if (mmutype == MMU_68060) { - pmap_changebit(ptpa, PG_CCB, 0); - pmap_changebit(ptpa, PG_CI, 1); - DCIS(); - } -#endif -#ifdef DEBUG - if (pmapdebug & (PDB_ENTER|PDB_PTPAGE)) { - int ix = pmap_ste(pmap, va) - pmap_ste(pmap, 0); - - printf("enter: add &Sysptmap[%d]: %x (KPT page %x)\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 %x\n", va); -#endif - if (uvm_fault_wire(pt_map, va, va + PAGE_SIZE, - VM_PROT_READ|VM_PROT_WRITE)) - panic("pmap_enter: uvm_fault failed"); - pmap_extract(pmap_kernel(), va, &ptpa); - } -#if defined(M68040) || defined(M68060) - /* - * Turn off copyback caching of page table pages, - * could get ugly otherwise. - */ -#ifdef DEBUG - if (dowriteback && dokwriteback) -#endif - if (mmutype <= MMU_68040) { - pt_entry_t *pte = pmap_pte(pmap_kernel(), va); -#ifdef DEBUG - if ((pmapdebug & PDB_PARANOIA) && (*pte & PG_CCB) == 0) - printf("%s PT no CCB: kva=%x ptpa=%x pte@%x=%x\n", - pmap == pmap_kernel() ? "Kernel" : "User", - va, ptpa, pte, *pte); -#endif - pmap_changebit(ptpa, PG_CCB, 0); -#ifdef M68060 - if (mmutype == MMU_68060) { - pmap_changebit(ptpa, PG_CI, 1); - DCIS(); - } -#endif - } -#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); - } -#ifdef DEBUG - if (pv == NULL) { - pv = pa_to_pvh(ptpa); - if (pv) { - printf("pv->pv_next = %x\n", pv->pv_next); - do { - printf("pmap %x va %x ptste %x ptpmap %x flags %x\n", - pv->pv_pmap, pv->pv_va, pv->pv_ptste, pv->pv_ptpmap, - pv->pv_flags); - if (pv->pv_pmap == pmap_kernel() && pv->pv_va == va) - break; - } while (pv = pv->pv_next); - } else - printf("pv at ptpa is 0\n"); - panic("pmap_enter_ptpage: PT page not entered"); - } -#endif - pv->pv_ptste = ste; - pv->pv_ptpmap = pmap; -#ifdef DEBUG - if (pmapdebug & (PDB_ENTER|PDB_PTPAGE)) - printf("enter: new PT page at PA %x, ste at %x\n", ptpa, ste); -#endif - - /* - * Map the new PT page into the segment table. - * Also increment the reference count on the segment table if this - * was a user page table page. 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. - */ -#if defined(M68040) || defined(M68060) - if (mmutype <= MMU_68040) { - st_entry_t *este; - - for (este = &ste[NPTEPG/SG4_LEV3SIZE]; ste < este; ste++) { - *ste = ptpa | SG_U | SG_RW | SG_V; - ptpa += SG4_LEV3SIZE * sizeof(st_entry_t); - } - } else -#endif - *ste = (ptpa & SG_FRAME) | SG_RW | SG_V; - if (pmap != pmap_kernel()) { -#ifdef DEBUG - if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB)) - printf("enter: stab %x refcnt %d\n", - pmap->pm_stab, pmap->pm_sref); -#endif - } -#if 0 - /* - * Flush stale TLB info. - */ - if (pmap == pmap_kernel()) - TBIAS(); - else - TBIAU(); -#endif - pmap->pm_ptpages++; - splx(s); -} - -/* - * pmap_ptpage_addref: - * - * Add a reference to the specified PT page. - */ -void -pmap_ptpage_addref(ptpva) - vaddr_t ptpva; -{ - struct vm_page *m; - - simple_lock(&uvm.kernel_object->vmobjlock); - m = uvm_pagelookup(uvm.kernel_object, ptpva - vm_map_min(kernel_map)); - m->wire_count++; - simple_unlock(&uvm.kernel_object->vmobjlock); -} - -/* - * pmap_ptpage_delref: - * - * Delete a reference to the specified PT page. - */ -int -pmap_ptpage_delref(ptpva) - vaddr_t ptpva; -{ - struct vm_page *m; - int rv; - - simple_lock(&uvm.kernel_object->vmobjlock); - m = uvm_pagelookup(uvm.kernel_object, ptpva - vm_map_min(kernel_map)); - rv = --m->wire_count; - simple_unlock(&uvm.kernel_object->vmobjlock); - return (rv); -} - -#ifdef DEBUG -/* static */ -void -pmap_pvdump(pa) - vm_offset_t pa; -{ - register struct pv_entry *pv; - - printf("pa %x", pa); - for (pv = pa_to_pvh(pa); pv; pv = pv->pv_next) - printf(" -> pmap %x, va %x, ptste %x, ptpmap %x, flags %x", - pv->pv_pmap, pv->pv_va, pv->pv_ptste, pv->pv_ptpmap, - pv->pv_flags); - printf("\n"); -} - -/* static */ -void -pmap_check_wiring(str, va) - char *str; - vm_offset_t va; -{ - struct vm_map_entry *entry; - register int count; - register pt_entry_t *pte; - - va = trunc_page(va); - if (!pmap_ste_v(pmap_kernel(), va) || - !pmap_pte_v(pmap_pte(pmap_kernel(), va))) - return; - if (!uvm_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 + NBPG); pte++) - if (*pte) - count++; - if (entry->wired_count != count) - printf("*%s*: %x: w%d/a%d\n", - str, va, entry->wired_count, count); -} -#endif - -void -pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot) -{ - pmap_enter(pmap_kernel(), va, pa, prot, VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); -} - -void -pmap_kremove(vaddr_t va, vsize_t len) -{ - for (len >>= PAGE_SHIFT; len > 0; len--, va += PAGE_SIZE) { - pmap_remove(pmap_kernel(), va, va + PAGE_SIZE); - } -} diff --git a/sys/arch/mvme68k/mvme68k/pmap_bootstrap.c b/sys/arch/mvme68k/mvme68k/pmap_bootstrap.c index 1aeaee500cc..aabf3ea5cef 100644 --- a/sys/arch/mvme68k/mvme68k/pmap_bootstrap.c +++ b/sys/arch/mvme68k/mvme68k/pmap_bootstrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap_bootstrap.c,v 1.13 2002/02/11 19:08:30 miod Exp $ */ +/* $OpenBSD: pmap_bootstrap.c,v 1.14 2002/02/22 22:45:34 miod Exp $ */ /* * Copyright (c) 1995 Theo de Raadt @@ -88,7 +88,6 @@ extern st_entry_t *Sysseg; extern pt_entry_t *Sysptmap, *Sysmap; extern int maxmem, physmem; -extern int protection_codes[]; extern paddr_t avail_start, avail_end; extern vaddr_t virtual_avail, virtual_end; extern vsize_t mem_size; @@ -500,25 +499,6 @@ pmap_bootstrap(nextpa, firstpa) #endif /* - * Initialize protection array. - * XXX don't use a switch statement, it might produce an - * absolute "jmp" table. - */ - { - register int *kp; - - kp = &RELOC(protection_codes, int); - kp[VM_PROT_NONE|VM_PROT_NONE|VM_PROT_NONE] = 0; - kp[VM_PROT_READ|VM_PROT_NONE|VM_PROT_NONE] = PG_RO; - kp[VM_PROT_READ|VM_PROT_NONE|VM_PROT_EXECUTE] = PG_RO; - kp[VM_PROT_NONE|VM_PROT_NONE|VM_PROT_EXECUTE] = PG_RO; - kp[VM_PROT_NONE|VM_PROT_WRITE|VM_PROT_NONE] = PG_RW; - kp[VM_PROT_NONE|VM_PROT_WRITE|VM_PROT_EXECUTE] = PG_RW; - kp[VM_PROT_READ|VM_PROT_WRITE|VM_PROT_NONE] = PG_RW; - kp[VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE] = PG_RW; - } - - /* * Kernel page/segment table allocated in locore, * just initialize pointers. */ @@ -570,3 +550,20 @@ pmap_bootstrap(nextpa, firstpa) RELOC(virtual_avail, vaddr_t) = va; } } + +void +pmap_init_md() +{ + vaddr_t addr; + + /* + * mark as unavailable the regions which we have mapped in + * pmap_bootstrap(). + */ + addr = (vaddr_t) intiobase; + if (uvm_map(kernel_map, &addr, m68k_ptob(iiomapsize+EIOMAPSIZE), + NULL, UVM_UNKNOWN_OFFSET, 0, + UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, + UVM_INH_NONE, UVM_ADV_RANDOM, UVM_FLAG_FIXED))) + panic("pmap_init: bogons in the VM system!\n"); +} |