1 /* $NetBSD: wired_map.c,v 1.6 2016/07/11 16:15:36 matt 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 similiar 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.6 2016/07/11 16:15:36 matt 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
mips3_wired_enter_page(vaddr_t va,paddr_t pa,vsize_t pgsize)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
mips3_wired_enter_region(vaddr_t va,paddr_t pa,vsize_t size)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 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