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