]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/mips/rmi/rmi_mips_exts.h
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / mips / rmi / rmi_mips_exts.h
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$
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             : "0"(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