Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/arch/m68knommu/platform/5307/entry.S | |
3 | * | |
2502b667 | 4 | * Copyright (C) 1999-2007, Greg Ungerer (gerg@snapgear.com) |
1da177e4 LT |
5 | * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>, |
6 | * Kenneth Albanowski <kjahds@kjahds.com>, | |
623f523c PDM |
7 | * Copyright (C) 2000 Lineo Inc. (www.lineo.com) |
8 | * Copyright (C) 2004-2006 Macq Electronique SA. (www.macqel.com) | |
1da177e4 LT |
9 | * |
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 | ||
1da177e4 LT |
29 | #include <linux/sys.h> |
30 | #include <linux/linkage.h> | |
31 | #include <asm/unistd.h> | |
32 | #include <asm/thread_info.h> | |
33 | #include <asm/errno.h> | |
34 | #include <asm/setup.h> | |
35 | #include <asm/segment.h> | |
36 | #include <asm/asm-offsets.h> | |
37 | #include <asm/entry.h> | |
38 | ||
1c83af5f GU |
39 | #ifdef CONFIG_COLDFIRE_SW_A7 |
40 | /* | |
41 | * Define software copies of the supervisor and user stack pointers. | |
42 | */ | |
1da177e4 | 43 | .bss |
1da177e4 LT |
44 | sw_ksp: |
45 | .long 0 | |
1da177e4 LT |
46 | sw_usp: |
47 | .long 0 | |
1c83af5f | 48 | #endif /* CONFIG_COLDFIRE_SW_A7 */ |
1da177e4 LT |
49 | |
50 | .text | |
51 | ||
52 | .globl system_call | |
53 | .globl resume | |
54 | .globl ret_from_exception | |
55 | .globl ret_from_signal | |
56 | .globl sys_call_table | |
1da177e4 LT |
57 | .globl inthandler |
58 | .globl fasthandler | |
59 | ||
623f523c PDM |
60 | enosys: |
61 | mov.l #sys_ni_syscall,%d3 | |
62 | bra 1f | |
63 | ||
1da177e4 LT |
64 | ENTRY(system_call) |
65 | SAVE_ALL | |
66 | move #0x2000,%sr /* enable intrs again */ | |
67 | ||
623f523c PDM |
68 | cmpl #NR_syscalls,%d0 |
69 | jcc enosys | |
1da177e4 | 70 | lea sys_call_table,%a0 |
623f523c PDM |
71 | lsll #2,%d0 /* movel %a0@(%d0:l:4),%d3 */ |
72 | movel %a0@(%d0),%d3 | |
73 | jeq enosys | |
1da177e4 | 74 | |
623f523c | 75 | 1: |
1da177e4 LT |
76 | movel %sp,%d2 /* get thread_info pointer */ |
77 | andl #-THREAD_SIZE,%d2 /* at start of kernel stack */ | |
78 | movel %d2,%a0 | |
151941a8 MW |
79 | movel %a0@,%a1 /* save top of frame */ |
80 | movel %sp,%a1@(TASK_THREAD+THREAD_ESP0) | |
623f523c | 81 | btst #(TIF_SYSCALL_TRACE%8),%a0@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8) |
1da177e4 LT |
82 | bnes 1f |
83 | ||
84 | movel %d3,%a0 | |
85 | jbsr %a0@ | |
c84b564e | 86 | movel %d0,%sp@(PT_OFF_D0) /* save the return value */ |
1da177e4 LT |
87 | jra ret_from_exception |
88 | 1: | |
c84b564e GU |
89 | movel #-ENOSYS,%d2 /* strace needs -ENOSYS in PT_OFF_D0 */ |
90 | movel %d2,PT_OFF_D0(%sp) /* on syscall entry */ | |
1da177e4 LT |
91 | subql #4,%sp |
92 | SAVE_SWITCH_STACK | |
55f411de | 93 | jbsr syscall_trace_enter |
1da177e4 LT |
94 | RESTORE_SWITCH_STACK |
95 | addql #4,%sp | |
96 | movel %d3,%a0 | |
97 | jbsr %a0@ | |
c84b564e | 98 | movel %d0,%sp@(PT_OFF_D0) /* save the return value */ |
1da177e4 LT |
99 | subql #4,%sp /* dummy return address */ |
100 | SAVE_SWITCH_STACK | |
55f411de | 101 | jbsr syscall_trace_leave |
1da177e4 LT |
102 | |
103 | ret_from_signal: | |
104 | RESTORE_SWITCH_STACK | |
105 | addql #4,%sp | |
106 | ||
107 | ret_from_exception: | |
6c5a7d50 | 108 | move #0x2700,%sr /* disable intrs */ |
c84b564e | 109 | btst #5,%sp@(PT_OFF_SR) /* check if returning to kernel */ |
1da177e4 LT |
110 | jeq Luser_return /* if so, skip resched, signals */ |
111 | ||
a19325a7 SS |
112 | #ifdef CONFIG_PREEMPT |
113 | movel %sp,%d1 /* get thread_info pointer */ | |
114 | andl #-THREAD_SIZE,%d1 /* at base of kernel stack */ | |
115 | movel %d1,%a0 | |
116 | movel %a0@(TI_FLAGS),%d1 /* get thread_info->flags */ | |
cddafa35 | 117 | andl #(1<<TIF_NEED_RESCHED),%d1 |
a19325a7 SS |
118 | jeq Lkernel_return |
119 | ||
120 | movel %a0@(TI_PREEMPTCOUNT),%d1 | |
121 | cmpl #0,%d1 | |
122 | jne Lkernel_return | |
123 | ||
124 | pea Lkernel_return | |
125 | jmp preempt_schedule_irq /* preempt the kernel */ | |
126 | #endif | |
127 | ||
1da177e4 LT |
128 | Lkernel_return: |
129 | moveml %sp@,%d1-%d5/%a0-%a2 | |
130 | lea %sp@(32),%sp /* space for 8 regs */ | |
131 | movel %sp@+,%d0 | |
132 | addql #4,%sp /* orig d0 */ | |
133 | addl %sp@+,%sp /* stk adj */ | |
134 | rte | |
135 | ||
136 | Luser_return: | |
137 | movel %sp,%d1 /* get thread_info pointer */ | |
138 | andl #-THREAD_SIZE,%d1 /* at base of kernel stack */ | |
139 | movel %d1,%a0 | |
140 | movel %a0@(TI_FLAGS),%d1 /* get thread_info->flags */ | |
1da177e4 LT |
141 | jne Lwork_to_do /* still work to do */ |
142 | ||
143 | Lreturn: | |
1c83af5f | 144 | RESTORE_USER |
1da177e4 LT |
145 | |
146 | Lwork_to_do: | |
147 | movel %a0@(TI_FLAGS),%d1 /* get thread_info->flags */ | |
6c5a7d50 | 148 | move #0x2000,%sr /* enable intrs again */ |
1da177e4 LT |
149 | btst #TIF_NEED_RESCHED,%d1 |
150 | jne reschedule | |
151 | ||
152 | /* GERG: do we need something here for TRACEing?? */ | |
153 | ||
154 | Lsignal_return: | |
155 | subql #4,%sp /* dummy return address */ | |
156 | SAVE_SWITCH_STACK | |
157 | pea %sp@(SWITCH_STACK_SIZE) | |
1da177e4 | 158 | jsr do_signal |
710e91e4 | 159 | addql #4,%sp |
1da177e4 LT |
160 | RESTORE_SWITCH_STACK |
161 | addql #4,%sp | |
d1574df7 | 162 | jmp Luser_return |
1da177e4 LT |
163 | |
164 | /* | |
165 | * This is the generic interrupt handler (for all hardware interrupt | |
25985edc | 166 | * sources). Calls up to high level code to do all the work. |
1da177e4 LT |
167 | */ |
168 | ENTRY(inthandler) | |
169 | SAVE_ALL | |
170 | moveq #-1,%d0 | |
c84b564e | 171 | movel %d0,%sp@(PT_OFF_ORIG_D0) |
1da177e4 | 172 | |
c84b564e | 173 | movew %sp@(PT_OFF_FORMATVEC),%d0 /* put exception # in d0 */ |
1da177e4 LT |
174 | andl #0x03fc,%d0 /* mask out vector only */ |
175 | ||
2502b667 | 176 | movel %sp,%sp@- /* push regs arg */ |
1da177e4 | 177 | lsrl #2,%d0 /* calculate real vector # */ |
2502b667 GU |
178 | movel %d0,%sp@- /* push vector number */ |
179 | jbsr do_IRQ /* call high level irq handler */ | |
180 | lea %sp@(8),%sp /* pop args off stack */ | |
1da177e4 | 181 | |
fb670fb8 | 182 | bra ret_from_exception |
1da177e4 LT |
183 | |
184 | /* | |
185 | * Beware - when entering resume, prev (the current task) is | |
186 | * in a0, next (the new task) is in a1,so don't change these | |
187 | * registers until their contents are no longer needed. | |
7160a673 GU |
188 | * This is always called in supervisor mode, so don't bother to save |
189 | * and restore sr; user's process sr is actually in the stack. | |
1da177e4 LT |
190 | */ |
191 | ENTRY(resume) | |
192 | movel %a0, %d1 /* get prev thread in d1 */ | |
1c83af5f GU |
193 | RDUSP |
194 | movel %a2,%a0@(TASK_THREAD+THREAD_USP) | |
1da177e4 LT |
195 | |
196 | SAVE_SWITCH_STACK | |
197 | movel %sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack pointer */ | |
198 | movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */ | |
199 | RESTORE_SWITCH_STACK | |
200 | ||
201 | movel %a1@(TASK_THREAD+THREAD_USP),%a0 /* restore thread user stack */ | |
1c83af5f | 202 | WRUSP |
1da177e4 | 203 | rts |