Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/m68k/kernel/entry_mm.S
10817 views
1
/* -*- mode: asm -*-
2
*
3
* linux/arch/m68k/kernel/entry.S
4
*
5
* Copyright (C) 1991, 1992 Linus Torvalds
6
*
7
* This file is subject to the terms and conditions of the GNU General Public
8
* License. See the file README.legal in the main directory of this archive
9
* for more details.
10
*
11
* Linux/m68k support by Hamish Macdonald
12
*
13
* 68060 fixes by Jesper Skov
14
*
15
*/
16
17
/*
18
* entry.S contains the system-call and fault low-level handling routines.
19
* This also contains the timer-interrupt handler, as well as all interrupts
20
* and faults that can result in a task-switch.
21
*
22
* NOTE: This code handles signal-recognition, which happens every time
23
* after a timer-interrupt and after each system call.
24
*
25
*/
26
27
/*
28
* 12/03/96 Jes: Currently we only support m68k single-cpu systems, so
29
* all pointers that used to be 'current' are now entry
30
* number 0 in the 'current_set' list.
31
*
32
* 6/05/00 RZ: addedd writeback completion after return from sighandler
33
* for 68040
34
*/
35
36
#include <linux/linkage.h>
37
#include <asm/entry.h>
38
#include <asm/errno.h>
39
#include <asm/setup.h>
40
#include <asm/segment.h>
41
#include <asm/traps.h>
42
#include <asm/unistd.h>
43
44
#include <asm/asm-offsets.h>
45
46
.globl system_call, buserr, trap, resume
47
.globl sys_call_table
48
.globl sys_fork, sys_clone, sys_vfork
49
.globl ret_from_interrupt, bad_interrupt
50
.globl auto_irqhandler_fixup
51
.globl user_irqvec_fixup, user_irqhandler_fixup
52
53
.text
54
ENTRY(buserr)
55
SAVE_ALL_INT
56
GET_CURRENT(%d0)
57
movel %sp,%sp@- | stack frame pointer argument
58
bsrl buserr_c
59
addql #4,%sp
60
jra .Lret_from_exception
61
62
ENTRY(trap)
63
SAVE_ALL_INT
64
GET_CURRENT(%d0)
65
movel %sp,%sp@- | stack frame pointer argument
66
bsrl trap_c
67
addql #4,%sp
68
jra .Lret_from_exception
69
70
| After a fork we jump here directly from resume,
71
| so that %d1 contains the previous task
72
| schedule_tail now used regardless of CONFIG_SMP
73
ENTRY(ret_from_fork)
74
movel %d1,%sp@-
75
jsr schedule_tail
76
addql #4,%sp
77
jra .Lret_from_exception
78
79
do_trace_entry:
80
movel #-ENOSYS,%sp@(PT_OFF_D0)| needed for strace
81
subql #4,%sp
82
SAVE_SWITCH_STACK
83
jbsr syscall_trace
84
RESTORE_SWITCH_STACK
85
addql #4,%sp
86
movel %sp@(PT_OFF_ORIG_D0),%d0
87
cmpl #NR_syscalls,%d0
88
jcs syscall
89
badsys:
90
movel #-ENOSYS,%sp@(PT_OFF_D0)
91
jra ret_from_syscall
92
93
do_trace_exit:
94
subql #4,%sp
95
SAVE_SWITCH_STACK
96
jbsr syscall_trace
97
RESTORE_SWITCH_STACK
98
addql #4,%sp
99
jra .Lret_from_exception
100
101
ENTRY(ret_from_signal)
102
tstb %curptr@(TASK_INFO+TINFO_FLAGS+2)
103
jge 1f
104
jbsr syscall_trace
105
1: RESTORE_SWITCH_STACK
106
addql #4,%sp
107
/* on 68040 complete pending writebacks if any */
108
#ifdef CONFIG_M68040
109
bfextu %sp@(PT_OFF_FORMATVEC){#0,#4},%d0
110
subql #7,%d0 | bus error frame ?
111
jbne 1f
112
movel %sp,%sp@-
113
jbsr berr_040cleanup
114
addql #4,%sp
115
1:
116
#endif
117
jra .Lret_from_exception
118
119
ENTRY(system_call)
120
SAVE_ALL_SYS
121
122
GET_CURRENT(%d1)
123
| save top of frame
124
movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
125
126
| syscall trace?
127
tstb %curptr@(TASK_INFO+TINFO_FLAGS+2)
128
jmi do_trace_entry
129
cmpl #NR_syscalls,%d0
130
jcc badsys
131
syscall:
132
jbsr @(sys_call_table,%d0:l:4)@(0)
133
movel %d0,%sp@(PT_OFF_D0) | save the return value
134
ret_from_syscall:
135
|oriw #0x0700,%sr
136
movew %curptr@(TASK_INFO+TINFO_FLAGS+2),%d0
137
jne syscall_exit_work
138
1: RESTORE_ALL
139
140
syscall_exit_work:
141
btst #5,%sp@(PT_OFF_SR) | check if returning to kernel
142
bnes 1b | if so, skip resched, signals
143
lslw #1,%d0
144
jcs do_trace_exit
145
jmi do_delayed_trace
146
lslw #8,%d0
147
jmi do_signal_return
148
pea resume_userspace
149
jra schedule
150
151
152
ENTRY(ret_from_exception)
153
.Lret_from_exception:
154
btst #5,%sp@(PT_OFF_SR) | check if returning to kernel
155
bnes 1f | if so, skip resched, signals
156
| only allow interrupts when we are really the last one on the
157
| kernel stack, otherwise stack overflow can occur during
158
| heavy interrupt load
159
andw #ALLOWINT,%sr
160
161
resume_userspace:
162
moveb %curptr@(TASK_INFO+TINFO_FLAGS+3),%d0
163
jne exit_work
164
1: RESTORE_ALL
165
166
exit_work:
167
| save top of frame
168
movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
169
lslb #1,%d0
170
jmi do_signal_return
171
pea resume_userspace
172
jra schedule
173
174
175
do_signal_return:
176
|andw #ALLOWINT,%sr
177
subql #4,%sp | dummy return address
178
SAVE_SWITCH_STACK
179
pea %sp@(SWITCH_STACK_SIZE)
180
bsrl do_signal
181
addql #4,%sp
182
RESTORE_SWITCH_STACK
183
addql #4,%sp
184
jbra resume_userspace
185
186
do_delayed_trace:
187
bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR
188
pea 1 | send SIGTRAP
189
movel %curptr,%sp@-
190
pea LSIGTRAP
191
jbsr send_sig
192
addql #8,%sp
193
addql #4,%sp
194
jbra resume_userspace
195
196
197
/* This is the main interrupt handler for autovector interrupts */
198
199
ENTRY(auto_inthandler)
200
SAVE_ALL_INT
201
GET_CURRENT(%d0)
202
addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
203
| put exception # in d0
204
bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0
205
subw #VEC_SPUR,%d0
206
207
movel %sp,%sp@-
208
movel %d0,%sp@- | put vector # on stack
209
auto_irqhandler_fixup = . + 2
210
jsr __m68k_handle_int | process the IRQ
211
addql #8,%sp | pop parameters off stack
212
213
ret_from_interrupt:
214
subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
215
jeq ret_from_last_interrupt
216
2: RESTORE_ALL
217
218
ALIGN
219
ret_from_last_interrupt:
220
moveq #(~ALLOWINT>>8)&0xff,%d0
221
andb %sp@(PT_OFF_SR),%d0
222
jne 2b
223
224
/* check if we need to do software interrupts */
225
tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING
226
jeq .Lret_from_exception
227
pea ret_from_exception
228
jra do_softirq
229
230
/* Handler for user defined interrupt vectors */
231
232
ENTRY(user_inthandler)
233
SAVE_ALL_INT
234
GET_CURRENT(%d0)
235
addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
236
| put exception # in d0
237
bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0
238
user_irqvec_fixup = . + 2
239
subw #VEC_USER,%d0
240
241
movel %sp,%sp@-
242
movel %d0,%sp@- | put vector # on stack
243
user_irqhandler_fixup = . + 2
244
jsr __m68k_handle_int | process the IRQ
245
addql #8,%sp | pop parameters off stack
246
247
subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
248
jeq ret_from_last_interrupt
249
RESTORE_ALL
250
251
/* Handler for uninitialized and spurious interrupts */
252
253
ENTRY(bad_inthandler)
254
SAVE_ALL_INT
255
GET_CURRENT(%d0)
256
addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
257
258
movel %sp,%sp@-
259
jsr handle_badint
260
addql #4,%sp
261
262
subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
263
jeq ret_from_last_interrupt
264
RESTORE_ALL
265
266
267
ENTRY(sys_fork)
268
SAVE_SWITCH_STACK
269
pea %sp@(SWITCH_STACK_SIZE)
270
jbsr m68k_fork
271
addql #4,%sp
272
RESTORE_SWITCH_STACK
273
rts
274
275
ENTRY(sys_clone)
276
SAVE_SWITCH_STACK
277
pea %sp@(SWITCH_STACK_SIZE)
278
jbsr m68k_clone
279
addql #4,%sp
280
RESTORE_SWITCH_STACK
281
rts
282
283
ENTRY(sys_vfork)
284
SAVE_SWITCH_STACK
285
pea %sp@(SWITCH_STACK_SIZE)
286
jbsr m68k_vfork
287
addql #4,%sp
288
RESTORE_SWITCH_STACK
289
rts
290
291
ENTRY(sys_sigreturn)
292
SAVE_SWITCH_STACK
293
jbsr do_sigreturn
294
RESTORE_SWITCH_STACK
295
rts
296
297
ENTRY(sys_rt_sigreturn)
298
SAVE_SWITCH_STACK
299
jbsr do_rt_sigreturn
300
RESTORE_SWITCH_STACK
301
rts
302
303
resume:
304
/*
305
* Beware - when entering resume, prev (the current task) is
306
* in a0, next (the new task) is in a1,so don't change these
307
* registers until their contents are no longer needed.
308
*/
309
310
/* save sr */
311
movew %sr,%a0@(TASK_THREAD+THREAD_SR)
312
313
/* save fs (sfc,%dfc) (may be pointing to kernel memory) */
314
movec %sfc,%d0
315
movew %d0,%a0@(TASK_THREAD+THREAD_FS)
316
317
/* save usp */
318
/* it is better to use a movel here instead of a movew 8*) */
319
movec %usp,%d0
320
movel %d0,%a0@(TASK_THREAD+THREAD_USP)
321
322
/* save non-scratch registers on stack */
323
SAVE_SWITCH_STACK
324
325
/* save current kernel stack pointer */
326
movel %sp,%a0@(TASK_THREAD+THREAD_KSP)
327
328
/* save floating point context */
329
#ifndef CONFIG_M68KFPU_EMU_ONLY
330
#ifdef CONFIG_M68KFPU_EMU
331
tstl m68k_fputype
332
jeq 3f
333
#endif
334
fsave %a0@(TASK_THREAD+THREAD_FPSTATE)
335
336
#if defined(CONFIG_M68060)
337
#if !defined(CPU_M68060_ONLY)
338
btst #3,m68k_cputype+3
339
beqs 1f
340
#endif
341
/* The 060 FPU keeps status in bits 15-8 of the first longword */
342
tstb %a0@(TASK_THREAD+THREAD_FPSTATE+2)
343
jeq 3f
344
#if !defined(CPU_M68060_ONLY)
345
jra 2f
346
#endif
347
#endif /* CONFIG_M68060 */
348
#if !defined(CPU_M68060_ONLY)
349
1: tstb %a0@(TASK_THREAD+THREAD_FPSTATE)
350
jeq 3f
351
#endif
352
2: fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
353
fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL)
354
3:
355
#endif /* CONFIG_M68KFPU_EMU_ONLY */
356
/* Return previous task in %d1 */
357
movel %curptr,%d1
358
359
/* switch to new task (a1 contains new task) */
360
movel %a1,%curptr
361
362
/* restore floating point context */
363
#ifndef CONFIG_M68KFPU_EMU_ONLY
364
#ifdef CONFIG_M68KFPU_EMU
365
tstl m68k_fputype
366
jeq 4f
367
#endif
368
#if defined(CONFIG_M68060)
369
#if !defined(CPU_M68060_ONLY)
370
btst #3,m68k_cputype+3
371
beqs 1f
372
#endif
373
/* The 060 FPU keeps status in bits 15-8 of the first longword */
374
tstb %a1@(TASK_THREAD+THREAD_FPSTATE+2)
375
jeq 3f
376
#if !defined(CPU_M68060_ONLY)
377
jra 2f
378
#endif
379
#endif /* CONFIG_M68060 */
380
#if !defined(CPU_M68060_ONLY)
381
1: tstb %a1@(TASK_THREAD+THREAD_FPSTATE)
382
jeq 3f
383
#endif
384
2: fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
385
fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
386
3: frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
387
4:
388
#endif /* CONFIG_M68KFPU_EMU_ONLY */
389
390
/* restore the kernel stack pointer */
391
movel %a1@(TASK_THREAD+THREAD_KSP),%sp
392
393
/* restore non-scratch registers */
394
RESTORE_SWITCH_STACK
395
396
/* restore user stack pointer */
397
movel %a1@(TASK_THREAD+THREAD_USP),%a0
398
movel %a0,%usp
399
400
/* restore fs (sfc,%dfc) */
401
movew %a1@(TASK_THREAD+THREAD_FS),%a0
402
movec %a0,%sfc
403
movec %a0,%dfc
404
405
/* restore status register */
406
movew %a1@(TASK_THREAD+THREAD_SR),%sr
407
408
rts
409
410
411