diff options
-rw-r--r-- | sys/arch/luna88k/conf/files.luna88k | 3 | ||||
-rw-r--r-- | sys/arch/luna88k/include/pmap.h | 82 | ||||
-rw-r--r-- | sys/arch/luna88k/include/pmap_table.h | 52 | ||||
-rw-r--r-- | sys/arch/luna88k/luna88k/pmap.c | 2731 | ||||
-rw-r--r-- | sys/arch/luna88k/luna88k/pmap_table.c | 3 | ||||
-rw-r--r-- | sys/arch/m88k/conf/files.m88k | 3 | ||||
-rw-r--r-- | sys/arch/m88k/include/pmap.h | 79 | ||||
-rw-r--r-- | sys/arch/m88k/include/pmap_table.h | 48 | ||||
-rw-r--r-- | sys/arch/m88k/m88k/pmap.c (renamed from sys/arch/mvme88k/mvme88k/pmap.c) | 78 | ||||
-rw-r--r-- | sys/arch/mvme88k/conf/files.mvme88k | 4 | ||||
-rw-r--r-- | sys/arch/mvme88k/include/pmap.h | 82 | ||||
-rw-r--r-- | sys/arch/mvme88k/include/pmap_table.h | 52 | ||||
-rw-r--r-- | sys/arch/mvme88k/mvme88k/pmap_bootstrap.c | 99 | ||||
-rw-r--r-- | sys/arch/mvme88k/mvme88k/pmap_table.c | 3 |
14 files changed, 270 insertions, 3049 deletions
diff --git a/sys/arch/luna88k/conf/files.luna88k b/sys/arch/luna88k/conf/files.luna88k index 770305f251e..9a8218757fb 100644 --- a/sys/arch/luna88k/conf/files.luna88k +++ b/sys/arch/luna88k/conf/files.luna88k @@ -1,4 +1,4 @@ -# $OpenBSD: files.luna88k,v 1.5 2004/07/23 15:34:02 miod Exp $ +# $OpenBSD: files.luna88k,v 1.6 2004/07/25 11:06:39 miod Exp $ # maxpartitions 16 @@ -82,7 +82,6 @@ file arch/luna88k/luna88k/isr.c file arch/luna88k/luna88k/locore_c_routines.c file arch/luna88k/luna88k/machdep.c file arch/luna88k/luna88k/mem.c -file arch/luna88k/luna88k/pmap.c file arch/luna88k/luna88k/pmap_table.c file arch/luna88k/ddb/db_interface.c ddb file arch/luna88k/dev/lcd.c diff --git a/sys/arch/luna88k/include/pmap.h b/sys/arch/luna88k/include/pmap.h index 6bac2b51e93..7782e7ae394 100644 --- a/sys/arch/luna88k/include/pmap.h +++ b/sys/arch/luna88k/include/pmap.h @@ -1,79 +1,11 @@ -/* $OpenBSD: pmap.h,v 1.3 2004/06/02 13:49:41 miod Exp $ */ -/* - * Mach Operating System - * Copyright (c) 1991 Carnegie Mellon University - * Copyright (c) 1991 OMRON Corporation - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - */ -#ifndef _MACHINE_PMAP_H_ -#define _MACHINE_PMAP_H_ +/* $OpenBSD: pmap.h,v 1.4 2004/07/25 11:06:41 miod Exp $ */ +/* public domain */ -#include <machine/mmu.h> -#include <machine/pcb.h> +#ifndef _LUNA88K_PMAP_H_ +#define _LUNA88K_PMAP_H_ -/* - * PMAP structure - */ +#include <m88k/pmap.h> -/* #define PMAP_USE_BATC */ -struct pmap { - sdt_entry_t *pm_stab; /* virtual pointer to sdt */ - u_int32_t pm_apr; - int pm_count; /* reference count */ - /* cpus using of this pmap; NCPU must be <= 32 */ - u_int32_t pm_cpus; - struct simplelock pm_lock; - struct pmap_statistics pm_stats; /* pmap statistics */ -#ifdef PMAP_USE_BATC - u_int32_t pm_ibatc[BATC_MAX]; /* instruction BATCs */ - u_int32_t pm_dbatc[BATC_MAX]; /* data BATCs */ -#endif -}; +#define pmap_bootstrap_md(va) (va) -#define PMAP_NULL ((pmap_t) 0) - -/* The PV (Physical to virtual) List. - * - * For each vm_page_t, pmap keeps a list of all currently valid virtual - * mappings of that page. An entry is a pv_entry_t; the list is the - * pv_head_table. This is used by things like pmap_remove, when we must - * find and remove all mappings for a particular physical page. - */ -/* XXX - struct pv_entry moved to vmparam.h because of include ordering issues */ - -typedef struct pmap *pmap_t; -typedef struct pv_entry *pv_entry_t; - -#ifdef _KERNEL - -extern pmap_t kernel_pmap; -extern struct pmap kernel_pmap_store; -extern caddr_t vmmap; - -#define pmap_kernel() (&kernel_pmap_store) -#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) -#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) -#define pmap_phys_address(frame) ((paddr_t)(ptoa(frame))) - -#define pmap_copy(dp,sp,d,l,s) do { /* nothing */ } while (0) -#define pmap_update(pmap) do { /* nothing (yet) */ } while (0) - -#define pmap_clear_modify(pg) pmap_unsetbit(pg, PG_M) -#define pmap_clear_reference(pg) pmap_unsetbit(pg, PG_U) - -#define pmap_proc_iflush(p,va,len) do { /* nothing */ } while (0) - -void pmap_bootstrap(vaddr_t); -void pmap_cache_ctrl(pmap_t, vaddr_t, vaddr_t, u_int); -boolean_t pmap_unsetbit(struct vm_page *, int); - -#endif /* _KERNEL */ - -#endif /* _MACHINE_PMAP_H_ */ +#endif _LUNA88K_PMAP_H_ diff --git a/sys/arch/luna88k/include/pmap_table.h b/sys/arch/luna88k/include/pmap_table.h index be2a91cb8b1..060dbb224b7 100644 --- a/sys/arch/luna88k/include/pmap_table.h +++ b/sys/arch/luna88k/include/pmap_table.h @@ -1,49 +1,3 @@ -/* $OpenBSD: pmap_table.h,v 1.1 2004/04/21 15:23:58 aoyama Exp $ */ -/* - * Mach Operating System - * Copyright (c) 1992 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ - -#ifndef __MACHINE_PMAP_TABLE_H__ -#define __MACHINE_PMAP_TABLE_H__ - -/* - * Built-in mappings list. - * An entry is considered invalid if pm_size = 0, and - * end of list is indicated by pm_size 0xffffffff - */ -typedef struct { - vaddr_t phys_start; /* in bytes */ - vaddr_t virt_start; /* in bytes */ - vsize_t size; /* in bytes */ - unsigned int prot; /* vm_prot_read, vm_prot_write */ - unsigned int cacheability; /* none, writeback, normal */ -} pmap_table_entry; - -typedef const pmap_table_entry *pmap_table_t; - -pmap_table_t pmap_table_build(void); - -#endif /* __MACHINE_PMAP_TABLE_H__ */ - +/* $OpenBSD: pmap_table.h,v 1.2 2004/07/25 11:06:41 miod Exp $ */ +/* public domain */ +#include <m88k/pmap_table.h> diff --git a/sys/arch/luna88k/luna88k/pmap.c b/sys/arch/luna88k/luna88k/pmap.c deleted file mode 100644 index 813dbaab563..00000000000 --- a/sys/arch/luna88k/luna88k/pmap.c +++ /dev/null @@ -1,2731 +0,0 @@ -/* $OpenBSD: pmap.c,v 1.5 2004/06/24 19:59:13 miod Exp $ */ -/* - * Copyright (c) 2001, 2002, 2003 Miodrag Vallat - * Copyright (c) 1998-2001 Steve Murphree, Jr. - * Copyright (c) 1996 Nivas Madhur - * All rights reserved. - * - * 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 Nivas Madhur. - * 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. - * - */ -/* - * Mach Operating System - * Copyright (c) 1991 Carnegie Mellon University - * Copyright (c) 1991 OMRON Corporation - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/simplelock.h> -#include <sys/proc.h> -#include <sys/malloc.h> -#include <sys/pool.h> -#include <sys/msgbuf.h> -#include <sys/user.h> - -#include <uvm/uvm.h> - -#include <machine/asm_macro.h> -#include <machine/board.h> -#include <machine/cmmu.h> -#include <machine/cpu_number.h> -#include <machine/pmap_table.h> - -/* - * VM externals - */ -extern vaddr_t avail_start, avail_end; -extern vaddr_t virtual_avail, virtual_end; -extern vaddr_t last_addr; - -/* - * Macros to operate pm_cpus field - */ -#define SETBIT_CPUSET(cpu_number, cpuset) (*(cpuset)) |= (1 << (cpu_number)); -#define CLRBIT_CPUSET(cpu_number, cpuset) (*(cpuset)) &= ~(1 << (cpu_number)); - -#ifdef DEBUG -/* - * Static variables, functions and variables for debugging - */ - -/* - * conditional debugging - */ -#define CD_FULL 0x02 - -#define CD_ACTIVATE 0x0000004 /* pmap_activate */ -#define CD_KMAP 0x0000008 /* pmap_expand_kmap */ -#define CD_MAP 0x0000010 /* pmap_map */ -#define CD_CACHE 0x0000020 /* pmap_cache_ctrl */ -#define CD_BOOT 0x0000040 /* pmap_bootstrap */ -#define CD_INIT 0x0000080 /* pmap_init */ -#define CD_CREAT 0x0000100 /* pmap_create */ -#define CD_FREE 0x0000200 /* pmap_release */ -#define CD_DESTR 0x0000400 /* pmap_destroy */ -#define CD_RM 0x0000800 /* pmap_remove */ -#define CD_RMAL 0x0001000 /* pmap_remove_all */ -#define CD_PROT 0x0002000 /* pmap_protect */ -#define CD_EXP 0x0004000 /* pmap_expand */ -#define CD_ENT 0x0008000 /* pmap_enter */ -#define CD_UPD 0x0010000 /* pmap_update */ -#define CD_COL 0x0020000 /* pmap_collect */ -#define CD_CBIT 0x0040000 /* pmap_changebit */ -#define CD_TBIT 0x0080000 /* pmap_testbit */ -#define CD_USBIT 0x0100000 /* pmap_unsetbit */ -#define CD_PGMV 0x0200000 /* pagemove */ -#define CD_ALL 0x0FFFFFC - -int pmap_con_dbg = 0; - -/* - * Alignment checks for pages (must lie on page boundaries). - */ -#define PAGE_ALIGNED(ad) (((vaddr_t)(ad) & PAGE_MASK) == 0) -#define CHECK_PAGE_ALIGN(ad, who) \ - if (!PAGE_ALIGNED(ad)) \ - printf("%s: addr %x not page aligned.\n", who, ad) - -#else /* DEBUG */ - -#define CHECK_PAGE_ALIGN(ad, who) - -#endif /* DEBUG */ - -struct pool pmappool, pvpool; - -caddr_t vmmap; -pt_entry_t *vmpte, *msgbufmap; - -struct pmap kernel_pmap_store; -pmap_t kernel_pmap = &kernel_pmap_store; - -typedef struct kpdt_entry *kpdt_entry_t; -struct kpdt_entry { - kpdt_entry_t next; - paddr_t phys; -}; -#define KPDT_ENTRY_NULL ((kpdt_entry_t)0) - -kpdt_entry_t kpdt_free; - -/* - * Two pages of scratch space per cpu. - * Used in pmap_copy_page() and pmap_zero_page(). - */ -vaddr_t phys_map_vaddr, phys_map_vaddr_end; - -#define PV_ENTRY_NULL ((pv_entry_t) 0) - -static pv_entry_t pg_to_pvh(struct vm_page *); - -static __inline pv_entry_t -pg_to_pvh(struct vm_page *pg) -{ - return &pg->mdpage.pvent; -} - -/* - * Locking primitives - */ - -/* - * We raise the interrupt level to splvm, to block interprocessor - * interrupts during pmap operations. - */ -#define SPLVM(spl) spl = splvm() -#define SPLX(spl) splx(spl) - -#define PMAP_LOCK(pmap,spl) \ - do { \ - SPLVM(spl); \ - simple_lock(&(pmap)->pm_lock); \ - } while (0) -#define PMAP_UNLOCK(pmap, spl) \ - do { \ - simple_unlock(&(pmap)->pm_lock); \ - SPLX(spl); \ - } while (0) - -#define ETHERPAGES 16 -void *etherbuf = NULL; -int etherlen; - -#ifdef PMAP_USE_BATC - -/* - * number of BATC entries used - */ -int batc_used; - -/* - * keep track BATC mapping - */ -batc_entry_t batc_entry[BATC_MAX]; - -#endif /* PMAP_USE_BATC */ - -vaddr_t kmapva = 0; - -/* - * Internal routines - */ -void flush_atc_entry(long, vaddr_t, boolean_t); -pt_entry_t *pmap_expand_kmap(vaddr_t, vm_prot_t); -void pmap_remove_pte(pmap_t, vaddr_t, pt_entry_t *); -void pmap_remove_range(pmap_t, vaddr_t, vaddr_t); -void pmap_expand(pmap_t, vaddr_t); -void pmap_release(pmap_t); -vaddr_t pmap_map(vaddr_t, paddr_t, paddr_t, vm_prot_t, u_int); -pt_entry_t *pmap_pte(pmap_t, vaddr_t); -void pmap_remove_all(struct vm_page *); -void pmap_changebit(struct vm_page *, int, int); -boolean_t pmap_unsetbit(struct vm_page *, int); -boolean_t pmap_testbit(struct vm_page *, int); - -/* - * quick PTE field checking macros - */ -#define pmap_pte_w(pte) (*(pte) & PG_W) -#define pmap_pte_prot(pte) (*(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)) - -/* - * Convert machine-independent protection code to M88K protection bits. - */ -static __inline u_int32_t -m88k_protection(pmap_t pmap, vm_prot_t prot) -{ - pt_entry_t p; - - p = (prot & VM_PROT_WRITE) ? PG_RW : PG_RO; - /* - * XXX this should not be necessary anymore now that pmap_enter - * does the correct thing... -- miod - */ -#ifdef M88110 - if (cputyp == CPU_88110) { - p |= PG_U; - /* if the map is the kernel's map and since this - * is not a paged kernel, we go ahead and mark - * the page as modified to avoid an exception - * upon writing to the page the first time. XXX smurph - */ - if (pmap == kernel_pmap) { - if ((p & PG_RO) == 0) - p |= PG_M; - } - } -#endif - return p; -} - -/* - * Routine: FLUSH_ATC_ENTRY - * - * Function: - * Flush atc(TLB) which maps given virtual address, in the CPUs which - * are specified by 'users', for the operating mode specified by - * 'kernel'. - * - * Parameters: - * users bit patterns of the CPUs which may hold the TLB, and - * should be flushed - * va virtual address that should be flushed - * kernel TRUE if supervisor mode, FALSE if user mode - */ -void -flush_atc_entry(long users, vaddr_t va, boolean_t kernel) -{ -#if NCPUS > 1 - int cpu; - - if (users == 0) - return; - -#ifdef DEBUG - if (ff1(users) >= MAX_CPUS) { - panic("flush_atc_entry: invalid ff1 users = %d", ff1(tusers)); - } -#endif - - while ((cpu = ff1(users)) != 32) { - if (cpu_sets[cpu]) { /* just checking to make sure */ - cmmu_flush_tlb(cpu, kernel, va, PAGE_SIZE); - } - users &= ~(1 << cpu); - } -#else - if (users != 0) - cmmu_flush_tlb(cpu_number(), kernel, va, PAGE_SIZE); -#endif -} - -/* - * Routine: PMAP_PTE - * - * Function: - * Given a map and a virtual address, compute a (virtual) pointer - * to the page table entry (PTE) which maps the address . - * If the page table associated with the address does not - * exist, PT_ENTRY_NULL is returned (and the map may need to grow). - * - * Parameters: - * pmap pointer to pmap structure - * virt virtual address for which page table entry is desired - * - * Otherwise the page table address is extracted from the segment table, - * the page table index is added, and the result is returned. - */ -pt_entry_t * -pmap_pte(pmap_t pmap, vaddr_t virt) -{ - sdt_entry_t *sdt; - -#ifdef DEBUG - /*XXX will this change if physical memory is not contiguous? */ - /* take a look at PDTIDX XXXnivas */ - if (pmap == PMAP_NULL) - panic("pmap_pte: pmap is NULL"); -#endif - - sdt = SDTENT(pmap, virt); - /* - * Check whether page table exists. - */ - if (!SDT_VALID(sdt)) - return (PT_ENTRY_NULL); - - return (pt_entry_t *)(PG_PFNUM(*(sdt + SDT_ENTRIES)) << PDT_SHIFT) + - PDTIDX(virt); -} - -/* - * Routine: PMAP_EXPAND_KMAP (internal) - * - * Function: - * Allocate a page descriptor table (pte_table) and validate associated - * segment table entry, returning pointer to page table entry. This is - * much like 'pmap_expand', except that table space is acquired - * from an area set up by pmap_bootstrap, instead of through - * uvm_km_zalloc. (Obviously, because uvm_km_zalloc uses the kernel map - * for allocation - which we can't do when trying to expand the - * kernel map!) Note that segment tables for the kernel map were - * all allocated at pmap_bootstrap time, so we only need to worry - * about the page table here. - * - * Parameters: - * virt VA for which translation tables are needed - * prot protection attributes for segment entries - * - * Extern/Global: - * kpdt_free kernel page table free queue - * - * Calls: - * m88k_protection - * - * This routine simply dequeues a table from the kpdt_free list, - * initializes all its entries (invalidates them), and sets the - * corresponding segment table entry to point to it. If the kpdt_free - * list is empty - we panic (no other places to get memory, sorry). (Such - * a panic indicates that pmap_bootstrap is not allocating enough table - * space for the kernel virtual address space). - * - */ -pt_entry_t * -pmap_expand_kmap(vaddr_t virt, vm_prot_t prot) -{ - sdt_entry_t template, *sdt; - kpdt_entry_t kpdt_ent; - -#ifdef DEBUG - if ((pmap_con_dbg & (CD_KMAP | CD_FULL)) == (CD_KMAP | CD_FULL)) - printf("(pmap_expand_kmap: %x) v %x\n", curproc, virt); -#endif - - template = m88k_protection(kernel_pmap, prot) | SG_V; - - /* segment table entry derivate from map and virt. */ - sdt = SDTENT(kernel_pmap, virt); -#ifdef DEBUG - if (SDT_VALID(sdt)) - panic("pmap_expand_kmap: segment table entry VALID"); -#endif - - kpdt_ent = kpdt_free; - if (kpdt_ent == KPDT_ENTRY_NULL) - panic("pmap_expand_kmap: Ran out of kernel pte tables"); - - kpdt_free = kpdt_free->next; - /* physical table */ - *sdt = kpdt_ent->phys | template; - /* virtual table */ - *(sdt + SDT_ENTRIES) = (vaddr_t)kpdt_ent | template; - - /* Reinitialize this kpdt area to zero */ - bzero((void *)kpdt_ent, PDT_SIZE); - - return (pt_entry_t *)(kpdt_ent) + PDTIDX(virt); -} - -/* - * Routine: PMAP_MAP - * - * Function: - * Map memory at initialization. The physical addresses being - * mapped are not managed and are never unmapped. - * - * Parameters: - * virt virtual address of range to map - * start physical address of range to map - * end physical address of end of range - * prot protection attributes - * cmode cache control attributes - * - * Calls: - * pmap_pte - * pmap_expand_kmap - * - * Special Assumptions - * For now, VM is already on, only need to map the specified - * memory. Used only by pmap_bootstrap() and vm_page_startup(). - * - * For each page that needs mapping: - * pmap_pte is called to obtain the address of the page table - * table entry (PTE). If the page table does not exist, - * pmap_expand_kmap is called to allocate it. Finally, the page table - * entry is set to point to the physical page. - * - * initialize template with paddr, prot, dt - * look for number of phys pages in range - * { - * pmap_pte(virt) - expand if necessary - * stuff pte from template - * increment virt one page - * increment template paddr one page - * } - * - */ -vaddr_t -pmap_map(vaddr_t virt, paddr_t start, paddr_t end, vm_prot_t prot, u_int cmode) -{ - u_int npages; - u_int num_phys_pages; - pt_entry_t template, *pte; - paddr_t page; -#ifdef PMAP_USE_BATC - u_int32_t batctmp; - int i; -#endif - -#ifdef DEBUG - if (pmap_con_dbg & CD_MAP) - printf ("(pmap_map: %x) phys address from %x to %x mapped at virtual %x, prot %x cmode %x\n", - curproc, start, end, virt, prot, cmode); -#endif - -#ifdef DEBUG - /* Check for zero if we map the very end of the address space... */ - if (start > end && end != 0) { - panic("pmap_map: start greater than end address"); - } -#endif - - template = m88k_protection(kernel_pmap, prot) | cmode | PG_V; - -#ifdef PMAP_USE_BATC - batctmp = BATC_SO | BATC_V; - if (template & CACHE_WT) - batctmp |= BATC_WT; - if (template & CACHE_GLOBAL) - batctmp |= BATC_GLOBAL; - if (template & CACHE_INH) - batctmp |= BATC_INH; - if (template & PG_PROT) - batctmp |= BATC_PROT; -#endif - - page = trunc_page(start); - npages = atop(round_page(end) - page); - for (num_phys_pages = npages; num_phys_pages != 0; num_phys_pages--) { -#ifdef PMAP_USE_BATC - -#ifdef DEBUG - if ((pmap_con_dbg & (CD_MAP | CD_FULL)) == (CD_MAP | CD_FULL)) - printf("(pmap_map: %x) num_phys_pg=%x, virt=%x, " - "align V=%d, page=%x, align P=%d\n", - curproc, num_phys_pages, virt, - BATC_BLK_ALIGNED(virt), page, - BATC_BLK_ALIGNED(page)); -#endif - - if (BATC_BLK_ALIGNED(virt) && BATC_BLK_ALIGNED(page) && - num_phys_pages >= BATC_BLKBYTES/PAGE_SIZE && - batc_used < BATC_MAX ) { - /* - * map by BATC - */ - batctmp |= M88K_BTOBLK(virt) << BATC_VSHIFT; - batctmp |= M88K_BTOBLK(page) << BATC_PSHIFT; - - for (i = 0; i < MAX_CPUS; i++) - if (cpu_sets[i]) - cmmu_set_pair_batc_entry(i, batc_used, - batctmp); - batc_entry[batc_used] = batctmp; -#ifdef DEBUG - if (pmap_con_dbg & CD_MAP) { - printf("(pmap_map: %x) BATC used=%d, data=%x\n", curproc, batc_used, batctmp); - for (i = 0; i < BATC_BLKBYTES; i += PAGE_SIZE) { - pte = pmap_pte(kernel_pmap, virt + i); - if (PDT_VALID(pte)) - printf("(pmap_map: %x) va %x is already mapped: pte %x\n", - curproc, virt + i, *pte); - } - } -#endif - batc_used++; - virt += BATC_BLKBYTES; - page += BATC_BLKBYTES; - num_phys_pages -= BATC_BLKBYTES/PAGE_SIZE; - continue; - } -#endif /* PMAP_USE_BATC */ - - if ((pte = pmap_pte(kernel_pmap, virt)) == PT_ENTRY_NULL) - pte = pmap_expand_kmap(virt, - VM_PROT_READ | VM_PROT_WRITE); - -#ifdef DEBUG - if ((pmap_con_dbg & (CD_MAP | CD_FULL)) == (CD_MAP | CD_FULL)) - if (PDT_VALID(pte)) - printf("(pmap_map: %x) pte @ 0x%p already valid\n", curproc, pte); -#endif - - *pte = template | page; - virt += PAGE_SIZE; - page += PAGE_SIZE; - } - return virt; -} - -/* - * Routine: PMAP_CACHE_CONTROL - * - * Function: - * Set the cache-control bits in the page table entries(PTE) which maps - * the specified virtual address range. - * - * Parameters: - * pmap_t pmap - * vaddr_t s - * vaddr_t e - * u_int mode - * - * Calls: - * pmap_pte - * invalidate_pte - * flush_atc_entry - * - * This routine sequences through the pages of the specified range. - * For each, it calls pmap_pte to acquire a pointer to the page table - * entry (PTE). If the PTE is invalid, or non-existent, nothing is done. - * Otherwise, the cache-control bits in the PTE's are adjusted as specified. - * - */ -void -pmap_cache_ctrl(pmap_t pmap, vaddr_t s, vaddr_t e, u_int mode) -{ - int spl; - pt_entry_t *pte; - vaddr_t va; - paddr_t pa; - boolean_t kflush; - int cpu; - u_int users; - -#ifdef DEBUG - if ((mode & CACHE_MASK) != mode) { - printf("(cache_ctrl) illegal mode %x\n", mode); - return; - } - if (pmap_con_dbg & CD_CACHE) { - printf("(pmap_cache_ctrl: %x) pmap %x, va %x, mode %x\n", curproc, pmap, s, mode); - } - - if (pmap == PMAP_NULL) - panic("pmap_cache_ctrl: pmap is NULL"); -#endif /* DEBUG */ - - PMAP_LOCK(pmap, spl); - - users = pmap->pm_cpus; - kflush = pmap == kernel_pmap; - - for (va = s; va < e; va += PAGE_SIZE) { - if ((pte = pmap_pte(pmap, va)) == PT_ENTRY_NULL) - continue; -#ifdef DEBUG - if (pmap_con_dbg & CD_CACHE) { - printf("(cache_ctrl) pte@0x%p\n", pte); - } -#endif /* DEBUG */ - /* - * Invalidate pte temporarily to avoid being written back - * the modified bit and/or the reference bit by any other cpu. - * XXX - */ - *pte = (invalidate_pte(pte) & ~CACHE_MASK) | mode; - flush_atc_entry(users, va, kflush); - - /* - * Data cache should be copied back and invalidated. - */ - pa = ptoa(PG_PFNUM(*pte)); - for (cpu = 0; cpu < MAX_CPUS; cpu++) - if (cpu_sets[cpu]) - cmmu_flush_cache(cpu, pa, PAGE_SIZE); - } - PMAP_UNLOCK(pmap, spl); -} - -/* - * Routine: PMAP_BOOTSTRAP - * - * Function: - * Bootstrap the system enough to run with virtual memory. - * Map the kernel's code and data, allocate the kernel - * translation table space, and map control registers - * and other IO addresses. - * - * Parameters: - * load_start PA where kernel was loaded - * - * Extern/Global: - * - * PAGE_SIZE VM (software) page size - * kernelstart start symbol of kernel text - * etext end of kernel text - * phys_map_vaddr VA of page mapped arbitrarily for debug/IO - * - * Calls: - * simple_lock_init - * pmap_map - * - * The physical address 'load_start' is mapped at - * VM_MIN_KERNEL_ADDRESS, which maps the kernel code and data at the - * virtual address for which it was (presumably) linked. Immediately - * following the end of the kernel code/data, sufficient page of - * physical memory are reserved to hold translation tables for the kernel - * address space. - * - * A pair of virtual pages per cpu are reserved for debugging and - * IO purposes. They are arbitrarily mapped when needed. They are used, - * for example, by pmap_copy_page and pmap_zero_page. - * - * For luna88k, we have to map ROM work area also. This is a read only - * mapping for 0x20000 bytes. We will end up having load_start as - * 0 and VM_MIN_KERNEL_ADDRESS as 0 - yes sir, we have one-to-one - * mapping!!! - */ - -void -pmap_bootstrap(vaddr_t load_start) -{ - kpdt_entry_t kpdt_virt; - sdt_entry_t *kmap; - vaddr_t vaddr, virt; - paddr_t s_text, e_text, kpdt_phys; - pt_entry_t *pte; - unsigned int kernel_pmap_size, pdt_size; - int i; - pmap_table_t ptable; - extern void *kernelstart, *etext; - - simple_lock_init(&kernel_pmap->pm_lock); - - /* - * Allocate the kernel page table from the front of available - * physical memory, i.e. just after where the kernel image was loaded. - */ - /* - * The calling sequence is - * ... - * pmap_bootstrap(&kernelstart, ...); - * kernelstart is the first symbol in the load image. - * We link the kernel such that &kernelstart == 0x20000 - * The expression (&kernelstart - load_start) will end up as - * 0, making virtual_avail == avail_start, giving a 1-to-1 map) - */ - - avail_start = round_page(avail_start); - virtual_avail = avail_start + - (trunc_page((vaddr_t)&kernelstart) - load_start); - - /* - * Initialize kernel_pmap structure - */ - kernel_pmap->pm_count = 1; - kernel_pmap->pm_cpus = 0; - kmap = (sdt_entry_t *)(avail_start); - kernel_pmap->pm_stab = (sdt_entry_t *)virtual_avail; - kmapva = virtual_avail; - - /* - * Reserve space for segment table entries. - * One for the regular segment table and one for the shadow table - * The shadow table keeps track of the virtual address of page - * tables. This is used in virtual-to-physical address translation - * functions. Remember, MMU cares only for physical addresses of - * segment and page table addresses. For kernel page tables, we - * really don't need this virtual stuff (since the kernel will - * be mapped 1-to-1) but for user page tables, this is required. - * Just to be consistent, we will maintain the shadow table for - * kernel pmap also. - */ - kernel_pmap_size = 2 * SDT_SIZE; - -#ifdef DEBUG - printf("kernel segment table size = 0x%x\n", kernel_pmap_size); -#endif - /* init all segment descriptors to zero */ - bzero(kernel_pmap->pm_stab, kernel_pmap_size); - - avail_start += kernel_pmap_size; - virtual_avail += kernel_pmap_size; - - /* make sure page tables are page aligned!! XXX smurph */ - avail_start = round_page(avail_start); - virtual_avail = round_page(virtual_avail); - - /* save pointers to where page table entries start in physical memory */ - kpdt_phys = avail_start; - kpdt_virt = (kpdt_entry_t)virtual_avail; - - /* Compute how much space we need for the kernel page table */ - pdt_size = atop(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) - * sizeof(pt_entry_t); - for (ptable = pmap_table_build(); ptable->size != (vsize_t)-1; ptable++) - pdt_size += atop(ptable->size) * sizeof(pt_entry_t); - pdt_size = round_page(pdt_size); - kernel_pmap_size += pdt_size; - avail_start += pdt_size; - virtual_avail += pdt_size; - - /* init all page descriptors to zero */ - bzero((void *)kpdt_phys, pdt_size); -#ifdef DEBUG - printf("--------------------------------------\n"); - printf(" kernel page start = 0x%x\n", kpdt_phys); - printf(" kernel page table size = 0x%x\n", pdt_size); - printf(" kernel page end = 0x%x\n", avail_start); - - printf("kpdt_virt = 0x%x\n", kpdt_virt); -#endif - /* - * init the kpdt queue - */ - kpdt_free = kpdt_virt; - for (i = pdt_size / PDT_SIZE; i != 0; i--) { - kpdt_virt->next = (kpdt_entry_t)((vaddr_t)kpdt_virt + PDT_SIZE); - kpdt_virt->phys = kpdt_phys; - kpdt_virt = kpdt_virt->next; - kpdt_phys += PDT_SIZE; - } - kpdt_virt->next = KPDT_ENTRY_NULL; /* terminate the list */ - - /* - * Map the kernel image into virtual space - */ - - s_text = load_start; /* paddr of text */ - e_text = load_start + - ((vaddr_t)&etext - trunc_page((vaddr_t)&kernelstart)); - /* paddr of end of text section*/ - e_text = round_page(e_text); - - /* map the first 128k (PROM work) read only, cache inhibited (? XXX) */ - vaddr = pmap_map(0, 0, 0x20000, VM_PROT_WRITE | VM_PROT_READ, - CACHE_INH); - - /* map the kernel text read only */ - vaddr = pmap_map(trunc_page((vaddr_t)&kernelstart), - s_text, e_text, VM_PROT_WRITE | VM_PROT_READ, - CACHE_GLOBAL); /* shouldn't it be RO? XXX*/ - - vaddr = pmap_map(vaddr, e_text, (paddr_t)kmap, - VM_PROT_WRITE | VM_PROT_READ, CACHE_GLOBAL); - - /* - * Map system segment & page tables - should be cache inhibited? - * 88200 manual says that CI bit is driven on the Mbus while accessing - * the translation tree. I don't think we need to map it CACHE_INH - * here... - */ - if (kmapva != vaddr) { - while (vaddr < (virtual_avail - kernel_pmap_size)) - vaddr = round_page(vaddr + 1); - } - vaddr = pmap_map(vaddr, (paddr_t)kmap, avail_start, - VM_PROT_WRITE | VM_PROT_READ, CACHE_INH); - - virtual_avail = round_page(virtual_avail); - virtual_end = VM_MAX_KERNEL_ADDRESS; - - /* - * Map two pages per cpu for copying/zeroing. - */ - - phys_map_vaddr = virtual_avail; - phys_map_vaddr_end = virtual_avail + 2 * (max_cpus << PAGE_SHIFT); - avail_start += 2 * (max_cpus << PAGE_SHIFT); - virtual_avail += 2 * (max_cpus << PAGE_SHIFT); - - /* - * Map all IO space 1-to-1. Ideally, I would like to not do this - * but have va for the given IO address dynamically allocated. But - * on the 88200, 2 of the BATCs are hardwired to map the IO space - * 1-to-1; I decided to map the rest of the IO space 1-to-1. - * And bug ROM & the SRAM need to be mapped 1-to-1 if we ever want to - * execute bug system calls after the MMU has been turned on. - * OBIO should be mapped cache inhibited. - */ - - for (ptable = pmap_table_build(); ptable->size != (vsize_t)-1; ptable++) - if (ptable->size != 0) { - pmap_map(ptable->virt_start, ptable->phys_start, - ptable->phys_start + ptable->size, - ptable->prot, ptable->cacheability); - } - - /* - * Allocate all the submaps we need. Note that SYSMAP just allocates - * kernel virtual address with no physical backing memory. The idea - * is physical memory will be mapped at this va before using that va. - * This means that if different physical pages are going to be mapped - * at different times, we better do a tlb flush before using it - - * else we will be referencing the wrong page. - */ - -#define SYSMAP(c, p, v, n) \ -({ \ - v = (c)virt; \ - if ((p = pmap_pte(kernel_pmap, virt)) == PT_ENTRY_NULL) \ - pmap_expand_kmap(virt, VM_PROT_READ | VM_PROT_WRITE); \ - virt += ((n) * PAGE_SIZE); \ -}) - - virt = virtual_avail; - - SYSMAP(caddr_t, vmpte, vmmap, 1); - invalidate_pte(vmpte); - - SYSMAP(struct msgbuf *, msgbufmap, msgbufp, btoc(MSGBUFSIZE)); - - virtual_avail = virt; - - /* - * Set translation for UPAGES at UADDR. The idea is we want to - * have translations set up for UADDR. Later on, the ptes for - * for this address will be set so that kstack will refer - * to the u area. Make sure pmap knows about this virtual - * address by doing vm_findspace on kernel_map. - */ - - for (i = 0, virt = UADDR; i < UPAGES; i++, virt += PAGE_SIZE) { - if ((pte = pmap_pte(kernel_pmap, virt)) == PT_ENTRY_NULL) - pmap_expand_kmap(virt, VM_PROT_READ | VM_PROT_WRITE); - } - - /* - * Switch to using new page tables - */ - - kernel_pmap->pm_apr = (atop(kmap) << PG_SHIFT) | - CACHE_GLOBAL | CACHE_WT | APR_V; - - /* Invalidate entire kernel TLB and get ready for address translation */ - for (i = 0; i < MAX_CPUS; i++) - if (cpu_sets[i]) { - cmmu_flush_tlb(i, TRUE, VM_MIN_KERNEL_ADDRESS, - VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS); - /* Load supervisor pointer to segment table. */ - cmmu_set_sapr(i, kernel_pmap->pm_apr); -#ifdef DEBUG - printf("cpu%d: running virtual\n", i); -#endif - SETBIT_CPUSET(i, &kernel_pmap->pm_cpus); - } -} - -/* - * Routine: PMAP_INIT - * - * Function: - * Initialize the pmap module. It is called by vm_init, to initialize - * any structures that the pmap system needs to map virtual memory. - * - * Calls: - * pool_init - * - * This routine does not really have much to do. It initializes - * pools for pmap structures and pv_entry structures. - */ -void -pmap_init(void) -{ -#ifdef DEBUG - if (pmap_con_dbg & CD_INIT) - printf("pmap_init()\n"); -#endif - - pool_init(&pmappool, sizeof(struct pmap), 0, 0, 0, "pmappl", - &pool_allocator_nointr); - pool_init(&pvpool, sizeof(pv_entry_t), 0, 0, 0, "pvpl", NULL); -} /* pmap_init() */ - -/* - * Routine: PMAP_ZERO_PAGE - * - * Function: - * Zeroes the specified page. - * - * Parameters: - * pg page to zero - * - * Extern/Global: - * phys_map_vaddr - * - * Calls: - * m88k_protection - * - * Special Assumptions: - * no locking required - * - * This routine maps the physical pages at the 'phys_map' virtual - * address set up in pmap_bootstrap. It flushes the TLB to make the new - * mappings effective, and zeros all the bits. - */ -void -pmap_zero_page(struct vm_page *pg) -{ - paddr_t pa = VM_PAGE_TO_PHYS(pg); - vaddr_t va; - int spl; - int cpu = cpu_number(); - pt_entry_t *pte; - - CHECK_PAGE_ALIGN(pa, "pmap_zero_page"); - - va = (vaddr_t)(phys_map_vaddr + 2 * (cpu << PAGE_SHIFT)); - pte = pmap_pte(kernel_pmap, va); - - SPLVM(spl); - - *pte = m88k_protection(kernel_pmap, VM_PROT_READ | VM_PROT_WRITE) | - CACHE_GLOBAL | PG_V | pa; - - /* - * We don't need the flush_atc_entry() dance, as these pages are - * bound to only one cpu. - */ - cmmu_flush_tlb(cpu, TRUE, va, PAGE_SIZE); - - /* - * The page is likely to be a non-kernel mapping, and as - * such write back. Also, we might have split U/S caches! - * So be sure to have the pa flushed after the filling. - */ - bzero((void *)va, PAGE_SIZE); - cmmu_flush_data_cache(cpu, pa, PAGE_SIZE); - - SPLX(spl); -} - -/* - * Routine: PMAP_CREATE - * - * Function: - * 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. - * - * This routines allocates a pmap structure. - */ -pmap_t -pmap_create(void) -{ - pmap_t pmap; - sdt_entry_t *segdt; - paddr_t stpa; - u_int s; -#ifdef PMAP_USE_BATC - int i; -#endif - - pmap = pool_get(&pmappool, PR_WAITOK); - bzero(pmap, sizeof(*pmap)); - - /* - * Allocate memory for *actual* segment table and *shadow* table. - */ - s = round_page(2 * SDT_SIZE); -#ifdef DEBUG - if (pmap_con_dbg & CD_CREAT) { - printf("(pmap_create: %x) need %d pages for sdt\n", - curproc, atop(s)); - } -#endif - - segdt = (sdt_entry_t *)uvm_km_zalloc(kernel_map, s); - if (segdt == NULL) - panic("pmap_create: uvm_km_zalloc failure"); - - /* - * Initialize pointer to segment table both virtual and physical. - */ - pmap->pm_stab = segdt; - if (pmap_extract(kernel_pmap, (vaddr_t)segdt, - (paddr_t *)&stpa) == FALSE) - panic("pmap_create: pmap_extract failed!"); - pmap->pm_apr = (atop(stpa) << PG_SHIFT) | - CACHE_GLOBAL | APR_V; - -#ifdef DEBUG - if (!PAGE_ALIGNED(stpa)) - panic("pmap_create: sdt_table 0x%x not aligned on page boundary", - (int)stpa); - - if (pmap_con_dbg & CD_CREAT) { - printf("(pmap_create: %x) pmap=0x%p, pm_stab=0x%x (pa 0x%x)\n", - curproc, pmap, pmap->pm_stab, stpa); - } -#endif - - /* memory for page tables should not be writeback or local */ - pmap_cache_ctrl(kernel_pmap, - (vaddr_t)segdt, (vaddr_t)segdt + s, CACHE_GLOBAL | CACHE_WT); - - /* - * Initialize SDT_ENTRIES. - */ - /* - * There is no need to clear segment table, since uvm_km_zalloc - * provides us clean pages. - */ - - /* - * Initialize pmap structure. - */ - pmap->pm_count = 1; - simple_lock_init(&pmap->pm_lock); - pmap->pm_cpus = 0; - -#ifdef PMAP_USE_BATC - /* initialize block address translation cache */ - for (i = 0; i < BATC_MAX; i++) { - pmap->pm_ibatc[i].bits = 0; - pmap->pm_dbatc[i].bits = 0; - } -#endif - - return pmap; -} - -/* - * Routine: PMAP_RELEASE - * - * Internal procedure used by pmap_destroy() to actualy deallocate - * the tables. - * - * Parameters: - * pmap pointer to pmap structure - * - * Calls: - * pmap_pte - * uvm_km_free - * - * Special Assumptions: - * No locking is needed, since this is only called which the - * pm_count field of the pmap structure goes to zero. - * - * This routine sequences of through the user address space, releasing - * all translation table space back to the system using uvm_km_free. - * The loops are indexed by the virtual address space - * ranges represented by the table group sizes(PDT_VA_SPACE). - * - */ -void -pmap_release(pmap_t pmap) -{ - unsigned long sdt_va; /* outer loop index */ - sdt_entry_t *sdttbl; /* ptr to first entry in the segment table */ - pt_entry_t *gdttbl; /* ptr to first entry in a page table */ - -#ifdef DEBUG - if (pmap_con_dbg & CD_FREE) - printf("(pmap_release: %x) pmap %x\n", curproc, pmap); -#endif - - /* Segment table Loop */ - for (sdt_va = VM_MIN_ADDRESS; sdt_va < VM_MAX_ADDRESS; - sdt_va += PDT_VA_SPACE) { - if ((gdttbl = pmap_pte(pmap, (vaddr_t)sdt_va)) != PT_ENTRY_NULL) { -#ifdef DEBUG - if ((pmap_con_dbg & (CD_FREE | CD_FULL)) == (CD_FREE | CD_FULL)) - printf("(pmap_release: %x) free page table = 0x%x\n", - curproc, gdttbl); -#endif - uvm_km_free(kernel_map, (vaddr_t)gdttbl, PAGE_SIZE); - } - } - - /* - * Freeing both *actual* and *shadow* segment tables - */ - sdttbl = pmap->pm_stab; /* addr of segment table */ -#ifdef DEBUG - if ((pmap_con_dbg & (CD_FREE | CD_FULL)) == (CD_FREE | CD_FULL)) - printf("(pmap_release: %x) free segment table = 0x%x\n", - curproc, sdttbl); -#endif - uvm_km_free(kernel_map, (vaddr_t)sdttbl, round_page(2 * SDT_SIZE)); - -#ifdef DEBUG - if (pmap_con_dbg & CD_FREE) - printf("(pmap_release: %x) pm_count = 0\n", curproc); -#endif -} - -/* - * Routine: PMAP_DESTROY - * - * Function: - * Retire the given physical map from service. Should only be called - * if the map contains no valid mappings. - * - * Parameters: - * pmap pointer to pmap structure - * - * Calls: - * pmap_release - * pool_put - * - * Special Assumptions: - * Map contains no valid mappings. - * - * This routine decrements the reference count in the pmap - * structure. If it goes to zero, pmap_release is called to release - * the memory space to the system. Then, call pool_put to free the - * pmap structure. - */ -void -pmap_destroy(pmap_t pmap) -{ - int count; - -#ifdef DEBUG - if (pmap == kernel_pmap) - panic("pmap_destroy: Attempt to destroy kernel pmap"); -#endif - - simple_lock(&pmap->pm_lock); - count = --pmap->pm_count; - simple_unlock(&pmap->pm_lock); - if (count == 0) { - pmap_release(pmap); - pool_put(&pmappool, pmap); - } -} - - -/* - * Routine: PMAP_REFERENCE - * - * Function: - * Add a reference to the specified pmap. - * - * Parameters: - * pmap pointer to pmap structure - * - * Under a pmap read lock, the pm_count field of the pmap structure - * is incremented. The function then returns. - */ -void -pmap_reference(pmap_t pmap) -{ - - simple_lock(&pmap->pm_lock); - pmap->pm_count++; - simple_unlock(&pmap->pm_lock); -} - -/* - * Routine: PMAP_REMOVE_PTE (internal) - * - * Function: - * Invalidate a given page table entry associated with the - * given virtual address. - * - * Parameters: - * pmap pointer to pmap structure - * va virtual address of page to remove - * pte existing pte - * - * External/Global: - * pv lists - * - * Calls: - * pool_put - * invalidate_pte - * flush_atc_entry - * - * Special Assumptions: - * The pmap must be locked. - * - * If the PTE is valid, the routine must invalidate the entry. The - * 'modified' bit, if on, is referenced to the VM, and into the appropriate - * entry in the PV list entry. Next, the function must find the PV - * list entry associated with this pmap/va (if it doesn't exist - the function - * panics). The PV list entry is unlinked from the list, and returned to - * its zone. - */ -void -pmap_remove_pte(pmap_t pmap, vaddr_t va, pt_entry_t *pte) -{ - pt_entry_t opte; - pv_entry_t prev, cur, pvl; - struct vm_page *pg; - paddr_t pa; - u_int users; - boolean_t kflush; - -#ifdef DEBUG - if (pmap_con_dbg & CD_RM) { - if (pmap == kernel_pmap) - printf("(pmap_remove_pte: %x) pmap kernel va %x\n", curproc, va); - else - printf("(pmap_remove_pte: %x) pmap %x va %x\n", curproc, pmap, va); - } -#endif - - if (pte == PT_ENTRY_NULL || !PDT_VALID(pte)) { - return; /* no page mapping, nothing to do! */ - } - - users = pmap->pm_cpus; - kflush = pmap == kernel_pmap; - - /* - * Update statistics. - */ - pmap->pm_stats.resident_count--; - if (pmap_pte_w(pte)) - pmap->pm_stats.wired_count--; - - pa = ptoa(PG_PFNUM(*pte)); - - /* - * Invalidate the pte. - */ - - opte = invalidate_pte(pte) & (PG_U | PG_M); - flush_atc_entry(users, va, kflush); - - pg = PHYS_TO_VM_PAGE(pa); - - /* If this isn't a managed page, just return. */ - if (pg == NULL) - return; - - /* - * Remove the mapping from the pvlist for - * this physical page. - */ - pvl = pg_to_pvh(pg); - -#ifdef DIAGNOSTIC - if (pvl->pv_pmap == PMAP_NULL) - panic("pmap_remove_pte: null pv_list"); -#endif - - prev = PV_ENTRY_NULL; - for (cur = pvl; cur != PV_ENTRY_NULL; cur = cur->pv_next) { - if (cur->pv_va == va && cur->pv_pmap == pmap) - break; - prev = cur; - } - if (cur == PV_ENTRY_NULL) { - panic("pmap_remove_pte: mapping for va " - "0x%lx (pa 0x%lx) not in pv list at 0x%p", - va, pa, pvl); - } - - if (prev == PV_ENTRY_NULL) { - /* - * Hander is the pv_entry. Copy the next one - * to hander and free the next one (we can't - * free the hander) - */ - cur = cur->pv_next; - if (cur != PV_ENTRY_NULL) { - cur->pv_flags = pvl->pv_flags; - *pvl = *cur; - pool_put(&pvpool, cur); - } else { - pvl->pv_pmap = PMAP_NULL; - } - } else { - prev->pv_next = cur->pv_next; - pool_put(&pvpool, cur); - } - - /* Update saved attributes for managed page */ - pvl->pv_flags |= opte; -} - -/* - * Routine: PMAP_REMOVE_RANGE (internal) - * - * Function: - * Invalidate page table entries associated with the - * given virtual address range. The entries given are the first - * (inclusive) and last (exclusive) entries for the VM pages. - * - * Parameters: - * pmap pointer to pmap structure - * s virtual address of start of range to remove - * e virtual address of end of range to remove - * - * External/Global: - * pv lists - * - * Calls: - * pmap_pte - * pmap_remove_pte - * - * Special Assumptions: - * The pmap must be locked. - * - * This routine sequences through the pages defined by the given - * range. For each page, the associated page table entry (PTE) is - * invalidated via pmap_remove_pte(). - * - * Empty segments are skipped for performance. - */ -void -pmap_remove_range(pmap_t pmap, vaddr_t s, vaddr_t e) -{ - vaddr_t va; - -#ifdef DEBUG - if (pmap_con_dbg & CD_RM) { - if (pmap == kernel_pmap) - printf("(pmap_remove_range: %x) pmap kernel s %x e %x\n", curproc, s, e); - else - printf("(pmap_remove_range: %x) pmap %x s %x e %x\n", curproc, pmap, s, e); - } -#endif - - /* - * Loop through the range in vm_page_size increments. - */ - for (va = s; va < e; va += PAGE_SIZE) { - sdt_entry_t *sdt; - - sdt = SDTENT(pmap, va); - - /* If no segment table, skip a whole segment */ - if (!SDT_VALID(sdt)) { - va &= SDT_MASK; - va += (1 << SDT_SHIFT) - PAGE_SIZE; - continue; - } - - pmap_remove_pte(pmap, va, pmap_pte(pmap, va)); - } -} - -/* - * Routine: PMAP_REMOVE - * - * Function: - * Remove the given range of addresses from the specified map. - * It is assumed that start and end are properly rounded to the VM page - * size. - * - * Parameters: - * pmap pointer to pmap structure - * s - * e - * - * Special Assumptions: - * Assumes not all entries must be valid in specified range. - * - * Calls: - * pmap_remove_range - * - * After taking pmap read lock, pmap_remove_range is called to do the - * real work. - */ -void -pmap_remove(pmap_t pmap, vaddr_t s, vaddr_t e) -{ - int spl; - - if (pmap == PMAP_NULL) - return; - -#ifdef DEBUG - if (s >= e) - panic("pmap_remove: start greater than end address"); -#endif - - PMAP_LOCK(pmap, spl); - pmap_remove_range(pmap, s, e); - PMAP_UNLOCK(pmap, spl); -} - -/* - * Routine: PMAP_REMOVE_ALL - * - * Function: - * Removes this physical page from all physical maps in which it - * resides. Reflects back modify bits to the pager. - * - * Parameters: - * pg physical pages which is to - * be removed from all maps - * - * Extern/Global: - * pv lists - * - * Calls: - * simple_lock - * pmap_pte - * pool_put - * - * If the page specified by the given address is not a managed page, - * this routine simply returns. Otherwise, the PV list associated with - * that page is traversed. For each pmap/va pair pmap_pte is called to - * obtain a pointer to the page table entry (PTE) associated with the - * va (the PTE must exist and be valid, otherwise the routine panics). - * The hardware 'modified' bit in the PTE is examined. If it is on, the - * corresponding bit in the PV list entry corresponding - * to the physical page is set to 1. - * Then, the PTE is invalidated, and the PV list entry is unlinked and - * freed. - * - * At the end of this function, the PV list for the specified page - * will be null. - */ -void -pmap_remove_all(struct vm_page *pg) -{ - pt_entry_t *pte; - pv_entry_t pvl; - vaddr_t va; - pmap_t pmap; - int spl; - - if (pg == NULL) { - /* not a managed page. */ -#ifdef DEBUG - if (pmap_con_dbg & CD_RMAL) - printf("(pmap_remove_all: %x) vm page 0x%x not a managed page\n", curproc, pg); -#endif - return; - } - -#ifdef DEBUG - if (pmap_con_dbg & CD_RMAL) - printf("(pmap_remove_all: %x) va %x\n", curproc, pg, pg_to_pvh(pg)->pv_va); -#endif - - SPLVM(spl); - /* - * Walk down PV list, removing all mappings. - * We don't have to lock the pv list, since we have the entire pmap - * system. - */ -remove_all_Retry: - - pvl = pg_to_pvh(pg); - - /* - * Loop for each entry on the pv list - */ - while (pvl != PV_ENTRY_NULL && (pmap = pvl->pv_pmap) != PMAP_NULL) { - if (!simple_lock_try(&pmap->pm_lock)) - goto remove_all_Retry; - - va = pvl->pv_va; - pte = pmap_pte(pmap, va); - - if (pte == PT_ENTRY_NULL || !PDT_VALID(pte)) { - pvl = pvl->pv_next; - goto next; /* no page mapping */ - } - if (pmap_pte_w(pte)) { -#ifdef DEBUG - if (pmap_con_dbg & CD_RMAL) - printf("pmap_remove_all: wired mapping for %lx not removed\n", - pg); -#endif - pvl = pvl->pv_next; - goto next; - } - - pmap_remove_pte(pmap, va, pte); - - /* - * Do not free any page tables, - * leaves that for when VM calls pmap_collect(). - */ -next: - simple_unlock(&pmap->pm_lock); - } - SPLX(spl); -} - -/* - * Routine: PMAP_PROTECT - * - * Function: - * Sets the physical protection on the specified range of this map - * as requested. - * - * Parameters: - * pmap pointer to pmap structure - * s start address of start of range - * e end address of end of range - * prot desired protection attributes - * - * Calls: - * PMAP_LOCK, PMAP_UNLOCK - * CHECK_PAGE_ALIGN - * pmap_pte - * PDT_VALID - * - * This routine sequences through the pages of the specified range. - * For each, it calls pmap_pte to acquire a pointer to the page table - * entry (PTE). If the PTE is invalid, or non-existent, nothing is done. - * Otherwise, the PTE's protection attributes are adjusted as specified. - */ -void -pmap_protect(pmap_t pmap, vaddr_t s, vaddr_t e, vm_prot_t prot) -{ - int spl; - pt_entry_t *pte, ap; - vaddr_t va; - u_int users; - boolean_t kflush; - -#ifdef DEBUG - if (s >= e) - panic("pmap_protect: start grater than end address"); -#endif - - if ((prot & VM_PROT_READ) == 0) { - pmap_remove(pmap, s, e); - return; - } - - ap = m88k_protection(pmap, prot) & PG_PROT; - - PMAP_LOCK(pmap, spl); - - users = pmap->pm_cpus; - kflush = pmap == kernel_pmap; - - CHECK_PAGE_ALIGN(s, "pmap_protect"); - - /* - * Loop through the range in vm_page_size increments. - */ - for (va = s; va < e; va += PAGE_SIZE) { - sdt_entry_t *sdt; - - sdt = SDTENT(pmap, va); - - /* If no segment table, skip a whole segment */ - if (!SDT_VALID(sdt)) { - va &= SDT_MASK; - va += (1 << SDT_SHIFT) - PAGE_SIZE; - continue; - } - - pte = pmap_pte(pmap, va); - if (pte == PT_ENTRY_NULL || !PDT_VALID(pte)) { - continue; /* no page mapping */ - } - - /* - * Invalidate pte temporarily to avoid the - * modified bit and/or the reference bit being - * written back by any other cpu. - */ - *pte = (invalidate_pte(pte) & ~PG_PROT) | ap; - flush_atc_entry(users, va, kflush); - pte++; - } - PMAP_UNLOCK(pmap, spl); -} - -/* - * Routine: PMAP_EXPAND - * - * Function: - * Expands a pmap to be able to map the specified virtual address. - * New kernel virtual memory is allocated for a page table. - * - * Must be called with the pmap system and the pmap unlocked, since - * these must be unlocked to use vm_allocate or vm_deallocate (via - * uvm_km_zalloc). Thus it must be called in a unlock/lock loop - * that checks whether the map has been expanded enough. (We won't loop - * forever, since page table aren't shrunk.) - * - * Parameters: - * pmap point to pmap structure - * v VA indicating which tables are needed - * - * Extern/Global: - * user_pt_map - * kernel_pmap - * - * Calls: - * pmap_pte - * uvm_km_free - * uvm_km_zalloc - * pmap_extract - * - * Special Assumptions - * no pmap locks held - * pmap != kernel_pmap - * - * 1: This routine immediately allocates space for a page table. - * - * 2: The page table entries (PTEs) are initialized (set invalid), and - * the corresponding segment table entry is set to point to the new - * page table. - */ -void -pmap_expand(pmap_t pmap, vaddr_t v) -{ - int spl; - vaddr_t pdt_vaddr; - paddr_t pdt_paddr; - sdt_entry_t *sdt; - pt_entry_t *pte; - -#ifdef DEBUG - if (pmap_con_dbg & CD_EXP) - printf ("(pmap_expand: %x) map %x v %x\n", curproc, pmap, v); -#endif - - CHECK_PAGE_ALIGN(v, "pmap_expand"); - - /* XXX */ - pdt_vaddr = uvm_km_zalloc(kernel_map, PAGE_SIZE); - if (pmap_extract(kernel_pmap, pdt_vaddr, &pdt_paddr) == FALSE) - panic("pmap_expand: pmap_extract failed"); - - /* memory for page tables should not be writeback or local */ - pmap_cache_ctrl(kernel_pmap, - pdt_vaddr, pdt_vaddr + PAGE_SIZE, CACHE_GLOBAL | CACHE_WT); - - PMAP_LOCK(pmap, spl); - - if ((pte = pmap_pte(pmap, v)) != PT_ENTRY_NULL) { - /* - * Someone else caused us to expand - * during our vm_allocate. - */ - simple_unlock(&pmap->pm_lock); - uvm_km_free(kernel_map, pdt_vaddr, PAGE_SIZE); - -#ifdef DEBUG - if (pmap_con_dbg & CD_EXP) - printf("(pmap_expand: %x) table has already been allocated\n", curproc); -#endif - splx(spl); - return; - } - /* - * Apply a mask to V to obtain the vaddr of the beginning of - * its containing page 'table group', i.e. the group of - * page tables that fit eithin a single VM page. - * Using that, obtain the segment table pointer that references the - * first page table in the group, and initialize all the - * segment table descriptions for the page 'table group'. - */ - v &= ~((1 << (PDT_BITS + PG_BITS)) - 1); - - sdt = SDTENT(pmap, v); - - /* - * Init each of the segment entries to point the freshly allocated - * page tables. - */ - *((sdt_entry_t *)sdt) = pdt_paddr | SG_RW | SG_V; - *((sdt_entry_t *)(sdt + SDT_ENTRIES)) = pdt_vaddr | SG_RW | SG_V; - - PMAP_UNLOCK(pmap, spl); -} - -/* - * Routine: PMAP_ENTER - * - * Function: - * Insert the given physical page (p) at the specified virtual - * address (v) in the target phisical map with the protecton requested. - * If specified, the page will be wired down, meaning that the - * related pte can not be reclaimed. - * - * N.B.: This is the only routine which MAY NOT lazy-evaluation or lose - * information. That is, this routine must actually insert this page - * into the given map NOW. - * - * Parameters: - * pmap pointer to pmap structure - * va VA of page to be mapped - * pa PA of page to be mapped - * prot protection attributes for page - * wired wired attribute for page - * - * Extern/Global: - * pv lists - * - * Calls: - * m88k_protection - * pmap_pte - * pmap_expand - * pmap_remove_pte - * - * This routine starts off by calling pmap_pte to obtain a (virtual) - * pointer to the page table entry corresponding to given virtual - * address. If the page table itself does not exist, pmap_expand is - * called to allocate it. - * - * If the page table entry (PTE) already maps the given physical page, - * all that is needed is to set the protection and wired attributes as - * given. TLB entries are flushed and pmap_enter returns. - * - * If the page table entry (PTE) maps a different physical page than - * that given, the old mapping is removed by a call to map_remove_range. - * And execution of pmap_enter continues. - * - * To map the new physical page, the routine first inserts a new - * entry in the PV list exhibiting the given pmap and virtual address. - * It then inserts the physical page address, protection attributes, and - * wired attributes into the page table entry (PTE). - * - * - * get machine-dependent prot code - * get the pte for this page - * if necessary pmap_expand(pmap, v) - * if (changing wired attribute or protection) { - * flush entry from TLB - * update template - * for (ptes per vm page) - * stuff pte - * } else if (mapped at wrong addr) - * flush entry from TLB - * pmap_remove_pte - * } else { - * enter mapping in pv_list - * setup template and stuff ptes - * } - * - */ -int -pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags) -{ - int spl; - pt_entry_t *pte, template; - paddr_t old_pa; - pv_entry_t pv_e, pvl; - u_int users; - boolean_t kflush; - boolean_t wired = (flags & PMAP_WIRED) != 0; - struct vm_page *pg; - - CHECK_PAGE_ALIGN(va, "pmap_entry - va"); - CHECK_PAGE_ALIGN(pa, "pmap_entry - pa"); - -#ifdef DEBUG - if (pmap_con_dbg & CD_ENT) { - if (pmap == kernel_pmap) - printf("(pmap_enter: %x) pmap kernel va %x pa %x\n", curproc, va, pa); - else - printf("(pmap_enter: %x) pmap %x va %x pa %x\n", curproc, pmap, va, pa); - } - - /* copying/zeroing pages are magic */ - if (pmap == kernel_pmap && - va >= phys_map_vaddr && va < phys_map_vaddr_end) { - return 0; - } -#endif - - template = m88k_protection(pmap, prot); - - PMAP_LOCK(pmap, spl); - users = pmap->pm_cpus; - kflush = pmap == kernel_pmap; - - /* - * Expand pmap to include this pte. - */ - while ((pte = pmap_pte(pmap, va)) == PT_ENTRY_NULL) { - if (pmap == kernel_pmap) { - pmap_expand_kmap(va, VM_PROT_READ | VM_PROT_WRITE); - } else { - /* - * Must unlock to expand the pmap. - */ - simple_unlock(&pmap->pm_lock); - pmap_expand(pmap, va); - simple_lock(&pmap->pm_lock); - } - } - /* - * Special case if the physical page is already mapped at this address. - */ - old_pa = ptoa(PG_PFNUM(*pte)); -#ifdef DEBUG - if (pmap_con_dbg & CD_ENT) - printf("(pmap_enter) old_pa %x pte %x\n", old_pa, *pte); -#endif - if (old_pa == pa) { - /* May be changing its wired attributes or protection */ - if (wired && !(pmap_pte_w(pte))) - pmap->pm_stats.wired_count++; - else if (!wired && pmap_pte_w(pte)) - pmap->pm_stats.wired_count--; - - pvl = NULL; - } else { /* if (pa == old_pa) */ - /* Remove old mapping from the PV list if necessary. */ - pmap_remove_pte(pmap, va, pte); - - pg = PHYS_TO_VM_PAGE(pa); - if (pg != NULL) { - /* - * Enter the mapping in the PV list for this - * physical page. - */ - pvl = pg_to_pvh(pg); - - if (pvl->pv_pmap == PMAP_NULL) { - /* - * No mappings yet - */ - pvl->pv_va = va; - pvl->pv_pmap = pmap; - pvl->pv_next = PV_ENTRY_NULL; - pvl->pv_flags = 0; - - } else { -#ifdef DEBUG - /* - * Check that this mapping is not already there - */ - for (pv_e = pvl; pv_e; pv_e = pv_e->pv_next) - if (pv_e->pv_pmap == pmap && - pv_e->pv_va == va) - panic("pmap_enter: already in pv_list"); -#endif - /* - * Add new pv_entry after header. - */ - pv_e = pool_get(&pvpool, PR_NOWAIT); - if (pv_e == NULL) { - if (flags & PMAP_CANFAIL) { - PMAP_UNLOCK(pmap, spl); - return (ENOMEM); - } else - panic("pmap_enter: " - "pvpool exhausted"); - } - pv_e->pv_va = va; - pv_e->pv_pmap = pmap; - pv_e->pv_next = pvl->pv_next; - pv_e->pv_flags = 0; - pvl->pv_next = pv_e; - } - } - - /* - * And count the mapping. - */ - pmap->pm_stats.resident_count++; - if (wired) - pmap->pm_stats.wired_count++; - } /* if (pa == old_pa) ... else */ - - template |= PG_V; - if (wired) - template |= PG_W; - - if ((unsigned long)pa >= last_addr) - template |= CACHE_INH; - else - template |= CACHE_GLOBAL; - - if (flags & VM_PROT_WRITE) - template |= PG_U | PG_M; - else if (flags & VM_PROT_ALL) - template |= PG_U; - - /* - * Invalidate pte temporarily to avoid being written - * back the modified bit and/or the reference bit by - * any other cpu. - */ - template |= invalidate_pte(pte) & (PG_U | PG_M); - *pte = template | pa; - flush_atc_entry(users, va, kflush); -#ifdef DEBUG - if (pmap_con_dbg & CD_ENT) - printf("(pmap_enter) set pte to %x\n", *pte); -#endif - - /* - * Cache attribute flags - */ - if (pvl != NULL) - pvl->pv_flags |= (template & (PG_U | PG_M)); - - PMAP_UNLOCK(pmap, spl); - - return 0; -} - -/* - * Routine: pmap_unwire - * - * Function: Change the wiring attributes for a map/virtual-address pair. - * - * Parameters: - * pmap pointer to pmap structure - * v virtual address of page to be unwired - * - * Calls: - * pmap_pte - * - * Special Assumptions: - * The mapping must already exist in the pmap. - */ -void -pmap_unwire(pmap_t pmap, vaddr_t v) -{ - pt_entry_t *pte; - int spl; - - PMAP_LOCK(pmap, spl); - - if ((pte = pmap_pte(pmap, v)) == PT_ENTRY_NULL) - panic("pmap_unwire: pte missing"); - - if (pmap_pte_w(pte)) { - /* unwired mapping */ - pmap->pm_stats.wired_count--; - *pte &= ~PG_W; - } - - PMAP_UNLOCK(pmap, spl); -} - -/* - * Routine: PMAP_EXTRACT - * - * Function: - * Extract the physical page address associoated - * with the given map/virtual_address pair. - * - * Parameters: - * pmap pointer to pmap structure - * va virtual address - * pap storage for result. - * - * Calls: - * PMAP_LOCK, PMAP_UNLOCK - * pmap_pte - * - * If BATC mapping is enabled and the specified pmap is kernel_pmap, - * batc_entry is scanned to find out the mapping. - * - * Then the routine calls pmap_pte to get a (virtual) pointer to - * the page table entry (PTE) associated with the given virtual - * address. If the page table does not exist, or if the PTE is not valid, - * then 0 address is returned. Otherwise, the physical page address from - * the PTE is returned. - */ -boolean_t -pmap_extract(pmap_t pmap, vaddr_t va, paddr_t *pap) -{ - pt_entry_t *pte; - paddr_t pa; - int spl; - boolean_t rv = FALSE; - -#ifdef PMAP_USE_BATC - int i; -#endif - -#ifdef DIAGNOSTIC - if (pmap == PMAP_NULL) - panic("pmap_extract: pmap is NULL"); -#endif - -#ifdef PMAP_USE_BATC - /* - * check BATC first - */ - if (pmap == kernel_pmap && batc_used != 0) - for (i = batc_used - 1; i != 0; i--) - if (batc_entry[i].lba == M88K_BTOBLK(va)) { - if (pap != NULL) - *pap = (batc_entry[i].pba << BATC_BLKSHIFT) | - (va & BATC_BLKMASK); - return TRUE; - } -#endif - - PMAP_LOCK(pmap, spl); - - pte = pmap_pte(pmap, va); - if (pte != PT_ENTRY_NULL && PDT_VALID(pte)) { - rv = TRUE; - if (pap != NULL) { - pa = ptoa(PG_PFNUM(*pte)); - pa |= (va & PAGE_MASK); /* offset within page */ - *pap = pa; - } - } - - PMAP_UNLOCK(pmap, spl); - return rv; -} - -/* - * Routine: PMAP_COLLECT - * - * Runction: - * Garbage collects the physical map system for pages which are - * no longer used. there may well be pages which are not - * referenced, but others may be collected as well. - * Called by the pageout daemon when pages are scarce. - * - * Parameters: - * pmap pointer to pmap structure - * - * Calls: - * pmap_pte - * pmap_remove_range - * uvm_km_free - * - * The intent of this routine is to release memory pages being used - * by translation tables. They can be release only if they contain no - * valid mappings, and their parent table entry has been invalidated. - * - * The routine sequences through the entries user address space, - * inspecting page-sized groups of page tables for wired entries. If - * a full page of tables has no wired enties, any otherwise valid - * entries are invalidated (via pmap_remove_range). Then, the segment - * table entries corresponding to this group of page tables are - * invalidated. Finally, uvm_km_free is called to return the page to the - * system. - * - * If all entries in a segment table are invalidated, it too can - * be returned to the system. - */ -void -pmap_collect(pmap_t pmap) -{ - vaddr_t sdt_va; /* outer loop index */ - sdt_entry_t *sdtp; /* ptr to index into segment table */ - pt_entry_t *gdttbl; /* ptr to first entry in a page table */ - pt_entry_t *gdttblend; /* ptr to byte after last entry in - table group */ - pt_entry_t *gdtp; /* ptr to index into a page table */ - boolean_t found_gdt_wired; /* flag indicating a wired page exists - in a page table's address range */ - int spl; - -#ifdef DEBUG - if (pmap_con_dbg & CD_COL) - printf ("(pmap_collect: %x) pmap %x\n", curproc, pmap); -#endif - - PMAP_LOCK(pmap, spl); - - sdtp = pmap->pm_stab; /* addr of segment table */ - - /* Segment table loop */ - for (sdt_va = VM_MIN_ADDRESS; sdt_va < VM_MAX_ADDRESS; - sdt_va += PDT_VA_SPACE, sdtp++) { - gdttbl = pmap_pte(pmap, sdt_va); - if (gdttbl == PT_ENTRY_NULL) - continue; /* no maps in this range */ - - gdttblend = gdttbl + PDT_ENTRIES; - - /* scan page maps for wired pages */ - found_gdt_wired = FALSE; - for (gdtp = gdttbl; gdtp < gdttblend; gdtp++) { - if (pmap_pte_w(gdtp)) { - found_gdt_wired = TRUE; - break; - } - } - - if (found_gdt_wired) - continue; /* can't free this range */ - - /* invalidate all maps in this range */ - pmap_remove_range(pmap, sdt_va, sdt_va + PDT_VA_SPACE); - - /* - * we can safely deallocate the page map(s) - */ - *((sdt_entry_t *) sdtp) = 0; - *((sdt_entry_t *)(sdtp + SDT_ENTRIES)) = 0; - - /* - * we have to unlock before freeing the table, since - * uvm_km_free will invoke another pmap routine - */ - simple_unlock(&pmap->pm_lock); - uvm_km_free(kernel_map, (vaddr_t)gdttbl, PAGE_SIZE); - simple_lock(&pmap->pm_lock); - } - - PMAP_UNLOCK(pmap, spl); - -#ifdef DEBUG - if (pmap_con_dbg & CD_COL) - printf("(pmap_collect: %x) done\n", curproc); -#endif -} - -/* - * Routine: PMAP_ACTIVATE - * - * Function: - * Binds the pmap associated to the process to the current processor. - * - * Parameters: - * p pointer to proc structure - * - * Notes: - * If the specified pmap is not kernel_pmap, this routine stores its - * apr template into UAPR (user area pointer register) in the - * CMMUs connected to the specified CPU. - * - * Then it flushes the TLBs mapping user virtual space, in the CMMUs - * connected to the specified CPU. - */ -void -pmap_activate(struct proc *p) -{ - pmap_t pmap = vm_map_pmap(&p->p_vmspace->vm_map); - int cpu = cpu_number(); -#ifdef PMAP_USE_BATC - int n; -#endif - -#ifdef DEBUG - if (pmap_con_dbg & CD_ACTIVATE) - printf("(pmap_activate: %x) pmap 0x%p\n", p, pmap); -#endif - - if (pmap != kernel_pmap) { - /* - * Lock the pmap to put this cpu in its active set. - */ - simple_lock(&pmap->pm_lock); - -#ifdef PMAP_USE_BATC - /* - * cmmu_pmap_activate will set the uapr and the batc entries, - * then flush the *USER* TLB. IF THE KERNEL WILL EVER CARE - * ABOUT THE BATC ENTRIES, THE SUPERVISOR TLBs SHOULB BE - * FLUSHED AS WELL. - */ - cmmu_pmap_activate(cpu, pmap->pm_apr, - pmap->pm_ibatc, pmap->pm_dbatc); - for (n = 0; n < BATC_MAX; n++) - *(register_t *)&batc_entry[n] = pmap->pm_ibatc[n].bits; -#else - cmmu_set_uapr(pmap->pm_apr); - cmmu_flush_tlb(cpu, FALSE, VM_MIN_ADDRESS, - VM_MAX_ADDRESS - VM_MIN_ADDRESS); -#endif /* PMAP_USE_BATC */ - - /* - * Mark that this cpu is using the pmap. - */ - SETBIT_CPUSET(cpu, &(pmap->pm_cpus)); - simple_unlock(&pmap->pm_lock); - } -} - -/* - * Routine: PMAP_DEACTIVATE - * - * Function: - * Unbinds the pmap associated to the process from the current processor. - * - * Parameters: - * p pointer to proc structure - */ -void -pmap_deactivate(struct proc *p) -{ - pmap_t pmap = vm_map_pmap(&p->p_vmspace->vm_map); - int cpu = cpu_number(); - - if (pmap != kernel_pmap) { - /* - * we expect the spl is already raised to sched level. - */ - simple_lock(&pmap->pm_lock); - CLRBIT_CPUSET(cpu, &(pmap->pm_cpus)); - simple_unlock(&pmap->pm_lock); - } -} - -/* - * Routine: PMAP_COPY_PAGE - * - * Function: - * Copies the specified pages. - * - * Parameters: - * src PA of source page - * dst PA of destination page - * - * Extern/Global: - * phys_map_vaddr - * - * Calls: - * m88k_protection - * - * Special Assumptions: - * no locking required - * - * This routine maps the physical pages at the 'phys_map' virtual - * addresses set up in pmap_bootstrap. It flushes the TLB to make the - * new mappings effective, and performs the copy. - */ -void -pmap_copy_page(struct vm_page *srcpg, struct vm_page *dstpg) -{ - paddr_t src = VM_PAGE_TO_PHYS(srcpg); - paddr_t dst = VM_PAGE_TO_PHYS(dstpg); - vaddr_t dstva, srcva; - int spl; - pt_entry_t *dstpte, *srcpte; - int cpu = cpu_number(); - - CHECK_PAGE_ALIGN(src, "pmap_copy_page - src"); - CHECK_PAGE_ALIGN(dst, "pmap_copy_page - dst"); - - dstva = (vaddr_t)(phys_map_vaddr + 2 * (cpu << PAGE_SHIFT)); - srcva = dstva + PAGE_SIZE; - dstpte = pmap_pte(kernel_pmap, dstva); - srcpte = pmap_pte(kernel_pmap, srcva); - - SPLVM(spl); - - *dstpte = m88k_protection(kernel_pmap, VM_PROT_READ | VM_PROT_WRITE) | - CACHE_GLOBAL | PG_V | dst; - *srcpte = m88k_protection(kernel_pmap, VM_PROT_READ) | - CACHE_GLOBAL | PG_V | src; - - /* - * We don't need the flush_atc_entry() dance, as these pages are - * bound to only one cpu. - */ - cmmu_flush_tlb(cpu, TRUE, dstva, 2 * PAGE_SIZE); - - /* - * The source page is likely to be a non-kernel mapping, and as - * such write back. Also, we might have split U/S caches! - * So be sure to have the source pa flushed before the copy is - * attempted, and the destination pa flushed afterwards. - */ - cmmu_flush_data_cache(cpu, src, PAGE_SIZE); - bcopy((const void *)srcva, (void *)dstva, PAGE_SIZE); - cmmu_flush_data_cache(cpu, dst, PAGE_SIZE); - - SPLX(spl); -} - -/* - * Routine: PMAP_CHANGEBIT - * - * Function: - * Update the pte bits on the specified physical page. - * - * Parameters: - * pg physical page - * set bits to set - * mask bits to mask - * - * Extern/Global: - * pv_lists - * - * Calls: - * pmap_pte - * - * The pte bits corresponding to the page's frame index will be changed as - * requested. The PV list will be traversed. - * For each pmap/va the hardware the necessary bits in the page descriptor - * table entry will be altered as well if necessary. If any bits were changed, - * a TLB flush will be performed. - */ -void -pmap_changebit(struct vm_page *pg, int set, int mask) -{ - pv_entry_t pvl, pvep; - pt_entry_t *pte, npte, opte; - pmap_t pmap; - int spl; - vaddr_t va; - u_int users; - boolean_t kflush; - - SPLVM(spl); - -changebit_Retry: - pvl = pg_to_pvh(pg); - - /* - * Clear saved attributes (modify, reference) - */ - pvl->pv_flags &= mask; - - if (pvl->pv_pmap == PMAP_NULL) { -#ifdef DEBUG - if (pmap_con_dbg & CD_CBIT) - printf("(pmap_changebit: %x) vm page 0x%x not mapped\n", - curproc, pg); -#endif - SPLX(spl); - return; - } - - /* for each listed pmap, update the affected bits */ - for (pvep = pvl; pvep != PV_ENTRY_NULL; pvep = pvep->pv_next) { - pmap = pvep->pv_pmap; - if (!simple_lock_try(&pmap->pm_lock)) { - goto changebit_Retry; - } - users = pmap->pm_cpus; - kflush = pmap == kernel_pmap; - - va = pvep->pv_va; - pte = pmap_pte(pmap, va); - - /* - * Check for existing and valid pte - */ - if (pte == PT_ENTRY_NULL || !PDT_VALID(pte)) { - goto next; /* no page mapping */ - } -#ifdef DIAGNOSTIC - if (ptoa(PG_PFNUM(*pte)) != VM_PAGE_TO_PHYS(pg)) - panic("pmap_changebit: pte %x in pmap %p %d doesn't point to page %p %lx", - *pte, pmap, kflush, pg, VM_PAGE_TO_PHYS(pg)); -#endif - - /* - * Update bits - */ - opte = *pte; - npte = (opte | set) & mask; - - /* - * Flush TLB of which cpus using pmap. - * - * Invalidate pte temporarily to avoid the modified bit - * and/or the reference being written back by any other cpu. - */ - if (npte != opte) { - invalidate_pte(pte); - *pte = npte; - flush_atc_entry(users, va, kflush); - } -next: - simple_unlock(&pmap->pm_lock); - } - SPLX(spl); -} - -/* - * Routine: PMAP_TESTBIT - * - * Function: - * Test the modified/referenced bits of a physical page. - * - * Parameters: - * pg physical page - * bit bit to test - * - * Extern/Global: - * pv lists - * - * Calls: - * simple_lock, simple_unlock - * pmap_pte - * - * If the attribute list for the given page has the bit, this routine - * returns TRUE. - * - * Otherwise, this routine walks the PV list corresponding to the - * given page. For each pmap/va pair, the page descriptor table entry is - * examined. If the selected bit is found on, the function returns TRUE - * immediately (doesn't need to walk remainder of list), and updates the - * attribute list. - */ -boolean_t -pmap_testbit(struct vm_page *pg, int bit) -{ - pv_entry_t pvl, pvep; - pt_entry_t *pte; - int spl; - - SPLVM(spl); - -testbit_Retry: - pvl = pg_to_pvh(pg); - - if (pvl->pv_flags & bit) { - /* we've already cached this flag for this page, - no use looking further... */ -#ifdef DEBUG - if (pmap_con_dbg & CD_TBIT) - printf("(pmap_testbit: %x) already cached a %x flag for this page\n", - curproc, bit); -#endif - SPLX(spl); - return (TRUE); - } - - if (pvl->pv_pmap == PMAP_NULL) { -#ifdef DEBUG - if (pmap_con_dbg & CD_TBIT) - printf("(pmap_testbit: %x) vm page 0x%x not mapped\n", - curproc, pg); -#endif - SPLX(spl); - return (FALSE); - } - - /* for each listed pmap, check modified bit for given page */ - for (pvep = pvl; pvep != PV_ENTRY_NULL; pvep = pvep->pv_next) { - if (!simple_lock_try(&pvep->pv_pmap->pm_lock)) { - goto testbit_Retry; - } - - pte = pmap_pte(pvep->pv_pmap, pvep->pv_va); - if (pte == PT_ENTRY_NULL || !PDT_VALID(pte)) { - goto next; - } - -#ifdef DIAGNOSTIC - if (ptoa(PG_PFNUM(*pte)) != VM_PAGE_TO_PHYS(pg)) - panic("pmap_testbit: pte %x in pmap %p %d doesn't point to page %p %lx", - *pte, pvep->pv_pmap, pvep->pv_pmap == kernel_pmap ? 1 : 0, pg, VM_PAGE_TO_PHYS(pg)); -#endif - - if ((*pte & bit) != 0) { - simple_unlock(&pvep->pv_pmap->pm_lock); - pvl->pv_flags |= bit; -#ifdef DEBUG - if ((pmap_con_dbg & (CD_TBIT | CD_FULL)) == (CD_TBIT | CD_FULL)) - printf("(pmap_testbit: %x) true on page pte@0x%p\n", curproc, pte); -#endif - SPLX(spl); - return (TRUE); - } -next: - simple_unlock(&pvep->pv_pmap->pm_lock); - } - - SPLX(spl); - return (FALSE); -} - -/* - * Routine: PMAP_UNSETBIT - * - * Function: - * Clears a pte bit and returns its previous state, for the - * specified physical page. - * This is an optimized version of: - * rv = pmap_testbit(pg, bit); - * pmap_changebit(pg, 0, ~bit); - * return rv; - */ -boolean_t -pmap_unsetbit(struct vm_page *pg, int bit) -{ - boolean_t rv = FALSE; - pv_entry_t pvl, pvep; - pt_entry_t *pte, opte; - pmap_t pmap; - int spl; - vaddr_t va; - u_int users; - boolean_t kflush; - - SPLVM(spl); - -unsetbit_Retry: - pvl = pg_to_pvh(pg); - - /* - * Clear saved attributes - */ - pvl->pv_flags &= ~bit; - - if (pvl->pv_pmap == PMAP_NULL) { -#ifdef DEBUG - if (pmap_con_dbg & CD_USBIT) - printf("(pmap_unsetbit: %x) vm page 0x%x not mapped\n", - curproc, pg); -#endif - SPLX(spl); - return (FALSE); - } - - /* for each listed pmap, update the specified bit */ - for (pvep = pvl; pvep != PV_ENTRY_NULL; pvep = pvep->pv_next) { - pmap = pvep->pv_pmap; - if (!simple_lock_try(&pmap->pm_lock)) { - goto unsetbit_Retry; - } - users = pmap->pm_cpus; - kflush = pmap == kernel_pmap; - - va = pvep->pv_va; - pte = pmap_pte(pmap, va); - - /* - * Check for existing and valid pte - */ - if (pte == PT_ENTRY_NULL || !PDT_VALID(pte)) { - goto next; /* no page mapping */ - } -#ifdef DIAGNOSTIC - if (ptoa(PG_PFNUM(*pte)) != VM_PAGE_TO_PHYS(pg)) - panic("pmap_unsetbit: pte %x in pmap %p %d doesn't point to page %p %lx", - *pte, pmap, kflush, pg, VM_PAGE_TO_PHYS(pg)); -#endif - - /* - * Update bits - */ - opte = *pte; - if (opte & bit) { - /* - * Flush TLB of which cpus using pmap. - * - * Invalidate pte temporarily to avoid the specified - * bit being written back by any other cpu. - */ - invalidate_pte(pte); - *pte = opte ^ bit; - flush_atc_entry(users, va, kflush); - } else - rv = TRUE; -next: - simple_unlock(&pmap->pm_lock); - } - SPLX(spl); - - return (rv); -} - -/* - * Routine: PMAP_IS_MODIFIED - * - * Function: - * Return whether or not the specified physical page is modified - * by any physical maps. - */ -boolean_t -pmap_is_modified(struct vm_page *pg) -{ - return pmap_testbit(pg, PG_M); -} - -/* - * Routine: PMAP_IS_REFERENCED - * - * Function: - * Return whether or not the specified physical page is referenced by - * any physical maps. - */ -boolean_t -pmap_is_referenced(struct vm_page *pg) -{ - return pmap_testbit(pg, PG_U); -} - -/* - * Routine: PMAP_PAGE_PROTECT - * - * Calls: - * pmap_changebit - * pmap_remove_all - * - * Lower the permission for all mappings to a given page. - */ -void -pmap_page_protect(struct vm_page *pg, vm_prot_t prot) -{ - if ((prot & VM_PROT_READ) == VM_PROT_NONE) - pmap_remove_all(pg); - else if ((prot & VM_PROT_WRITE) == VM_PROT_NONE) - pmap_changebit(pg, PG_RO, ~0); -} - -void -pmap_virtual_space(vaddr_t *startp, vaddr_t *endp) -{ - *startp = virtual_avail; - *endp = virtual_end; -} - -void -pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot) -{ - int spl; - pt_entry_t template, *pte; - u_int users; - - CHECK_PAGE_ALIGN(va, "pmap_kenter_pa - VA"); - CHECK_PAGE_ALIGN(pa, "pmap_kenter_pa - PA"); - -#ifdef DEBUG - if (pmap_con_dbg & CD_ENT) { - printf ("(pmap_kenter_pa: %x) va %x pa %x\n", curproc, va, pa); - } -#endif - - PMAP_LOCK(kernel_pmap, spl); - users = kernel_pmap->pm_cpus; - - template = m88k_protection(kernel_pmap, prot); - - /* - * Expand pmap to include this pte. - */ - while ((pte = pmap_pte(kernel_pmap, va)) == PT_ENTRY_NULL) - pmap_expand_kmap(va, VM_PROT_READ | VM_PROT_WRITE); - - /* - * And count the mapping. - */ - kernel_pmap->pm_stats.resident_count++; - kernel_pmap->pm_stats.wired_count++; - - invalidate_pte(pte); - if ((unsigned long)pa >= last_addr) - template |= CACHE_INH | PG_V | PG_W; - else - template |= CACHE_GLOBAL | PG_V | PG_W; - *pte = template | pa; - flush_atc_entry(users, va, TRUE); - - PMAP_UNLOCK(kernel_pmap, spl); -} - -void -pmap_kremove(vaddr_t va, vsize_t len) -{ - int spl; - u_int users; - vaddr_t e; - -#ifdef DEBUG - if (pmap_con_dbg & CD_RM) - printf("(pmap_kremove: %x) va %x len %x\n", curproc, va, len); -#endif - - CHECK_PAGE_ALIGN(va, "pmap_kremove addr"); - CHECK_PAGE_ALIGN(len, "pmap_kremove len"); - - PMAP_LOCK(kernel_pmap, spl); - users = kernel_pmap->pm_cpus; - - e = va + len; - for (; va < e; va += PAGE_SIZE) { - sdt_entry_t *sdt; - pt_entry_t *pte; - - sdt = SDTENT(kernel_pmap, va); - - /* If no segment table, skip a whole segment */ - if (!SDT_VALID(sdt)) { - va &= SDT_MASK; - va += (1 << SDT_SHIFT) - PAGE_SIZE; - continue; - } - - pte = pmap_pte(kernel_pmap, va); - if (pte == PT_ENTRY_NULL || !PDT_VALID(pte)) { - continue; /* no page mapping */ - } - - /* - * Update the counts - */ - kernel_pmap->pm_stats.resident_count--; - kernel_pmap->pm_stats.wired_count--; - - invalidate_pte(pte); - flush_atc_entry(users, va, TRUE); - } - PMAP_UNLOCK(map, spl); -} diff --git a/sys/arch/luna88k/luna88k/pmap_table.c b/sys/arch/luna88k/luna88k/pmap_table.c index 22792e2fc99..816db12cdb6 100644 --- a/sys/arch/luna88k/luna88k/pmap_table.c +++ b/sys/arch/luna88k/luna88k/pmap_table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap_table.c,v 1.3 2004/06/14 12:57:02 aoyama Exp $ */ +/* $OpenBSD: pmap_table.c,v 1.4 2004/07/25 11:06:41 miod Exp $ */ /* * Mach Operating System @@ -28,7 +28,6 @@ #include <sys/param.h> #include <sys/systm.h> -#include <sys/types.h> #include <machine/board.h> #include <machine/cmmu.h> #include <uvm/uvm_extern.h> diff --git a/sys/arch/m88k/conf/files.m88k b/sys/arch/m88k/conf/files.m88k index 6f6b9c46ad8..83210d99d37 100644 --- a/sys/arch/m88k/conf/files.m88k +++ b/sys/arch/m88k/conf/files.m88k @@ -1,4 +1,4 @@ -# $OpenBSD: files.m88k,v 1.4 2004/07/23 15:34:03 miod Exp $ +# $OpenBSD: files.m88k,v 1.5 2004/07/25 11:06:42 miod Exp $ file arch/m88k/m88k/cmmu.c file arch/m88k/m88k/db_disasm.c ddb @@ -7,6 +7,7 @@ file arch/m88k/m88k/db_trace.c ddb file arch/m88k/m88k/m88100_fp.S m88100 file arch/m88k/m88k/m88110_fp.S m88110 file arch/m88k/m88k/m88110_mmu.S m88110 +file arch/m88k/m88k/pmap.c file arch/m88k/m88k/process.S file arch/m88k/m88k/process_machdep.c file arch/m88k/m88k/subr.S diff --git a/sys/arch/m88k/include/pmap.h b/sys/arch/m88k/include/pmap.h new file mode 100644 index 00000000000..a4c5e8bb3b7 --- /dev/null +++ b/sys/arch/m88k/include/pmap.h @@ -0,0 +1,79 @@ +/* $OpenBSD: pmap.h,v 1.1 2004/07/25 11:06:42 miod Exp $ */ +/* + * Mach Operating System + * Copyright (c) 1991 Carnegie Mellon University + * Copyright (c) 1991 OMRON Corporation + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + */ +#ifndef _M88K_PMAP_H_ +#define _M88K_PMAP_H_ + +#include <machine/mmu.h> +#include <machine/pcb.h> + +/* + * PMAP structure + */ + +/* #define PMAP_USE_BATC */ +struct pmap { + sdt_entry_t *pm_stab; /* virtual pointer to sdt */ + u_int32_t pm_apr; + int pm_count; /* reference count */ + /* cpus using of this pmap; NCPU must be <= 32 */ + u_int32_t pm_cpus; + struct simplelock pm_lock; + struct pmap_statistics pm_stats; /* pmap statistics */ +#ifdef PMAP_USE_BATC + u_int32_t pm_ibatc[BATC_MAX]; /* instruction BATCs */ + u_int32_t pm_dbatc[BATC_MAX]; /* data BATCs */ +#endif +}; + +#define PMAP_NULL ((pmap_t) 0) + +/* The PV (Physical to virtual) List. + * + * For each vm_page_t, pmap keeps a list of all currently valid virtual + * mappings of that page. An entry is a pv_entry_t; the list is the + * pv_head_table. This is used by things like pmap_remove, when we must + * find and remove all mappings for a particular physical page. + */ +/* XXX - struct pv_entry moved to vmparam.h because of include ordering issues */ + +typedef struct pmap *pmap_t; +typedef struct pv_entry *pv_entry_t; + +#ifdef _KERNEL + +extern pmap_t kernel_pmap; +extern struct pmap kernel_pmap_store; +extern caddr_t vmmap; + +#define pmap_kernel() (&kernel_pmap_store) +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) +#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) +#define pmap_phys_address(frame) ((paddr_t)(ptoa(frame))) + +#define pmap_copy(dp,sp,d,l,s) do { /* nothing */ } while (0) +#define pmap_update(pmap) do { /* nothing (yet) */ } while (0) + +#define pmap_clear_modify(pg) pmap_unsetbit(pg, PG_M) +#define pmap_clear_reference(pg) pmap_unsetbit(pg, PG_U) + +#define pmap_proc_iflush(p,va,len) do { /* nothing */ } while (0) + +void pmap_bootstrap(vaddr_t); +void pmap_cache_ctrl(pmap_t, vaddr_t, vaddr_t, u_int); +boolean_t pmap_unsetbit(struct vm_page *, int); + +#endif /* _KERNEL */ + +#endif /* _M88K_PMAP_H_ */ diff --git a/sys/arch/m88k/include/pmap_table.h b/sys/arch/m88k/include/pmap_table.h new file mode 100644 index 00000000000..9d90e393949 --- /dev/null +++ b/sys/arch/m88k/include/pmap_table.h @@ -0,0 +1,48 @@ +/* $OpenBSD: pmap_table.h,v 1.1 2004/07/25 11:06:42 miod Exp $ */ +/* + * Mach Operating System + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#ifndef __M88K_PMAP_TABLE_H__ +#define __M88K_PMAP_TABLE_H__ + +/* + * Built-in mappings list. + * An entry is considered invalid if pm_size = 0, and + * end of list is indicated by pm_size 0xffffffff + */ +typedef struct { + vaddr_t phys_start; /* in bytes */ + vaddr_t virt_start; /* in bytes */ + vsize_t size; /* in bytes */ + unsigned int prot; /* vm_prot_read, vm_prot_write */ + unsigned int cacheability; /* none, writeback, normal */ +} pmap_table_entry; + +typedef const pmap_table_entry *pmap_table_t; + +pmap_table_t pmap_table_build(void); + +#endif /* __M88K_PMAP_TABLE_H__ */ diff --git a/sys/arch/mvme88k/mvme88k/pmap.c b/sys/arch/m88k/m88k/pmap.c index 1e317972b1a..6ebc8a2ae86 100644 --- a/sys/arch/mvme88k/mvme88k/pmap.c +++ b/sys/arch/m88k/m88k/pmap.c @@ -1,6 +1,6 @@ -/* $OpenBSD: pmap.c,v 1.117 2004/06/24 19:59:14 miod Exp $ */ +/* $OpenBSD: pmap.c,v 1.1 2004/07/25 11:06:42 miod Exp $ */ /* - * Copyright (c) 2001, 2002, 2003 Miodrag Vallat + * Copyright (c) 2001-2004, Miodrag Vallat * Copyright (c) 1998-2001 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur * All rights reserved. @@ -45,7 +45,6 @@ * */ -#include <sys/types.h> #include <sys/param.h> #include <sys/systm.h> #include <sys/simplelock.h> @@ -178,10 +177,6 @@ pg_to_pvh(struct vm_page *pg) SPLX(spl); \ } while (0) -#define ETHERPAGES 16 -void *etherbuf = NULL; -int etherlen; - #ifdef PMAP_USE_BATC /* @@ -610,7 +605,6 @@ pmap_cache_ctrl(pmap_t pmap, vaddr_t s, vaddr_t e, u_int mode) * Extern/Global: * * PAGE_SIZE VM (software) page size - * kernelstart start symbol of kernel text * etext end of kernel text * phys_map_vaddr VA of page mapped arbitrarily for debug/IO * @@ -629,10 +623,9 @@ pmap_cache_ctrl(pmap_t pmap, vaddr_t s, vaddr_t e, u_int mode) * IO purposes. They are arbitrarily mapped when needed. They are used, * for example, by pmap_copy_page and pmap_zero_page. * - * For m88k, we have to map BUG memory also. This is a read only - * mapping for 0x10000 bytes. We will end up having load_start as - * 0 and VM_MIN_KERNEL_ADDRESS as 0 - yes sir, we have one-to-one - * mapping!!! + * This implementation also assumes that the space below the kernel + * is reserved (typically from PROM purposes). We should ideally map it + * read only except when invoking its services... */ void @@ -646,7 +639,7 @@ pmap_bootstrap(vaddr_t load_start) unsigned int kernel_pmap_size, pdt_size; int i; pmap_table_t ptable; - extern void *kernelstart, *etext; + extern void *etext; simple_lock_init(&kernel_pmap->pm_lock); @@ -659,15 +652,10 @@ pmap_bootstrap(vaddr_t load_start) * ... * pmap_bootstrap(&kernelstart, ...); * kernelstart being the first symbol in the load image. - * The kernel is linked such that &kernelstart == 0x10000 (size of - * BUG reserved memory area). - * The expression (&kernelstart - load_start) will end up as - * 0, making virtual_avail == avail_start, giving a 1-to-1 map) */ avail_start = round_page(avail_start); - virtual_avail = avail_start + - (trunc_page((vaddr_t)&kernelstart) - load_start); + virtual_avail = avail_start; /* * Initialize kernel_pmap structure @@ -745,20 +733,16 @@ pmap_bootstrap(vaddr_t load_start) * Map the kernel image into virtual space */ - s_text = load_start; /* paddr of text */ - e_text = load_start + - ((vaddr_t)&etext - trunc_page((vaddr_t)&kernelstart)); - /* paddr of end of text section*/ - e_text = round_page(e_text); + s_text = trunc_page(load_start); /* paddr of text */ + e_text = round_page((vaddr_t)&etext); /* paddr of end of text */ - /* map the first 64k (BUG ROM) read only, cache inhibited (? XXX) */ - vaddr = pmap_map(0, 0, 0x10000, VM_PROT_WRITE | VM_PROT_READ, - CACHE_INH); + /* map the PROM area */ + vaddr = pmap_map(0, 0, s_text, VM_PROT_WRITE | VM_PROT_READ, CACHE_INH); /* map the kernel text read only */ - vaddr = pmap_map(trunc_page((vaddr_t)&kernelstart), - s_text, e_text, VM_PROT_WRITE | VM_PROT_READ, - CACHE_GLOBAL); /* shouldn't it be RO? XXX*/ + vaddr = pmap_map(s_text, s_text, e_text, + VM_PROT_WRITE | VM_PROT_READ, /* shouldn't it be RO? XXX*/ + CACHE_GLOBAL); vaddr = pmap_map(vaddr, e_text, (paddr_t)kmap, VM_PROT_WRITE | VM_PROT_READ, CACHE_GLOBAL); @@ -776,31 +760,7 @@ pmap_bootstrap(vaddr_t load_start) vaddr = pmap_map(vaddr, (paddr_t)kmap, avail_start, VM_PROT_WRITE | VM_PROT_READ, CACHE_INH); -#if defined (MVME187) || defined (MVME197) - /* - * Get ethernet buffer - need etherlen bytes physically contiguous. - * 1 to 1 mapped as well???. There is actually a bug in the macros - * used by the 1x7 ethernet driver. Remove this when that is fixed. - * XXX -nivas - */ - if (brdtyp == BRD_187 || brdtyp == BRD_8120 || brdtyp == BRD_197) { - avail_start = vaddr; - etherlen = ETHERPAGES * PAGE_SIZE; - etherbuf = (void *)vaddr; - - vaddr = pmap_map(vaddr, avail_start, avail_start + etherlen, - VM_PROT_WRITE | VM_PROT_READ, CACHE_INH); - - virtual_avail += etherlen; - avail_start += etherlen; - - if (vaddr != virtual_avail) { - virtual_avail = vaddr; - avail_start = round_page(avail_start); - } - } - -#endif /* defined (MVME187) || defined (MVME197) */ + vaddr = pmap_bootstrap_md(vaddr); virtual_avail = round_page(virtual_avail); virtual_end = VM_MAX_KERNEL_ADDRESS; @@ -815,13 +775,7 @@ pmap_bootstrap(vaddr_t load_start) virtual_avail += 2 * (max_cpus << PAGE_SHIFT); /* - * Map all IO space 1-to-1. Ideally, I would like to not do this - * but have va for the given IO address dynamically allocated. But - * on the 88200, 2 of the BATCs are hardwired to map the IO space - * 1-to-1; I decided to map the rest of the IO space 1-to-1. - * And bug ROM & the SRAM need to be mapped 1-to-1 if we ever want to - * execute bug system calls after the MMU has been turned on. - * OBIO should be mapped cache inhibited. + * Create all the machine-specific mappings. */ for (ptable = pmap_table_build(); ptable->size != (vsize_t)-1; ptable++) diff --git a/sys/arch/mvme88k/conf/files.mvme88k b/sys/arch/mvme88k/conf/files.mvme88k index 8ff131f0786..c0a48317c71 100644 --- a/sys/arch/mvme88k/conf/files.mvme88k +++ b/sys/arch/mvme88k/conf/files.mvme88k @@ -1,4 +1,4 @@ -# $OpenBSD: files.mvme88k,v 1.31 2004/07/23 15:34:03 miod Exp $ +# $OpenBSD: files.mvme88k,v 1.32 2004/07/25 11:06:42 miod Exp $ # maxpartitions 16 @@ -85,7 +85,7 @@ file arch/mvme88k/mvme88k/eh.S file arch/mvme88k/mvme88k/locore_c_routines.c file arch/mvme88k/mvme88k/machdep.c file arch/mvme88k/mvme88k/mem.c -file arch/mvme88k/mvme88k/pmap.c +file arch/mvme88k/mvme88k/pmap_bootstrap.c file arch/mvme88k/mvme88k/pmap_table.c file arch/mvme88k/ddb/db_interface.c ddb file arch/mvme88k/dev/bugio.c diff --git a/sys/arch/mvme88k/include/pmap.h b/sys/arch/mvme88k/include/pmap.h index 6cd196398ce..12165a55839 100644 --- a/sys/arch/mvme88k/include/pmap.h +++ b/sys/arch/mvme88k/include/pmap.h @@ -1,79 +1,13 @@ -/* $OpenBSD: pmap.h,v 1.35 2004/05/20 09:20:42 kettenis Exp $ */ -/* - * Mach Operating System - * Copyright (c) 1991 Carnegie Mellon University - * Copyright (c) 1991 OMRON Corporation - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - */ -#ifndef _MACHINE_PMAP_H_ -#define _MACHINE_PMAP_H_ +/* $OpenBSD: pmap.h,v 1.36 2004/07/25 11:06:42 miod Exp $ */ +/* public domain */ -#include <machine/mmu.h> -#include <machine/pcb.h> +#ifndef _MVME88K_PMAP_H_ +#define _MVME88K_PMAP_H_ -/* - * PMAP structure - */ - -/* #define PMAP_USE_BATC */ -struct pmap { - sdt_entry_t *pm_stab; /* virtual pointer to sdt */ - u_int32_t pm_apr; - int pm_count; /* reference count */ - /* cpus using of this pmap; NCPU must be <= 32 */ - u_int32_t pm_cpus; - struct simplelock pm_lock; - struct pmap_statistics pm_stats; /* pmap statistics */ -#ifdef PMAP_USE_BATC - u_int32_t pm_ibatc[BATC_MAX]; /* instruction BATCs */ - u_int32_t pm_dbatc[BATC_MAX]; /* data BATCs */ -#endif -}; - -#define PMAP_NULL ((pmap_t) 0) - -/* The PV (Physical to virtual) List. - * - * For each vm_page_t, pmap keeps a list of all currently valid virtual - * mappings of that page. An entry is a pv_entry_t; the list is the - * pv_head_table. This is used by things like pmap_remove, when we must - * find and remove all mappings for a particular physical page. - */ -/* XXX - struct pv_entry moved to vmparam.h because of include ordering issues */ - -typedef struct pmap *pmap_t; -typedef struct pv_entry *pv_entry_t; +#include <m88k/pmap.h> #ifdef _KERNEL +vaddr_t pmap_bootstrap_md(vaddr_t); +#endif -extern pmap_t kernel_pmap; -extern struct pmap kernel_pmap_store; -extern caddr_t vmmap; - -#define pmap_kernel() (&kernel_pmap_store) -#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) -#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) -#define pmap_phys_address(frame) ((paddr_t)(ptoa(frame))) - -#define pmap_copy(dp,sp,d,l,s) do { /* nothing */ } while (0) -#define pmap_update(pmap) do { /* nothing (yet) */ } while (0) - -#define pmap_clear_modify(pg) pmap_unsetbit(pg, PG_M) -#define pmap_clear_reference(pg) pmap_unsetbit(pg, PG_U) - -#define pmap_proc_iflush(p,va,len) do { /* nothing */ } while (0) - -void pmap_bootstrap(vaddr_t); -void pmap_cache_ctrl(pmap_t, vaddr_t, vaddr_t, u_int); -boolean_t pmap_unsetbit(struct vm_page *, int); - -#endif /* _KERNEL */ - -#endif /* _MACHINE_PMAP_H_ */ +#endif _MVME88K_PMAP_H_ diff --git a/sys/arch/mvme88k/include/pmap_table.h b/sys/arch/mvme88k/include/pmap_table.h index faab4e416ee..327226180d3 100644 --- a/sys/arch/mvme88k/include/pmap_table.h +++ b/sys/arch/mvme88k/include/pmap_table.h @@ -1,49 +1,3 @@ -/* $OpenBSD: pmap_table.h,v 1.10 2003/10/05 20:27:46 miod Exp $ */ -/* - * Mach Operating System - * Copyright (c) 1992 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ - -#ifndef __MACHINE_PMAP_TABLE_H__ -#define __MACHINE_PMAP_TABLE_H__ - -/* - * Built-in mappings list. - * An entry is considered invalid if pm_size = 0, and - * end of list is indicated by pm_size 0xffffffff - */ -typedef struct { - vaddr_t phys_start; /* in bytes */ - vaddr_t virt_start; /* in bytes */ - vsize_t size; /* in bytes */ - unsigned int prot; /* vm_prot_read, vm_prot_write */ - unsigned int cacheability; /* none, writeback, normal */ -} pmap_table_entry; - -typedef const pmap_table_entry *pmap_table_t; - -pmap_table_t pmap_table_build(void); - -#endif /* __MACHINE_PMAP_TABLE_H__ */ - +/* $OpenBSD: pmap_table.h,v 1.11 2004/07/25 11:06:42 miod Exp $ */ +/* public domain */ +#include <m88k/pmap_table.h> diff --git a/sys/arch/mvme88k/mvme88k/pmap_bootstrap.c b/sys/arch/mvme88k/mvme88k/pmap_bootstrap.c new file mode 100644 index 00000000000..e23fb808b2e --- /dev/null +++ b/sys/arch/mvme88k/mvme88k/pmap_bootstrap.c @@ -0,0 +1,99 @@ +/* $OpenBSD: pmap_bootstrap.c,v 1.1 2004/07/25 11:06:43 miod Exp $ */ +/* + * Copyright (c) 2001-2004, Miodrag Vallat + * Copyright (c) 1998-2001 Steve Murphree, Jr. + * Copyright (c) 1996 Nivas Madhur + * All rights reserved. + * + * 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 Nivas Madhur. + * 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. + * + */ +/* + * Mach Operating System + * Copyright (c) 1991 Carnegie Mellon University + * Copyright (c) 1991 OMRON Corporation + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +/* +#include <sys/simplelock.h> +#include <sys/proc.h> +#include <sys/malloc.h> +#include <sys/pool.h> +#include <sys/msgbuf.h> +#include <sys/user.h> +*/ + +#include <uvm/uvm.h> + +/* +#include <machine/asm_macro.h> +#include <machine/board.h> +#include <machine/cmmu.h> +#include <machine/cpu_number.h> +#include <machine/pmap_table.h> +*/ + +extern vaddr_t pmap_map(vaddr_t, paddr_t, paddr_t, vm_prot_t, u_int); +extern vaddr_t avail_start; +extern vaddr_t virtual_avail; + +#define ETHERPAGES 16 +void *etherbuf = NULL; +int etherlen; + +vaddr_t +pmap_bootstrap_md(vaddr_t vaddr) +{ +#if defined (MVME187) || defined (MVME197) + /* + * Get ethernet buffer - need ETHERPAGES pages physically contiguous. + * XXX need to switch if_ie to bus_space... + */ + if (brdtyp == BRD_187 || brdtyp == BRD_8120 || brdtyp == BRD_197) { + etherlen = ETHERPAGES * PAGE_SIZE; + etherbuf = (void *)vaddr; + + vaddr = pmap_map(vaddr, avail_start, + avail_start + ETHERPAGES * PAGE_SIZE, + VM_PROT_WRITE | VM_PROT_READ, CACHE_INH); + + virtual_avail += etherlen; + avail_start += etherlen; + } +#endif /* defined (MVME187) || defined (MVME197) */ + + return vaddr; +} diff --git a/sys/arch/mvme88k/mvme88k/pmap_table.c b/sys/arch/mvme88k/mvme88k/pmap_table.c index 7ee71423bc6..c9252b290af 100644 --- a/sys/arch/mvme88k/mvme88k/pmap_table.c +++ b/sys/arch/mvme88k/mvme88k/pmap_table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap_table.c,v 1.18 2004/05/19 14:30:53 miod Exp $ */ +/* $OpenBSD: pmap_table.c,v 1.19 2004/07/25 11:06:43 miod Exp $ */ /* * Mach Operating System @@ -28,7 +28,6 @@ #include <sys/param.h> #include <sys/systm.h> -#include <sys/types.h> #include <machine/board.h> #include <machine/cmmu.h> #include <uvm/uvm_extern.h> |