cache_r10k.c revision 1.2 1 /* $NetBSD: cache_r10k.c,v 1.2 2003/11/01 04:42:56 shin 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/cache.h>
65 #include <mips/cache_r4k.h>
66 #include <mips/cache_r10k.h>
67
68 /*
69 * Cache operations for R10000-style caches:
70 *
71 * 2-way, write-back
72 * primary cache: virtual index/physical tag
73 * secondary cache: physical index/physical tag
74 */
75
76 __asm(".set mips3");
77
78 #define round_line(x) (((x) + 64 - 1) & ~(64 - 1))
79 #define trunc_line(x) ((x) & ~(64 - 1))
80
81 void
82 r10k_icache_sync_all(void)
83 {
84 vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
85 vaddr_t eva = va + mips_picache_way_size;
86
87 mips_dcache_wbinv_all();
88
89 __asm __volatile("sync");
90
91 while (va < eva) {
92 cache_op_r4k_line(va+0, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
93 cache_op_r4k_line(va+1, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
94 va += 64;
95 }
96 }
97
98 void
99 r10k_icache_sync_range(vaddr_t va, vsize_t size)
100 {
101 vaddr_t eva = round_line(va + size);
102
103 va = trunc_line(va);
104
105 mips_dcache_wb_range(va, (eva - va));
106
107 __asm __volatile("sync");
108
109 while (va < eva) {
110 cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
111 va += 64;
112 }
113 }
114
115 void
116 r10k_icache_sync_range_index(vaddr_t va, vsize_t size)
117 {
118 vaddr_t eva, orig_va;
119
120 orig_va = va;
121
122 eva = round_line(va + size);
123 va = trunc_line(va);
124
125 mips_dcache_wbinv_range_index(va, (eva - va));
126
127 __asm __volatile("sync");
128
129 /*
130 * Since we're doing Index ops, we expect to not be able
131 * to access the address we've been given. So, get the
132 * bits that determine the cache index, and make a KSEG0
133 * address out of them.
134 */
135 va = MIPS_PHYS_TO_KSEG0(orig_va & mips_picache_way_mask);
136
137 eva = round_line(va + size);
138 va = trunc_line(va);
139
140 while (va < eva) {
141 cache_op_r4k_line(va+0, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
142 cache_op_r4k_line(va+1, CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
143 va += 64;
144 }
145 }
146
147 #undef round_line
148 #undef trunc_line
149
150 #define round_line(x) (((x) + 32 - 1) & ~(32 - 1))
151 #define trunc_line(x) ((x) & ~(32 - 1))
152
153 void
154 r10k_pdcache_wbinv_all(void)
155 {
156 vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
157 vaddr_t eva = va + mips_pdcache_way_size;
158
159 while (va < eva) {
160 cache_op_r4k_line(va+0, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
161 cache_op_r4k_line(va+1, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
162 va += 32;
163 }
164 }
165
166 void
167 r10k_pdcache_wbinv_range(vaddr_t va, vsize_t size)
168 {
169 vaddr_t eva = round_line(va + size);
170
171 va = trunc_line(va);
172
173 while (va < eva) {
174 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
175 va += 32;
176 }
177 }
178
179 void
180 r10k_pdcache_wbinv_range_index(vaddr_t va, vsize_t size)
181 {
182 vaddr_t eva;
183
184 /*
185 * Since we're doing Index ops, we expect to not be able
186 * to access the address we've been given. So, get the
187 * bits that determine the cache index, and make a KSEG0
188 * address out of them.
189 */
190 va = MIPS_PHYS_TO_KSEG0(va & mips_pdcache_way_mask);
191
192 eva = round_line(va + size);
193 va = trunc_line(va);
194
195 while (va < eva) {
196 cache_op_r4k_line(va+0, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
197 cache_op_r4k_line(va+1, CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
198 va += 32;
199 }
200 }
201
202 void
203 r10k_pdcache_inv_range(vaddr_t va, vsize_t size)
204 {
205 vaddr_t eva = round_line(va + size);
206
207 va = trunc_line(va);
208
209 while (va < eva) {
210 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
211 va += 32;
212 }
213 }
214
215 void
216 r10k_pdcache_wb_range(vaddr_t va, vsize_t size)
217 {
218 vaddr_t eva = round_line(va + size);
219
220 va = trunc_line(va);
221
222 while (va < eva) {
223 /* R10000 does not support HitWriteBack operation */
224 cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
225 va += 32;
226 }
227 }
228
229 #undef round_line
230 #undef trunc_line
231
232 #define round_line(x) (((x) + mips_sdcache_line_size - 1) & ~(mips_sdcache_line_size - 1))
233 #define trunc_line(x) ((x) & ~(mips_sdcache_line_size - 1))
234
235 void
236 r10k_sdcache_wbinv_all(void)
237 {
238 vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
239 vaddr_t eva = va + mips_sdcache_way_size;
240 int line_size = mips_sdcache_line_size;
241
242 while (va < eva) {
243 cache_op_r4k_line(va+0, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
244 cache_op_r4k_line(va+1, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
245 va += line_size;
246 }
247 }
248
249 void
250 r10k_sdcache_wbinv_range(vaddr_t va, vsize_t size)
251 {
252 vaddr_t eva = round_line(va + size);
253 int line_size = mips_sdcache_line_size;
254
255 va = trunc_line(va);
256
257 while (va < eva) {
258 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
259 va += line_size;
260 }
261 }
262
263 void
264 r10k_sdcache_wbinv_range_index(vaddr_t va, vsize_t size)
265 {
266 vaddr_t eva;
267 int line_size = mips_sdcache_line_size;
268
269 /*
270 * Since we're doing Index ops, we expect to not be able
271 * to access the address we've been given. So, get the
272 * bits that determine the cache index, and make a KSEG0
273 * address out of them.
274 */
275 va = MIPS_PHYS_TO_KSEG0(va & mips_sdcache_way_mask);
276
277 eva = round_line(va + size);
278 va = trunc_line(va);
279
280 while (va < eva) {
281 cache_op_r4k_line(va+0, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
282 cache_op_r4k_line(va+1, CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
283 va += line_size;
284 }
285 }
286
287 void
288 r10k_sdcache_inv_range(vaddr_t va, vsize_t size)
289 {
290 vaddr_t eva = round_line(va + size);
291 int line_size = mips_sdcache_line_size;
292
293 va = trunc_line(va);
294
295 while (va < eva) {
296 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
297 va += line_size;
298 }
299 }
300
301 void
302 r10k_sdcache_wb_range(vaddr_t va, vsize_t size)
303 {
304 vaddr_t eva = round_line(va + size);
305 int line_size = mips_sdcache_line_size;
306
307 va = trunc_line(va);
308
309 while (va < eva) {
310 /* R10000 does not support HitWriteBack operation */
311 cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
312 va += line_size;
313 }
314 }
315
316 #undef round_line
317 #undef trunc_line
318