xref: /f-stack/freebsd/mips/mips/cache.c (revision 22ce4aff)
1 /*      $NetBSD: cache.c,v 1.33 2005/12/24 23:24:01 perry Exp $ */
2 
3 /*-
4  * SPDX-License-Identifier: BSD-4-Clause AND BSD-3-Clause
5  *
6  * Copyright 2001, 2002 Wasabi Systems, Inc.
7  * All rights reserved.
8  *
9  * Written by Jason R. Thorpe and Simon Burge for Wasabi Systems, Inc.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *      This product includes software developed for the NetBSD Project by
22  *      Wasabi Systems, Inc.
23  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
24  *    or promote products derived from this software without specific prior
25  *    written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 /*-
41  * Copyright 2000, 2001
42  * Broadcom Corporation. All rights reserved.
43  *
44  * This software is furnished under license and may be used and copied only
45  * in accordance with the following terms and conditions.  Subject to these
46  * conditions, you may download, copy, install, use, modify and distribute
47  * modified or unmodified copies of this software in source and/or binary
48  * form. No title or ownership is transferred hereby.
49  *
50  * 1) Any source code used, modified or distributed must reproduce and
51  *    retain this copyright notice and list of conditions as they appear in
52  *    the source file.
53  *
54  * 2) No right is granted to use any trade name, trademark, or logo of
55  *    Broadcom Corporation.  The "Broadcom Corporation" name may not be
56  *    used to endorse or promote products derived from this software
57  *    without the prior written permission of Broadcom Corporation.
58  *
59  * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED
60  *    WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
61  *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
62  *    NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE
63  *    FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE
64  *    LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
65  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
66  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
67  *    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
68  *    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
69  *    OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
70  */
71 
72 #include <sys/cdefs.h>
73 __FBSDID("$FreeBSD$");
74 
75 #include <sys/types.h>
76 #include <sys/systm.h>
77 
78 #include <machine/cpuinfo.h>
79 #include <machine/cache.h>
80 
81 struct mips_cache_ops mips_cache_ops;
82 
83 #if defined(MIPS_DISABLE_L1_CACHE) || defined(CPU_RMI) || defined(CPU_NLM)
84 static void
cache_noop(vm_offset_t va,vm_size_t size)85 cache_noop(vm_offset_t va, vm_size_t size)
86 {
87 }
88 #endif
89 
90 void
mips_config_cache(struct mips_cpuinfo * cpuinfo)91 mips_config_cache(struct mips_cpuinfo * cpuinfo)
92 {
93 
94 	switch (cpuinfo->l1.ic_linesize) {
95 	case 16:
96 		mips_cache_ops.mco_icache_sync_all = mipsNN_icache_sync_all_16;
97 		mips_cache_ops.mco_icache_sync_range =
98 		    mipsNN_icache_sync_range_16;
99 		mips_cache_ops.mco_icache_sync_range_index =
100 		    mipsNN_icache_sync_range_index_16;
101 		break;
102 	case 32:
103 		mips_cache_ops.mco_icache_sync_all = mipsNN_icache_sync_all_32;
104 		mips_cache_ops.mco_icache_sync_range =
105 		    mipsNN_icache_sync_range_32;
106 		mips_cache_ops.mco_icache_sync_range_index =
107 		    mipsNN_icache_sync_range_index_32;
108 		break;
109 	case 64:
110 		mips_cache_ops.mco_icache_sync_all = mipsNN_icache_sync_all_64;
111 		mips_cache_ops.mco_icache_sync_range =
112 		    mipsNN_icache_sync_range_64;
113 		mips_cache_ops.mco_icache_sync_range_index =
114 		    mipsNN_icache_sync_range_index_64;
115 		break;
116 	case 128:
117 		mips_cache_ops.mco_icache_sync_all = mipsNN_icache_sync_all_128;
118 		mips_cache_ops.mco_icache_sync_range =
119 		    mipsNN_icache_sync_range_128;
120 		mips_cache_ops.mco_icache_sync_range_index =
121 		    mipsNN_icache_sync_range_index_128;
122 		break;
123 
124 #ifdef MIPS_DISABLE_L1_CACHE
125 	case 0:
126 		mips_cache_ops.mco_icache_sync_all = (void (*)(void))cache_noop;
127 		mips_cache_ops.mco_icache_sync_range = cache_noop;
128 		mips_cache_ops.mco_icache_sync_range_index = cache_noop;
129 		break;
130 #endif
131 	default:
132 		panic("no Icache ops for %d byte lines",
133 		    cpuinfo->l1.ic_linesize);
134 	}
135 
136 	switch (cpuinfo->l1.dc_linesize) {
137 	case 16:
138 		mips_cache_ops.mco_pdcache_wbinv_all =
139 		    mips_cache_ops.mco_intern_pdcache_wbinv_all =
140 		    mipsNN_pdcache_wbinv_all_16;
141 		mips_cache_ops.mco_pdcache_wbinv_range =
142 		    mipsNN_pdcache_wbinv_range_16;
143 		mips_cache_ops.mco_pdcache_wbinv_range_index =
144 		    mips_cache_ops.mco_intern_pdcache_wbinv_range_index =
145 		    mipsNN_pdcache_wbinv_range_index_16;
146 		mips_cache_ops.mco_pdcache_inv_range =
147 		    mipsNN_pdcache_inv_range_16;
148 		mips_cache_ops.mco_pdcache_wb_range =
149 		    mips_cache_ops.mco_intern_pdcache_wb_range =
150 		    mipsNN_pdcache_wb_range_16;
151 		break;
152 	case 32:
153 		mips_cache_ops.mco_pdcache_wbinv_all =
154 		    mips_cache_ops.mco_intern_pdcache_wbinv_all =
155 		    mipsNN_pdcache_wbinv_all_32;
156 #if defined(CPU_RMI) || defined(CPU_NLM)
157 		mips_cache_ops.mco_pdcache_wbinv_range = cache_noop;
158 #else
159 		mips_cache_ops.mco_pdcache_wbinv_range =
160 		    mipsNN_pdcache_wbinv_range_32;
161 #endif
162 #if defined(CPU_RMI) || defined(CPU_NLM)
163 		mips_cache_ops.mco_pdcache_wbinv_range_index =
164 		    mips_cache_ops.mco_intern_pdcache_wbinv_range_index = cache_noop;
165 		mips_cache_ops.mco_pdcache_inv_range = cache_noop;
166 #else
167 		mips_cache_ops.mco_pdcache_wbinv_range_index =
168 		    mips_cache_ops.mco_intern_pdcache_wbinv_range_index =
169 		    mipsNN_pdcache_wbinv_range_index_32;
170 		mips_cache_ops.mco_pdcache_inv_range =
171 		    mipsNN_pdcache_inv_range_32;
172 #endif
173 #if defined(CPU_RMI) || defined(CPU_NLM)
174 		mips_cache_ops.mco_pdcache_wb_range =
175 		    mips_cache_ops.mco_intern_pdcache_wb_range = cache_noop;
176 #else
177 		mips_cache_ops.mco_pdcache_wb_range =
178 		    mips_cache_ops.mco_intern_pdcache_wb_range =
179 		    mipsNN_pdcache_wb_range_32;
180 #endif
181 		break;
182 	case 64:
183 		mips_cache_ops.mco_pdcache_wbinv_all =
184 		    mips_cache_ops.mco_intern_pdcache_wbinv_all =
185 		    mipsNN_pdcache_wbinv_all_64;
186 		mips_cache_ops.mco_pdcache_wbinv_range =
187 		    mipsNN_pdcache_wbinv_range_64;
188 		mips_cache_ops.mco_pdcache_wbinv_range_index =
189 		    mips_cache_ops.mco_intern_pdcache_wbinv_range_index =
190 		    mipsNN_pdcache_wbinv_range_index_64;
191 		mips_cache_ops.mco_pdcache_inv_range =
192 		    mipsNN_pdcache_inv_range_64;
193 		mips_cache_ops.mco_pdcache_wb_range =
194 		    mips_cache_ops.mco_intern_pdcache_wb_range =
195 		    mipsNN_pdcache_wb_range_64;
196 		break;
197 	case 128:
198 		mips_cache_ops.mco_pdcache_wbinv_all =
199 		    mips_cache_ops.mco_intern_pdcache_wbinv_all =
200 		    mipsNN_pdcache_wbinv_all_128;
201 		mips_cache_ops.mco_pdcache_wbinv_range =
202 		    mipsNN_pdcache_wbinv_range_128;
203 		mips_cache_ops.mco_pdcache_wbinv_range_index =
204 		    mips_cache_ops.mco_intern_pdcache_wbinv_range_index =
205 		    mipsNN_pdcache_wbinv_range_index_128;
206 		mips_cache_ops.mco_pdcache_inv_range =
207 		    mipsNN_pdcache_inv_range_128;
208 		mips_cache_ops.mco_pdcache_wb_range =
209 		    mips_cache_ops.mco_intern_pdcache_wb_range =
210 		    mipsNN_pdcache_wb_range_128;
211 		break;
212 #ifdef MIPS_DISABLE_L1_CACHE
213 	case 0:
214 		mips_cache_ops.mco_pdcache_wbinv_all =
215 		    mips_cache_ops.mco_intern_pdcache_wbinv_all =
216 		    (void (*)(void))cache_noop;
217 		mips_cache_ops.mco_pdcache_wbinv_range = cache_noop;
218 		mips_cache_ops.mco_pdcache_wbinv_range_index = cache_noop;
219 		mips_cache_ops.mco_intern_pdcache_wbinv_range_index =
220 		    cache_noop;
221 		mips_cache_ops.mco_pdcache_inv_range = cache_noop;
222 		mips_cache_ops.mco_pdcache_wb_range = cache_noop;
223 		mips_cache_ops.mco_intern_pdcache_wb_range = cache_noop;
224 		break;
225 #endif
226 	default:
227 		panic("no Dcache ops for %d byte lines",
228 		    cpuinfo->l1.dc_linesize);
229 	}
230 
231 	mipsNN_cache_init(cpuinfo);
232 
233 #if 0
234 	if (mips_cpu_flags &
235 	    (CPU_MIPS_D_CACHE_COHERENT | CPU_MIPS_I_D_CACHE_COHERENT)) {
236 #ifdef CACHE_DEBUG
237 		printf("  Dcache is coherent\n");
238 #endif
239 		mips_cache_ops.mco_pdcache_wbinv_all =
240 		    (void (*)(void))cache_noop;
241 		mips_cache_ops.mco_pdcache_wbinv_range = cache_noop;
242 		mips_cache_ops.mco_pdcache_wbinv_range_index = cache_noop;
243 		mips_cache_ops.mco_pdcache_inv_range = cache_noop;
244 		mips_cache_ops.mco_pdcache_wb_range = cache_noop;
245 	}
246 	if (mips_cpu_flags & CPU_MIPS_I_D_CACHE_COHERENT) {
247 #ifdef CACHE_DEBUG
248 		printf("  Icache is coherent against Dcache\n");
249 #endif
250 		mips_cache_ops.mco_intern_pdcache_wbinv_all =
251 		    (void (*)(void))cache_noop;
252 		mips_cache_ops.mco_intern_pdcache_wbinv_range_index =
253 		    cache_noop;
254 		mips_cache_ops.mco_intern_pdcache_wb_range = cache_noop;
255 	}
256 #endif
257 
258 	/* Check that all cache ops are set up. */
259 	/* must have primary Icache */
260 	if (cpuinfo->l1.ic_size) {
261 
262 		if (!mips_cache_ops.mco_icache_sync_all)
263 			panic("no icache_sync_all cache op");
264 		if (!mips_cache_ops.mco_icache_sync_range)
265 			panic("no icache_sync_range cache op");
266 		if (!mips_cache_ops.mco_icache_sync_range_index)
267 			panic("no icache_sync_range_index cache op");
268 	}
269 	/* must have primary Dcache */
270 	if (cpuinfo->l1.dc_size) {
271 		if (!mips_cache_ops.mco_pdcache_wbinv_all)
272 			panic("no pdcache_wbinv_all");
273 		if (!mips_cache_ops.mco_pdcache_wbinv_range)
274 			panic("no pdcache_wbinv_range");
275 		if (!mips_cache_ops.mco_pdcache_wbinv_range_index)
276 			panic("no pdcache_wbinv_range_index");
277 		if (!mips_cache_ops.mco_pdcache_inv_range)
278 			panic("no pdcache_inv_range");
279 		if (!mips_cache_ops.mco_pdcache_wb_range)
280 			panic("no pdcache_wb_range");
281 	}
282 
283 	/* L2 data cache */
284 	if (!cpuinfo->l2.dc_size) {
285 		/* No L2 found, ignore */
286 		return;
287 	}
288 
289 	switch (cpuinfo->l2.dc_linesize) {
290 	case 32:
291 		mips_cache_ops.mco_sdcache_wbinv_all =
292 			mipsNN_sdcache_wbinv_all_32;
293 		mips_cache_ops.mco_sdcache_wbinv_range =
294 			mipsNN_sdcache_wbinv_range_32;
295 		mips_cache_ops.mco_sdcache_wbinv_range_index =
296 			mipsNN_sdcache_wbinv_range_index_32;
297 		mips_cache_ops.mco_sdcache_inv_range =
298 			mipsNN_sdcache_inv_range_32;
299 		mips_cache_ops.mco_sdcache_wb_range =
300 			mipsNN_sdcache_wb_range_32;
301 		break;
302 	case 64:
303 		mips_cache_ops.mco_sdcache_wbinv_all =
304 			mipsNN_sdcache_wbinv_all_64;
305 		mips_cache_ops.mco_sdcache_wbinv_range =
306 			mipsNN_sdcache_wbinv_range_64;
307 		mips_cache_ops.mco_sdcache_wbinv_range_index =
308 			mipsNN_sdcache_wbinv_range_index_64;
309 		mips_cache_ops.mco_sdcache_inv_range =
310 			mipsNN_sdcache_inv_range_64;
311 		mips_cache_ops.mco_sdcache_wb_range =
312 			mipsNN_sdcache_wb_range_64;
313 		break;
314 	case 128:
315 		mips_cache_ops.mco_sdcache_wbinv_all =
316 			mipsNN_sdcache_wbinv_all_128;
317 		mips_cache_ops.mco_sdcache_wbinv_range =
318 			mipsNN_sdcache_wbinv_range_128;
319 		mips_cache_ops.mco_sdcache_wbinv_range_index =
320 			mipsNN_sdcache_wbinv_range_index_128;
321 		mips_cache_ops.mco_sdcache_inv_range =
322 			mipsNN_sdcache_inv_range_128;
323 		mips_cache_ops.mco_sdcache_wb_range =
324 			mipsNN_sdcache_wb_range_128;
325 		break;
326 	default:
327 #ifdef CACHE_DEBUG
328 		printf("  no sdcache ops for %d byte lines",
329 		    cpuinfo->l2.dc_linesize);
330 #endif
331 		break;
332 	}
333 }
334