xref: /linux/arch/mips/kernel/entry.S (revision 36c8b586896f60cb91a4fd526233190b34316baf)
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.
81da177e4SLinus Torvalds * Copyright (C) 2001 MIPS Technologies, Inc.
91da177e4SLinus Torvalds */
101da177e4SLinus Torvalds
111da177e4SLinus Torvalds#include <asm/asm.h>
121da177e4SLinus Torvalds#include <asm/asmmacro.h>
131da177e4SLinus Torvalds#include <asm/regdef.h>
141da177e4SLinus Torvalds#include <asm/mipsregs.h>
151da177e4SLinus Torvalds#include <asm/stackframe.h>
161da177e4SLinus Torvalds#include <asm/isadep.h>
171da177e4SLinus Torvalds#include <asm/thread_info.h>
181da177e4SLinus Torvalds#include <asm/war.h>
1941c594abSRalf Baechle#ifdef CONFIG_MIPS_MT_SMTC
2041c594abSRalf Baechle#include <asm/mipsmtregs.h>
2141c594abSRalf Baechle#endif
221da177e4SLinus Torvalds
231da177e4SLinus Torvalds#ifdef CONFIG_PREEMPT
24c2648527SThiemo Seufer	.macro	preempt_stop
251da177e4SLinus Torvalds	.endm
261da177e4SLinus Torvalds#else
27c2648527SThiemo Seufer	.macro	preempt_stop
28c2648527SThiemo Seufer	local_irq_disable
291da177e4SLinus Torvalds	.endm
301da177e4SLinus Torvalds#define resume_kernel	restore_all
311da177e4SLinus Torvalds#endif
321da177e4SLinus Torvalds
331da177e4SLinus Torvalds	.text
341da177e4SLinus Torvalds	.align	5
351da177e4SLinus TorvaldsFEXPORT(ret_from_exception)
361da177e4SLinus Torvalds	preempt_stop
371da177e4SLinus TorvaldsFEXPORT(ret_from_irq)
381da177e4SLinus Torvalds	LONG_L	t0, PT_STATUS(sp)		# returning to kernel mode?
391da177e4SLinus Torvalds	andi	t0, t0, KU_USER
401da177e4SLinus Torvalds	beqz	t0, resume_kernel
411da177e4SLinus Torvalds
42c2648527SThiemo Seuferresume_userspace:
43c2648527SThiemo Seufer	local_irq_disable		# make sure we dont miss an
441da177e4SLinus Torvalds					# interrupt setting need_resched
451da177e4SLinus Torvalds					# between sampling and return
461da177e4SLinus Torvalds	LONG_L	a2, TI_FLAGS($28)	# current->work
47c2648527SThiemo Seufer	andi	t0, a2, _TIF_WORK_MASK	# (ignoring syscall_trace)
48c2648527SThiemo Seufer	bnez	t0, work_pending
491da177e4SLinus Torvalds	j	restore_all
501da177e4SLinus Torvalds
511da177e4SLinus Torvalds#ifdef CONFIG_PREEMPT
52c2648527SThiemo Seuferresume_kernel:
53a18815abSRalf Baechle	local_irq_disable
541da177e4SLinus Torvalds	lw	t0, TI_PRE_COUNT($28)
551da177e4SLinus Torvalds	bnez	t0, restore_all
561da177e4SLinus Torvaldsneed_resched:
571da177e4SLinus Torvalds	LONG_L	t0, TI_FLAGS($28)
581da177e4SLinus Torvalds	andi	t1, t0, _TIF_NEED_RESCHED
591da177e4SLinus Torvalds	beqz	t1, restore_all
601da177e4SLinus Torvalds	LONG_L	t0, PT_STATUS(sp)		# Interrupts off?
611da177e4SLinus Torvalds	andi	t0, 1
621da177e4SLinus Torvalds	beqz	t0, restore_all
63a18815abSRalf Baechle	jal	preempt_schedule_irq
64cdaed73aSRalf Baechle	b	need_resched
651da177e4SLinus Torvalds#endif
661da177e4SLinus Torvalds
671da177e4SLinus TorvaldsFEXPORT(ret_from_fork)
68*36c8b586SIngo Molnar	jal	schedule_tail		# a0 = struct task_struct *prev
691da177e4SLinus Torvalds
701da177e4SLinus TorvaldsFEXPORT(syscall_exit)
711da177e4SLinus Torvalds	local_irq_disable		# make sure need_resched and
721da177e4SLinus Torvalds					# signals dont change between
731da177e4SLinus Torvalds					# sampling and return
741da177e4SLinus Torvalds	LONG_L	a2, TI_FLAGS($28)	# current->work
751da177e4SLinus Torvalds	li	t0, _TIF_ALLWORK_MASK
761da177e4SLinus Torvalds	and	t0, a2, t0
771da177e4SLinus Torvalds	bnez	t0, syscall_exit_work
781da177e4SLinus Torvalds
791da177e4SLinus TorvaldsFEXPORT(restore_all)			# restore full frame
8041c594abSRalf Baechle#ifdef CONFIG_MIPS_MT_SMTC
8141c594abSRalf Baechle/* Detect and execute deferred IPI "interrupts" */
8241c594abSRalf Baechle	move	a0,sp
8341c594abSRalf Baechle	jal	deferred_smtc_ipi
8441c594abSRalf Baechle/* Re-arm any temporarily masked interrupts not explicitly "acked" */
8541c594abSRalf Baechle	mfc0	v0, CP0_TCSTATUS
8641c594abSRalf Baechle	ori	v1, v0, TCSTATUS_IXMT
8741c594abSRalf Baechle	mtc0	v1, CP0_TCSTATUS
8841c594abSRalf Baechle	andi	v0, TCSTATUS_IXMT
894277ff5eSRalf Baechle	_ehb
9041c594abSRalf Baechle	mfc0	t0, CP0_TCCONTEXT
9141c594abSRalf Baechle	DMT	9				# dmt t1
9241c594abSRalf Baechle	jal	mips_ihb
9341c594abSRalf Baechle	mfc0	t2, CP0_STATUS
9441c594abSRalf Baechle	andi	t3, t0, 0xff00
9541c594abSRalf Baechle	or	t2, t2, t3
9641c594abSRalf Baechle	mtc0	t2, CP0_STATUS
974277ff5eSRalf Baechle	_ehb
9841c594abSRalf Baechle	andi	t1, t1, VPECONTROL_TE
9941c594abSRalf Baechle	beqz	t1, 1f
10041c594abSRalf Baechle	EMT
10141c594abSRalf Baechle1:
10241c594abSRalf Baechle	mfc0	v1, CP0_TCSTATUS
103477654fcSRalf Baechle	/* We set IXMT above, XOR should clear it here */
10441c594abSRalf Baechle	xori	v1, v1, TCSTATUS_IXMT
10541c594abSRalf Baechle	or	v1, v0, v1
10641c594abSRalf Baechle	mtc0	v1, CP0_TCSTATUS
1074277ff5eSRalf Baechle	_ehb
10841c594abSRalf Baechle	xor	t0, t0, t3
10941c594abSRalf Baechle	mtc0	t0, CP0_TCCONTEXT
11041c594abSRalf Baechle#endif /* CONFIG_MIPS_MT_SMTC */
1111da177e4SLinus Torvalds	.set	noat
1121da177e4SLinus Torvalds	RESTORE_TEMP
1131da177e4SLinus Torvalds	RESTORE_AT
1141da177e4SLinus Torvalds	RESTORE_STATIC
1151da177e4SLinus TorvaldsFEXPORT(restore_partial)		# restore partial frame
1161da177e4SLinus Torvalds	RESTORE_SOME
1171da177e4SLinus Torvalds	RESTORE_SP_AND_RET
1181da177e4SLinus Torvalds	.set	at
1191da177e4SLinus Torvalds
120c2648527SThiemo Seuferwork_pending:
121c2648527SThiemo Seufer	andi	t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
1221da177e4SLinus Torvalds	beqz	t0, work_notifysig
1231da177e4SLinus Torvaldswork_resched:
1241da177e4SLinus Torvalds	jal	schedule
1251da177e4SLinus Torvalds
126c2648527SThiemo Seufer	local_irq_disable		# make sure need_resched and
1271da177e4SLinus Torvalds					# signals dont change between
1281da177e4SLinus Torvalds					# sampling and return
1291da177e4SLinus Torvalds	LONG_L	a2, TI_FLAGS($28)
1301da177e4SLinus Torvalds	andi	t0, a2, _TIF_WORK_MASK	# is there any work to be done
1311da177e4SLinus Torvalds					# other than syscall tracing?
1321da177e4SLinus Torvalds	beqz	t0, restore_all
1331da177e4SLinus Torvalds	andi	t0, a2, _TIF_NEED_RESCHED
1341da177e4SLinus Torvalds	bnez	t0, work_resched
1351da177e4SLinus Torvalds
1361da177e4SLinus Torvaldswork_notifysig:				# deal with pending signals and
1371da177e4SLinus Torvalds					# notify-resume requests
1381da177e4SLinus Torvalds	move	a0, sp
1391da177e4SLinus Torvalds	li	a1, 0
1401da177e4SLinus Torvalds	jal	do_notify_resume	# a2 already loaded
1410bf0e3e2SRalf Baechle	j	resume_userspace
1421da177e4SLinus Torvalds
1431da177e4SLinus TorvaldsFEXPORT(syscall_exit_work_partial)
1441da177e4SLinus Torvalds	SAVE_STATIC
145c2648527SThiemo Seufersyscall_exit_work:
146c2648527SThiemo Seufer	li	t0, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
147c2648527SThiemo Seufer	and	t0, a2			# a2 is preloaded with TI_FLAGS
148c2648527SThiemo Seufer	beqz	t0, work_pending	# trace bit set?
1491da177e4SLinus Torvalds	local_irq_enable		# could let do_syscall_trace()
1501da177e4SLinus Torvalds					# call schedule() instead
1511da177e4SLinus Torvalds	move	a0, sp
1521da177e4SLinus Torvalds	li	a1, 1
1531da177e4SLinus Torvalds	jal	do_syscall_trace
1541da177e4SLinus Torvalds	b	resume_userspace
155bce1a286SRalf Baechle
156bce1a286SRalf Baechle#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT)
157bce1a286SRalf Baechle
158bce1a286SRalf Baechle/*
159bce1a286SRalf Baechle * MIPS32R2 Instruction Hazard Barrier - must be called
160bce1a286SRalf Baechle *
161bce1a286SRalf Baechle * For C code use the inline version named instruction_hazard().
162bce1a286SRalf Baechle */
163bce1a286SRalf BaechleLEAF(mips_ihb)
164bce1a286SRalf Baechle	.set	mips32r2
165bce1a286SRalf Baechle	jr.hb	ra
166bce1a286SRalf Baechle	nop
167bce1a286SRalf Baechle	END(mips_ihb)
168bce1a286SRalf Baechle
169bce1a286SRalf Baechle#endif /* CONFIG_CPU_MIPSR2 or CONFIG_MIPS_MT */
170