692 lines · 14.9 KB · Assembly
RawDownload
/* * This file is subject to the terms and conditions of the GNU General Public * License.  See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. * Copyright (C) 2002, 2007  Maciej W. Rozycki * Copyright (C) 2001, 2012 MIPS Technologies, Inc.  All rights reserved. */#include <linux/init.h> #include <asm/asm.h>#include <asm/asmmacro.h>#include <asm/cacheops.h>#include <asm/irqflags.h>#include <asm/regdef.h>#include <asm/fpregdef.h>#include <asm/mipsregs.h>#include <asm/stackframe.h>#include <asm/sync.h>#include <asm/thread_info.h> 	__INIT /* * General exception vector for all other CPUs. * * Be careful when changing this, it has to be at most 128 bytes * to fit into space reserved for the exception handler. */NESTED(except_vec3_generic, 0, sp)	.set	push	.set	noat	mfc0	k1, CP0_CAUSE	andi	k1, k1, 0x7c#ifdef CONFIG_64BIT	dsll	k1, k1, 1#endif	PTR_L	k0, exception_handlers(k1)	jr	k0	.set	pop	END(except_vec3_generic) /* * General exception handler for CPUs with virtual coherency exception. * * Be careful when changing this, it has to be at most 256 (as a special * exception) bytes to fit into space reserved for the exception handler. */NESTED(except_vec3_r4000, 0, sp)	.set	push	.set	arch=r4000	.set	noat	mfc0	k1, CP0_CAUSE	li	k0, 31<<2	andi	k1, k1, 0x7c	.set	push	.set	noreorder	.set	nomacro	beq	k1, k0, handle_vced	 li	k0, 14<<2	beq	k1, k0, handle_vcei#ifdef CONFIG_64BIT	 dsll	k1, k1, 1#endif	.set	pop	PTR_L	k0, exception_handlers(k1)	jr	k0 	/*	 * Big shit, we now may have two dirty primary cache lines for the same	 * physical address.  We can safely invalidate the line pointed to by	 * c0_badvaddr because after return from this exception handler the	 * load / store will be re-executed.	 */handle_vced:	MFC0	k0, CP0_BADVADDR	li	k1, -4					# Is this ...	and	k0, k1					# ... really needed?	mtc0	zero, CP0_TAGLO	cache	Index_Store_Tag_D, (k0)	cache	Hit_Writeback_Inv_SD, (k0)#ifdef CONFIG_PROC_FS	PTR_LA	k0, vced_count	lw	k1, (k0)	addiu	k1, 1	sw	k1, (k0)#endif	eret handle_vcei:	MFC0	k0, CP0_BADVADDR	cache	Hit_Writeback_Inv_SD, (k0)		# also cleans pi#ifdef CONFIG_PROC_FS	PTR_LA	k0, vcei_count	lw	k1, (k0)	addiu	k1, 1	sw	k1, (k0)#endif	eret	.set	pop	END(except_vec3_r4000) 	__FINIT 	.section .cpuidle.text,"ax"	/* Align to 32 bytes for the maximum idle interrupt region size. */	.align	5LEAF(r4k_wait)	/* Keep the ISA bit clear for calculations on local labels here. */0:	.fill	0	/* Start of idle interrupt region. */	local_irq_enable	/*	 * If an interrupt lands here, before going idle on the next	 * instruction, we must *NOT* go idle since the interrupt could	 * have set TIF_NEED_RESCHED or caused a timer to need resched.	 * Fall through -- see skipover_handler below -- and have the	 * idle loop take care of things.	 */1:	.fill	0	/* The R2 EI/EHB sequence takes 8 bytes, otherwise pad up.  */	.if	1b - 0b > 32	.error	"overlong idle interrupt region"	.elseif	1b - 0b > 8	.align	4	.endif2:	.fill	0	.equ	r4k_wait_idle_size, 2b - 0b	/* End of idle interrupt region; size has to be a power of 2. */	.set	MIPS_ISA_ARCH_LEVEL_RAWr4k_wait_insn:	waitr4k_wait_exit:	.set	mips0	local_irq_disable	jr	ra	END(r4k_wait)	.previous 	.macro	BUILD_SKIPOVER_PROLOGUE handler	FEXPORT(skipover_\handler)	.set	push	.set	noat	MFC0	k0, CP0_EPC	/* Subtract/add 2 to let the ISA bit propagate through the mask.  */	PTR_LA	k1, r4k_wait_insn - 2	ori	k0, r4k_wait_idle_size - 2	.set	noreorder	bne	k0, k1, \handler	 PTR_ADDIU	k0, r4k_wait_exit - r4k_wait_insn + 2	.set	reorder	MTC0	k0, CP0_EPC	.set pop	.endm 	.align	5BUILD_SKIPOVER_PROLOGUE handle_intNESTED(handle_int, PT_SIZE, sp)	.cfi_signal_frame#ifdef CONFIG_TRACE_IRQFLAGS	/*	 * Check to see if the interrupted code has just disabled	 * interrupts and ignore this interrupt for now if so.	 *	 * local_irq_disable() disables interrupts and then calls	 * trace_hardirqs_off() to track the state. If an interrupt is taken	 * after interrupts are disabled but before the state is updated	 * it will appear to restore_all that it is incorrectly returning with	 * interrupts disabled	 */	.set	push	.set	noat	mfc0	k0, CP0_STATUS#if defined(CONFIG_CPU_R3000)	and	k0, ST0_IEP	bnez	k0, 1f 	mfc0	k0, CP0_EPC	.set	noreorder	j	k0	 rfe#else	and	k0, ST0_IE	bnez	k0, 1f 	eret#endif1:	.set pop#endif	SAVE_ALL docfi=1	CLI	TRACE_IRQS_OFF 	LONG_L	s0, TI_REGS($28)	LONG_S	sp, TI_REGS($28) 	/*	 * SAVE_ALL ensures we are using a valid kernel stack for the thread.	 * Check if we are already using the IRQ stack.	 */	move	s1, sp # Preserve the sp 	/* Get IRQ stack for this CPU */	ASM_CPUID_MFC0	k0, ASM_SMP_CPUID_REG#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)	lui	k1, %hi(irq_stack)#else	lui	k1, %highest(irq_stack)	daddiu	k1, %higher(irq_stack)	dsll	k1, 16	daddiu	k1, %hi(irq_stack)	dsll	k1, 16#endif	LONG_SRL	k0, SMP_CPUID_PTRSHIFT	LONG_ADDU	k1, k0	LONG_L	t0, %lo(irq_stack)(k1) 	# Check if already on IRQ stack	PTR_LI	t1, ~(_THREAD_SIZE-1)	and	t1, t1, sp	beq	t0, t1, 2f 	/* Switch to IRQ stack */	li	t1, _IRQ_STACK_START	PTR_ADD sp, t0, t1 	/* Save task's sp on IRQ stack so that unwinding can follow it */	LONG_S	s1, 0(sp)2:	jal	plat_irq_dispatch 	/* Restore sp */	move	sp, s1 	j	ret_from_irq#ifdef CONFIG_CPU_MICROMIPS	nop#endif	END(handle_int) 	__INIT /* * Special interrupt vector for MIPS64 ISA & embedded MIPS processors. * This is a dedicated interrupt exception vector which reduces the * interrupt processing overhead.  The jump instruction will be replaced * at the initialization time. * * Be careful when changing this, it has to be at most 128 bytes * to fit into space reserved for the exception handler. */NESTED(except_vec4, 0, sp)1:	j	1b			/* Dummy, will be replaced */	END(except_vec4) /* * EJTAG debug exception handler. * The EJTAG debug exception entry point is 0xbfc00480, which * normally is in the boot PROM, so the boot PROM must do an * unconditional jump to this vector. */NESTED(except_vec_ejtag_debug, 0, sp)	j	ejtag_debug_handler#ifdef CONFIG_CPU_MICROMIPS	 nop#endif	END(except_vec_ejtag_debug) 	__FINIT /* * Vectored interrupt handler. * This prototype is copied to ebase + n*IntCtl.VS and patched * to invoke the handler */BUILD_SKIPOVER_PROLOGUE except_vec_viNESTED(except_vec_vi, 0, sp)	SAVE_SOME docfi=1	SAVE_AT docfi=1	.set	push	.set	noreorder	PTR_LA	v1, except_vec_vi_handler	jr	v1FEXPORT(except_vec_vi_ori)	 ori	v0, zero, 0		/* Offset in vi_handlers[] */	.set	pop	END(except_vec_vi)EXPORT(except_vec_vi_end) /* * Common Vectored Interrupt code * Complete the register saves and invoke the handler, $v0 holds * offset into vi_handlers[] */NESTED(except_vec_vi_handler, 0, sp)	SAVE_TEMP	SAVE_STATIC	CLI#ifdef CONFIG_TRACE_IRQFLAGS	move	s0, v0	TRACE_IRQS_OFF	move	v0, s0#endif 	LONG_L	s0, TI_REGS($28)	LONG_S	sp, TI_REGS($28) 	/*	 * SAVE_ALL ensures we are using a valid kernel stack for the thread.	 * Check if we are already using the IRQ stack.	 */	move	s1, sp # Preserve the sp 	/* Get IRQ stack for this CPU */	ASM_CPUID_MFC0	k0, ASM_SMP_CPUID_REG#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)	lui	k1, %hi(irq_stack)#else	lui	k1, %highest(irq_stack)	daddiu	k1, %higher(irq_stack)	dsll	k1, 16	daddiu	k1, %hi(irq_stack)	dsll	k1, 16#endif	LONG_SRL	k0, SMP_CPUID_PTRSHIFT	LONG_ADDU	k1, k0	LONG_L	t0, %lo(irq_stack)(k1) 	# Check if already on IRQ stack	PTR_LI	t1, ~(_THREAD_SIZE-1)	and	t1, t1, sp	beq	t0, t1, 2f 	/* Switch to IRQ stack */	li	t1, _IRQ_STACK_START	PTR_ADD sp, t0, t1 	/* Save task's sp on IRQ stack so that unwinding can follow it */	LONG_S	s1, 0(sp)2:	PTR_L	v0, vi_handlers(v0)	jalr	v0 	/* Restore sp */	move	sp, s1 	j	ret_from_irq	END(except_vec_vi_handler) /* * EJTAG debug exception handler. */NESTED(ejtag_debug_handler, PT_SIZE, sp)	.set	push	.set	noat	MTC0	k0, CP0_DESAVE	mfc0	k0, CP0_DEBUG 	andi	k0, k0, MIPS_DEBUG_DBP	# Check for SDBBP.	beqz	k0, ejtag_return #ifdef CONFIG_SMP1:	PTR_LA	k0, ejtag_debug_buffer_spinlock	__SYNC(full, loongson3_war)2:	ll	k0, 0(k0)	bnez	k0, 2b	PTR_LA	k0, ejtag_debug_buffer_spinlock	sc	k0, 0(k0)	beqz	k0, 1b# ifdef CONFIG_WEAK_REORDERING_BEYOND_LLSC	sync# endif 	PTR_LA	k0, ejtag_debug_buffer	LONG_S	k1, 0(k0) 	ASM_CPUID_MFC0 k1, ASM_SMP_CPUID_REG	PTR_SRL	k1, SMP_CPUID_PTRSHIFT	PTR_SLL	k1, LONGLOG	PTR_LA	k0, ejtag_debug_buffer_per_cpu	PTR_ADDU k0, k1 	PTR_LA	k1, ejtag_debug_buffer	LONG_L	k1, 0(k1)	LONG_S	k1, 0(k0) 	PTR_LA	k0, ejtag_debug_buffer_spinlock	sw	zero, 0(k0)#else	PTR_LA	k0, ejtag_debug_buffer	LONG_S	k1, 0(k0)#endif 	SAVE_ALL	move	a0, sp	jal	ejtag_exception_handler	RESTORE_ALL #ifdef CONFIG_SMP	ASM_CPUID_MFC0 k1, ASM_SMP_CPUID_REG	PTR_SRL	k1, SMP_CPUID_PTRSHIFT	PTR_SLL	k1, LONGLOG	PTR_LA	k0, ejtag_debug_buffer_per_cpu	PTR_ADDU k0, k1	LONG_L	k1, 0(k0)#else	PTR_LA	k0, ejtag_debug_buffer	LONG_L	k1, 0(k0)#endif ejtag_return:	back_to_back_c0_hazard	MFC0	k0, CP0_DESAVE	.set	mips32	deret	.set	pop	END(ejtag_debug_handler) /* * This buffer is reserved for the use of the EJTAG debug * handler. */	.dataEXPORT(ejtag_debug_buffer)	.fill	LONGSIZE#ifdef CONFIG_SMPEXPORT(ejtag_debug_buffer_spinlock)	.fill	LONGSIZEEXPORT(ejtag_debug_buffer_per_cpu)	.fill	LONGSIZE * NR_CPUS#endif	.previous 	__INIT /* * NMI debug exception handler for MIPS reference boards. * The NMI debug exception entry point is 0xbfc00000, which * normally is in the boot PROM, so the boot PROM must do a * unconditional jump to this vector. */NESTED(except_vec_nmi, 0, sp)	j	nmi_handler#ifdef CONFIG_CPU_MICROMIPS	 nop#endif	END(except_vec_nmi) 	__FINIT NESTED(nmi_handler, PT_SIZE, sp)	.cfi_signal_frame	.set	push	.set	noat	/*	 * Clear ERL - restore segment mapping	 * Clear BEV - required for page fault exception handler to work	 */	mfc0	k0, CP0_STATUS	ori	k0, k0, ST0_EXL	li	k1, ~(ST0_BEV | ST0_ERL)	and	k0, k0, k1	mtc0	k0, CP0_STATUS	_ehb	SAVE_ALL	move	a0, sp	jal	nmi_exception_handler	/* nmi_exception_handler never returns */	.set	pop	END(nmi_handler) 	.macro	__build_clear_none	.endm 	.macro	__build_clear_sti	TRACE_IRQS_ON	STI	.endm 	.macro	__build_clear_cli	CLI	TRACE_IRQS_OFF	.endm 	.macro	__build_clear_fpe	CLI	TRACE_IRQS_OFF	.set	push	/* gas fails to assemble cfc1 for some archs (octeon).*/ \	.set	mips1	.set	hardfloat	cfc1	a1, fcr31	.set	pop	.endm 	.macro	__build_clear_msa_fpe	CLI

Lines 1–500 of 692.