rmi_mips_exts.h revision 211994
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: head/sys/mips/rmi/rmi_mips_exts.h 211994 2010-08-30 13:05:21Z 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
44static __inline__ unsigned int read_32bit_phnx_ctrl_reg(int block, int reg)
45{
46	unsigned int __res;
47
48	__asm__ __volatile__(
49			".set\tpush\n\t"
50			".set\tnoreorder\n\t"
51			"move $9, %1\n"
52			/* "mfcr\t$8, $9\n\t"          */
53			".word 0x71280018\n"
54			"move %0, $8\n"
55			".set\tpop"
56			: "=r" (__res) : "r"((block<<8)|reg)
57			: "$8", "$9"
58			);
59	return __res;
60}
61
62static __inline__ void write_32bit_phnx_ctrl_reg(int block, int reg, unsigned int value)
63{
64	__asm__ __volatile__(
65			".set\tpush\n\t"
66			".set\tnoreorder\n\t"
67			"move $8, %0\n"
68			"move $9, %1\n"
69			/* "mtcr\t$8, $9\n\t"  */
70			".word 0x71280019\n"
71			".set\tpop"
72			:
73			: "r" (value), "r"((block<<8)|reg)
74			: "$8", "$9"
75			);
76}
77
78static __inline__ unsigned long long read_64bit_phnx_ctrl_reg(int block, int reg)
79{
80	unsigned int high, low;
81
82	__asm__ __volatile__(
83		".set\tmips64\n\t"
84		"move    $9, %2\n"
85		/* "mfcr    $8, $9\n" */
86		".word   0x71280018\n"
87		"dsrl32  %0, $8, 0\n\t"
88		"dsll32  $8, $8, 0\n\t"
89		"dsrl32  %1, $8, 0\n\t"
90		".set mips0"
91		: "=r" (high), "=r"(low)
92		: "r"((block<<8)|reg)
93		: "$8", "$9"
94		);
95
96	return ( (((unsigned long long)high)<<32) | low);
97}
98
99static __inline__ void write_64bit_phnx_ctrl_reg(int block, int reg,unsigned long long value)
100{
101	__uint32_t low, high;
102	high = value >> 32;
103	low = value & 0xffffffff;
104
105	__asm__ __volatile__(
106		".set push\n"
107		".set noreorder\n"
108		".set mips4\n\t"
109		/* Set up "rs" */
110		"move $9, %0\n"
111
112		/* Store 64 bit value in "rt" */
113		"dsll32 $10, %1, 0  \n\t"
114		"dsll32 $8, %2, 0  \n\t"
115		"dsrl32 $8, $8, 0  \n\t"
116		"or     $10, $8, $8 \n\t"
117
118		".word 0x71280019\n" /* mtcr $8, $9 */
119
120		".set pop\n"
121
122		:  /* No outputs */
123		: "r"((block<<8)|reg), "r" (high), "r" (low)
124		: "$8", "$9", "$10"
125		);
126}
127
128#define read_c0_register32(reg, sel)                            \
129({ unsigned int __rv;                                           \
130        __asm__ __volatile__(                                   \
131        ".set\tpush\n\t"                                        \
132        ".set mips32\n\t"                                       \
133        "mfc0\t%0,$%1,%2\n\t"                                   \
134        ".set\tpop"                                             \
135        : "=r" (__rv) : "i" (reg), "i" (sel) );                 \
136        __rv;})
137
138#define write_c0_register32(reg,  sel, value)                   \
139        __asm__ __volatile__(                                   \
140        ".set\tpush\n\t"                                        \
141        ".set mips32\n\t"                                       \
142        "mtc0\t%0,$%1,%2\n\t"                                   \
143        ".set\tpop"                                             \
144        : : "r" (value), "i" (reg), "i" (sel) );
145
146#define read_c0_register64(reg, sel)                            \
147   ({ unsigned int __high, __low;                               \
148        __asm__ __volatile__(                                   \
149        ".set\tpush\n\t"                                        \
150        ".set mips64\n\t"                                       \
151        "dmfc0\t $8, $%2, %3\n\t"                               \
152        "dsrl32\t%0, $8, 0\n\t"                                 \
153        "dsll32\t$8, $8, 0\n\t"                                 \
154        "dsrl32\t%1, $8, 0\n\t"                                 \
155        ".set\tpop"                                             \
156        : "=r"(__high), "=r"(__low): "i"(reg), "i"(sel): "$8" );\
157        (((unsigned long long)__high << 32) | __low);})
158
159#define write_c0_register64(reg, sel, value)                    \
160 do{                                                            \
161       unsigned int __high = val>>32;                           \
162       unsigned int __low = val & 0xffffffff;                   \
163        __asm__ __volatile__(                                   \
164        ".set\tpush\n\t"                                        \
165        ".set mips64\n\t"                                       \
166        "dsll32\t$8, %1, 0\n\t"                                 \
167        "dsll32\t$9, %0, 0\n\t"                                 \
168        "or\t    $8, $8, $9\n\t"                                \
169        "dmtc0\t $8, $%2, %3\n\t"                               \
170        ".set\tpop"                                             \
171        :: "r"(high), "r"(low),  "i"(reg), "i"(sel):"$8", "$9");\
172   } while(0)
173
174#define read_c2_register32(reg, sel)                            \
175({ unsigned int __rv;                                           \
176        __asm__ __volatile__(                                   \
177        ".set\tpush\n\t"                                        \
178        ".set mips32\n\t"                                       \
179        "mfc2\t%0,$%1,%2\n\t"                                   \
180        ".set\tpop"                                             \
181        : "=r" (__rv) : "i" (reg), "i" (sel) );                 \
182        __rv;})
183
184#define write_c2_register32(reg,  sel, value)                   \
185        __asm__ __volatile__(                                   \
186        ".set\tpush\n\t"                                        \
187        ".set mips32\n\t"                                       \
188        "mtc2\t%0,$%1,%2\n\t"                                   \
189        ".set\tpop"                                             \
190        : : "r" (value), "i" (reg), "i" (sel) );
191
192#define read_c2_register64(reg, sel)                            \
193   ({ unsigned int __high, __low;                               \
194        __asm__ __volatile__(                                   \
195        ".set mips64\n\t"                                       \
196        "dmfc2\t $8, $%2, %3\n\t"                               \
197        "dsrl32\t%0, $8, 0\n\t"                                 \
198        "dsll32\t$8, $8, 0\n\t"                                 \
199        "dsrl32\t%1, $8, 0\n\t"                                 \
200        ".set\tmips0"                                           \
201        : "=r"(__high), "=r"(__low): "i"(reg), "i"(sel): "$8" );\
202        (((unsigned long long)__high << 32) | __low);})
203
204#define write_c2_register64(reg, sel, value)                    \
205 do{                                                            \
206       unsigned int __high = value>>32;                         \
207       unsigned int __low = value & 0xffffffff;                 \
208        __asm__ __volatile__(                                   \
209        ".set mips64\n\t"                                       \
210        "dsll32\t$8, %1, 0\n\t"                                 \
211        "dsll32\t$9, %0, 0\n\t"                                 \
212        "dsrl32\t$8, $8, 0\n\t"                                 \
213        "or\t    $8, $8, $9\n\t"                                \
214        "dmtc2\t $8, $%2, %3\n\t"                               \
215        ".set\tmips0"                                           \
216        :: "r"(__high), "r"(__low),                             \
217           "i"(reg), "i"(sel)                                   \
218        :"$8", "$9");                                           \
219   } while(0)
220
221#define xlr_cpu_id()                                            \
222({int __id;                                                     \
223 __asm__ __volatile__ (                                         \
224           ".set push\n"                                        \
225           ".set noreorder\n"                                   \
226           "mfc0 $8, $15, 1\n"                                  \
227           "andi %0, $8, 0x1f\n"                                \
228           ".set pop\n"                                         \
229           : "=r" (__id) : : "$8");                             \
230 __id;})
231
232#define xlr_core_id()                                           \
233({int __id;                                                     \
234 __asm__ __volatile__ (                                         \
235           ".set push\n"                                        \
236           ".set noreorder\n"                                   \
237           "mfc0 $8, $15, 1\n"                                  \
238           "andi %0, $8, 0x1f\n"                                \
239           ".set pop\n"                                         \
240           : "=r" (__id) : : "$8");                             \
241 __id/4;})
242
243#define xlr_thr_id()                                            \
244({int __id;                                                     \
245 __asm__ __volatile__ (                                         \
246           ".set push\n"                                        \
247           ".set noreorder\n"                                   \
248           "mfc0 $8, $15, 1\n"                                  \
249           "andi %0, $8, 0x3\n"                                 \
250           ".set pop\n"                                         \
251           : "=r" (__id) : : "$8");                             \
252 __id;})
253
254
255/* Additional registers on the XLR */
256#define MIPS_COP_0_OSSCRATCH   22
257
258#define XLR_CACHELINE_SIZE 32
259
260#define XLR_MAX_CORES 8
261
262/* functions to write to and read from the extended
263 * cp0 registers.
264 * EIRR : Extended Interrupt Request Register
265 *        cp0 register 9 sel 6
266 *        bits 0...7 are same as cause register 8...15
267 * EIMR : Extended Interrupt Mask Register
268 *        cp0 register 9 sel 7
269 *        bits 0...7 are same as status register 8...15
270 */
271
272static inline uint64_t
273read_c0_eirr64(void)
274{
275	__uint32_t high, low;
276
277	__asm__ __volatile__(
278	            ".set push\n"
279	            ".set noreorder\n"
280	            ".set noat\n"
281	            ".set mips4\n"
282
283	            ".word 0x40214806  \n\t"
284	            "nop               \n\t"
285	            "dsra32 %0, $1, 0  \n\t"
286	            "sll    %1, $1, 0  \n\t"
287
288	            ".set pop\n"
289
290	    :       "=r"(high), "=r"(low)
291	);
292
293	return (((__uint64_t) high) << 32) | low;
294}
295
296static inline __uint64_t
297read_c0_eimr64(void)
298{
299	__uint32_t high, low;
300
301	__asm__ __volatile__(
302	            ".set push\n"
303	            ".set noreorder\n"
304	            ".set noat\n"
305	            ".set mips4\n"
306
307	            ".word 0x40214807  \n\t"
308	            "nop               \n\t"
309	            "dsra32 %0, $1, 0  \n\t"
310	            "sll    %1, $1, 0  \n\t"
311
312	            ".set pop\n"
313
314	    :       "=r"(high), "=r"(low)
315	);
316
317	return (((__uint64_t) high) << 32) | low;
318}
319
320static inline void
321write_c0_eirr64(__uint64_t value)
322{
323	__uint32_t low, high;
324
325	high = value >> 32;
326	low = value & 0xffffffff;
327
328	__asm__ __volatile__(
329	            ".set push\n"
330	            ".set noreorder\n"
331	            ".set noat\n"
332	            ".set mips4\n\t"
333
334	            "dsll32 $2, %1, 0  \n\t"
335	            "dsll32 $1, %0, 0  \n\t"
336	            "dsrl32 $2, $2, 0  \n\t"
337	            "or     $1, $1, $2 \n\t"
338	            ".word  0x40a14806 \n\t"
339	            "nop               \n\t"
340
341	            ".set pop\n"
342
343	    :
344	    :       "r"(high), "r"(low)
345	    :       "$1", "$2");
346}
347
348static inline void
349write_c0_eimr64(__uint64_t value)
350{
351	__uint32_t low, high;
352
353	high = value >> 32;
354	low = value & 0xffffffff;
355
356	__asm__ __volatile__(
357	            ".set push\n"
358	            ".set noreorder\n"
359	            ".set noat\n"
360	            ".set mips4\n\t"
361
362	            "dsll32 $2, %1, 0  \n\t"
363	            "dsll32 $1, %0, 0  \n\t"
364	            "dsrl32 $2, $2, 0  \n\t"
365	            "or     $1, $1, $2 \n\t"
366	            ".word  0x40a14807 \n\t"
367	            "nop               \n\t"
368
369	            ".set pop\n"
370
371	    :
372	    :       "r"(high), "r"(low)
373	    :       "$1", "$2");
374}
375
376static __inline__ int
377xlr_test_and_set(int *lock)
378{
379	int oldval = 0;
380
381	__asm__ __volatile__(".set push\n"
382	            ".set noreorder\n"
383	            "move $9, %2\n"
384	            "li $8, 1\n"
385	    //      "swapw $8, $9\n"
386	            ".word 0x71280014\n"
387	            "move %1, $8\n"
388	            ".set pop\n"
389	    :       "+m"(*lock), "=r"(oldval)
390	    :       "r"((unsigned long)lock)
391	    :       "$8", "$9"
392	);
393
394	return (oldval == 0 ? 1 /* success */ : 0 /* failure */ );
395}
396
397static __inline__ uint32_t
398xlr_mfcr(uint32_t reg)
399{
400	uint32_t val;
401
402	__asm__ __volatile__(
403	            "move   $8, %1\n"
404	            ".word  0x71090018\n"
405	            "move   %0, $9\n"
406	    :       "=r"(val)
407	    :       "r"(reg):"$8", "$9");
408
409	return val;
410}
411
412static __inline__ void
413xlr_mtcr(uint32_t reg, uint32_t val)
414{
415	__asm__ __volatile__(
416	            "move   $8, %1\n"
417	            "move   $9, %0\n"
418	            ".word  0x71090019\n"
419	    ::      "r"(val), "r"(reg)
420	    :       "$8", "$9");
421}
422
423static __inline__ uint32_t
424xlr_paddr_lw(uint64_t paddr)
425{
426        uint32_t high, low, tmp;
427
428        high = 0x98000000 | (paddr >> 32);
429        low = paddr & 0xffffffff;
430
431        __asm__ __volatile__(
432                    ".set push         \n\t"
433                    ".set mips64       \n\t"
434                    "dsll32 %1, %1, 0  \n\t"
435                    "dsll32 %2, %2, 0  \n\t"  /* get rid of the */
436                    "dsrl32 %2, %2, 0  \n\t"  /* sign extend */
437                    "or     %1, %1, %2 \n\t"
438                    "lw     %0, 0(%1)  \n\t"
439                    ".set pop           \n"
440            :       "=r"(tmp)
441            :       "r"(high), "r"(low));
442
443	return tmp;
444}
445
446/* for cpuid to hardware thread id mapping */
447extern uint32_t xlr_hw_thread_mask;
448extern int xlr_cpuid_to_hwtid[];
449extern int xlr_hwtid_to_cpuid[];
450
451#endif
452