entry.S 5.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 *  linux/arch/m68knommu/platform/5307/entry.S
 *
G
Greg Ungerer 已提交
4
 *  Copyright (C) 1999-2007, Greg Ungerer (gerg@snapgear.com)
L
Linus Torvalds 已提交
5 6
 *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
 *                      Kenneth Albanowski <kjahds@kjahds.com>,
7 8
 *  Copyright (C) 2000  Lineo Inc. (www.lineo.com)
 *  Copyright (C) 2004-2006  Macq Electronique SA. (www.macqel.com)
L
Linus Torvalds 已提交
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
 *
 * Based on:
 *
 *  linux/arch/m68k/kernel/entry.S
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file README.legal in the main directory of this archive
 * for more details.
 *
 * Linux/m68k support by Hamish Macdonald
 *
 * 68060 fixes by Jesper Skov
 * ColdFire support by Greg Ungerer (gerg@snapgear.com)
 * 5307 fixes by David W. Miller
 * linux 2.4 support David McCullough <davidm@snapgear.com>
 * Bug, speed and maintainability fixes by Philippe De Muyter <phdm@macqel.be>
 */

#include <linux/sys.h>
#include <linux/linkage.h>
#include <asm/unistd.h>
#include <asm/thread_info.h>
#include <asm/errno.h>
#include <asm/setup.h>
#include <asm/segment.h>
#include <asm/asm-offsets.h>
#include <asm/entry.h>

.bss

sw_ksp:
.long	0

sw_usp:
.long	0

.text

.globl system_call
.globl resume
.globl ret_from_exception
.globl ret_from_signal
.globl sys_call_table
.globl ret_from_interrupt
.globl inthandler
.globl fasthandler

58 59 60 61
enosys:
	mov.l	#sys_ni_syscall,%d3
	bra	1f

L
Linus Torvalds 已提交
62 63 64 65
ENTRY(system_call)
	SAVE_ALL
	move	#0x2000,%sr		/* enable intrs again */

66 67
	cmpl	#NR_syscalls,%d0
	jcc	enosys
L
Linus Torvalds 已提交
68
	lea	sys_call_table,%a0
69 70 71
	lsll	#2,%d0			/* movel %a0@(%d0:l:4),%d3 */
	movel	%a0@(%d0),%d3
	jeq	enosys
L
Linus Torvalds 已提交
72

73
1:
L
Linus Torvalds 已提交
74 75 76
	movel	%sp,%d2			/* get thread_info pointer */
	andl	#-THREAD_SIZE,%d2	/* at start of kernel stack */
	movel	%d2,%a0
M
Matt Waddel 已提交
77 78
	movel	%a0@,%a1		/* save top of frame */
	movel	%sp,%a1@(TASK_THREAD+THREAD_ESP0)
79
	btst	#(TIF_SYSCALL_TRACE%8),%a0@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
L
Linus Torvalds 已提交
80 81 82 83 84 85 86
	bnes	1f

	movel	%d3,%a0
	jbsr	%a0@
	movel	%d0,%sp@(PT_D0)		/* save the return value */
	jra	ret_from_exception
1:
M
Matt Waddel 已提交
87 88
	movel	#-ENOSYS,%d2		/* strace needs -ENOSYS in PT_D0 */
	movel	%d2,PT_D0(%sp)		/* on syscall entry */
L
Linus Torvalds 已提交
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
	subql	#4,%sp
	SAVE_SWITCH_STACK
	jbsr	syscall_trace
	RESTORE_SWITCH_STACK
	addql	#4,%sp
	movel	%d3,%a0
	jbsr	%a0@
	movel	%d0,%sp@(PT_D0)		/* save the return value */
	subql	#4,%sp			/* dummy return address */
	SAVE_SWITCH_STACK
	jbsr	syscall_trace

ret_from_signal:
	RESTORE_SWITCH_STACK
	addql	#4,%sp

ret_from_exception:
	btst	#5,%sp@(PT_SR)		/* check if returning to kernel */
	jeq	Luser_return		/* if so, skip resched, signals */

Lkernel_return:
	moveml	%sp@,%d1-%d5/%a0-%a2
	lea	%sp@(32),%sp		/* space for 8 regs */
	movel	%sp@+,%d0
	addql	#4,%sp			/* orig d0 */
	addl	%sp@+,%sp		/* stk adj */
	rte

Luser_return:
	movel	%sp,%d1			/* get thread_info pointer */
	andl	#-THREAD_SIZE,%d1	/* at base of kernel stack */
	movel	%d1,%a0
	movel	%a0@(TI_FLAGS),%d1	/* get thread_info->flags */
	andl	#_TIF_WORK_MASK,%d1
	jne	Lwork_to_do		/* still work to do */

Lreturn:
126 127
	move	#0x2700,%sr		/* disable intrs */
	movel	sw_usp,%a0		/* get usp */
