1 /* $OpenBSD: cache_octeon.c,v 1.13 2018/12/04 16:24:13 visa Exp $ */
2 /*
3 * Copyright (c) 2010 Takuya ASADA.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17 /*
18 * Copyright (c) 1998-2004 Opsycon AB (www.opsycon.se)
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
30 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
33 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 *
41 */
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46
47 #include <uvm/uvm_extern.h>
48
49 #include <mips64/cache.h>
50 #include <machine/cpu.h>
51
52 #define SYNCI() \
53 asm volatile( \
54 ".set push\n" \
55 ".set mips64r2\n" \
56 ".word 0x041f0000\n" \
57 "nop\n" \
58 ".set pop")
59
60 void
Octeon_ConfigCache(struct cpu_info * ci)61 Octeon_ConfigCache(struct cpu_info *ci)
62 {
63 uint32_t cfg;
64 uint32_t s, l, a;
65
66 switch (ci->ci_hw.type) {
67 default:
68 /* OCTEON and OCTEON Plus */
69
70 cfg = cp0_get_config_1();
71
72 /*
73 * Octeon L1 cache information does not follow the mips64
74 * standard encoding.
75 */
76
77 a = (cfg >> 16) & 0x07;
78 l = (cfg >> 19) & 0x07;
79 s = (cfg >> 22) & 0x07;
80 ci->ci_l1inst.linesize = 2 << l;
81 ci->ci_l1inst.setsize = (64 << s) * ci->ci_l1inst.linesize;
82 if (a >= 1)
83 ci->ci_l1inst.sets = 1 << (a - 1);
84 else
85 ci->ci_l1inst.sets = 1;
86 ci->ci_l1inst.size = ci->ci_l1inst.sets * ci->ci_l1inst.setsize;
87
88 ci->ci_l1data.linesize = 128;
89 ci->ci_l1data.setsize = 2 * 128;
90 ci->ci_l1data.sets = 64;
91 ci->ci_l1data.size = ci->ci_l1data.sets * ci->ci_l1data.setsize;
92
93 break;
94
95 case MIPS_CN61XX:
96 case MIPS_CN63XX:
97 case MIPS_CN66XX:
98 case MIPS_CN68XX:
99 /* OCTEON II */
100
101 ci->ci_l1inst.linesize = 128;
102 ci->ci_l1inst.setsize = 8 * 128;
103 ci->ci_l1inst.sets = 37;
104 ci->ci_l1inst.size = ci->ci_l1inst.sets * ci->ci_l1inst.setsize;
105
106 ci->ci_l1data.linesize = 128;
107 ci->ci_l1data.setsize = 8 * 128;
108 ci->ci_l1data.sets = 32;
109 ci->ci_l1data.size = ci->ci_l1data.sets * ci->ci_l1data.setsize;
110
111 break;
112
113 case MIPS_CN71XX:
114 case MIPS_CN73XX:
115 case MIPS_CN78XX:
116 /* OCTEON III */
117
118 ci->ci_l1inst.linesize = 128;
119 ci->ci_l1inst.setsize = 16 * 128;
120 ci->ci_l1inst.sets = 39;
121 ci->ci_l1inst.size = ci->ci_l1inst.sets * ci->ci_l1inst.setsize;
122
123 ci->ci_l1data.linesize = 128;
124 ci->ci_l1data.setsize = 8 * 128;
125 ci->ci_l1data.sets = 32;
126 ci->ci_l1data.size = ci->ci_l1data.sets * ci->ci_l1data.setsize;
127
128 break;
129 }
130
131 cfg = cp0_get_config_2();
132
133 a = 1 + ((cfg >> 0) & 0x0f);
134 l = (cfg >> 4) & 0x0f;
135 s = (cfg >> 8) & 0x0f;
136
137 ci->ci_l2.linesize = 2 << l;
138 ci->ci_l2.sets = a;
139 ci->ci_l2.setsize = (64 << s) * ci->ci_l2.linesize;
140 ci->ci_l2.size = ci->ci_l2.sets * ci->ci_l2.setsize;
141
142 memset(&ci->ci_l3, 0, sizeof(struct cache_info));
143
144 ci->ci_SyncCache = Octeon_SyncCache;
145 ci->ci_InvalidateICache = Octeon_InvalidateICache;
146 ci->ci_InvalidateICachePage = Octeon_InvalidateICachePage;
147 ci->ci_SyncICache = Octeon_SyncICache;
148 ci->ci_SyncDCachePage = Octeon_SyncDCachePage;
149 ci->ci_HitSyncDCachePage = Octeon_SyncDCachePage;
150 ci->ci_HitSyncDCache = Octeon_HitSyncDCache;
151 ci->ci_HitInvalidateDCache = Octeon_HitInvalidateDCache;
152 ci->ci_IOSyncDCache = Octeon_IOSyncDCache;
153 }
154
155 void
Octeon_SyncCache(struct cpu_info * ci)156 Octeon_SyncCache(struct cpu_info *ci)
157 {
158 mips_sync();
159 }
160
161 void
Octeon_InvalidateICache(struct cpu_info * ci,vaddr_t va,size_t len)162 Octeon_InvalidateICache(struct cpu_info *ci, vaddr_t va, size_t len)
163 {
164 /* A SYNCI flushes the entire icache on OCTEON */
165 SYNCI();
166 }
167
168 /*
169 * Register a given page for I$ invalidation.
170 */
171 void
Octeon_InvalidateICachePage(struct cpu_info * ci,vaddr_t va)172 Octeon_InvalidateICachePage(struct cpu_info *ci, vaddr_t va)
173 {
174 /*
175 * Since there is apparently no way to operate on a subset of I$,
176 * all we need to do here is remember there are postponed flushes.
177 */
178 ci->ci_cachepending_l1i = 1;
179 }
180
181 /*
182 * Perform postponed I$ invalidation.
183 */
184 void
Octeon_SyncICache(struct cpu_info * ci)185 Octeon_SyncICache(struct cpu_info *ci)
186 {
187 if (ci->ci_cachepending_l1i != 0) {
188 SYNCI(); /* Octeon_InvalidateICache(ci, 0, PAGE_SIZE); */
189 ci->ci_cachepending_l1i = 0;
190 }
191 }
192
193 void
Octeon_SyncDCachePage(struct cpu_info * ci,vaddr_t va,paddr_t pa)194 Octeon_SyncDCachePage(struct cpu_info *ci, vaddr_t va, paddr_t pa)
195 {
196 }
197
198 void
Octeon_HitSyncDCache(struct cpu_info * ci,vaddr_t va,size_t len)199 Octeon_HitSyncDCache(struct cpu_info *ci, vaddr_t va, size_t len)
200 {
201 }
202
203 void
Octeon_HitInvalidateDCache(struct cpu_info * ci,vaddr_t va,size_t len)204 Octeon_HitInvalidateDCache(struct cpu_info *ci, vaddr_t va, size_t len)
205 {
206 }
207
208 void
Octeon_IOSyncDCache(struct cpu_info * ci,vaddr_t va,size_t len,int how)209 Octeon_IOSyncDCache(struct cpu_info *ci, vaddr_t va, size_t len, int how)
210 {
211 switch (how) {
212 default:
213 case CACHE_SYNC_R:
214 break;
215 case CACHE_SYNC_W: /* writeback */
216 case CACHE_SYNC_X: /* writeback and invalidate */
217 mips_sync();
218 break;
219 }
220 }
221
222 void
Octeon_lock_secondary_cache(struct cpu_info * ci,paddr_t _pa,size_t _sz)223 Octeon_lock_secondary_cache(struct cpu_info *ci, paddr_t _pa, size_t _sz)
224 {
225 size_t linesize = ci->ci_l2.linesize;
226 size_t sz;
227 paddr_t pa;
228 vaddr_t end, va;
229
230 pa = _pa & ~(linesize - 1);
231 sz = ((_pa + _sz + linesize - 1) & ~(linesize - 1)) - pa;
232
233 va = PHYS_TO_XKPHYS(pa, 0ul);
234 end = va + sz;
235 while (va < end) {
236 asm volatile ("cache 31, (%0)" : : "r" (va));
237 va += linesize;
238 }
239
240 /* Wait for the lock operations to finish. */
241 mips_sync();
242 }
243
244 void
Octeon_unlock_secondary_cache(struct cpu_info * ci,paddr_t _pa,size_t _sz)245 Octeon_unlock_secondary_cache(struct cpu_info *ci, paddr_t _pa, size_t _sz)
246 {
247 size_t linesize = ci->ci_l2.linesize;
248 size_t sz;
249 paddr_t pa;
250 vaddr_t end, va;
251
252 pa = _pa & ~(linesize - 1);
253 sz = ((_pa + _sz + linesize - 1) & ~(linesize - 1)) - pa;
254
255 va = PHYS_TO_XKPHYS(pa, 0ul);
256 end = va + sz;
257 while (va < end) {
258 asm volatile ("cache 23, (%0)" : : "r" (va));
259 va += linesize;
260 }
261 }
262