xref: /kernel/linux/linux-6.6/arch/m68k/68000/entry.S (revision 62306a36)
162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci *  entry.S -- non-mmu 68000 interrupt and exception entry points
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci *  Copyright (C) 1991, 1992  Linus Torvalds
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
762306a36Sopenharmony_ci * License.  See the file README.legal in the main directory of this archive
862306a36Sopenharmony_ci * for more details.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * Linux/m68k support by Hamish Macdonald
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/linkage.h>
1462306a36Sopenharmony_ci#include <asm/thread_info.h>
1562306a36Sopenharmony_ci#include <asm/unistd.h>
1662306a36Sopenharmony_ci#include <asm/errno.h>
1762306a36Sopenharmony_ci#include <asm/setup.h>
1862306a36Sopenharmony_ci#include <asm/traps.h>
1962306a36Sopenharmony_ci#include <asm/asm-offsets.h>
2062306a36Sopenharmony_ci#include <asm/entry.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci.text
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci.globl system_call
2562306a36Sopenharmony_ci.globl resume
2662306a36Sopenharmony_ci.globl ret_from_exception
2762306a36Sopenharmony_ci.globl sys_call_table
2862306a36Sopenharmony_ci.globl bad_interrupt
2962306a36Sopenharmony_ci.globl inthandler1
3062306a36Sopenharmony_ci.globl inthandler2
3162306a36Sopenharmony_ci.globl inthandler3
3262306a36Sopenharmony_ci.globl inthandler4
3362306a36Sopenharmony_ci.globl inthandler5
3462306a36Sopenharmony_ci.globl inthandler6
3562306a36Sopenharmony_ci.globl inthandler7
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cibadsys:
3862306a36Sopenharmony_ci	movel	#-ENOSYS,%sp@(PT_OFF_D0)
3962306a36Sopenharmony_ci	jra	ret_from_exception
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cido_trace:
4262306a36Sopenharmony_ci	movel	#-ENOSYS,%sp@(PT_OFF_D0) /* needed for strace*/
4362306a36Sopenharmony_ci	subql	#4,%sp
4462306a36Sopenharmony_ci	SAVE_SWITCH_STACK
4562306a36Sopenharmony_ci	jbsr	syscall_trace_enter
4662306a36Sopenharmony_ci	RESTORE_SWITCH_STACK
4762306a36Sopenharmony_ci	addql	#4,%sp
4862306a36Sopenharmony_ci	addql	#1,%d0
4962306a36Sopenharmony_ci	jeq	ret_from_exception
5062306a36Sopenharmony_ci	movel	%sp@(PT_OFF_ORIG_D0),%d1
5162306a36Sopenharmony_ci	movel	#-ENOSYS,%d0
5262306a36Sopenharmony_ci	cmpl	#NR_syscalls,%d1
5362306a36Sopenharmony_ci	jcc	1f
5462306a36Sopenharmony_ci	lsl	#2,%d1
5562306a36Sopenharmony_ci	lea	sys_call_table, %a0
5662306a36Sopenharmony_ci	jbsr	%a0@(%d1)
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci1:	movel	%d0,%sp@(PT_OFF_D0)	/* save the return value */
5962306a36Sopenharmony_ci	subql	#4,%sp			/* dummy return address */
6062306a36Sopenharmony_ci	SAVE_SWITCH_STACK
6162306a36Sopenharmony_ci	jbsr	syscall_trace_leave
6262306a36Sopenharmony_ci	RESTORE_SWITCH_STACK
6362306a36Sopenharmony_ci	addql	#4,%sp
6462306a36Sopenharmony_ci	jra	ret_from_exception
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ciENTRY(system_call)
6762306a36Sopenharmony_ci	SAVE_ALL_SYS
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	/* save top of frame*/
7062306a36Sopenharmony_ci	pea	%sp@
7162306a36Sopenharmony_ci	jbsr	set_esp0
7262306a36Sopenharmony_ci	addql	#4,%sp
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	movel	%sp@(PT_OFF_ORIG_D0),%d0
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	movel	%sp,%d1			/* get thread_info pointer */
7762306a36Sopenharmony_ci	andl	#-THREAD_SIZE,%d1
7862306a36Sopenharmony_ci	movel	%d1,%a2
7962306a36Sopenharmony_ci	btst	#(TIF_SYSCALL_TRACE%8),%a2@(TINFO_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
8062306a36Sopenharmony_ci	jne	do_trace
8162306a36Sopenharmony_ci	cmpl	#NR_syscalls,%d0
8262306a36Sopenharmony_ci	jcc	badsys
8362306a36Sopenharmony_ci	lsl	#2,%d0
8462306a36Sopenharmony_ci	lea	sys_call_table,%a0
8562306a36Sopenharmony_ci	movel	%a0@(%d0), %a0
8662306a36Sopenharmony_ci	jbsr	%a0@
8762306a36Sopenharmony_ci	movel	%d0,%sp@(PT_OFF_D0)	/* save the return value*/
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ciret_from_exception:
9062306a36Sopenharmony_ci	btst	#5,%sp@(PT_OFF_SR)	/* check if returning to kernel*/
9162306a36Sopenharmony_ci	jeq	Luser_return		/* if so, skip resched, signals*/
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ciLkernel_return:
9462306a36Sopenharmony_ci	RESTORE_ALL
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ciLuser_return:
9762306a36Sopenharmony_ci	/* only allow interrupts when we are really the last one on the*/
9862306a36Sopenharmony_ci	/* kernel stack, otherwise stack overflow can occur during*/
9962306a36Sopenharmony_ci	/* heavy interrupt load*/
10062306a36Sopenharmony_ci	andw	#ALLOWINT,%sr
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	movel	%sp,%d1			/* get thread_info pointer */
10362306a36Sopenharmony_ci	andl	#-THREAD_SIZE,%d1
10462306a36Sopenharmony_ci	movel	%d1,%a2
10562306a36Sopenharmony_ci1:
10662306a36Sopenharmony_ci	move	%a2@(TINFO_FLAGS),%d1	/* thread_info->flags */
10762306a36Sopenharmony_ci	jne	Lwork_to_do
10862306a36Sopenharmony_ci	RESTORE_ALL
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ciLwork_to_do:
11162306a36Sopenharmony_ci	movel	%a2@(TINFO_FLAGS),%d1	/* thread_info->flags */
11262306a36Sopenharmony_ci	btst	#TIF_NEED_RESCHED,%d1
11362306a36Sopenharmony_ci	jne	reschedule
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ciLsignal_return:
11662306a36Sopenharmony_ci	subql	#4,%sp			/* dummy return address*/
11762306a36Sopenharmony_ci	SAVE_SWITCH_STACK
11862306a36Sopenharmony_ci	pea	%sp@(SWITCH_STACK_SIZE)
11962306a36Sopenharmony_ci	bsrw	do_notify_resume
12062306a36Sopenharmony_ci	addql	#4,%sp
12162306a36Sopenharmony_ci	RESTORE_SWITCH_STACK
12262306a36Sopenharmony_ci	addql	#4,%sp
12362306a36Sopenharmony_ci	jra	1b
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci/*
12662306a36Sopenharmony_ci * This is the main interrupt handler, responsible for calling process_int()
12762306a36Sopenharmony_ci */
12862306a36Sopenharmony_ciinthandler1:
12962306a36Sopenharmony_ci	SAVE_ALL_INT
13062306a36Sopenharmony_ci	movew	%sp@(PT_OFF_FORMATVEC), %d0
13162306a36Sopenharmony_ci	and	#0x3ff, %d0
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	movel	%sp,%sp@-
13462306a36Sopenharmony_ci	movel	#65,%sp@- 		/*  put vector # on stack*/
13562306a36Sopenharmony_ci	jbsr	process_int		/*  process the IRQ*/
13662306a36Sopenharmony_ci3:     	addql	#8,%sp			/*  pop parameters off stack*/
13762306a36Sopenharmony_ci	bra	ret_from_exception
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ciinthandler2:
14062306a36Sopenharmony_ci	SAVE_ALL_INT
14162306a36Sopenharmony_ci	movew	%sp@(PT_OFF_FORMATVEC), %d0
14262306a36Sopenharmony_ci	and	#0x3ff, %d0
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	movel	%sp,%sp@-
14562306a36Sopenharmony_ci	movel	#66,%sp@- 		/*  put vector # on stack*/
14662306a36Sopenharmony_ci	jbsr	process_int		/*  process the IRQ*/
14762306a36Sopenharmony_ci3:     	addql	#8,%sp			/*  pop parameters off stack*/
14862306a36Sopenharmony_ci	bra	ret_from_exception
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ciinthandler3:
15162306a36Sopenharmony_ci	SAVE_ALL_INT
15262306a36Sopenharmony_ci	movew	%sp@(PT_OFF_FORMATVEC), %d0
15362306a36Sopenharmony_ci	and	#0x3ff, %d0
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	movel	%sp,%sp@-
15662306a36Sopenharmony_ci	movel	#67,%sp@- 		/*  put vector # on stack*/
15762306a36Sopenharmony_ci	jbsr	process_int		/*  process the IRQ*/
15862306a36Sopenharmony_ci3:     	addql	#8,%sp			/*  pop parameters off stack*/
15962306a36Sopenharmony_ci	bra	ret_from_exception
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ciinthandler4:
16262306a36Sopenharmony_ci	SAVE_ALL_INT
16362306a36Sopenharmony_ci	movew	%sp@(PT_OFF_FORMATVEC), %d0
16462306a36Sopenharmony_ci	and	#0x3ff, %d0
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	movel	%sp,%sp@-
16762306a36Sopenharmony_ci	movel	#68,%sp@- 		/*  put vector # on stack*/
16862306a36Sopenharmony_ci	jbsr	process_int		/*  process the IRQ*/
16962306a36Sopenharmony_ci3:     	addql	#8,%sp			/*  pop parameters off stack*/
17062306a36Sopenharmony_ci	bra	ret_from_exception
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ciinthandler5:
17362306a36Sopenharmony_ci	SAVE_ALL_INT
17462306a36Sopenharmony_ci	movew	%sp@(PT_OFF_FORMATVEC), %d0
17562306a36Sopenharmony_ci	and	#0x3ff, %d0
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	movel	%sp,%sp@-
17862306a36Sopenharmony_ci	movel	#69,%sp@- 		/*  put vector # on stack*/
17962306a36Sopenharmony_ci	jbsr	process_int		/*  process the IRQ*/
18062306a36Sopenharmony_ci3:     	addql	#8,%sp			/*  pop parameters off stack*/
18162306a36Sopenharmony_ci	bra	ret_from_exception
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ciinthandler6:
18462306a36Sopenharmony_ci	SAVE_ALL_INT
18562306a36Sopenharmony_ci	movew	%sp@(PT_OFF_FORMATVEC), %d0
18662306a36Sopenharmony_ci	and	#0x3ff, %d0
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	movel	%sp,%sp@-
18962306a36Sopenharmony_ci	movel	#70,%sp@- 		/*  put vector # on stack*/
19062306a36Sopenharmony_ci	jbsr	process_int		/*  process the IRQ*/
19162306a36Sopenharmony_ci3:     	addql	#8,%sp			/*  pop parameters off stack*/
19262306a36Sopenharmony_ci	bra	ret_from_exception
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ciinthandler7:
19562306a36Sopenharmony_ci	SAVE_ALL_INT
19662306a36Sopenharmony_ci	movew	%sp@(PT_OFF_FORMATVEC), %d0
19762306a36Sopenharmony_ci	and	#0x3ff, %d0
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	movel	%sp,%sp@-
20062306a36Sopenharmony_ci	movel	#71,%sp@- 		/*  put vector # on stack*/
20162306a36Sopenharmony_ci	jbsr	process_int		/*  process the IRQ*/
20262306a36Sopenharmony_ci3:     	addql	#8,%sp			/*  pop parameters off stack*/
20362306a36Sopenharmony_ci	bra	ret_from_exception
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ciinthandler:
20662306a36Sopenharmony_ci	SAVE_ALL_INT
20762306a36Sopenharmony_ci	movew	%sp@(PT_OFF_FORMATVEC), %d0
20862306a36Sopenharmony_ci	and	#0x3ff, %d0
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	movel	%sp,%sp@-
21162306a36Sopenharmony_ci	movel	%d0,%sp@- 		/*  put vector # on stack*/
21262306a36Sopenharmony_ci	jbsr	process_int		/*  process the IRQ*/
21362306a36Sopenharmony_ci3:     	addql	#8,%sp			/*  pop parameters off stack*/
21462306a36Sopenharmony_ci	bra	ret_from_exception
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci/*
21762306a36Sopenharmony_ci * Handler for uninitialized and spurious interrupts.
21862306a36Sopenharmony_ci */
21962306a36Sopenharmony_ciENTRY(bad_interrupt)
22062306a36Sopenharmony_ci	addql	#1,irq_err_count
22162306a36Sopenharmony_ci	rte
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci/*
22462306a36Sopenharmony_ci * Beware - when entering resume, prev (the current task) is
22562306a36Sopenharmony_ci * in a0, next (the new task) is in a1, so don't change these
22662306a36Sopenharmony_ci * registers until their contents are no longer needed.
22762306a36Sopenharmony_ci */
22862306a36Sopenharmony_ciENTRY(resume)
22962306a36Sopenharmony_ci	movel	%a0,%d1				/* save prev thread in d1 */
23062306a36Sopenharmony_ci	movew	%sr,%a0@(TASK_THREAD+THREAD_SR)	/* save sr */
23162306a36Sopenharmony_ci	SAVE_SWITCH_STACK
23262306a36Sopenharmony_ci	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack */
23362306a36Sopenharmony_ci	movel	%usp,%a3			/* save usp */
23462306a36Sopenharmony_ci	movel	%a3,%a0@(TASK_THREAD+THREAD_USP)
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	movel	%a1@(TASK_THREAD+THREAD_USP),%a3 /* restore user stack */
23762306a36Sopenharmony_ci	movel	%a3,%usp
23862306a36Sopenharmony_ci	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
23962306a36Sopenharmony_ci	RESTORE_SWITCH_STACK
24062306a36Sopenharmony_ci	movew	%a1@(TASK_THREAD+THREAD_SR),%sr	/* restore thread status reg */
24162306a36Sopenharmony_ci	rts
24262306a36Sopenharmony_ci
243