L
Linus Torvalds 已提交
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
	movel	%sp@(PT_PC),%a0@-	/* copy exception program counter */
	movel	%sp@(PT_FORMATVEC),%a0@-/* copy exception format/vector/sr */
	moveml	%sp@,%d1-%d5/%a0-%a2
	lea	%sp@(32),%sp		/* space for 8 regs */
	movel	%sp@+,%d0
	addql	#4,%sp			/* orig d0 */
	addl	%sp@+,%sp		/* stk adj */
	addql	#8,%sp			/* remove exception */
	movel	%sp,sw_ksp		/* save ksp */
	subql	#8,sw_usp		/* set exception */
	movel	sw_usp,%sp		/* restore usp */
	rte

Lwork_to_do:
	movel	%a0@(TI_FLAGS),%d1	/* get thread_info->flags */
	btst	#TIF_NEED_RESCHED,%d1
	jne	reschedule

	/* GERG: do we need something here for TRACEing?? */

Lsignal_return:
	subql	#4,%sp			/* dummy return address */
	SAVE_SWITCH_STACK
	pea	%sp@(SWITCH_STACK_SIZE)
	clrl	%sp@-
	jsr	do_signal
	addql	#8,%sp
	RESTORE_SWITCH_STACK
	addql	#4,%sp
	jmp	Lreturn

/*
 * This is the generic interrupt handler (for all hardware interrupt
G
Greg Ungerer 已提交
161
 * sources). Calls upto high level code to do all the work.
L
Linus Torvalds 已提交
162 163 164 165 166 167
 */
ENTRY(inthandler)
	SAVE_ALL
	moveq	#-1,%d0
	movel	%d0,%sp@(PT_ORIG_D0)

168
	movew	%sp@(PT_FORMATVEC),%d0	/* put exception # in d0 */
L
Linus Torvalds 已提交
169 170
	andl	#0x03fc,%d0		/* mask out vector only */

G
Greg Ungerer 已提交
171
	movel	%sp,%sp@-		/* push regs arg */
L
Linus Torvalds 已提交
172
	lsrl	#2,%d0			/* calculate real vector # */
G
Greg Ungerer 已提交
173 174 175
	movel	%d0,%sp@-		/* push vector number */
	jbsr	do_IRQ			/* call high level irq handler */
	lea	%sp@(8),%sp		/* pop args off stack */
L
Linus Torvalds 已提交
176 177 178 179 180 181 182 183 184 185 186 187

	bra	ret_from_interrupt	/* this was fallthrough */

/*
 * This is the fast interrupt handler (for certain hardware interrupt
 * sources). Unlike the normal interrupt handler it just uses the
 * current stack (doesn't care if it is user or kernel). It also
 * doesn't bother doing the bottom half handlers.
 */
ENTRY(fasthandler)
	SAVE_LOCAL

188
	movew	%sp@(PT_FORMATVEC),%d0
L
Linus Torvalds 已提交
189 190
	andl	#0x03fc,%d0		/* mask out vector only */

G
Greg Ungerer 已提交
191
	movel	%sp,%sp@-		/* push regs arg */
L
Linus Torvalds 已提交
192
	lsrl	#2,%d0			/* calculate real vector # */
G
Greg Ungerer 已提交
193 194 195
	movel	%d0,%sp@-		/* push vector number */
	jbsr	do_IRQ			/* call high level irq handler */
	lea	%sp@(8),%sp		/* pop args off stack */
L
Linus Torvalds 已提交
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218

	RESTORE_LOCAL

ENTRY(ret_from_interrupt)
	jeq	2f
1:
	RESTORE_ALL
2:
	moveb	%sp@(PT_SR),%d0
	andl	#0x7,%d0
	jhi	1b

	/* check if we need to do software interrupts */
	movel	irq_stat+CPUSTAT_SOFTIRQ_PENDING,%d0
	jeq	ret_from_exception

	pea	ret_from_exception
	jmp	do_softirq

/*
 * Beware - when entering resume, prev (the current task) is
 * in a0, next (the new task) is in a1,so don't change these
 * registers until their contents are no longer needed.
219 220
 * This is always called in supervisor mode, so don't bother to save
 * and restore sr; user's process sr is actually in the stack.
L
Linus Torvalds 已提交
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
 */
ENTRY(resume)
	movel	%a0, %d1			/* get prev thread in d1 */

	movel	sw_usp,%d0			/* save usp */
	movel	%d0,%a0@(TASK_THREAD+THREAD_USP)

	SAVE_SWITCH_STACK
	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack pointer */
	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
	RESTORE_SWITCH_STACK

	movel	%a1@(TASK_THREAD+THREAD_USP),%a0 /* restore thread user stack */
	movel	%a0, sw_usp
	rts