Path: blob/master/arch/m68k/platform/coldfire/entry.S
10819 views
/*1* linux/arch/m68knommu/platform/5307/entry.S2*3* Copyright (C) 1999-2007, Greg Ungerer ([email protected])4* Copyright (C) 1998 D. Jeff Dionne <[email protected]>,5* Kenneth Albanowski <[email protected]>,6* Copyright (C) 2000 Lineo Inc. (www.lineo.com)7* Copyright (C) 2004-2006 Macq Electronique SA. (www.macqel.com)8*9* Based on:10*11* linux/arch/m68k/kernel/entry.S12*13* Copyright (C) 1991, 1992 Linus Torvalds14*15* This file is subject to the terms and conditions of the GNU General Public16* License. See the file README.legal in the main directory of this archive17* for more details.18*19* Linux/m68k support by Hamish Macdonald20*21* 68060 fixes by Jesper Skov22* ColdFire support by Greg Ungerer ([email protected])23* 5307 fixes by David W. Miller24* linux 2.4 support David McCullough <[email protected]>25* Bug, speed and maintainability fixes by Philippe De Muyter <[email protected]>26*/2728#include <linux/linkage.h>29#include <asm/unistd.h>30#include <asm/thread_info.h>31#include <asm/errno.h>32#include <asm/setup.h>33#include <asm/segment.h>34#include <asm/asm-offsets.h>35#include <asm/entry.h>3637#ifdef CONFIG_COLDFIRE_SW_A738/*39* Define software copies of the supervisor and user stack pointers.40*/41.bss42sw_ksp:43.long 044sw_usp:45.long 046#endif /* CONFIG_COLDFIRE_SW_A7 */4748.text4950.globl system_call51.globl resume52.globl ret_from_exception53.globl ret_from_signal54.globl sys_call_table55.globl inthandler56.globl fasthandler5758enosys:59mov.l #sys_ni_syscall,%d360bra 1f6162ENTRY(system_call)63SAVE_ALL64move #0x2000,%sr /* enable intrs again */6566cmpl #NR_syscalls,%d067jcc enosys68lea sys_call_table,%a069lsll #2,%d0 /* movel %a0@(%d0:l:4),%d3 */70movel %a0@(%d0),%d371jeq enosys72731:74movel %sp,%d2 /* get thread_info pointer */75andl #-THREAD_SIZE,%d2 /* at start of kernel stack */76movel %d2,%a077movel %a0@,%a1 /* save top of frame */78movel %sp,%a1@(TASK_THREAD+THREAD_ESP0)79btst #(TIF_SYSCALL_TRACE%8),%a0@(TINFO_FLAGS+(31-TIF_SYSCALL_TRACE)/8)80bnes 1f8182movel %d3,%a083jbsr %a0@84movel %d0,%sp@(PT_OFF_D0) /* save the return value */85jra ret_from_exception861:87movel #-ENOSYS,%d2 /* strace needs -ENOSYS in PT_OFF_D0 */88movel %d2,PT_OFF_D0(%sp) /* on syscall entry */89subql #4,%sp90SAVE_SWITCH_STACK91jbsr syscall_trace_enter92RESTORE_SWITCH_STACK93addql #4,%sp94movel %d3,%a095jbsr %a0@96movel %d0,%sp@(PT_OFF_D0) /* save the return value */97subql #4,%sp /* dummy return address */98SAVE_SWITCH_STACK99jbsr syscall_trace_leave100101ret_from_signal:102RESTORE_SWITCH_STACK103addql #4,%sp104105ret_from_exception:106move #0x2700,%sr /* disable intrs */107btst #5,%sp@(PT_OFF_SR) /* check if returning to kernel */108jeq Luser_return /* if so, skip resched, signals */109110#ifdef CONFIG_PREEMPT111movel %sp,%d1 /* get thread_info pointer */112andl #-THREAD_SIZE,%d1 /* at base of kernel stack */113movel %d1,%a0114movel %a0@(TINFO_FLAGS),%d1 /* get thread_info->flags */115andl #(1<<TIF_NEED_RESCHED),%d1116jeq Lkernel_return117118movel %a0@(TINFO_PREEMPT),%d1119cmpl #0,%d1120jne Lkernel_return121122pea Lkernel_return123jmp preempt_schedule_irq /* preempt the kernel */124#endif125126Lkernel_return:127moveml %sp@,%d1-%d5/%a0-%a2128lea %sp@(32),%sp /* space for 8 regs */129movel %sp@+,%d0130addql #4,%sp /* orig d0 */131addl %sp@+,%sp /* stk adj */132rte133134Luser_return:135movel %sp,%d1 /* get thread_info pointer */136andl #-THREAD_SIZE,%d1 /* at base of kernel stack */137movel %d1,%a0138movel %a0@(TINFO_FLAGS),%d1 /* get thread_info->flags */139jne Lwork_to_do /* still work to do */140141Lreturn:142RESTORE_USER143144Lwork_to_do:145movel %a0@(TINFO_FLAGS),%d1 /* get thread_info->flags */146move #0x2000,%sr /* enable intrs again */147btst #TIF_NEED_RESCHED,%d1148jne reschedule149150/* GERG: do we need something here for TRACEing?? */151152Lsignal_return:153subql #4,%sp /* dummy return address */154SAVE_SWITCH_STACK155pea %sp@(SWITCH_STACK_SIZE)156jsr do_signal157addql #4,%sp158RESTORE_SWITCH_STACK159addql #4,%sp160jmp Luser_return161162/*163* This is the generic interrupt handler (for all hardware interrupt164* sources). Calls up to high level code to do all the work.165*/166ENTRY(inthandler)167SAVE_ALL168moveq #-1,%d0169movel %d0,%sp@(PT_OFF_ORIG_D0)170171movew %sp@(PT_OFF_FORMATVEC),%d0 /* put exception # in d0 */172andl #0x03fc,%d0 /* mask out vector only */173174movel %sp,%sp@- /* push regs arg */175lsrl #2,%d0 /* calculate real vector # */176movel %d0,%sp@- /* push vector number */177jbsr do_IRQ /* call high level irq handler */178lea %sp@(8),%sp /* pop args off stack */179180bra ret_from_exception181182/*183* Beware - when entering resume, prev (the current task) is184* in a0, next (the new task) is in a1,so don't change these185* registers until their contents are no longer needed.186* This is always called in supervisor mode, so don't bother to save187* and restore sr; user's process sr is actually in the stack.188*/189ENTRY(resume)190movel %a0, %d1 /* get prev thread in d1 */191RDUSP192movel %a2,%a0@(TASK_THREAD+THREAD_USP)193194SAVE_SWITCH_STACK195movel %sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack pointer */196movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */197RESTORE_SWITCH_STACK198199movel %a1@(TASK_THREAD+THREAD_USP),%a0 /* restore thread user stack */200WRUSP201rts202203204