blob: 9ddf5476ef8f0eb49970f74dcf93de3f24bc5eca [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/arch/m68knommu/platform/5307/entry.S
3 *
4 * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
5 * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
6 * Kenneth Albanowski <kjahds@kjahds.com>,
Philippe De Muyter623f5232006-06-26 11:37:57 +10007 * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
8 * Copyright (C) 2004-2006 Macq Electronique SA. (www.macqel.com)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 *
10 * Based on:
11 *
12 * linux/arch/m68k/kernel/entry.S
13 *
14 * Copyright (C) 1991, 1992 Linus Torvalds
15 *
16 * This file is subject to the terms and conditions of the GNU General Public
17 * License. See the file README.legal in the main directory of this archive
18 * for more details.
19 *
20 * Linux/m68k support by Hamish Macdonald
21 *
22 * 68060 fixes by Jesper Skov
23 * ColdFire support by Greg Ungerer (gerg@snapgear.com)
24 * 5307 fixes by David W. Miller
25 * linux 2.4 support David McCullough <davidm@snapgear.com>
26 * Bug, speed and maintainability fixes by Philippe De Muyter <phdm@macqel.be>
27 */
28
29#include <linux/config.h>
30#include <linux/sys.h>
31#include <linux/linkage.h>
32#include <asm/unistd.h>
33#include <asm/thread_info.h>
34#include <asm/errno.h>
35#include <asm/setup.h>
36#include <asm/segment.h>
37#include <asm/asm-offsets.h>
38#include <asm/entry.h>
39
40.bss
41
42sw_ksp:
43.long 0
44
45sw_usp:
46.long 0
47
48.text
49
50.globl system_call
51.globl resume
52.globl ret_from_exception
53.globl ret_from_signal
54.globl sys_call_table
55.globl ret_from_interrupt
56.globl inthandler
57.globl fasthandler
58
Philippe De Muyter623f5232006-06-26 11:37:57 +100059enosys:
60 mov.l #sys_ni_syscall,%d3
61 bra 1f
62
Linus Torvalds1da177e2005-04-16 15:20:36 -070063ENTRY(system_call)
64 SAVE_ALL
65 move #0x2000,%sr /* enable intrs again */
66
Philippe De Muyter623f5232006-06-26 11:37:57 +100067 cmpl #NR_syscalls,%d0
68 jcc enosys
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 lea sys_call_table,%a0
Philippe De Muyter623f5232006-06-26 11:37:57 +100070 lsll #2,%d0 /* movel %a0@(%d0:l:4),%d3 */
71 movel %a0@(%d0),%d3
72 jeq enosys
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
Philippe De Muyter623f5232006-06-26 11:37:57 +1000741:
Linus Torvalds1da177e2005-04-16 15:20:36 -070075 movel %sp,%d2 /* get thread_info pointer */
76 andl #-THREAD_SIZE,%d2 /* at start of kernel stack */
77 movel %d2,%a0
Philippe De Muyter623f5232006-06-26 11:37:57 +100078 movel %sp,%a0@(THREAD_ESP0) /* save top of frame */
79 btst #(TIF_SYSCALL_TRACE%8),%a0@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 bnes 1f
81
82 movel %d3,%a0
83 jbsr %a0@
84 movel %d0,%sp@(PT_D0) /* save the return value */
85 jra ret_from_exception
861:
87 subql #4,%sp
88 SAVE_SWITCH_STACK
89 jbsr syscall_trace
90 RESTORE_SWITCH_STACK
91 addql #4,%sp
92 movel %d3,%a0
93 jbsr %a0@
94 movel %d0,%sp@(PT_D0) /* save the return value */
95 subql #4,%sp /* dummy return address */
96 SAVE_SWITCH_STACK
97 jbsr syscall_trace
98
99ret_from_signal:
100 RESTORE_SWITCH_STACK
101 addql #4,%sp
102
103ret_from_exception:
104 btst #5,%sp@(PT_SR) /* check if returning to kernel */
105 jeq Luser_return /* if so, skip resched, signals */
106
107Lkernel_return:
108 moveml %sp@,%d1-%d5/%a0-%a2
109 lea %sp@(32),%sp /* space for 8 regs */
110 movel %sp@+,%d0
111 addql #4,%sp /* orig d0 */
112 addl %sp@+,%sp /* stk adj */
113 rte
114
115Luser_return:
116 movel %sp,%d1 /* get thread_info pointer */
117 andl #-THREAD_SIZE,%d1 /* at base of kernel stack */
118 movel %d1,%a0
119 movel %a0@(TI_FLAGS),%d1 /* get thread_info->flags */
120 andl #_TIF_WORK_MASK,%d1
121 jne Lwork_to_do /* still work to do */
122
123Lreturn:
Philippe De Muyter623f5232006-06-26 11:37:57 +1000124 move #0x2700,%sr /* disable intrs */
125 movel sw_usp,%a0 /* get usp */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 movel %sp@(PT_PC),%a0@- /* copy exception program counter */
127 movel %sp@(PT_FORMATVEC),%a0@-/* copy exception format/vector/sr */
128 moveml %sp@,%d1-%d5/%a0-%a2
129 lea %sp@(32),%sp /* space for 8 regs */
130 movel %sp@+,%d0
131 addql #4,%sp /* orig d0 */
132 addl %sp@+,%sp /* stk adj */
133 addql #8,%sp /* remove exception */
134 movel %sp,sw_ksp /* save ksp */
135 subql #8,sw_usp /* set exception */
136 movel sw_usp,%sp /* restore usp */
137 rte
138
139Lwork_to_do:
140 movel %a0@(TI_FLAGS),%d1 /* get thread_info->flags */
141 btst #TIF_NEED_RESCHED,%d1
142 jne reschedule
143
144 /* GERG: do we need something here for TRACEing?? */
145
146Lsignal_return:
147 subql #4,%sp /* dummy return address */
148 SAVE_SWITCH_STACK
149 pea %sp@(SWITCH_STACK_SIZE)
150 clrl %sp@-
151 jsr do_signal
152 addql #8,%sp
153 RESTORE_SWITCH_STACK
154 addql #4,%sp
155 jmp Lreturn
156
157/*
158 * This is the generic interrupt handler (for all hardware interrupt
159 * sources). It figures out the vector number and calls the appropriate
160 * interrupt service routine directly.
161 */
162ENTRY(inthandler)
163 SAVE_ALL
164 moveq #-1,%d0
165 movel %d0,%sp@(PT_ORIG_D0)
166 addql #1,local_irq_count
167
Philippe De Muyter623f5232006-06-26 11:37:57 +1000168 movew %sp@(PT_FORMATVEC),%d0 /* put exception # in d0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 andl #0x03fc,%d0 /* mask out vector only */
170
171 leal per_cpu__kstat+STAT_IRQ,%a0
172 addql #1,%a0@(%d0)
173
174 lsrl #2,%d0 /* calculate real vector # */
175 movel %d0,%d1 /* calculate array offset */
176 lsll #4,%d1
177 lea irq_list,%a0
178 addl %d1,%a0 /* pointer to array struct */
179
180 movel %sp,%sp@- /* push regs arg onto stack */
181 movel %a0@(8),%sp@- /* push devid arg */
Philippe De Muyter623f5232006-06-26 11:37:57 +1000182 movel %d0,%sp@- /* push vector # on stack */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183
184 movel %a0@,%a0 /* get function to call */
185 jbsr %a0@ /* call vector handler */
186 lea %sp@(12),%sp /* pop parameters off stack */
187
188 bra ret_from_interrupt /* this was fallthrough */
189
190/*
191 * This is the fast interrupt handler (for certain hardware interrupt
192 * sources). Unlike the normal interrupt handler it just uses the
193 * current stack (doesn't care if it is user or kernel). It also
194 * doesn't bother doing the bottom half handlers.
195 */
196ENTRY(fasthandler)
197 SAVE_LOCAL
198
Philippe De Muyter623f5232006-06-26 11:37:57 +1000199 movew %sp@(PT_FORMATVEC),%d0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 andl #0x03fc,%d0 /* mask out vector only */
201
202 leal per_cpu__kstat+STAT_IRQ,%a0
203 addql #1,%a0@(%d0)
204
205 movel %sp,%sp@- /* push regs arg onto stack */
206 clrl %sp@- /* push devid arg */
207 lsrl #2,%d0 /* calculate real vector # */
Philippe De Muyter623f5232006-06-26 11:37:57 +1000208 movel %d0,%sp@- /* push vector # on stack */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209
210 lsll #4,%d0 /* adjust for array offset */
211 lea irq_list,%a0
212 movel %a0@(%d0),%a0 /* get function to call */
213 jbsr %a0@ /* call vector handler */
214 lea %sp@(12),%sp /* pop parameters off stack */
215
216 RESTORE_LOCAL
217
218ENTRY(ret_from_interrupt)
219 subql #1,local_irq_count
220 jeq 2f
2211:
222 RESTORE_ALL
2232:
224 moveb %sp@(PT_SR),%d0
225 andl #0x7,%d0
226 jhi 1b
227
228 /* check if we need to do software interrupts */
229 movel irq_stat+CPUSTAT_SOFTIRQ_PENDING,%d0
230 jeq ret_from_exception
231
232 pea ret_from_exception
233 jmp do_softirq
234
235/*
236 * Beware - when entering resume, prev (the current task) is
237 * in a0, next (the new task) is in a1,so don't change these
238 * registers until their contents are no longer needed.
239 */
240ENTRY(resume)
241 movel %a0, %d1 /* get prev thread in d1 */
242
243 movew %sr,%d0 /* save thread status reg */
244 movew %d0,%a0@(TASK_THREAD+THREAD_SR)
245
246 oril #0x700,%d0 /* disable interrupts */
247 move %d0,%sr
248
249 movel sw_usp,%d0 /* save usp */
250 movel %d0,%a0@(TASK_THREAD+THREAD_USP)
251
252 SAVE_SWITCH_STACK
253 movel %sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack pointer */
254 movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
255 RESTORE_SWITCH_STACK
256
257 movel %a1@(TASK_THREAD+THREAD_USP),%a0 /* restore thread user stack */
258 movel %a0, sw_usp
259
260 movew %a1@(TASK_THREAD+THREAD_SR),%d0 /* restore thread status reg */
261 movew %d0, %sr
262 rts