1 /*-
2 * Copyright (c) 2003-2009 RMI Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of RMI Corporation, nor the names of its contributors,
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * RMI_BSD
30 * $FreeBSD: releng/11.1/sys/mips/rmi/rmi_mips_exts.h 213441 2010-10-05 05:49:38Z jchandra $
31 */
32 #ifndef __MIPS_EXTS_H__
33 #define __MIPS_EXTS_H__
34
35 #define CPU_BLOCKID_IFU 0
36 #define CPU_BLOCKID_ICU 1
37 #define CPU_BLOCKID_IEU 2
38 #define CPU_BLOCKID_LSU 3
39 #define CPU_BLOCKID_MMU 4
40 #define CPU_BLOCKID_PRF 5
41
42 #define LSU_CERRLOG_REGID 9
43
44 #if defined(__mips_n64) || defined(__mips_n32)
45 static __inline uint64_t
46 read_xlr_ctrl_register(int block, int reg)
47 {
48 uint64_t res;
49
50 __asm__ __volatile__(
51 ".set push\n\t"
52 ".set noreorder\n\t"
53 "move $9, %1\n\t"
54 ".word 0x71280018\n\t" /* mfcr $8, $9 */
55 "move %0, $8\n\t"
56 ".set pop\n"
57 : "=r" (res) : "r"((block << 8) | reg)
58 : "$8", "$9"
59 );
60 return (res);
61 }
62
63 static __inline void
64 write_xlr_ctrl_register(int block, int reg, uint64_t value)
65 {
66 __asm__ __volatile__(
67 ".set push\n\t"
68 ".set noreorder\n\t"
69 "move $8, %0\n"
70 "move $9, %1\n"
71 ".word 0x71280019\n" /* mtcr $8, $9 */
72 ".set pop\n"
73 :
74 : "r" (value), "r" ((block << 8) | reg)
75 : "$8", "$9"
76 );
77 }
78
79 #else /* !(defined(__mips_n64) || defined(__mips_n32)) */
80
81 static __inline uint64_t
82 read_xlr_ctrl_register(int block, int reg)
83 {
84 uint32_t high, low;
85
86 __asm__ __volatile__(
87 ".set push\n\t"
88 ".set noreorder\n\t"
89 ".set mips64\n\t"
90 "move $9, %2\n"
91 ".word 0x71280018\n" /* "mfcr $8, $9\n" */
92 "dsra32 %0, $8, 0\n\t"
93 "sll %1, $8, 0\n\t"
94 ".set pop"
95 : "=r" (high), "=r"(low)
96 : "r" ((block << 8) | reg)
97 : "$8", "$9");
98
99 return ( (((uint64_t)high) << 32) | low);
100 }
101
102 static __inline void
103 write_xlr_ctrl_register(int block, int reg, uint64_t value)
104 {
105 uint32_t low, high;
106 high = value >> 32;
107 low = value & 0xffffffff;
108
109 __asm__ __volatile__(
110 ".set push\n\t"
111 ".set noreorder\n\t"
112 ".set mips64\n\t"
113 "dsll32 $9, %0, 0\n\t"
114 "dsll32 $8, %1, 0\n\t"
115 "dsrl32 $8, $8, 0\n\t"
116 "or $8, $9, $8\n\t"
117 "move $9, %2\n\t"
118 ".word 0x71280019\n\t" /* mtcr $8, $9 */
119 ".set pop\n"
120 : /* No outputs */
121 : "r" (high), "r" (low), "r"((block << 8) | reg)
122 : "$8", "$9");
123 }
124 #endif /* defined(__mips_n64) || defined(__mips_n32) */
125
126 /*
127 * 32 bit read write for c0
128 */
129 #define read_c0_register32(reg, sel) \
130 ({ \
131 uint32_t __rv; \
132 __asm__ __volatile__( \
133 ".set push\n\t" \
134 ".set mips32\n\t" \
135 "mfc0 %0, $%1, %2\n\t" \
136 ".set pop\n" \
137 : "=r" (__rv) : "i" (reg), "i" (sel) ); \
138 __rv; \
139 })
140
141 #define write_c0_register32(reg, sel, value) \
142 __asm__ __volatile__( \
143 ".set push\n\t" \
144 ".set mips32\n\t" \
145 "mtc0 %0, $%1, %2\n\t" \
146 ".set pop\n" \
147 : : "r" (value), "i" (reg), "i" (sel) );
148
149 #define read_c2_register32(reg, sel) \
150 ({ \
151 uint32_t __rv; \
152 __asm__ __volatile__( \
153 ".set push\n\t" \
154 ".set mips32\n\t" \
155 "mfc2 %0, $%1, %2\n\t" \
156 ".set pop\n" \
157 : "=r" (__rv) : "i" (reg), "i" (sel) ); \
158 __rv; \
159 })
160
161 #define write_c2_register32(reg, sel, value) \
162 __asm__ __volatile__( \
163 ".set push\n\t" \
164 ".set mips32\n\t" \
165 "mtc2 %0, $%1, %2\n\t" \
166 ".set pop\n" \
167 : : "r" (value), "i" (reg), "i" (sel) );
168
169 #if defined(__mips_n64) || defined(__mips_n32)
170 /*
171 * On 64 bit compilation, the operations are simple
172 */
173 #define read_c0_register64(reg, sel) \
174 ({ \
175 uint64_t __rv; \
176 __asm__ __volatile__( \
177 ".set push\n\t" \
178 ".set mips64\n\t" \
179 "dmfc0 %0, $%1, %2\n\t" \
180 ".set pop\n" \
181 : "=r" (__rv) : "i" (reg), "i" (sel) ); \
182 __rv; \
183 })
184
185 #define write_c0_register64(reg, sel, value) \
186 __asm__ __volatile__( \
187 ".set push\n\t" \
188 ".set mips64\n\t" \
189 "dmtc0 %0, $%1, %2\n\t" \
190 ".set pop\n" \
191 : : "r" (value), "i" (reg), "i" (sel) );
192
193 #define read_c2_register64(reg, sel) \
194 ({ \
195 uint64_t __rv; \
196 __asm__ __volatile__( \
197 ".set push\n\t" \
198 ".set mips64\n\t" \
199 "dmfc2 %0, $%1, %2\n\t" \
200 ".set pop\n" \
201 : "=r" (__rv) : "i" (reg), "i" (sel) ); \
202 __rv; \
203 })
204
205 #define write_c2_register64(reg, sel, value) \
206 __asm__ __volatile__( \
207 ".set push\n\t" \
208 ".set mips64\n\t" \
209 "dmtc2 %0, $%1, %2\n\t" \
210 ".set pop\n" \
211 : : "r" (value), "i" (reg), "i" (sel) );
212
213 #else /* ! (defined(__mips_n64) || defined(__mips_n32)) */
214
215 /*
216 * 32 bit compilation, 64 bit values has to split
217 */
218 #define read_c0_register64(reg, sel) \
219 ({ \
220 uint32_t __high, __low; \
221 __asm__ __volatile__( \
222 ".set push\n\t" \
223 ".set noreorder\n\t" \
224 ".set mips64\n\t" \
225 "dmfc0 $8, $%2, %3\n\t" \
226 "dsra32 %0, $8, 0\n\t" \
227 "sll %1, $8, 0\n\t" \
228 ".set pop\n" \
229 : "=r"(__high), "=r"(__low): "i"(reg), "i"(sel) \
230 : "$8"); \
231 ((uint64_t)__high << 32) | __low; \
232 })
233
234 #define write_c0_register64(reg, sel, value) \
235 do { \
236 uint32_t __high = value >> 32; \
237 uint32_t __low = value & 0xffffffff; \
238 __asm__ __volatile__( \
239 ".set push\n\t" \
240 ".set noreorder\n\t" \
241 ".set mips64\n\t" \
242 "dsll32 $8, %1, 0\n\t" \
243 "dsll32 $9, %0, 0\n\t" \
244 "dsrl32 $8, $8, 0\n\t" \
245 "or $8, $8, $9\n\t" \
246 "dmtc0 $8, $%2, %3\n\t" \
247 ".set pop" \
248 :: "r"(__high), "r"(__low), "i"(reg), "i"(sel) \
249 :"$8", "$9"); \
250 } while(0)
251
252 #define read_c2_register64(reg, sel) \
253 ({ \
254 uint32_t __high, __low; \
255 __asm__ __volatile__( \
256 ".set push\n\t" \
257 ".set noreorder\n\t" \
258 ".set mips64\n\t" \
259 "dmfc2 $8, $%2, %3\n\t" \
260 "dsra32 %0, $8, 0\n\t" \
261 "sll %1, $8, 0\n\t" \
262 ".set pop\n" \
263 : "=r"(__high), "=r"(__low): "i"(reg), "i"(sel) \
264 : "$8"); \
265 ((uint64_t)__high << 32) | __low; \
266 })
267
268 #define write_c2_register64(reg, sel, value) \
269 do { \
270 uint32_t __high = value >> 32; \
271 uint32_t __low = value & 0xffffffff; \
272 __asm__ __volatile__( \
273 ".set push\n\t" \
274 ".set noreorder\n\t" \
275 ".set mips64\n\t" \
276 "dsll32 $8, %1, 0\n\t" \
277 "dsll32 $9, %0, 0\n\t" \
278 "dsrl32 $8, $8, 0\n\t" \
279 "or $8, $8, $9\n\t" \
280 "dmtc2 $8, $%2, %3\n\t" \
281 ".set pop" \
282 :: "r"(__high), "r"(__low), "i"(reg), "i"(sel) \
283 :"$8", "$9"); \
284 } while(0)
285
286 #endif /* defined(__mips_n64) || defined(__mips_n32) */
287
288 static __inline int
289 xlr_cpu_id(void)
290 {
291
292 return (read_c0_register32(15, 1) & 0x1f);
293 }
294
295 static __inline int
296 xlr_core_id(void)
297 {
298
299 return (xlr_cpu_id() / 4);
300 }
301
302 static __inline int
303 xlr_thr_id(void)
304 {
305
306 return (read_c0_register32(15, 1) & 0x3);
307 }
308
309 /* Additional registers on the XLR */
310 #define MIPS_COP_0_OSSCRATCH 22
311 #define XLR_CACHELINE_SIZE 32
312
313 /* functions to write to and read from the extended
314 * cp0 registers.
315 * EIRR : Extended Interrupt Request Register
316 * cp0 register 9 sel 6
317 * bits 0...7 are same as cause register 8...15
318 * EIMR : Extended Interrupt Mask Register
319 * cp0 register 9 sel 7
320 * bits 0...7 are same as status register 8...15
321 */
322 static __inline uint64_t
323 read_c0_eirr64(void)
324 {
325
326 return (read_c0_register64(9, 6));
327 }
328
329 static __inline void
330 write_c0_eirr64(uint64_t val)
331 {
332
333 write_c0_register64(9, 6, val);
334 }
335
336 static __inline uint64_t
337 read_c0_eimr64(void)
338 {
339
340 return (read_c0_register64(9, 7));
341 }
342
343 static __inline void
344 write_c0_eimr64(uint64_t val)
345 {
346
347 write_c0_register64(9, 7, val);
348 }
349
350 static __inline int
351 xlr_test_and_set(int *lock)
352 {
353 int oldval = 0;
354
355 __asm__ __volatile__(
356 ".set push\n"
357 ".set noreorder\n"
358 "move $9, %2\n"
359 "li $8, 1\n"
360 // "swapw $8, $9\n"
361 ".word 0x71280014\n"
362 "move %1, $8\n"
363 ".set pop\n"
364 : "+m"(*lock), "=r"(oldval)
365 : "r"((unsigned long)lock)
366 : "$8", "$9"
367 );
368
369 return (oldval == 0 ? 1 /* success */ : 0 /* failure */);
370 }
371
372 static __inline uint32_t
373 xlr_mfcr(uint32_t reg)
374 {
375 uint32_t val;
376
377 __asm__ __volatile__(
378 "move $8, %1\n"
379 ".word 0x71090018\n"
380 "move %0, $9\n"
381 : "=r"(val)
382 : "r"(reg):"$8", "$9");
383
384 return val;
385 }
386
387 static __inline void
388 xlr_mtcr(uint32_t reg, uint32_t val)
389 {
390 __asm__ __volatile__(
391 "move $8, %1\n"
392 "move $9, %0\n"
393 ".word 0x71090019\n"
394 :: "r"(val), "r"(reg)
395 : "$8", "$9");
396 }
397
398 /*
399 * Atomic increment a unsigned int
400 */
401 static __inline unsigned int
402 xlr_ldaddwu(unsigned int value, unsigned int *addr)
403 {
404 __asm__ __volatile__(
405 ".set push\n"
406 ".set noreorder\n"
407 "move $8, %2\n"
408 "move $9, %3\n"
409 ".word 0x71280011\n" /* ldaddwu $8, $9 */
410 "move %0, $8\n"
411 ".set pop\n"
412 : "=&r"(value), "+m"(*addr)
413 : ""(value), "r" ((unsigned long)addr)
414 : "$8", "$9");
415
416 return (value);
417 }
418
419 #if defined(__mips_n64)
420 static __inline uint32_t
421 xlr_paddr_lw(uint64_t paddr)
422 {
423
424 paddr |= 0x9800000000000000ULL;
425 return (*(uint32_t *)(uintptr_t)paddr);
426 }
427
428 static __inline uint64_t
429 xlr_paddr_ld(uint64_t paddr)
430 {
431
432 paddr |= 0x9800000000000000ULL;
433 return (*(uint64_t *)(uintptr_t)paddr);
434 }
435
436 #elif defined(__mips_n32)
437 static __inline uint32_t
438 xlr_paddr_lw(uint64_t paddr)
439 {
440 uint32_t val;
441
442 paddr |= 0x9800000000000000ULL;
443 __asm__ __volatile__(
444 ".set push \n\t"
445 ".set mips64 \n\t"
446 "lw %0, 0(%1) \n\t"
447 ".set pop \n"
448 : "=r"(val)
449 : "r"(paddr));
450
451 return (val);
452 }
453
454 static __inline uint64_t
455 xlr_paddr_ld(uint64_t paddr)
456 {
457 uint64_t val;
458
459 paddr |= 0x9800000000000000ULL;
460 __asm__ __volatile__(
461 ".set push \n\t"
462 ".set mips64 \n\t"
463 "ld %0, 0(%1) \n\t"
464 ".set pop \n"
465 : "=r"(val)
466 : "r"(paddr));
467
468 return (val);
469 }
470
471 #else /* o32 compilation */
472 static __inline uint32_t
473 xlr_paddr_lw(uint64_t paddr)
474 {
475 uint32_t addrh, addrl;
476 uint32_t val;
477
478 addrh = 0x98000000 | (paddr >> 32);
479 addrl = paddr & 0xffffffff;
480
481 __asm__ __volatile__(
482 ".set push \n\t"
483 ".set mips64 \n\t"
484 "dsll32 $8, %1, 0 \n\t"
485 "dsll32 $9, %2, 0 \n\t" /* get rid of the */
486 "dsrl32 $9, $9, 0 \n\t" /* sign extend */
487 "or $9, $8, $8 \n\t"
488 "lw %0, 0($9) \n\t"
489 ".set pop \n"
490 : "=r"(val)
491 : "r"(addrh), "r"(addrl)
492 : "$8", "$9");
493
494 return (val);
495 }
496
497 static __inline uint64_t
498 xlr_paddr_ld(uint64_t paddr)
499 {
500 uint32_t addrh, addrl;
501 uint32_t valh, vall;
502
503 addrh = 0x98000000 | (paddr >> 32);
504 addrl = paddr & 0xffffffff;
505
506 __asm__ __volatile__(
507 ".set push \n\t"
508 ".set mips64 \n\t"
509 "dsll32 %0, %2, 0 \n\t"
510 "dsll32 %1, %3, 0 \n\t" /* get rid of the */
511 "dsrl32 %1, %1, 0 \n\t" /* sign extend */
512 "or %0, %0, %1 \n\t"
513 "lw %1, 4(%0) \n\t"
514 "lw %0, 0(%0) \n\t"
515 ".set pop \n"
516 : "=&r"(valh), "=&r"(vall)
517 : "r"(addrh), "r"(addrl));
518
519 return (((uint64_t)valh << 32) | vall);
520 }
521 #endif
522
523 /*
524 * XXX: Not really needed in n32 or n64, retain for now
525 */
526 #if defined(__mips_n64) || defined(__mips_n32)
527 static __inline uint32_t
528 xlr_enable_kx(void)
529 {
530
531 return (0);
532 }
533
534 static __inline void
535 xlr_restore_kx(uint32_t sr)
536 {
537 }
538
539 #else /* !defined(__mips_n64) && !defined(__mips_n32) */
540 /*
541 * o32 compilation, we will disable interrupts and enable
542 * the KX bit so that we can use XKPHYS to access any 40bit
543 * physical address
544 */
545 static __inline uint32_t
546 xlr_enable_kx(void)
547 {
548 uint32_t sr = mips_rd_status();
549
550 mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_KX);
551 return (sr);
552 }
553
554 static __inline void
555 xlr_restore_kx(uint32_t sr)
556 {
557
558 mips_wr_status(sr);
559 }
560 #endif /* defined(__mips_n64) || defined(__mips_n32) */
561
562 /*
563 * XLR/XLS processors have maximum 8 cores, and maximum 4 threads
564 * per core
565 */
566 #define XLR_MAX_CORES 8
567 #define XLR_NTHREADS 4
568
569 /*
570 * FreeBSD can be started with few threads and cores turned off,
571 * so have a hardware thread id to FreeBSD cpuid mapping.
572 */
573 extern int xlr_ncores;
574 extern int xlr_threads_per_core;
575 extern uint32_t xlr_hw_thread_mask;
576 extern int xlr_cpuid_to_hwtid[];
577 extern int xlr_hwtid_to_cpuid[];
578
579 #endif
Cache object: 5361cdb25e2c99f04700fa32269dc4b0
|