📄 entry.s
字号:
/* -*- mode: asm -*- * * 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 * *//* * entry.S contains the system-call and fault low-level handling routines. * This also contains the timer-interrupt handler, as well as all interrupts * and faults that can result in a task-switch. * * NOTE: This code handles signal-recognition, which happens every time * after a timer-interrupt and after each system call. * *//* * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so * all pointers that used to be 'current' are now entry * number 0 in the 'current_set' list. * * 6/05/00 RZ: addedd writeback completion after return from sighandler * for 68040 */#include <linux/config.h>#include <linux/linkage.h>#include <asm/entry.h>#include <asm/errno.h>#include <asm/setup.h>#include <asm/segment.h>#include <asm/traps.h>#include <asm/unistd.h>#include <asm/asm-offsets.h>.globl system_call, buserr, trap, resume.globl inthandler, sys_call_table.globl sys_fork, sys_clone, sys_vfork.globl ret_from_interrupt, bad_interrupt.textENTRY(buserr) SAVE_ALL_INT GET_CURRENT(%d0) movel %sp,%sp@- | stack frame pointer argument bsrl buserr_c addql #4,%sp jra .Lret_from_exceptionENTRY(trap) SAVE_ALL_INT GET_CURRENT(%d0) movel %sp,%sp@- | stack frame pointer argument bsrl trap_c addql #4,%sp jra .Lret_from_exception | After a fork we jump here directly from resume, | so that %d1 contains the previous task | schedule_tail now used regardless of CONFIG_SMPENTRY(ret_from_fork) movel %d1,%sp@- jsr schedule_tail addql #4,%sp jra .Lret_from_exceptiondo_trace_entry: movel #-ENOSYS,%sp@(PT_D0) | needed for strace subql #4,%sp SAVE_SWITCH_STACK jbsr syscall_trace RESTORE_SWITCH_STACK addql #4,%sp movel %sp@(PT_ORIG_D0),%d0 cmpl #NR_syscalls,%d0 jcs syscallbadsys: movel #-ENOSYS,%sp@(PT_D0) jra ret_from_syscalldo_trace_exit: subql #4,%sp SAVE_SWITCH_STACK jbsr syscall_trace RESTORE_SWITCH_STACK addql #4,%sp jra .Lret_from_exceptionENTRY(ret_from_signal) RESTORE_SWITCH_STACK addql #4,%sp/* on 68040 complete pending writebacks if any */#ifdef CONFIG_M68040 bfextu %sp@(PT_VECTOR){#0,#4},%d0 subql #7,%d0 | bus error frame ? jbne 1f movel %sp,%sp@- jbsr berr_040cleanup addql #4,%sp1:#endif jra .Lret_from_exceptionENTRY(system_call) SAVE_ALL_SYS GET_CURRENT(%d1) | save top of frame movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) | syscall trace? tstb %curptr@(TASK_INFO+TINFO_FLAGS+2) jmi do_trace_entry cmpl #NR_syscalls,%d0 jcc badsyssyscall: jbsr @(sys_call_table,%d0:l:4)@(0) movel %d0,%sp@(PT_D0) | save the return valueret_from_syscall: |oriw #0x0700,%sr movew %curptr@(TASK_INFO+TINFO_FLAGS+2),%d0 jne syscall_exit_work1: RESTORE_ALLsyscall_exit_work: btst #5,%sp@(PT_SR) | check if returning to kernel bnes 1b | if so, skip resched, signals lslw #1,%d0 jcs do_trace_exit jmi do_delayed_trace lslw #8,%d0 jmi do_signal_return pea resume_userspace jra scheduleENTRY(ret_from_exception).Lret_from_exception: btst #5,%sp@(PT_SR) | check if returning to kernel bnes 1f | if so, skip resched, signals | only allow interrupts when we are really the last one on the | kernel stack, otherwise stack overflow can occur during | heavy interrupt load andw #ALLOWINT,%srresume_userspace: moveb %curptr@(TASK_INFO+TINFO_FLAGS+3),%d0 jne exit_work1: RESTORE_ALLexit_work: | save top of frame movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) lslb #1,%d0 jmi do_signal_return pea resume_userspace jra scheduledo_signal_return: |andw #ALLOWINT,%sr subql #4,%sp | dummy return address SAVE_SWITCH_STACK pea %sp@(SWITCH_STACK_SIZE) clrl %sp@- bsrl do_signal addql #8,%sp RESTORE_SWITCH_STACK addql #4,%sp jbra resume_userspacedo_delayed_trace: bclr #7,%sp@(PT_SR) | clear trace bit in SR pea 1 | send SIGTRAP movel %curptr,%sp@- pea LSIGTRAP jbsr send_sig addql #8,%sp addql #4,%sp jbra resume_userspace#if 0#ifdef CONFIG_AMIGAami_inthandler: addql #1,irq_stat+CPUSTAT_LOCAL_IRQ_COUNT SAVE_ALL_INT GET_CURRENT(%d0) bfextu %sp@(PT_VECTOR){#4,#12},%d0 movel %d0,%a0 addql #1,%a0@(kstat+STAT_IRQ-VECOFF(VEC_SPUR)) movel %a0@(autoirq_list-VECOFF(VEC_SPUR)),%a0| amiga vector int handler get the req mask instead of irq vector lea CUSTOMBASE,%a1 movew %a1@(C_INTREQR),%d0 andw %a1@(C_INTENAR),%d0| prepare stack (push frame pointer, dev_id & req mask) pea %sp@ movel %a0@(IRQ_DEVID),%sp@- movel %d0,%sp@- pea %pc@(ret_from_interrupt:w) jbra @(IRQ_HANDLER,%a0)@(0)ENTRY(nmi_handler) rte#endif#endif/*** This is the main interrupt handler, responsible for calling process_int()*/inthandler: SAVE_ALL_INT GET_CURRENT(%d0) addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2) | put exception # in d0 bfextu %sp@(PT_VECTOR){#4,#10},%d0 movel %sp,%sp@- movel %d0,%sp@- | put vector # on stack#if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD) btstb #4,0xff000000 | Q40 floppy needs very special treatment ... jbeq 1f btstb #3,0xff000004 jbeq 1f jbsr floppy_hardint jbra 3f1:#endif jbsr process_int | process the IRQ3: addql #8,%sp | pop parameters off stackret_from_interrupt: subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2) jeq 1f2: RESTORE_ALL1: moveq #(~ALLOWINT>>8)&0xff,%d0 andb %sp@(PT_SR),%d0 jne 2b /* check if we need to do software interrupts */ tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING jeq .Lret_from_exception pea ret_from_exception jra do_softirq/* Handler for uninitialized and spurious interrupts */bad_interrupt: addql #1,num_spurious rteENTRY(sys_fork) SAVE_SWITCH_STACK pea %sp@(SWITCH_STACK_SIZE) jbsr m68k_fork addql #4,%sp RESTORE_SWITCH_STACK rtsENTRY(sys_clone) SAVE_SWITCH_STACK pea %sp@(SWITCH_STACK_SIZE) jbsr m68k_clone addql #4,%sp RESTORE_SWITCH_STACK rtsENTRY(sys_vfork) SAVE_SWITCH_STACK pea %sp@(SWITCH_STACK_SIZE) jbsr m68k_vfork addql #4,%sp RESTORE_SWITCH_STACK rtsENTRY(sys_sigsuspend) SAVE_SWITCH_STACK pea %sp@(SWITCH_STACK_SIZE) jbsr do_sigsuspend addql #4,%sp RESTORE_SWITCH_STACK rtsENTRY(sys_rt_sigsuspend) SAVE_SWITCH_STACK pea %sp@(SWITCH_STACK_SIZE) jbsr do_rt_sigsuspend addql #4,%sp RESTORE_SWITCH_STACK rtsENTRY(sys_sigreturn) SAVE_SWITCH_STACK jbsr do_sigreturn RESTORE_SWITCH_STACK rtsENTRY(sys_rt_sigreturn) SAVE_SWITCH_STACK jbsr do_rt_sigreturn RESTORE_SWITCH_STACK rtsresume: /* * 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. */ /* save sr */ movew %sr,%a0@(TASK_THREAD+THREAD_SR) /* save fs (sfc,%dfc) (may be pointing to kernel memory) */ movec %sfc,%d0 movew %d0,%a0@(TASK_THREAD+THREAD_FS) /* save usp */ /* it is better to use a movel here instead of a movew 8*) */ movec %usp,%d0 movel %d0,%a0@(TASK_THREAD+THREAD_USP) /* save non-scratch registers on stack */ SAVE_SWITCH_STACK /* save current kernel stack pointer */ movel %sp,%a0@(TASK_THREAD+THREAD_KSP) /* save floating point context */#ifndef CONFIG_M68KFPU_EMU_ONLY#ifdef CONFIG_M68KFPU_EMU tstl m68k_fputype jeq 3f#endif fsave %a0@(TASK_THREAD+THREAD_FPSTATE)#if defined(CONFIG_M68060)#if !defined(CPU_M68060_ONLY) btst #3,m68k_cputype+3 beqs 1f
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -