Home | History | Annotate | Line # | Download | only in mips
      1 /*	$NetBSD: wired_map.c,v 1.8 2023/09/21 09:31:50 msaitoh Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2005 Tadpole Computer Inc.
      5  * All rights reserved.
      6  *
      7  * Written by Garrett D'Amore for Tadpole Computer Inc.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. The name of Tadpole Computer Inc. may not be used to endorse
     18  *    or promote products derived from this software without specific
     19  *    prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY TADPOLE COMPUTER INC. ``AS IS'' AND
     22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL TADPOLE COMPUTER INC.
     25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31  * POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 /*
     34  * Copyright (C) 2000 Shuichiro URATA.  All rights reserved.
     35  *
     36  * Redistribution and use in source and binary forms, with or without
     37  * modification, are permitted provided that the following conditions
     38  * are met:
     39  * 1. Redistributions of source code must retain the above copyright
     40  *    notice, this list of conditions and the following disclaimer.
     41  * 2. Redistributions in binary form must reproduce the above copyright
     42  *    notice, this list of conditions and the following disclaimer in the
     43  *    documentation and/or other materials provided with the distribution.
     44  * 3. The name of the author may not be used to endorse or promote products
     45  *    derived from this software without specific prior written permission.
     46  *
     47  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     48  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     49  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     50  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     51  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     52  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     53  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     54  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     55  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     56  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     57  */
     58 
     59 /*
     60  * This code is derived from similar code in the ARC port of NetBSD, but
     61  * it now bears little resemblence to it owing to quite different needs
     62  * from the mapping logic.
     63  */
     64 
     65 #include <sys/cdefs.h>
     66 __KERNEL_RCSID(0, "$NetBSD: wired_map.c,v 1.8 2023/09/21 09:31:50 msaitoh Exp $");
     67 
     68 #define __PMAP_PRIVATE
     69 
     70 #include <sys/param.h>
     71 #include <sys/systm.h>
     72 #include <sys/cpu.h>
     73 
     74 #include <uvm/uvm_extern.h>
     75 
     76 #include <machine/pte.h>
     77 #include <machine/vmparam.h>
     78 #include <machine/wired_map.h>
     79 
     80 #include <mips/locore.h>
     81 #include <mips/pte.h>
     82 
     83 struct wired_map_entry mips3_wired_map[MIPS3_NWIRED_ENTRY];
     84 int mips3_nwired_page;
     85 
     86 /*
     87  * Lower layer API, to supply an explicit page size.  It only wires a
     88  * single page at a time.
     89  */
     90 bool
     91 mips3_wired_enter_page(vaddr_t va, paddr_t pa, vsize_t pgsize)
     92 {
     93 	struct tlbmask tlb;
     94 	vaddr_t va0;
     95 	int found, index;
     96 
     97 	/* make sure entries are aligned */
     98 	KASSERT((va & (pgsize - 1)) == 0);
     99 	KASSERT((pa & (pgsize - 1)) == 0);
    100 
    101 	/* TLB entries come in pairs: this is the first address of the pair */
    102 	va0 = va & ~MIPS3_WIRED_ENTRY_OFFMASK(pgsize);
    103 
    104 	found = 0;
    105 	for (index = 0; index < mips3_nwired_page; index++) {
    106 		if (mips3_wired_map[index].va == va0) {
    107 			if ((va & pgsize) == 0) {
    108 				/* EntryLo0 */
    109 				mips3_wired_map[index].pa0 = pa;
    110 			} else {
    111 				/* EntryLo1 */
    112 				mips3_wired_map[index].pa1 = pa;
    113 			}
    114 			found = 1;
    115 			break;
    116 		}
    117 	}
    118 
    119 	if (found == 0) {
    120 		/* we have to allocate a new wired entry */
    121 		if (mips3_nwired_page >= MIPS3_NWIRED_ENTRY) {
    122 #ifdef DIAGNOSTIC
    123 			printf("mips3_wired_map: entries exhausted\n");
    124 #endif
    125 			return false;
    126 		}
    127 
    128 		index = mips3_nwired_page;
    129 		mips3_nwired_page++;
    130 		if (va == va0) {
    131 			/* EntryLo0 */
    132 			mips3_wired_map[index].pa0 = pa;
    133 			mips3_wired_map[index].pa1 = 0;
    134 		} else {
    135 			/* EntryLo1 */
    136 			mips3_wired_map[index].pa0 = 0;
    137 			mips3_wired_map[index].pa1 = pa;
    138 		}
    139 		mips3_wired_map[index].va = va0;
    140 		mips3_wired_map[index].pgmask = MIPS3_PG_SIZE_TO_MASK(pgsize);
    141 
    142 		/* Allocate new wired entry */
    143 		mips3_cp0_wired_write(MIPS3_TLB_WIRED_UPAGES +
    144 		    mips3_nwired_page + 1);
    145 	}
    146 
    147 	/* map it */
    148 	tlb.tlb_mask = mips3_wired_map[index].pgmask;
    149 	tlb.tlb_hi = mips3_vad_to_vpn(va0);
    150 	if (mips3_wired_map[index].pa0 == 0)
    151 		tlb.tlb_lo0 = MIPS3_PG_G;
    152 	else
    153 		tlb.tlb_lo0 =
    154 		    mips3_paddr_to_tlbpfn(mips3_wired_map[index].pa0) |
    155 		    MIPS3_PG_IOPAGE(
    156 			    PMAP_CCA_FOR_PA(mips3_wired_map[index].pa0));
    157 	if (mips3_wired_map[index].pa1 == 0)
    158 		tlb.tlb_lo1 = MIPS3_PG_G;
    159 	else
    160 		tlb.tlb_lo1 = mips3_paddr_to_tlbpfn(
    161 			mips3_wired_map[index].pa1) |
    162 		    MIPS3_PG_IOPAGE(
    163 			    PMAP_CCA_FOR_PA(mips3_wired_map[index].pa1));
    164 	tlb_write_entry(MIPS3_TLB_WIRED_UPAGES + index, &tlb);
    165 	return true;
    166 }
    167 
    168 
    169 /*
    170  * Wire down a mapping from a virtual to physical address.  The size
    171  * of the region must be a multiple of MIPS3_WIRED_SIZE, with
    172  * matching alignment.
    173  *
    174  * Typically the caller will just pass a physaddr that is the same as
    175  * the vaddr with bits 35-32 set nonzero.
    176  */
    177 bool
    178 mips3_wired_enter_region(vaddr_t va, paddr_t pa, vsize_t size)
    179 {
    180 	vaddr_t	vend;
    181 	/*
    182 	 * This routine allows for wired mappings to be set up,
    183 	 * and handles previously defined mappings and mapping
    184 	 * overlaps reasonably well.  However, caution should be used
    185 	 * not to attempt to change the mapping for a page unless you
    186 	 * are certain that you are the only user of the virtual
    187 	 * address space, otherwise chaos may ensue.
    188 	 */
    189 
    190 	/* offsets within the page have to be identical */
    191 	KASSERT((va & MIPS3_WIRED_OFFMASK) == (pa & MIPS3_WIRED_OFFMASK));
    192 
    193 	vend = va + size;
    194 	/* adjust for alignment */
    195 	va &= ~MIPS3_WIRED_OFFMASK;
    196 	pa &= ~MIPS3_WIRED_OFFMASK;
    197 
    198 	while (va < vend) {
    199 		if (!mips3_wired_enter_page(va, pa, MIPS3_WIRED_SIZE))
    200 			return false;
    201 		va += MIPS3_WIRED_SIZE;
    202 		pa += MIPS3_WIRED_SIZE;
    203 	}
    204 	return true;
    205 }
    206