xref: /openbmc/linux/arch/mips/kernel/genex.S (revision 80a20d2f)
11da177e4SLinus Torvalds/*
21da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public
31da177e4SLinus Torvalds * License.  See the file "COPYING" in the main directory of this archive
41da177e4SLinus Torvalds * for more details.
51da177e4SLinus Torvalds *
61da177e4SLinus Torvalds * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle
71da177e4SLinus Torvalds * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8619b6e18SMaciej W. Rozycki * Copyright (C) 2002, 2007  Maciej W. Rozycki
92a0b24f5SSteven J. Hill * Copyright (C) 2001, 2012 MIPS Technologies, Inc.  All rights reserved.
101da177e4SLinus Torvalds */
111da177e4SLinus Torvalds#include <linux/init.h>
121da177e4SLinus Torvalds
131da177e4SLinus Torvalds#include <asm/asm.h>
1441c594abSRalf Baechle#include <asm/asmmacro.h>
151da177e4SLinus Torvalds#include <asm/cacheops.h>
16192ef366SRalf Baechle#include <asm/irqflags.h>
171da177e4SLinus Torvalds#include <asm/regdef.h>
181da177e4SLinus Torvalds#include <asm/fpregdef.h>
191da177e4SLinus Torvalds#include <asm/mipsregs.h>
201da177e4SLinus Torvalds#include <asm/stackframe.h>
2112dbb04fSPaul Burton#include <asm/sync.h>
22c65a5480SAtsushi Nemoto#include <asm/thread_info.h>
231da177e4SLinus Torvalds
241da177e4SLinus Torvalds	__INIT
251da177e4SLinus Torvalds
261da177e4SLinus Torvalds/*
271da177e4SLinus Torvalds * General exception vector for all other CPUs.
281da177e4SLinus Torvalds *
291da177e4SLinus Torvalds * Be careful when changing this, it has to be at most 128 bytes
301da177e4SLinus Torvalds * to fit into space reserved for the exception handler.
311da177e4SLinus Torvalds */
321da177e4SLinus TorvaldsNESTED(except_vec3_generic, 0, sp)
331da177e4SLinus Torvalds	.set	push
341da177e4SLinus Torvalds	.set	noat
351da177e4SLinus Torvalds	mfc0	k1, CP0_CAUSE
361da177e4SLinus Torvalds	andi	k1, k1, 0x7c
37875d43e7SRalf Baechle#ifdef CONFIG_64BIT
381da177e4SLinus Torvalds	dsll	k1, k1, 1
391da177e4SLinus Torvalds#endif
401da177e4SLinus Torvalds	PTR_L	k0, exception_handlers(k1)
411da177e4SLinus Torvalds	jr	k0
421da177e4SLinus Torvalds	.set	pop
431da177e4SLinus Torvalds	END(except_vec3_generic)
441da177e4SLinus Torvalds
451da177e4SLinus Torvalds/*
461da177e4SLinus Torvalds * General exception handler for CPUs with virtual coherency exception.
471da177e4SLinus Torvalds *
481da177e4SLinus Torvalds * Be careful when changing this, it has to be at most 256 (as a special
491da177e4SLinus Torvalds * exception) bytes to fit into space reserved for the exception handler.
501da177e4SLinus Torvalds */
511da177e4SLinus TorvaldsNESTED(except_vec3_r4000, 0, sp)
521da177e4SLinus Torvalds	.set	push
53a809d460SRalf Baechle	.set	arch=r4000
541da177e4SLinus Torvalds	.set	noat
551da177e4SLinus Torvalds	mfc0	k1, CP0_CAUSE
561da177e4SLinus Torvalds	li	k0, 31<<2
571da177e4SLinus Torvalds	andi	k1, k1, 0x7c
581da177e4SLinus Torvalds	.set	push
591da177e4SLinus Torvalds	.set	noreorder
601da177e4SLinus Torvalds	.set	nomacro
611da177e4SLinus Torvalds	beq	k1, k0, handle_vced
621da177e4SLinus Torvalds	 li	k0, 14<<2
631da177e4SLinus Torvalds	beq	k1, k0, handle_vcei
64875d43e7SRalf Baechle#ifdef CONFIG_64BIT
651da177e4SLinus Torvalds	 dsll	k1, k1, 1
661da177e4SLinus Torvalds#endif
671da177e4SLinus Torvalds	.set	pop
681da177e4SLinus Torvalds	PTR_L	k0, exception_handlers(k1)
691da177e4SLinus Torvalds	jr	k0
701da177e4SLinus Torvalds
711da177e4SLinus Torvalds	/*
721da177e4SLinus Torvalds	 * Big shit, we now may have two dirty primary cache lines for the same
7369903d65SThiemo Seufer	 * physical address.  We can safely invalidate the line pointed to by
741da177e4SLinus Torvalds	 * c0_badvaddr because after return from this exception handler the
751da177e4SLinus Torvalds	 * load / store will be re-executed.
761da177e4SLinus Torvalds	 */
771da177e4SLinus Torvaldshandle_vced:
7869903d65SThiemo Seufer	MFC0	k0, CP0_BADVADDR
791da177e4SLinus Torvalds	li	k1, -4					# Is this ...
801da177e4SLinus Torvalds	and	k0, k1					# ... really needed?
811da177e4SLinus Torvalds	mtc0	zero, CP0_TAGLO
821da177e4SLinus Torvalds	cache	Index_Store_Tag_D, (k0)
831da177e4SLinus Torvalds	cache	Hit_Writeback_Inv_SD, (k0)
841da177e4SLinus Torvalds#ifdef CONFIG_PROC_FS
851da177e4SLinus Torvalds	PTR_LA	k0, vced_count
861da177e4SLinus Torvalds	lw	k1, (k0)
871da177e4SLinus Torvalds	addiu	k1, 1
881da177e4SLinus Torvalds	sw	k1, (k0)
891da177e4SLinus Torvalds#endif
901da177e4SLinus Torvalds	eret
911da177e4SLinus Torvalds
921da177e4SLinus Torvaldshandle_vcei:
931da177e4SLinus Torvalds	MFC0	k0, CP0_BADVADDR
941da177e4SLinus Torvalds	cache	Hit_Writeback_Inv_SD, (k0)		# also cleans pi
951da177e4SLinus Torvalds#ifdef CONFIG_PROC_FS
961da177e4SLinus Torvalds	PTR_LA	k0, vcei_count
971da177e4SLinus Torvalds	lw	k1, (k0)
981da177e4SLinus Torvalds	addiu	k1, 1
991da177e4SLinus Torvalds	sw	k1, (k0)
1001da177e4SLinus Torvalds#endif
1011da177e4SLinus Torvalds	eret
1021da177e4SLinus Torvalds	.set	pop
1031da177e4SLinus Torvalds	END(except_vec3_r4000)
1041da177e4SLinus Torvalds
105e4ac58afSRalf Baechle	__FINIT
106e4ac58afSRalf Baechle
107c65a5480SAtsushi Nemoto	.align	5	/* 32 byte rollback region */
108087d990bSRalf BaechleLEAF(__r4k_wait)
109c65a5480SAtsushi Nemoto	.set	push
110c65a5480SAtsushi Nemoto	.set	noreorder
111c65a5480SAtsushi Nemoto	/* start of rollback region */
112c65a5480SAtsushi Nemoto	LONG_L	t0, TI_FLAGS($28)
113c65a5480SAtsushi Nemoto	nop
114c65a5480SAtsushi Nemoto	andi	t0, _TIF_NEED_RESCHED
115c65a5480SAtsushi Nemoto	bnez	t0, 1f
116c65a5480SAtsushi Nemoto	 nop
117c65a5480SAtsushi Nemoto	nop
118c65a5480SAtsushi Nemoto	nop
1192a0b24f5SSteven J. Hill#ifdef CONFIG_CPU_MICROMIPS
1202a0b24f5SSteven J. Hill	nop
1212a0b24f5SSteven J. Hill	nop
1222a0b24f5SSteven J. Hill	nop
1232a0b24f5SSteven J. Hill	nop
1242a0b24f5SSteven J. Hill#endif
125938c1282SMarkos Chandras	.set	MIPS_ISA_ARCH_LEVEL_RAW
126c65a5480SAtsushi Nemoto	wait
127c65a5480SAtsushi Nemoto	/* end of rollback region (the region size must be power of two) */
128c65a5480SAtsushi Nemoto1:
129c65a5480SAtsushi Nemoto	jr	ra
1302a0b24f5SSteven J. Hill	 nop
1312a0b24f5SSteven J. Hill	.set	pop
132087d990bSRalf Baechle	END(__r4k_wait)
133c65a5480SAtsushi Nemoto
134c65a5480SAtsushi Nemoto	.macro	BUILD_ROLLBACK_PROLOGUE handler
135c65a5480SAtsushi Nemoto	FEXPORT(rollback_\handler)
136c65a5480SAtsushi Nemoto	.set	push
137c65a5480SAtsushi Nemoto	.set	noat
138c65a5480SAtsushi Nemoto	MFC0	k0, CP0_EPC
139087d990bSRalf Baechle	PTR_LA	k1, __r4k_wait
140c65a5480SAtsushi Nemoto	ori	k0, 0x1f	/* 32 byte rollback region */
141c65a5480SAtsushi Nemoto	xori	k0, 0x1f
1421eefcbc8SPaul Burton	bne	k0, k1, \handler
143c65a5480SAtsushi Nemoto	MTC0	k0, CP0_EPC
144c65a5480SAtsushi Nemoto	.set pop
145c65a5480SAtsushi Nemoto	.endm
146c65a5480SAtsushi Nemoto
147e4ac58afSRalf Baechle	.align	5
148c65a5480SAtsushi NemotoBUILD_ROLLBACK_PROLOGUE handle_int
149e4ac58afSRalf BaechleNESTED(handle_int, PT_SIZE, sp)
150866b6a89SCorey Minyard	.cfi_signal_frame
151fe99f1b1SChris Dearman#ifdef CONFIG_TRACE_IRQFLAGS
152fe99f1b1SChris Dearman	/*
153fe99f1b1SChris Dearman	 * Check to see if the interrupted code has just disabled
154fe99f1b1SChris Dearman	 * interrupts and ignore this interrupt for now if so.
155fe99f1b1SChris Dearman	 *
156fe99f1b1SChris Dearman	 * local_irq_disable() disables interrupts and then calls
157fe99f1b1SChris Dearman	 * trace_hardirqs_off() to track the state. If an interrupt is taken
158fe99f1b1SChris Dearman	 * after interrupts are disabled but before the state is updated
159fe99f1b1SChris Dearman	 * it will appear to restore_all that it is incorrectly returning with
160fe99f1b1SChris Dearman	 * interrupts disabled
161fe99f1b1SChris Dearman	 */
162fe99f1b1SChris Dearman	.set	push
163fe99f1b1SChris Dearman	.set	noat
164fe99f1b1SChris Dearman	mfc0	k0, CP0_STATUS
165455481fcSThomas Bogendoerfer#if defined(CONFIG_CPU_R3000)
166fe99f1b1SChris Dearman	and	k0, ST0_IEP
167fe99f1b1SChris Dearman	bnez	k0, 1f
168fe99f1b1SChris Dearman
169c6563e85SAtsushi Nemoto	mfc0	k0, CP0_EPC
170fe99f1b1SChris Dearman	.set	noreorder
171fe99f1b1SChris Dearman	j	k0
172fe99f1b1SChris Dearman	 rfe
173fe99f1b1SChris Dearman#else
174fe99f1b1SChris Dearman	and	k0, ST0_IE
175fe99f1b1SChris Dearman	bnez	k0, 1f
176fe99f1b1SChris Dearman
177fe99f1b1SChris Dearman	eret
178fe99f1b1SChris Dearman#endif
179fe99f1b1SChris Dearman1:
180fe99f1b1SChris Dearman	.set pop
181fe99f1b1SChris Dearman#endif
182866b6a89SCorey Minyard	SAVE_ALL docfi=1
183e4ac58afSRalf Baechle	CLI
184192ef366SRalf Baechle	TRACE_IRQS_OFF
185e4ac58afSRalf Baechle
186937a8015SRalf Baechle	LONG_L	s0, TI_REGS($28)
187937a8015SRalf Baechle	LONG_S	sp, TI_REGS($28)
188dda45f70SMatt Redfearn
189dda45f70SMatt Redfearn	/*
190dda45f70SMatt Redfearn	 * SAVE_ALL ensures we are using a valid kernel stack for the thread.
191dda45f70SMatt Redfearn	 * Check if we are already using the IRQ stack.
192dda45f70SMatt Redfearn	 */
193dda45f70SMatt Redfearn	move	s1, sp # Preserve the sp
194dda45f70SMatt Redfearn
195dda45f70SMatt Redfearn	/* Get IRQ stack for this CPU */
196dda45f70SMatt Redfearn	ASM_CPUID_MFC0	k0, ASM_SMP_CPUID_REG
197dda45f70SMatt Redfearn#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
198dda45f70SMatt Redfearn	lui	k1, %hi(irq_stack)
199dda45f70SMatt Redfearn#else
200dda45f70SMatt Redfearn	lui	k1, %highest(irq_stack)
201dda45f70SMatt Redfearn	daddiu	k1, %higher(irq_stack)
202dda45f70SMatt Redfearn	dsll	k1, 16
203dda45f70SMatt Redfearn	daddiu	k1, %hi(irq_stack)
204dda45f70SMatt Redfearn	dsll	k1, 16
205dda45f70SMatt Redfearn#endif
206dda45f70SMatt Redfearn	LONG_SRL	k0, SMP_CPUID_PTRSHIFT
207dda45f70SMatt Redfearn	LONG_ADDU	k1, k0
208dda45f70SMatt Redfearn	LONG_L	t0, %lo(irq_stack)(k1)
209dda45f70SMatt Redfearn
210dda45f70SMatt Redfearn	# Check if already on IRQ stack
211dda45f70SMatt Redfearn	PTR_LI	t1, ~(_THREAD_SIZE-1)
212dda45f70SMatt Redfearn	and	t1, t1, sp
213dda45f70SMatt Redfearn	beq	t0, t1, 2f
214dda45f70SMatt Redfearn
215dda45f70SMatt Redfearn	/* Switch to IRQ stack */
216db8466c5SMatt Redfearn	li	t1, _IRQ_STACK_START
217dda45f70SMatt Redfearn	PTR_ADD sp, t0, t1
218dda45f70SMatt Redfearn
219db8466c5SMatt Redfearn	/* Save task's sp on IRQ stack so that unwinding can follow it */
220db8466c5SMatt Redfearn	LONG_S	s1, 0(sp)
221dda45f70SMatt Redfearn2:
222dda45f70SMatt Redfearn	jal	plat_irq_dispatch
223dda45f70SMatt Redfearn
224dda45f70SMatt Redfearn	/* Restore sp */
225dda45f70SMatt Redfearn	move	sp, s1
226dda45f70SMatt Redfearn
227dda45f70SMatt Redfearn	j	ret_from_irq
2282a0b24f5SSteven J. Hill#ifdef CONFIG_CPU_MICROMIPS
2292a0b24f5SSteven J. Hill	nop
2302a0b24f5SSteven J. Hill#endif
231e4ac58afSRalf Baechle	END(handle_int)
232e4ac58afSRalf Baechle
233e4ac58afSRalf Baechle	__INIT
234e4ac58afSRalf Baechle
2351da177e4SLinus Torvalds/*
2361da177e4SLinus Torvalds * Special interrupt vector for MIPS64 ISA & embedded MIPS processors.
2371da177e4SLinus Torvalds * This is a dedicated interrupt exception vector which reduces the
2381da177e4SLinus Torvalds * interrupt processing overhead.  The jump instruction will be replaced
2391da177e4SLinus Torvalds * at the initialization time.
2401da177e4SLinus Torvalds *
2411da177e4SLinus Torvalds * Be careful when changing this, it has to be at most 128 bytes
2421da177e4SLinus Torvalds * to fit into space reserved for the exception handler.
2431da177e4SLinus Torvalds */
2441da177e4SLinus TorvaldsNESTED(except_vec4, 0, sp)
2451da177e4SLinus Torvalds1:	j	1b			/* Dummy, will be replaced */
2461da177e4SLinus Torvalds	END(except_vec4)
2471da177e4SLinus Torvalds
2481da177e4SLinus Torvalds/*
2491da177e4SLinus Torvalds * EJTAG debug exception handler.
2501da177e4SLinus Torvalds * The EJTAG debug exception entry point is 0xbfc00480, which
2512a0b24f5SSteven J. Hill * normally is in the boot PROM, so the boot PROM must do an
2521da177e4SLinus Torvalds * unconditional jump to this vector.
2531da177e4SLinus Torvalds */
2541da177e4SLinus TorvaldsNESTED(except_vec_ejtag_debug, 0, sp)
2551da177e4SLinus Torvalds	j	ejtag_debug_handler
2562a0b24f5SSteven J. Hill#ifdef CONFIG_CPU_MICROMIPS
2572a0b24f5SSteven J. Hill	 nop
2582a0b24f5SSteven J. Hill#endif
2591da177e4SLinus Torvalds	END(except_vec_ejtag_debug)
2601da177e4SLinus Torvalds
2611da177e4SLinus Torvalds	__FINIT
2621da177e4SLinus Torvalds
2631da177e4SLinus Torvalds/*
264e01402b1SRalf Baechle * Vectored interrupt handler.
265e01402b1SRalf Baechle * This prototype is copied to ebase + n*IntCtl.VS and patched
266e01402b1SRalf Baechle * to invoke the handler
267e01402b1SRalf Baechle */
268c65a5480SAtsushi NemotoBUILD_ROLLBACK_PROLOGUE except_vec_vi
269e01402b1SRalf BaechleNESTED(except_vec_vi, 0, sp)
270866b6a89SCorey Minyard	SAVE_SOME docfi=1
271866b6a89SCorey Minyard	SAVE_AT docfi=1
272e01402b1SRalf Baechle	.set	push
273e01402b1SRalf Baechle	.set	noreorder
2742a0b24f5SSteven J. Hill	PTR_LA	v1, except_vec_vi_handler
2757df42461SRalf BaechleFEXPORT(except_vec_vi_lui)
276e01402b1SRalf Baechle	lui	v0, 0		/* Patched */
2772a0b24f5SSteven J. Hill	jr	v1
2787df42461SRalf BaechleFEXPORT(except_vec_vi_ori)
279e01402b1SRalf Baechle	 ori	v0, 0		/* Patched */
280e01402b1SRalf Baechle	.set	pop
281e01402b1SRalf Baechle	END(except_vec_vi)
282e01402b1SRalf BaechleEXPORT(except_vec_vi_end)
283e01402b1SRalf Baechle
284e01402b1SRalf Baechle/*
285e01402b1SRalf Baechle * Common Vectored Interrupt code
286e01402b1SRalf Baechle * Complete the register saves and invoke the handler which is passed in $v0
287e01402b1SRalf Baechle */
288e01402b1SRalf BaechleNESTED(except_vec_vi_handler, 0, sp)
289e01402b1SRalf Baechle	SAVE_TEMP
290e01402b1SRalf Baechle	SAVE_STATIC
291e01402b1SRalf Baechle	CLI
2928c364435SRalf Baechle#ifdef CONFIG_TRACE_IRQFLAGS
2938c364435SRalf Baechle	move	s0, v0
294192ef366SRalf Baechle	TRACE_IRQS_OFF
2958c364435SRalf Baechle	move	v0, s0
2968c364435SRalf Baechle#endif
297937a8015SRalf Baechle
298937a8015SRalf Baechle	LONG_L	s0, TI_REGS($28)
299937a8015SRalf Baechle	LONG_S	sp, TI_REGS($28)
300dda45f70SMatt Redfearn
301dda45f70SMatt Redfearn	/*
302dda45f70SMatt Redfearn	 * SAVE_ALL ensures we are using a valid kernel stack for the thread.
303dda45f70SMatt Redfearn	 * Check if we are already using the IRQ stack.
304dda45f70SMatt Redfearn	 */
305dda45f70SMatt Redfearn	move	s1, sp # Preserve the sp
306dda45f70SMatt Redfearn
307dda45f70SMatt Redfearn	/* Get IRQ stack for this CPU */
308dda45f70SMatt Redfearn	ASM_CPUID_MFC0	k0, ASM_SMP_CPUID_REG
309dda45f70SMatt Redfearn#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
310dda45f70SMatt Redfearn	lui	k1, %hi(irq_stack)
311dda45f70SMatt Redfearn#else
312dda45f70SMatt Redfearn	lui	k1, %highest(irq_stack)
313dda45f70SMatt Redfearn	daddiu	k1, %higher(irq_stack)
314dda45f70SMatt Redfearn	dsll	k1, 16
315dda45f70SMatt Redfearn	daddiu	k1, %hi(irq_stack)
316dda45f70SMatt Redfearn	dsll	k1, 16
317dda45f70SMatt Redfearn#endif
318dda45f70SMatt Redfearn	LONG_SRL	k0, SMP_CPUID_PTRSHIFT
319dda45f70SMatt Redfearn	LONG_ADDU	k1, k0
320dda45f70SMatt Redfearn	LONG_L	t0, %lo(irq_stack)(k1)
321dda45f70SMatt Redfearn
322dda45f70SMatt Redfearn	# Check if already on IRQ stack
323dda45f70SMatt Redfearn	PTR_LI	t1, ~(_THREAD_SIZE-1)
324dda45f70SMatt Redfearn	and	t1, t1, sp
325dda45f70SMatt Redfearn	beq	t0, t1, 2f
326dda45f70SMatt Redfearn
327dda45f70SMatt Redfearn	/* Switch to IRQ stack */
328db8466c5SMatt Redfearn	li	t1, _IRQ_STACK_START
329dda45f70SMatt Redfearn	PTR_ADD sp, t0, t1
330dda45f70SMatt Redfearn
331db8466c5SMatt Redfearn	/* Save task's sp on IRQ stack so that unwinding can follow it */
332db8466c5SMatt Redfearn	LONG_S	s1, 0(sp)
333dda45f70SMatt Redfearn2:
334c25f8064SMatt Redfearn	jalr	v0
335dda45f70SMatt Redfearn
336dda45f70SMatt Redfearn	/* Restore sp */
337dda45f70SMatt Redfearn	move	sp, s1
338dda45f70SMatt Redfearn
339dda45f70SMatt Redfearn	j	ret_from_irq
340e01402b1SRalf Baechle	END(except_vec_vi_handler)
341e01402b1SRalf Baechle
342e01402b1SRalf Baechle/*
3431da177e4SLinus Torvalds * EJTAG debug exception handler.
3441da177e4SLinus Torvalds */
3451da177e4SLinus TorvaldsNESTED(ejtag_debug_handler, PT_SIZE, sp)
3461da177e4SLinus Torvalds	.set	push
3471da177e4SLinus Torvalds	.set	noat
3481da177e4SLinus Torvalds	MTC0	k0, CP0_DESAVE
3491da177e4SLinus Torvalds	mfc0	k0, CP0_DEBUG
3501da177e4SLinus Torvalds
351ee54d379STiezhu Yang	andi	k0, k0, MIPS_DEBUG_DBP	# Check for SDBBP.
352ee54d379STiezhu Yang	beqz	k0, ejtag_return
3531da177e4SLinus Torvalds
354c8bf3805SHeiher#ifdef CONFIG_SMP
355c8bf3805SHeiher1:	PTR_LA	k0, ejtag_debug_buffer_spinlock
35612dbb04fSPaul Burton	__SYNC(full, loongson3_war)
3574dee90d7SPaul Burton2:	ll	k0, 0(k0)
3584dee90d7SPaul Burton	bnez	k0, 2b
359c8bf3805SHeiher	PTR_LA	k0, ejtag_debug_buffer_spinlock
360c8bf3805SHeiher	sc	k0, 0(k0)
361c8bf3805SHeiher	beqz	k0, 1b
362c8bf3805SHeiher# ifdef CONFIG_WEAK_REORDERING_BEYOND_LLSC
363c8bf3805SHeiher	sync
364c8bf3805SHeiher# endif
365c8bf3805SHeiher
3661da177e4SLinus Torvalds	PTR_LA	k0, ejtag_debug_buffer
3671da177e4SLinus Torvalds	LONG_S	k1, 0(k0)
368c8bf3805SHeiher
369c8bf3805SHeiher	ASM_CPUID_MFC0 k1, ASM_SMP_CPUID_REG
370c8bf3805SHeiher	PTR_SRL	k1, SMP_CPUID_PTRSHIFT
371c8bf3805SHeiher	PTR_SLL	k1, LONGLOG
372c8bf3805SHeiher	PTR_LA	k0, ejtag_debug_buffer_per_cpu
373c8bf3805SHeiher	PTR_ADDU k0, k1
374c8bf3805SHeiher
375c8bf3805SHeiher	PTR_LA	k1, ejtag_debug_buffer
376c8bf3805SHeiher	LONG_L	k1, 0(k1)
377c8bf3805SHeiher	LONG_S	k1, 0(k0)
378c8bf3805SHeiher
379c8bf3805SHeiher	PTR_LA	k0, ejtag_debug_buffer_spinlock
380c8bf3805SHeiher	sw	zero, 0(k0)
381c8bf3805SHeiher#else
382c8bf3805SHeiher	PTR_LA	k0, ejtag_debug_buffer
383c8bf3805SHeiher	LONG_S	k1, 0(k0)
384c8bf3805SHeiher#endif
385c8bf3805SHeiher
3861da177e4SLinus Torvalds	SAVE_ALL
3871da177e4SLinus Torvalds	move	a0, sp
3881da177e4SLinus Torvalds	jal	ejtag_exception_handler
3891da177e4SLinus Torvalds	RESTORE_ALL
390c8bf3805SHeiher
391c8bf3805SHeiher#ifdef CONFIG_SMP
392c8bf3805SHeiher	ASM_CPUID_MFC0 k1, ASM_SMP_CPUID_REG
393c8bf3805SHeiher	PTR_SRL	k1, SMP_CPUID_PTRSHIFT
394c8bf3805SHeiher	PTR_SLL	k1, LONGLOG
395c8bf3805SHeiher	PTR_LA	k0, ejtag_debug_buffer_per_cpu
396c8bf3805SHeiher	PTR_ADDU k0, k1
397c8bf3805SHeiher	LONG_L	k1, 0(k0)
398c8bf3805SHeiher#else
3991da177e4SLinus Torvalds	PTR_LA	k0, ejtag_debug_buffer
4001da177e4SLinus Torvalds	LONG_L	k1, 0(k0)
401c8bf3805SHeiher#endif
4021da177e4SLinus Torvalds
4031da177e4SLinus Torvaldsejtag_return:
404c8bf3805SHeiher	back_to_back_c0_hazard
4051da177e4SLinus Torvalds	MFC0	k0, CP0_DESAVE
4061da177e4SLinus Torvalds	.set	mips32
4071da177e4SLinus Torvalds	deret
4081da177e4SLinus Torvalds	.set	pop
4091da177e4SLinus Torvalds	END(ejtag_debug_handler)
4101da177e4SLinus Torvalds
4111da177e4SLinus Torvalds/*
4121da177e4SLinus Torvalds * This buffer is reserved for the use of the EJTAG debug
4131da177e4SLinus Torvalds * handler.
4141da177e4SLinus Torvalds */
4151da177e4SLinus Torvalds	.data
4161da177e4SLinus TorvaldsEXPORT(ejtag_debug_buffer)
4171da177e4SLinus Torvalds	.fill	LONGSIZE
418c8bf3805SHeiher#ifdef CONFIG_SMP
419c8bf3805SHeiherEXPORT(ejtag_debug_buffer_spinlock)
420c8bf3805SHeiher	.fill	LONGSIZE
421c8bf3805SHeiherEXPORT(ejtag_debug_buffer_per_cpu)
422c8bf3805SHeiher	.fill	LONGSIZE * NR_CPUS
423c8bf3805SHeiher#endif
4241da177e4SLinus Torvalds	.previous
4251da177e4SLinus Torvalds
4261da177e4SLinus Torvalds	__INIT
4271da177e4SLinus Torvalds
4281da177e4SLinus Torvalds/*
4291da177e4SLinus Torvalds * NMI debug exception handler for MIPS reference boards.
4301da177e4SLinus Torvalds * The NMI debug exception entry point is 0xbfc00000, which
4311da177e4SLinus Torvalds * normally is in the boot PROM, so the boot PROM must do a
4321da177e4SLinus Torvalds * unconditional jump to this vector.
4331da177e4SLinus Torvalds */
4341da177e4SLinus TorvaldsNESTED(except_vec_nmi, 0, sp)
4351da177e4SLinus Torvalds	j	nmi_handler
4362a0b24f5SSteven J. Hill#ifdef CONFIG_CPU_MICROMIPS
4372a0b24f5SSteven J. Hill	 nop
4382a0b24f5SSteven J. Hill#endif
4391da177e4SLinus Torvalds	END(except_vec_nmi)
4401da177e4SLinus Torvalds
4411da177e4SLinus Torvalds	__FINIT
4421da177e4SLinus Torvalds
4431da177e4SLinus TorvaldsNESTED(nmi_handler, PT_SIZE, sp)
444866b6a89SCorey Minyard	.cfi_signal_frame
4451da177e4SLinus Torvalds	.set	push
4461da177e4SLinus Torvalds	.set	noat
44783e4da1eSLeonid Yegoshin	/*
44883e4da1eSLeonid Yegoshin	 * Clear ERL - restore segment mapping
44983e4da1eSLeonid Yegoshin	 * Clear BEV - required for page fault exception handler to work
45083e4da1eSLeonid Yegoshin	 */
45183e4da1eSLeonid Yegoshin	mfc0	k0, CP0_STATUS
45283e4da1eSLeonid Yegoshin	ori	k0, k0, ST0_EXL
45383e4da1eSLeonid Yegoshin	li	k1, ~(ST0_BEV | ST0_ERL)
45483e4da1eSLeonid Yegoshin	and	k0, k0, k1
45583e4da1eSLeonid Yegoshin	mtc0	k0, CP0_STATUS
45683e4da1eSLeonid Yegoshin	_ehb
4571da177e4SLinus Torvalds	SAVE_ALL
4581da177e4SLinus Torvalds	move	a0, sp
4591da177e4SLinus Torvalds	jal	nmi_exception_handler
46083e4da1eSLeonid Yegoshin	/* nmi_exception_handler never returns */
4611da177e4SLinus Torvalds	.set	pop
4621da177e4SLinus Torvalds	END(nmi_handler)
4631da177e4SLinus Torvalds
4641da177e4SLinus Torvalds	.macro	__build_clear_none
4651da177e4SLinus Torvalds	.endm
4661da177e4SLinus Torvalds
4671da177e4SLinus Torvalds	.macro	__build_clear_sti
468192ef366SRalf Baechle	TRACE_IRQS_ON
4691da177e4SLinus Torvalds	STI
4701da177e4SLinus Torvalds	.endm
4711da177e4SLinus Torvalds
4721da177e4SLinus Torvalds	.macro	__build_clear_cli
4731da177e4SLinus Torvalds	CLI
474192ef366SRalf Baechle	TRACE_IRQS_OFF
4751da177e4SLinus Torvalds	.endm
4761da177e4SLinus Torvalds
4771da177e4SLinus Torvalds	.macro	__build_clear_fpe
47831e1b3efSYuanJunQing	CLI
47931e1b3efSYuanJunQing	TRACE_IRQS_OFF
48025c30003SDavid Daney	.set	push
48125c30003SDavid Daney	/* gas fails to assemble cfc1 for some archs (octeon).*/ \
48225c30003SDavid Daney	.set	mips1
483*80a20d2fSNathan Chancellor	.set	hardfloat
4841da177e4SLinus Torvalds	cfc1	a1, fcr31
48525c30003SDavid Daney	.set	pop
4861da177e4SLinus Torvalds	.endm
4871da177e4SLinus Torvalds
488091be550SPaul Burton	.macro	__build_clear_msa_fpe
48964bedffeSJames Hogan	CLI
49064bedffeSJames Hogan	TRACE_IRQS_OFF
49131e1b3efSYuanJunQing	_cfcmsa	a1, MSA_CSR
492091be550SPaul Burton	.endm
493091be550SPaul Burton
4941da177e4SLinus Torvalds	.macro	__build_clear_ade
4951da177e4SLinus Torvalds	MFC0	t0, CP0_BADVADDR
4961da177e4SLinus Torvalds	PTR_S	t0, PT_BVADDR(sp)
4971da177e4SLinus Torvalds	KMODE
4981da177e4SLinus Torvalds	.endm
4991da177e4SLinus Torvalds
500bc6e8dc1SWANG Xuerui	.macro __build_clear_gsexc
501bc6e8dc1SWANG Xuerui	.set	push
502bc6e8dc1SWANG Xuerui	/*
503bc6e8dc1SWANG Xuerui	 * We need to specify a selector to access the CP0.Diag1 (GSCause)
504bc6e8dc1SWANG Xuerui	 * register. All GSExc-equipped processors have MIPS32.
505bc6e8dc1SWANG Xuerui	 */
506bc6e8dc1SWANG Xuerui	.set	mips32
507bc6e8dc1SWANG Xuerui	mfc0	a1, CP0_DIAGNOSTIC1
508bc6e8dc1SWANG Xuerui	.set	pop
509bc6e8dc1SWANG Xuerui	TRACE_IRQS_ON
510bc6e8dc1SWANG Xuerui	STI
511bc6e8dc1SWANG Xuerui	.endm
512bc6e8dc1SWANG Xuerui
5131da177e4SLinus Torvalds	.macro	__BUILD_silent exception
5141da177e4SLinus Torvalds	.endm
5151da177e4SLinus Torvalds
516da706e50SHuacai Chen	/* Gas tries to parse the ASM_PRINT argument as a string containing
5171da177e4SLinus Torvalds	   string escapes and emits bogus warnings if it believes to
5181da177e4SLinus Torvalds	   recognize an unknown escape code.  So make the arguments
5191da177e4SLinus Torvalds	   start with an n and gas will believe \n is ok ...  */
5201da177e4SLinus Torvalds	.macro	__BUILD_verbose nexception
5211da177e4SLinus Torvalds	LONG_L	a1, PT_EPC(sp)
522766160c2SYoichi Yuasa#ifdef CONFIG_32BIT
523da706e50SHuacai Chen	ASM_PRINT("Got \nexception at %08lx\012")
5241da177e4SLinus Torvalds#endif
525766160c2SYoichi Yuasa#ifdef CONFIG_64BIT
526da706e50SHuacai Chen	ASM_PRINT("Got \nexception at %016lx\012")
5271da177e4SLinus Torvalds#endif
5281da177e4SLinus Torvalds	.endm
5291da177e4SLinus Torvalds
5301da177e4SLinus Torvalds	.macro	__BUILD_count exception
5311da177e4SLinus Torvalds	LONG_L	t0,exception_count_\exception
5321da177e4SLinus Torvalds	LONG_ADDIU	t0, 1
5331da177e4SLinus Torvalds	LONG_S	t0,exception_count_\exception
5341da177e4SLinus Torvalds	.comm	exception_count\exception, 8, 8
5351da177e4SLinus Torvalds	.endm
5361da177e4SLinus Torvalds
5371da177e4SLinus Torvalds	.macro	__BUILD_HANDLER exception handler clear verbose ext
5381da177e4SLinus Torvalds	.align	5
5391da177e4SLinus Torvalds	NESTED(handle_\exception, PT_SIZE, sp)
540866b6a89SCorey Minyard	.cfi_signal_frame
5411da177e4SLinus Torvalds	.set	noat
5421da177e4SLinus Torvalds	SAVE_ALL
5431da177e4SLinus Torvalds	FEXPORT(handle_\exception\ext)
544158d3b2aSRalf Baechle	__build_clear_\clear
5451da177e4SLinus Torvalds	.set	at
5461da177e4SLinus Torvalds	__BUILD_\verbose \exception
5471da177e4SLinus Torvalds	move	a0, sp
548866b6a89SCorey Minyard	jal	do_\handler
549866b6a89SCorey Minyard	j	ret_from_exception
5501da177e4SLinus Torvalds	END(handle_\exception)
5511da177e4SLinus Torvalds	.endm
5521da177e4SLinus Torvalds
5531da177e4SLinus Torvalds	.macro	BUILD_HANDLER exception handler clear verbose
5541da177e4SLinus Torvalds	__BUILD_HANDLER \exception \handler \clear \verbose _int
5551da177e4SLinus Torvalds	.endm
5561da177e4SLinus Torvalds
5571da177e4SLinus Torvalds	BUILD_HANDLER adel ade ade silent		/* #4  */
5581da177e4SLinus Torvalds	BUILD_HANDLER ades ade ade silent		/* #5  */
5591da177e4SLinus Torvalds	BUILD_HANDLER ibe be cli silent			/* #6  */
5601da177e4SLinus Torvalds	BUILD_HANDLER dbe be cli silent			/* #7  */
5611da177e4SLinus Torvalds	BUILD_HANDLER bp bp sti silent			/* #9  */
5621da177e4SLinus Torvalds	BUILD_HANDLER ri ri sti silent			/* #10 */
5631da177e4SLinus Torvalds	BUILD_HANDLER cpu cpu sti silent		/* #11 */
5641da177e4SLinus Torvalds	BUILD_HANDLER ov ov sti silent			/* #12 */
5651da177e4SLinus Torvalds	BUILD_HANDLER tr tr sti silent			/* #13 */
566091be550SPaul Burton	BUILD_HANDLER msa_fpe msa_fpe msa_fpe silent	/* #14 */
5675328f742SPaul Burton#ifdef CONFIG_MIPS_FP_SUPPORT
5681da177e4SLinus Torvalds	BUILD_HANDLER fpe fpe fpe silent		/* #15 */
5695328f742SPaul Burton#endif
57075b5b5e0SLeonid Yegoshin	BUILD_HANDLER ftlb ftlb none silent		/* #16 */
571bc6e8dc1SWANG Xuerui	BUILD_HANDLER gsexc gsexc gsexc silent		/* #16 */
5721db1af84SPaul Burton	BUILD_HANDLER msa msa sti silent		/* #21 */
5731da177e4SLinus Torvalds	BUILD_HANDLER mdmx mdmx sti silent		/* #22 */
574b67b2b70SDavid Daney#ifdef	CONFIG_HARDWARE_WATCHPOINTS
5758bc6d05bSDavid Daney	/*
5768bc6d05bSDavid Daney	 * For watch, interrupts will be enabled after the watch
5778bc6d05bSDavid Daney	 * registers are read.
5788bc6d05bSDavid Daney	 */
5798bc6d05bSDavid Daney	BUILD_HANDLER watch watch cli silent		/* #23 */
580b67b2b70SDavid Daney#else
5811da177e4SLinus Torvalds	BUILD_HANDLER watch watch sti verbose		/* #23 */
582b67b2b70SDavid Daney#endif
5831da177e4SLinus Torvalds	BUILD_HANDLER mcheck mcheck cli verbose		/* #24 */
584e35a5e35SChris Dearman	BUILD_HANDLER mt mt sti silent			/* #25 */
585e50c0a8fSRalf Baechle	BUILD_HANDLER dsp dsp sti silent		/* #26 */
5861da177e4SLinus Torvalds	BUILD_HANDLER reserved reserved sti verbose	/* others */
5871da177e4SLinus Torvalds
5885b10496bSAtsushi Nemoto	.align	5
5895a341331SHuacai Chen	LEAF(handle_ri_rdhwr_tlbp)
5905b10496bSAtsushi Nemoto	.set	push
5915b10496bSAtsushi Nemoto	.set	noat
5925b10496bSAtsushi Nemoto	.set	noreorder
5935b10496bSAtsushi Nemoto	/* check if TLB contains a entry for EPC */
5945b10496bSAtsushi Nemoto	MFC0	k1, CP0_ENTRYHI
5952db003a5SPaul Burton	andi	k1, MIPS_ENTRYHI_ASID | MIPS_ENTRYHI_ASIDX
5965b10496bSAtsushi Nemoto	MFC0	k0, CP0_EPC
597bef9ae3dSRalf Baechle	PTR_SRL	k0, _PAGE_SHIFT + 1
598bef9ae3dSRalf Baechle	PTR_SLL	k0, _PAGE_SHIFT + 1
5995b10496bSAtsushi Nemoto	or	k1, k0
6005b10496bSAtsushi Nemoto	MTC0	k1, CP0_ENTRYHI
6015b10496bSAtsushi Nemoto	mtc0_tlbw_hazard
6025b10496bSAtsushi Nemoto	tlbp
6035b10496bSAtsushi Nemoto	tlb_probe_hazard
6045b10496bSAtsushi Nemoto	mfc0	k1, CP0_INDEX
6055b10496bSAtsushi Nemoto	.set	pop
6065b10496bSAtsushi Nemoto	bltz	k1, handle_ri	/* slow path */
6075b10496bSAtsushi Nemoto	/* fall thru */
6085a341331SHuacai Chen	END(handle_ri_rdhwr_tlbp)
6095b10496bSAtsushi Nemoto
6105b10496bSAtsushi Nemoto	LEAF(handle_ri_rdhwr)
6115b10496bSAtsushi Nemoto	.set	push
6125b10496bSAtsushi Nemoto	.set	noat
6135b10496bSAtsushi Nemoto	.set	noreorder
6142a0b24f5SSteven J. Hill	/* MIPS32:    0x7c03e83b: rdhwr v1,$29 */
6152a0b24f5SSteven J. Hill	/* microMIPS: 0x007d6b3c: rdhwr v1,$29 */
6165b10496bSAtsushi Nemoto	MFC0	k1, CP0_EPC
6172a0b24f5SSteven J. Hill#if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS64_R2)
6182a0b24f5SSteven J. Hill	and	k0, k1, 1
6192a0b24f5SSteven J. Hill	beqz	k0, 1f
6202a0b24f5SSteven J. Hill	 xor	k1, k0
6212a0b24f5SSteven J. Hill	lhu	k0, (k1)
6222a0b24f5SSteven J. Hill	lhu	k1, 2(k1)
6232a0b24f5SSteven J. Hill	ins	k1, k0, 16, 16
6242a0b24f5SSteven J. Hill	lui	k0, 0x007d
6252a0b24f5SSteven J. Hill	b	docheck
6262a0b24f5SSteven J. Hill	 ori	k0, 0x6b3c
6272a0b24f5SSteven J. Hill1:
6285b10496bSAtsushi Nemoto	lui	k0, 0x7c03
6295b10496bSAtsushi Nemoto	lw	k1, (k1)
6305b10496bSAtsushi Nemoto	ori	k0, 0xe83b
6312a0b24f5SSteven J. Hill#else
6322a0b24f5SSteven J. Hill	andi	k0, k1, 1
6332a0b24f5SSteven J. Hill	bnez	k0, handle_ri
6342a0b24f5SSteven J. Hill	 lui	k0, 0x7c03
6352a0b24f5SSteven J. Hill	lw	k1, (k1)
6362a0b24f5SSteven J. Hill	ori	k0, 0xe83b
6372a0b24f5SSteven J. Hill#endif
6385b10496bSAtsushi Nemoto	.set	reorder
6392a0b24f5SSteven J. Hilldocheck:
6405b10496bSAtsushi Nemoto	bne	k0, k1, handle_ri	/* if not ours */
6412a0b24f5SSteven J. Hill
6422a0b24f5SSteven J. Hillisrdhwr:
6435b10496bSAtsushi Nemoto	/* The insn is rdhwr.  No need to check CAUSE.BD here. */
6445b10496bSAtsushi Nemoto	get_saved_sp	/* k1 := current_thread_info */
6455b10496bSAtsushi Nemoto	.set	noreorder
6465b10496bSAtsushi Nemoto	MFC0	k0, CP0_EPC
647455481fcSThomas Bogendoerfer#if defined(CONFIG_CPU_R3000)
6485b10496bSAtsushi Nemoto	ori	k1, _THREAD_MASK
6495b10496bSAtsushi Nemoto	xori	k1, _THREAD_MASK
6505b10496bSAtsushi Nemoto	LONG_L	v1, TI_TP_VALUE(k1)
6515b10496bSAtsushi Nemoto	LONG_ADDIU	k0, 4
6525b10496bSAtsushi Nemoto	jr	k0
6535b10496bSAtsushi Nemoto	 rfe
6545b10496bSAtsushi Nemoto#else
655619b6e18SMaciej W. Rozycki#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
6565b10496bSAtsushi Nemoto	LONG_ADDIU	k0, 4		/* stall on $k0 */
657619b6e18SMaciej W. Rozycki#else
658619b6e18SMaciej W. Rozycki	.set	at=v1
659619b6e18SMaciej W. Rozycki	LONG_ADDIU	k0, 4
660619b6e18SMaciej W. Rozycki	.set	noat
661619b6e18SMaciej W. Rozycki#endif
6625b10496bSAtsushi Nemoto	MTC0	k0, CP0_EPC
6635b10496bSAtsushi Nemoto	/* I hope three instructions between MTC0 and ERET are enough... */
6645b10496bSAtsushi Nemoto	ori	k1, _THREAD_MASK
6655b10496bSAtsushi Nemoto	xori	k1, _THREAD_MASK
6665b10496bSAtsushi Nemoto	LONG_L	v1, TI_TP_VALUE(k1)
667378ed6f0SPaul Burton	.set	push
668a809d460SRalf Baechle	.set	arch=r4000
6695b10496bSAtsushi Nemoto	eret
670378ed6f0SPaul Burton	.set	pop
6715b10496bSAtsushi Nemoto#endif
6725b10496bSAtsushi Nemoto	.set	pop
6735b10496bSAtsushi Nemoto	END(handle_ri_rdhwr)
6745b10496bSAtsushi Nemoto
675071d2f0bSPaul Burton#ifdef CONFIG_CPU_R4X00_BUGS64
6761da177e4SLinus Torvalds/* A temporary overflow handler used by check_daddi(). */
6771da177e4SLinus Torvalds
6781da177e4SLinus Torvalds	__INIT
6791da177e4SLinus Torvalds
6801da177e4SLinus Torvalds	BUILD_HANDLER  daddi_ov daddi_ov none silent	/* #12 */
6811da177e4SLinus Torvalds#endif
682