3 * linux/arch/m68k/kernel/entry.S
5 * Copyright (C) 1991, 1992 Linus Torvalds
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
11 * Linux/m68k support by Hamish Macdonald
13 * 68060 fixes by Jesper Skov
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.
22 * NOTE: This code handles signal-recognition, which happens every time
23 * after a timer-interrupt and after each system call.
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.
33 #include <linux/sys.h>
34 #include <linux/config.h>
35 #include <linux/linkage.h>
36 #include <asm/entry.h>
37 #include <asm/setup.h>
38 #include <asm/segment.h>
40 #include "m68k_defs.h"
42 .globl SYMBOL_NAME(system_call), SYMBOL_NAME(buserr), SYMBOL_NAME(trap)
43 .globl SYMBOL_NAME(resume), SYMBOL_NAME(ret_from_exception)
44 .globl SYMBOL_NAME(ret_from_signal)
45 .globl SYMBOL_NAME(inthandler), SYMBOL_NAME(sys_call_table)
46 .globl SYMBOL_NAME(sys_fork), SYMBOL_NAME(sys_clone)
47 .globl SYMBOL_NAME(ret_from_interrupt), SYMBOL_NAME(bad_interrupt)
53 movel %sp,%sp@- | stack frame pointer argument
54 bsrl SYMBOL_NAME(buserr_c)
56 jra SYMBOL_NAME(ret_from_exception)
61 movel %sp,%sp@- | stack frame pointer argument
62 bsrl SYMBOL_NAME(trap_c)
64 jra SYMBOL_NAME(ret_from_exception)
68 movel %sp,%curptr@(TS_ESP0)
70 pea SYMBOL_NAME(ret_from_exception)
71 jmp SYMBOL_NAME(schedule)
74 movel #-LENOSYS,LPT_OFF_D0(%sp)
75 jra SYMBOL_NAME(ret_from_exception)
78 movel #-LENOSYS,LPT_OFF_D0(%sp) | needed for strace
81 jbsr SYMBOL_NAME(syscall_trace)
84 jbsr @(SYMBOL_NAME(sys_call_table),%d2:l:4)@(0)
85 movel %d0,%sp@(LPT_OFF_D0) | save the return value
86 subql #4,%sp | dummy return address
88 jbsr SYMBOL_NAME(syscall_trace)
90 SYMBOL_NAME_LABEL(ret_from_signal)
93 jra SYMBOL_NAME(ret_from_exception)
101 movel %sp,%curptr@(TS_ESP0)
103 cmpl #NR_syscalls,%d2
105 btst #LPF_TRACESYS_BIT,%curptr@(LTASK_FLAGS+LPF_TRACESYS_OFF)
107 jbsr @(SYMBOL_NAME(sys_call_table),%d2:l:4)@(0)
108 movel %d0,%sp@(LPT_OFF_D0) | save the return value
110 SYMBOL_NAME_LABEL(ret_from_exception)
111 btst #5,%sp@(LPT_OFF_SR) | check if returning to kernel
112 bnes 2f | if so, skip resched, signals
113 | only allow interrupts when we are really the last one on the
114 | kernel stack, otherwise stack overflow can occur during
115 | heavy interupt load
117 tstl %curptr@(LTASK_NEEDRESCHED)
118 jne SYMBOL_NAME(reschedule)
119 cmpl #SYMBOL_NAME(task),%curptr | task[0] cannot have signals
121 | check for delayed trace
122 bclr #LPF_DTRACE_BIT,%curptr@(LTASK_FLAGS+LPF_DTRACE_OFF)
125 tstl %curptr@(LTASK_STATE) | state
126 jne SYMBOL_NAME(reschedule)
128 tstl %curptr@(LTASK_SIGPENDING)
133 subql #4,%sp | dummy return address
135 pea %sp@(SWITCH_STACK_SIZE)
137 bsrl SYMBOL_NAME(do_signal)
144 bclr #7,%sp@(LPT_OFF_SR) | clear trace bit in SR
148 jbsr SYMBOL_NAME(send_sig)
154 ** This is the main interrupt handler, responsible for calling process_int()
156 SYMBOL_NAME_LABEL(inthandler)
159 addql #1,SYMBOL_NAME(local_irq_count)
160 | put exception # in d0
161 bfextu %sp@(LPT_OFF_FORMATVEC){#4,#10},%d0
164 movel %d0,%sp@- | put vector # on stack
165 jbsr SYMBOL_NAME(process_int)| process the IRQ
166 addql #8,%sp | pop parameters off stack
168 SYMBOL_NAME_LABEL(ret_from_interrupt)
169 subql #1,SYMBOL_NAME(local_irq_count)
175 bfextu %sp@(LPT_OFF_SR){#5,#3},%d0 | Check for nested interrupt.
176 #if MAX_NOINT_IPL > 0
177 cmpiw #MAX_NOINT_IPL,%d0
181 /* check if we need to do software interrupts */
183 movel SYMBOL_NAME(bh_active),%d0
184 andl SYMBOL_NAME(bh_mask),%d0
185 jeq SYMBOL_NAME(ret_from_exception)
187 pea SYMBOL_NAME(ret_from_exception)
188 jra SYMBOL_NAME(do_bottom_half)
191 /* Handler for uninitialized and spurious interrupts */
193 SYMBOL_NAME_LABEL(bad_interrupt)
194 addql #1,SYMBOL_NAME(num_spurious)
199 pea %sp@(SWITCH_STACK_SIZE)
200 jbsr SYMBOL_NAME(m68k_fork)
207 pea %sp@(SWITCH_STACK_SIZE)
208 jbsr SYMBOL_NAME(m68k_clone)
213 ENTRY(sys_sigsuspend)
215 pea %sp@(SWITCH_STACK_SIZE)
216 jbsr SYMBOL_NAME(do_sigsuspend)
221 ENTRY(sys_rt_sigsuspend)
223 pea %sp@(SWITCH_STACK_SIZE)
224 jbsr SYMBOL_NAME(do_rt_sigsuspend)
231 jbsr SYMBOL_NAME(do_sigreturn)
235 ENTRY(sys_rt_sigreturn)
237 jbsr SYMBOL_NAME(do_rt_sigreturn)
241 SYMBOL_NAME_LABEL(resume)
243 * Beware - when entering resume, offset of tss is in d1,
244 * prev (the current task) is in a0, next (the new task)
245 * is in a1 and d2.b is non-zero if the mm structure is
246 * shared between the tasks, so don't change these
247 * registers until their contents are no longer needed.
250 /* offset of tss struct (processor state) from beginning
255 movew %sr,%a0@(LTSS_SR)
257 /* save fs (sfc,%dfc) (may be pointing to kernel memory) */
259 movew %d0,%a0@(LTSS_FS)
262 /* it is better to use a movel here instead of a movew 8*) */
264 movel %d0,%a0@(LTSS_USP)
266 /* save non-scratch registers on stack */
269 /* save current kernel stack pointer */
270 movel %sp,%a0@(LTSS_KSP)
272 /* save floating point context */
273 fsave %a0@(LTSS_FPCTXT+27*4)
275 #if defined(CONFIG_M68060)
276 #if !defined(CPU_M68060_ONLY)
277 btst #3,SYMBOL_NAME(m68k_cputype)+3
280 /* The 060 FPU keeps status in bits 15-8 of the first longword */
281 tstb %a0@(LTSS_FPCTXT+27*4+2)
283 #if !defined(CPU_M68060_ONLY)
286 #endif /* CONFIG_M68060 */
287 #if !defined(CPU_M68060_ONLY)
288 1: tstb %a0@(LTSS_FPCTXT+27*4)
291 2: fmovemx %fp0-%fp7,%a0@(LTSS_FPCTXT)
292 fmoveml %fpcr/%fpsr/%fpiar,%a0@(LTSS_FPCTXT+24*4)
295 /* get pointer to tss struct (a1 contains new task) */
299 /* Skip address space switching if they are the same. */
303 #if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
304 /* 68040 or 68060 ? */
305 tstl SYMBOL_NAME(m68k_is040or060)
308 #if defined(CPU_M68020_OR_M68030)
310 * switch address space
313 /* flush MC68030/MC68020 caches (they are virtually addressed) */
315 oriw #LFLUSH_I_AND_D,%d0
318 /* switch the root pointer */
319 pmove %a1@(LTSS_CRP),%crp
322 #if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
323 jra 2f /* skip m68040 stuff */
326 #if defined(CPU_M68040_OR_M68060)
328 * switch address space
332 /* flush address translation cache (user entries) */
335 /* switch the root pointer */
336 movel %a1@(LTSS_CRP+4),%d0
339 #if defined (CONFIG_M68060)
341 #if !defined(CPU_M68060_ONLY)
342 btst #3,SYMBOL_NAME(m68k_cputype)+3
345 /* clear user entries in the branch cache */
349 #endif /* CONFIG_M68060 */
351 #endif /* CPU_M68040_OR_M68060 */
354 /* restore floating point context */
356 #if defined(CONFIG_M68060)
357 #if !defined(CPU_M68060_ONLY)
358 btst #3,SYMBOL_NAME(m68k_cputype)+3
361 /* The 060 FPU keeps status in bits 15-8 of the first longword */
362 tstb %a1@(LTSS_FPCTXT+27*4+2)
364 #if !defined(CPU_M68060_ONLY)
367 #endif /* CONFIG_M68060 */
368 #if !defined(CPU_M68060_ONLY)
369 1: tstb %a1@(LTSS_FPCTXT+27*4)
372 2: fmovemx %a1@(LTSS_FPCTXT),%fp0-%fp7
373 fmoveml %a1@(LTSS_FPCTXT+24*4),%fpcr/%fpsr/%fpiar
374 3: frestore %a1@(LTSS_FPCTXT+27*4)
376 /* restore the kernel stack pointer */
377 movel %a1@(LTSS_KSP),%sp
379 /* restore non-scratch registers */
382 /* restore user stack pointer */
383 movel %a1@(LTSS_USP),%a0
386 /* restore fs (sfc,%dfc) */
387 movew %a1@(LTSS_FS),%a0
391 /* restore status register */
392 movew %a1@(LTSS_SR),%sr
398 SYMBOL_NAME_LABEL(sys_call_table)
399 .long SYMBOL_NAME(sys_setup) /* 0 */
400 .long SYMBOL_NAME(sys_exit)
401 .long SYMBOL_NAME(sys_fork)
402 .long SYMBOL_NAME(sys_read)
403 .long SYMBOL_NAME(sys_write)
404 .long SYMBOL_NAME(sys_open) /* 5 */
405 .long SYMBOL_NAME(sys_close)
406 .long SYMBOL_NAME(sys_waitpid)
407 .long SYMBOL_NAME(sys_creat)
408 .long SYMBOL_NAME(sys_link)
409 .long SYMBOL_NAME(sys_unlink) /* 10 */
410 .long SYMBOL_NAME(sys_execve)
411 .long SYMBOL_NAME(sys_chdir)
412 .long SYMBOL_NAME(sys_time)
413 .long SYMBOL_NAME(sys_mknod)
414 .long SYMBOL_NAME(sys_chmod) /* 15 */
415 .long SYMBOL_NAME(sys_chown)
416 .long SYMBOL_NAME(sys_ni_syscall) /* old break syscall holder */
417 .long SYMBOL_NAME(sys_stat)
418 .long SYMBOL_NAME(sys_lseek)
419 .long SYMBOL_NAME(sys_getpid) /* 20 */
420 .long SYMBOL_NAME(sys_mount)
421 .long SYMBOL_NAME(sys_umount)
422 .long SYMBOL_NAME(sys_setuid)
423 .long SYMBOL_NAME(sys_getuid)
424 .long SYMBOL_NAME(sys_stime) /* 25 */
425 .long SYMBOL_NAME(sys_ptrace)
426 .long SYMBOL_NAME(sys_alarm)
427 .long SYMBOL_NAME(sys_fstat)
428 .long SYMBOL_NAME(sys_pause)
429 .long SYMBOL_NAME(sys_utime) /* 30 */
430 .long SYMBOL_NAME(sys_ni_syscall) /* old stty syscall holder */
431 .long SYMBOL_NAME(sys_ni_syscall) /* old gtty syscall holder */
432 .long SYMBOL_NAME(sys_access)
433 .long SYMBOL_NAME(sys_nice)
434 .long SYMBOL_NAME(sys_ni_syscall) /* 35 */ /* old ftime syscall holder */
435 .long SYMBOL_NAME(sys_sync)
436 .long SYMBOL_NAME(sys_kill)
437 .long SYMBOL_NAME(sys_rename)
438 .long SYMBOL_NAME(sys_mkdir)
439 .long SYMBOL_NAME(sys_rmdir) /* 40 */
440 .long SYMBOL_NAME(sys_dup)
441 .long SYMBOL_NAME(sys_pipe)
442 .long SYMBOL_NAME(sys_times)
443 .long SYMBOL_NAME(sys_ni_syscall) /* old prof syscall holder */
444 .long SYMBOL_NAME(sys_brk) /* 45 */
445 .long SYMBOL_NAME(sys_setgid)
446 .long SYMBOL_NAME(sys_getgid)
447 .long SYMBOL_NAME(sys_signal)
448 .long SYMBOL_NAME(sys_geteuid)
449 .long SYMBOL_NAME(sys_getegid) /* 50 */
450 .long SYMBOL_NAME(sys_acct)
451 .long SYMBOL_NAME(sys_ni_syscall) /* old phys syscall holder */
452 .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */
453 .long SYMBOL_NAME(sys_ioctl)
454 .long SYMBOL_NAME(sys_fcntl) /* 55 */
455 .long SYMBOL_NAME(sys_ni_syscall) /* old mpx syscall holder */
456 .long SYMBOL_NAME(sys_setpgid)
457 .long SYMBOL_NAME(sys_ni_syscall) /* old ulimit syscall holder */
458 .long SYMBOL_NAME(sys_ni_syscall)
459 .long SYMBOL_NAME(sys_umask) /* 60 */
460 .long SYMBOL_NAME(sys_chroot)
461 .long SYMBOL_NAME(sys_ustat)
462 .long SYMBOL_NAME(sys_dup2)
463 .long SYMBOL_NAME(sys_getppid)
464 .long SYMBOL_NAME(sys_getpgrp) /* 65 */
465 .long SYMBOL_NAME(sys_setsid)
466 .long SYMBOL_NAME(sys_sigaction)
467 .long SYMBOL_NAME(sys_sgetmask)
468 .long SYMBOL_NAME(sys_ssetmask)
469 .long SYMBOL_NAME(sys_setreuid) /* 70 */
470 .long SYMBOL_NAME(sys_setregid)
471 .long SYMBOL_NAME(sys_sigsuspend)
472 .long SYMBOL_NAME(sys_sigpending)
473 .long SYMBOL_NAME(sys_sethostname)
474 .long SYMBOL_NAME(sys_setrlimit) /* 75 */
475 .long SYMBOL_NAME(sys_getrlimit)
476 .long SYMBOL_NAME(sys_getrusage)
477 .long SYMBOL_NAME(sys_gettimeofday)
478 .long SYMBOL_NAME(sys_settimeofday)
479 .long SYMBOL_NAME(sys_getgroups) /* 80 */
480 .long SYMBOL_NAME(sys_setgroups)
481 .long SYMBOL_NAME(old_select)
482 .long SYMBOL_NAME(sys_symlink)
483 .long SYMBOL_NAME(sys_lstat)
484 .long SYMBOL_NAME(sys_readlink) /* 85 */
485 .long SYMBOL_NAME(sys_uselib)
486 .long SYMBOL_NAME(sys_swapon)
487 .long SYMBOL_NAME(sys_reboot)
488 .long SYMBOL_NAME(old_readdir)
489 .long SYMBOL_NAME(old_mmap) /* 90 */
490 .long SYMBOL_NAME(sys_munmap)
491 .long SYMBOL_NAME(sys_truncate)
492 .long SYMBOL_NAME(sys_ftruncate)
493 .long SYMBOL_NAME(sys_fchmod)
494 .long SYMBOL_NAME(sys_fchown) /* 95 */
495 .long SYMBOL_NAME(sys_getpriority)
496 .long SYMBOL_NAME(sys_setpriority)
497 .long SYMBOL_NAME(sys_ni_syscall) /* old profil syscall holder */
498 .long SYMBOL_NAME(sys_statfs)
499 .long SYMBOL_NAME(sys_fstatfs) /* 100 */
500 .long SYMBOL_NAME(sys_ioperm)
501 .long SYMBOL_NAME(sys_socketcall)
502 .long SYMBOL_NAME(sys_syslog)
503 .long SYMBOL_NAME(sys_setitimer)
504 .long SYMBOL_NAME(sys_getitimer) /* 105 */
505 .long SYMBOL_NAME(sys_newstat)
506 .long SYMBOL_NAME(sys_newlstat)
507 .long SYMBOL_NAME(sys_newfstat)
508 .long SYMBOL_NAME(sys_ni_syscall)
509 .long SYMBOL_NAME(sys_ni_syscall) /* iopl for i386 */ /* 110 */
510 .long SYMBOL_NAME(sys_vhangup)
511 .long SYMBOL_NAME(sys_idle)
512 .long SYMBOL_NAME(sys_ni_syscall) /* vm86old for i386 */
513 .long SYMBOL_NAME(sys_wait4)
514 .long SYMBOL_NAME(sys_swapoff) /* 115 */
515 .long SYMBOL_NAME(sys_sysinfo)
516 .long SYMBOL_NAME(sys_ipc)
517 .long SYMBOL_NAME(sys_fsync)
518 .long SYMBOL_NAME(sys_sigreturn)
519 .long SYMBOL_NAME(sys_clone) /* 120 */
520 .long SYMBOL_NAME(sys_setdomainname)
521 .long SYMBOL_NAME(sys_newuname)
522 .long SYMBOL_NAME(sys_cacheflush) /* modify_ldt for i386 */
523 .long SYMBOL_NAME(sys_adjtimex)
524 .long SYMBOL_NAME(sys_mprotect) /* 125 */
525 .long SYMBOL_NAME(sys_sigprocmask)
526 .long SYMBOL_NAME(sys_create_module)
527 .long SYMBOL_NAME(sys_init_module)
528 .long SYMBOL_NAME(sys_delete_module)
529 .long SYMBOL_NAME(sys_get_kernel_syms) /* 130 */
530 .long SYMBOL_NAME(sys_quotactl)
531 .long SYMBOL_NAME(sys_getpgid)
532 .long SYMBOL_NAME(sys_fchdir)
533 .long SYMBOL_NAME(sys_bdflush)
534 .long SYMBOL_NAME(sys_sysfs) /* 135 */
535 .long SYMBOL_NAME(sys_personality)
536 .long SYMBOL_NAME(sys_ni_syscall) /* for afs_syscall */
537 .long SYMBOL_NAME(sys_setfsuid)
538 .long SYMBOL_NAME(sys_setfsgid)
539 .long SYMBOL_NAME(sys_llseek) /* 140 */
540 .long SYMBOL_NAME(sys_getdents)
541 .long SYMBOL_NAME(sys_select)
542 .long SYMBOL_NAME(sys_flock)
543 .long SYMBOL_NAME(sys_msync)
544 .long SYMBOL_NAME(sys_readv) /* 145 */
545 .long SYMBOL_NAME(sys_writev)
546 .long SYMBOL_NAME(sys_getsid)
547 .long SYMBOL_NAME(sys_fdatasync)
548 .long SYMBOL_NAME(sys_sysctl)
549 .long SYMBOL_NAME(sys_mlock) /* 150 */
550 .long SYMBOL_NAME(sys_munlock)
551 .long SYMBOL_NAME(sys_mlockall)
552 .long SYMBOL_NAME(sys_munlockall)
553 .long SYMBOL_NAME(sys_sched_setparam)
554 .long SYMBOL_NAME(sys_sched_getparam) /* 155 */
555 .long SYMBOL_NAME(sys_sched_setscheduler)
556 .long SYMBOL_NAME(sys_sched_getscheduler)
557 .long SYMBOL_NAME(sys_sched_yield)
558 .long SYMBOL_NAME(sys_sched_get_priority_max)
559 .long SYMBOL_NAME(sys_sched_get_priority_min) /* 160 */
560 .long SYMBOL_NAME(sys_sched_rr_get_interval)
561 .long SYMBOL_NAME(sys_nanosleep)
562 .long SYMBOL_NAME(sys_mremap)
563 .long SYMBOL_NAME(sys_setresuid)
564 .long SYMBOL_NAME(sys_getresuid) /* 165 */
565 .long SYMBOL_NAME(sys_ni_syscall) /* for vm86 */
566 .long SYMBOL_NAME(sys_query_module)
567 .long SYMBOL_NAME(sys_poll)
568 .long SYMBOL_NAME(sys_nfsservctl)
569 .long SYMBOL_NAME(sys_setresgid) /* 170 */
570 .long SYMBOL_NAME(sys_getresgid)
571 .long SYMBOL_NAME(sys_prctl)
572 .long SYMBOL_NAME(sys_rt_sigreturn)
573 .long SYMBOL_NAME(sys_rt_sigaction)
574 .long SYMBOL_NAME(sys_rt_sigprocmask) /* 175 */
575 .long SYMBOL_NAME(sys_rt_sigpending)
576 .long SYMBOL_NAME(sys_rt_sigtimedwait)
577 .long SYMBOL_NAME(sys_rt_sigqueueinfo)
578 .long SYMBOL_NAME(sys_rt_sigsuspend)
579 .long SYMBOL_NAME(sys_pread) /* 180 */
580 .long SYMBOL_NAME(sys_pwrite)
581 .long SYMBOL_NAME(sys_lchown);
582 .long SYMBOL_NAME(sys_getcwd)
583 .long SYMBOL_NAME(sys_capget)
584 .long SYMBOL_NAME(sys_capset) /* 185 */
585 .long SYMBOL_NAME(sys_sigaltstack)
586 .long SYMBOL_NAME(sys_sendfile)
587 .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
588 .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
590 .rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4
591 .long SYMBOL_NAME(sys_ni_syscall)