cache_r10k.c revision 1.7 1 /* $NetBSD: cache_r10k.c,v 1.7 2016/07/11 16:15:36 matt Exp $ */
2
3 /*-
4 * Copyright (c) 2003 Takao Shinohara.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 /*
28 * Copyright 2001 Wasabi Systems, Inc.
29 * All rights reserved.
30 *
31 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed for the NetBSD Project by
44 * Wasabi Systems, Inc.
45 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
46 * or promote products derived from this software without specific prior
47 * written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
51 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
52 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
53 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
54 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
55 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
56 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
57 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59 * POSSIBILITY OF SUCH DAMAGE.
60 */
61
62 #include <sys/param.h>
63
64 #include <mips/cpuregs.h>
65 #include <mips/cache.h>
66 #include <mips/cache_r4k.h>
67 #include <mips/cache_r10k.h>
68
69 /*
70 * Cache operations for R10000-style caches:
71 *
72 * 2-way, write-back
73 * primary cache: virtual index/physical tag
74 * secondary cache: physical index/physical tag
75 */
76
77 __asm(".set mips3");
78
79 #define round_line(x) (((x) + 64 - 1) & ~(64 - 1))
80 #define trunc_line(x) ((x) & ~(64 - 1))
81
82 void
83 r10k_icache_sync_all(void)
84 {
85 const struct mips_cache_info * const mci = &mips_cache_info;
86 vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
87 vaddr_t eva = va + mci->mci_picache_way_size;
88
89 mips_dcache_wbinv_all();
90
91 __asm volatile("sync");
92
93 while (va < eva) {
94 cache_op_r4k_line(va+0, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
95 cache_op_r4k_line(va+1, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
96 va += 64;
97 }
98 }
99
100 void
101 r10k_icache_sync_range(register_t va, vsize_t size)
102 {
103 vaddr_t eva = round_line(va + size);
104
105 va = trunc_line(va);
106
107 mips_dcache_wb_range(va, (eva - va));
108
109 __asm volatile("sync");
110
111 while (va < eva) {
112 cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
113 va += 64;
114 }
115 }
116
117 void
118 r10k_icache_sync_range_index(vaddr_t va, vsize_t size)
119 {
120 const struct mips_cache_info * const mci = &mips_cache_info;
121 vaddr_t eva, orig_va;
122
123 orig_va = va;
124
125 eva = round_line(va + size);
126 va = trunc_line(va);
127
128 mips_dcache_wbinv_range_index(va, (eva - va));
129
130 __asm volatile("sync");
131
132 /*
133 * Since we're doing Index ops, we expect to not be able
134 * to access the address we've been given. So, get the
135 * bits that determine the cache index, and make a KSEG0
136 * address out of them.
137 */
138 va = MIPS_PHYS_TO_KSEG0(orig_va & mci->mci_picache_way_mask);
139
140 eva = round_line(va + size);
141 va = trunc_line(va);
142
143 while (va < eva) {
144 cache_op_r4k_line(va+0, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
145 cache_op_r4k_line(va+1, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
146 va += 64;
147 }
148 }
149
150 #undef round_line
151 #undef trunc_line
152
153 #define round_line(x) (((x) + 32 - 1) & ~(32 - 1))
154 #define trunc_line(x) ((x) & ~(32 - 1))
155
156 void
157 r10k_pdcache_wbinv_all(void)
158 {
159 const struct mips_cache_info * const mci = &mips_cache_info;
160 vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
161 vaddr_t eva = va + mci->mci_pdcache_way_size;
162
163 while (va < eva) {
164 cache_op_r4k_line(va+0, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
165 cache_op_r4k_line(va+1, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
166 va += 32;
167 }
168 }
169
170 void
171 r10k_pdcache_wbinv_range(register_t va, vsize_t size)
172 {
173 vaddr_t eva = round_line(va + size);
174
175 va = trunc_line(va);
176
177 while (va < eva) {
178 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
179 va += 32;
180 }
181 }
182
183 void
184 r10k_pdcache_wbinv_range_index(vaddr_t va, vsize_t size)
185 {
186 const struct mips_cache_info * const mci = &mips_cache_info;
187 vaddr_t eva;
188
189 /*
190 * Since we're doing Index ops, we expect to not be able
191 * to access the address we've been given. So, get the
192 * bits that determine the cache index, and make a KSEG0
193 * address out of them.
194 */
195 va = MIPS_PHYS_TO_KSEG0(va & mci->mci_pdcache_way_mask);
196
197 eva = round_line(va + size);
198 va = trunc_line(va);
199
200 while (va < eva) {
201 cache_op_r4k_line(va+0, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
202 cache_op_r4k_line(va+1, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
203 va += 32;
204 }
205 }
206
207 void
208 r10k_pdcache_inv_range(register_t va, vsize_t size)
209 {
210 vaddr_t eva = round_line(va + size);
211
212 va = trunc_line(va);
213
214 while (va < eva) {
215 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
216 va += 32;
217 }
218 }
219
220 void
221 r10k_pdcache_wb_range(register_t va, vsize_t size)
222 {
223 vaddr_t eva = round_line(va + size);
224
225 va = trunc_line(va);
226
227 while (va < eva) {
228 /* R10000 does not support HitWriteBack operation */
229 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
230 va += 32;
231 }
232 }
233
234 #undef round_line
235 #undef trunc_line
236
237 #define round_line(x) (((x) + mci->mci_sdcache_line_size - 1) & ~(mci->mci_sdcache_line_size - 1))
238 #define trunc_line(x) ((x) & ~(mci->mci_sdcache_line_size - 1))
239
240 void
241 r10k_sdcache_wbinv_all(void)
242 {
243 const struct mips_cache_info * const mci = &mips_cache_info;
244 vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
245 vaddr_t eva = va + mci->mci_sdcache_way_size;
246 vsize_t line_size = mci->mci_sdcache_line_size;
247
248 while (va < eva) {
249 cache_op_r4k_line(va+0, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
250 cache_op_r4k_line(va+1, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
251 va += line_size;
252 }
253 }
254
255 void
256 r10k_sdcache_wbinv_range(register_t va, vsize_t size)
257 {
258 const struct mips_cache_info * const mci = &mips_cache_info;
259 vaddr_t eva = round_line(va + size);
260 vsize_t line_size = mci->mci_sdcache_line_size;
261
262 va = trunc_line(va);
263
264 while (va < eva) {
265 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
266 va += line_size;
267 }
268 }
269
270 void
271 r10k_sdcache_wbinv_range_index(vaddr_t va, vsize_t size)
272 {
273 const struct mips_cache_info * const mci = &mips_cache_info;
274 vaddr_t eva;
275 vsize_t line_size = mci->mci_sdcache_line_size;
276
277 /*
278 * Since we're doing Index ops, we expect to not be able
279 * to access the address we've been given. So, get the
280 * bits that determine the cache index, and make a KSEG0
281 * address out of them.
282 */
283 va = MIPS_PHYS_TO_KSEG0(va & mci->mci_sdcache_way_mask);
284
285 eva = round_line(va + size);
286 va = trunc_line(va);
287
288 while (va < eva) {
289 cache_op_r4k_line(va+0, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
290 cache_op_r4k_line(va+1, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
291 va += line_size;
292 }
293 }
294
295 void
296 r10k_sdcache_inv_range(register_t va, vsize_t size)
297 {
298 const struct mips_cache_info * const mci = &mips_cache_info;
299 vaddr_t eva = round_line(va + size);
300 vsize_t line_size = mci->mci_sdcache_line_size;
301
302 va = trunc_line(va);
303
304 while (va < eva) {
305 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
306 va += line_size;
307 }
308 }
309
310 void
311 r10k_sdcache_wb_range(register_t va, vsize_t size)
312 {
313 const struct mips_cache_info * const mci = &mips_cache_info;
314 vaddr_t eva = round_line(va + size);
315 vsize_t line_size = mci->mci_sdcache_line_size;
316
317 va = trunc_line(va);
318
319 while (va < eva) {
320 /* R10000 does not support HitWriteBack operation */
321 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
322 va += line_size;
323 }
324 }
325
326 #undef round_line
327 #undef trunc_line
328