xref: /linux/arch/mips/kernel/genex.S (revision e4ac58afdfac792c0583af30dbd9eae53e24c78b)
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License.  See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle
7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8 * Copyright (C) 2001 MIPS Technologies, Inc.
9 * Copyright (C) 2002 Maciej W. Rozycki
10 */
11#include <linux/config.h>
12#include <linux/init.h>
13
14#include <asm/asm.h>
15#include <asm/cacheops.h>
16#include <asm/regdef.h>
17#include <asm/fpregdef.h>
18#include <asm/mipsregs.h>
19#include <asm/stackframe.h>
20#include <asm/war.h>
21
22#define PANIC_PIC(msg)					\
23		.set push;				\
24		.set	reorder;			\
25		PTR_LA	a0,8f;				\
26		.set	noat;				\
27		PTR_LA	AT, panic;			\
28		jr	AT;				\
299:		b	9b;				\
30		.set	pop;				\
31		TEXT(msg)
32
33	__INIT
34
35NESTED(except_vec0_generic, 0, sp)
36	PANIC_PIC("Exception vector 0 called")
37	END(except_vec0_generic)
38
39NESTED(except_vec1_generic, 0, sp)
40	PANIC_PIC("Exception vector 1 called")
41	END(except_vec1_generic)
42
43/*
44 * General exception vector for all other CPUs.
45 *
46 * Be careful when changing this, it has to be at most 128 bytes
47 * to fit into space reserved for the exception handler.
48 */
49NESTED(except_vec3_generic, 0, sp)
50	.set	push
51	.set	noat
52#if R5432_CP0_INTERRUPT_WAR
53	mfc0	k0, CP0_INDEX
54#endif
55	mfc0	k1, CP0_CAUSE
56	andi	k1, k1, 0x7c
57#ifdef CONFIG_64BIT
58	dsll	k1, k1, 1
59#endif
60	PTR_L	k0, exception_handlers(k1)
61	jr	k0
62	.set	pop
63	END(except_vec3_generic)
64
65/*
66 * General exception handler for CPUs with virtual coherency exception.
67 *
68 * Be careful when changing this, it has to be at most 256 (as a special
69 * exception) bytes to fit into space reserved for the exception handler.
70 */
71NESTED(except_vec3_r4000, 0, sp)
72	.set	push
73	.set	mips3
74	.set	noat
75	mfc0	k1, CP0_CAUSE
76	li	k0, 31<<2
77	andi	k1, k1, 0x7c
78	.set	push
79	.set	noreorder
80	.set	nomacro
81	beq	k1, k0, handle_vced
82	 li	k0, 14<<2
83	beq	k1, k0, handle_vcei
84#ifdef CONFIG_64BIT
85	 dsll	k1, k1, 1
86#endif
87	.set	pop
88	PTR_L	k0, exception_handlers(k1)
89	jr	k0
90
91	/*
92	 * Big shit, we now may have two dirty primary cache lines for the same
93	 * physical address.  We can safely invalidate the line pointed to by
94	 * c0_badvaddr because after return from this exception handler the
95	 * load / store will be re-executed.
96	 */
97handle_vced:
98	MFC0	k0, CP0_BADVADDR
99	li	k1, -4					# Is this ...
100	and	k0, k1					# ... really needed?
101	mtc0	zero, CP0_TAGLO
102	cache	Index_Store_Tag_D, (k0)
103	cache	Hit_Writeback_Inv_SD, (k0)
104#ifdef CONFIG_PROC_FS
105	PTR_LA	k0, vced_count
106	lw	k1, (k0)
107	addiu	k1, 1
108	sw	k1, (k0)
109#endif
110	eret
111
112handle_vcei:
113	MFC0	k0, CP0_BADVADDR
114	cache	Hit_Writeback_Inv_SD, (k0)		# also cleans pi
115#ifdef CONFIG_PROC_FS
116	PTR_LA	k0, vcei_count
117	lw	k1, (k0)
118	addiu	k1, 1
119	sw	k1, (k0)
120#endif
121	eret
122	.set	pop
123	END(except_vec3_r4000)
124
125	__FINIT
126
127	.align  5
128NESTED(handle_int, PT_SIZE, sp)
129	SAVE_ALL
130	CLI
131
132	PTR_LA	ra, ret_from_irq
133	move	a0, sp
134	j	plat_irq_dispatch
135	END(handle_int)
136
137	__INIT
138
139/*
140 * Special interrupt vector for MIPS64 ISA & embedded MIPS processors.
141 * This is a dedicated interrupt exception vector which reduces the
142 * interrupt processing overhead.  The jump instruction will be replaced
143 * at the initialization time.
144 *
145 * Be careful when changing this, it has to be at most 128 bytes
146 * to fit into space reserved for the exception handler.
147 */
148NESTED(except_vec4, 0, sp)
1491:	j	1b			/* Dummy, will be replaced */
150	END(except_vec4)
151
152/*
153 * EJTAG debug exception handler.
154 * The EJTAG debug exception entry point is 0xbfc00480, which
155 * normally is in the boot PROM, so the boot PROM must do a
156 * unconditional jump to this vector.
157 */
158NESTED(except_vec_ejtag_debug, 0, sp)
159	j	ejtag_debug_handler
160	END(except_vec_ejtag_debug)
161
162	__FINIT
163
164/*
165 * Vectored interrupt handler.
166 * This prototype is copied to ebase + n*IntCtl.VS and patched
167 * to invoke the handler
168 */
169NESTED(except_vec_vi, 0, sp)
170	SAVE_SOME
171	SAVE_AT
172	.set	push
173	.set	noreorder
174EXPORT(except_vec_vi_lui)
175	lui	v0, 0		/* Patched */
176	j	except_vec_vi_handler
177EXPORT(except_vec_vi_ori)
178	 ori	v0, 0		/* Patched */
179	.set	pop
180	END(except_vec_vi)
181EXPORT(except_vec_vi_end)
182
183/*
184 * Common Vectored Interrupt code
185 * Complete the register saves and invoke the handler which is passed in $v0
186 */
187NESTED(except_vec_vi_handler, 0, sp)
188	SAVE_TEMP
189	SAVE_STATIC
190	CLI
191	move	a0, sp
192	jalr	v0
193	j	ret_from_irq
194	END(except_vec_vi_handler)
195
196/*
197 * EJTAG debug exception handler.
198 */
199NESTED(ejtag_debug_handler, PT_SIZE, sp)
200	.set	push
201	.set	noat
202	MTC0	k0, CP0_DESAVE
203	mfc0	k0, CP0_DEBUG
204
205	sll	k0, k0, 30	# Check for SDBBP.
206	bgez	k0, ejtag_return
207
208	PTR_LA	k0, ejtag_debug_buffer
209	LONG_S	k1, 0(k0)
210	SAVE_ALL
211	move	a0, sp
212	jal	ejtag_exception_handler
213	RESTORE_ALL
214	PTR_LA	k0, ejtag_debug_buffer
215	LONG_L	k1, 0(k0)
216
217ejtag_return:
218	MFC0	k0, CP0_DESAVE
219	.set	mips32
220	deret
221	.set pop
222	END(ejtag_debug_handler)
223
224/*
225 * This buffer is reserved for the use of the EJTAG debug
226 * handler.
227 */
228	.data
229EXPORT(ejtag_debug_buffer)
230	.fill	LONGSIZE
231	.previous
232
233	__INIT
234
235/*
236 * NMI debug exception handler for MIPS reference boards.
237 * The NMI debug exception entry point is 0xbfc00000, which
238 * normally is in the boot PROM, so the boot PROM must do a
239 * unconditional jump to this vector.
240 */
241NESTED(except_vec_nmi, 0, sp)
242	j	nmi_handler
243	END(except_vec_nmi)
244
245	__FINIT
246
247NESTED(nmi_handler, PT_SIZE, sp)
248	.set	push
249	.set	noat
250	SAVE_ALL
251 	move	a0, sp
252	jal	nmi_exception_handler
253	RESTORE_ALL
254	.set	mips3
255	eret
256	.set	pop
257	END(nmi_handler)
258
259	.macro	__build_clear_none
260	.endm
261
262	.macro	__build_clear_sti
263	STI
264	.endm
265
266	.macro	__build_clear_cli
267	CLI
268	.endm
269
270	.macro	__build_clear_fpe
271	cfc1	a1, fcr31
272	li	a2, ~(0x3f << 12)
273	and	a2, a1
274	ctc1	a2, fcr31
275	STI
276	.endm
277
278	.macro	__build_clear_ade
279	MFC0	t0, CP0_BADVADDR
280	PTR_S	t0, PT_BVADDR(sp)
281	KMODE
282	.endm
283
284	.macro	__BUILD_silent exception
285	.endm
286
287	/* Gas tries to parse the PRINT argument as a string containing
288	   string escapes and emits bogus warnings if it believes to
289	   recognize an unknown escape code.  So make the arguments
290	   start with an n and gas will believe \n is ok ...  */
291	.macro	__BUILD_verbose	nexception
292	LONG_L	a1, PT_EPC(sp)
293#ifdef CONFIG_32BIT
294	PRINT("Got \nexception at %08lx\012")
295#endif
296#ifdef CONFIG_64BIT
297	PRINT("Got \nexception at %016lx\012")
298#endif
299	.endm
300
301	.macro	__BUILD_count exception
302	LONG_L	t0,exception_count_\exception
303	LONG_ADDIU t0, 1
304	LONG_S	t0,exception_count_\exception
305	.comm	exception_count\exception, 8, 8
306	.endm
307
308	.macro	__BUILD_HANDLER exception handler clear verbose ext
309	.align	5
310	NESTED(handle_\exception, PT_SIZE, sp)
311	.set	noat
312	SAVE_ALL
313	FEXPORT(handle_\exception\ext)
314	__BUILD_clear_\clear
315	.set	at
316	__BUILD_\verbose \exception
317	move	a0, sp
318	jal	do_\handler
319	j	ret_from_exception
320	END(handle_\exception)
321	.endm
322
323	.macro	BUILD_HANDLER exception handler clear verbose
324	__BUILD_HANDLER	\exception \handler \clear \verbose _int
325	.endm
326
327	BUILD_HANDLER adel ade ade silent		/* #4  */
328	BUILD_HANDLER ades ade ade silent		/* #5  */
329	BUILD_HANDLER ibe be cli silent			/* #6  */
330	BUILD_HANDLER dbe be cli silent			/* #7  */
331	BUILD_HANDLER bp bp sti silent			/* #9  */
332	BUILD_HANDLER ri ri sti silent			/* #10 */
333	BUILD_HANDLER cpu cpu sti silent		/* #11 */
334	BUILD_HANDLER ov ov sti silent			/* #12 */
335	BUILD_HANDLER tr tr sti silent			/* #13 */
336	BUILD_HANDLER fpe fpe fpe silent		/* #15 */
337	BUILD_HANDLER mdmx mdmx sti silent		/* #22 */
338	BUILD_HANDLER watch watch sti verbose		/* #23 */
339	BUILD_HANDLER mcheck mcheck cli verbose		/* #24 */
340	BUILD_HANDLER mt mt sti verbose			/* #25 */
341	BUILD_HANDLER dsp dsp sti silent		/* #26 */
342	BUILD_HANDLER reserved reserved sti verbose	/* others */
343
344#ifdef CONFIG_64BIT
345/* A temporary overflow handler used by check_daddi(). */
346
347	__INIT
348
349	BUILD_HANDLER  daddi_ov daddi_ov none silent	/* #12 */
350#endif
351