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