162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * entry.S -- interrupt and exception processing for ColdFire 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 1999-2007, Greg Ungerer (gerg@snapgear.com) 562306a36Sopenharmony_ci * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>, 662306a36Sopenharmony_ci * Kenneth Albanowski <kjahds@kjahds.com>, 762306a36Sopenharmony_ci * Copyright (C) 2000 Lineo Inc. (www.lineo.com) 862306a36Sopenharmony_ci * Copyright (C) 2004-2006 Macq Electronique SA. (www.macqel.com) 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Based on: 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * linux/arch/m68k/kernel/entry.S 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 1762306a36Sopenharmony_ci * License. See the file README.legal in the main directory of this archive 1862306a36Sopenharmony_ci * for more details. 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * Linux/m68k support by Hamish Macdonald 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * 68060 fixes by Jesper Skov 2362306a36Sopenharmony_ci * ColdFire support by Greg Ungerer (gerg@snapgear.com) 2462306a36Sopenharmony_ci * 5307 fixes by David W. Miller 2562306a36Sopenharmony_ci * linux 2.4 support David McCullough <davidm@snapgear.com> 2662306a36Sopenharmony_ci * Bug, speed and maintainability fixes by Philippe De Muyter <phdm@macqel.be> 2762306a36Sopenharmony_ci */ 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include <linux/linkage.h> 3062306a36Sopenharmony_ci#include <asm/unistd.h> 3162306a36Sopenharmony_ci#include <asm/thread_info.h> 3262306a36Sopenharmony_ci#include <asm/errno.h> 3362306a36Sopenharmony_ci#include <asm/setup.h> 3462306a36Sopenharmony_ci#include <asm/asm-offsets.h> 3562306a36Sopenharmony_ci#include <asm/entry.h> 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#ifdef CONFIG_COLDFIRE_SW_A7 3862306a36Sopenharmony_ci/* 3962306a36Sopenharmony_ci * Define software copies of the supervisor and user stack pointers. 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ci.bss 4262306a36Sopenharmony_cisw_ksp: 4362306a36Sopenharmony_ci.long 0 4462306a36Sopenharmony_cisw_usp: 4562306a36Sopenharmony_ci.long 0 4662306a36Sopenharmony_ci#endif /* CONFIG_COLDFIRE_SW_A7 */ 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci.text 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci.globl system_call 5162306a36Sopenharmony_ci.globl resume 5262306a36Sopenharmony_ci.globl ret_from_exception 5362306a36Sopenharmony_ci.globl sys_call_table 5462306a36Sopenharmony_ci.globl inthandler 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cienosys: 5762306a36Sopenharmony_ci mov.l #sys_ni_syscall,%d3 5862306a36Sopenharmony_ci bra 1f 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ciENTRY(system_call) 6162306a36Sopenharmony_ci SAVE_ALL_SYS 6262306a36Sopenharmony_ci move #0x2000,%sr /* enable intrs again */ 6362306a36Sopenharmony_ci GET_CURRENT(%d2) 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci cmpl #NR_syscalls,%d0 6662306a36Sopenharmony_ci jcc enosys 6762306a36Sopenharmony_ci lea sys_call_table,%a0 6862306a36Sopenharmony_ci lsll #2,%d0 /* movel %a0@(%d0:l:4),%d3 */ 6962306a36Sopenharmony_ci movel %a0@(%d0),%d3 7062306a36Sopenharmony_ci jeq enosys 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci1: 7362306a36Sopenharmony_ci movel %sp,%d2 /* get thread_info pointer */ 7462306a36Sopenharmony_ci andl #-THREAD_SIZE,%d2 /* at start of kernel stack */ 7562306a36Sopenharmony_ci movel %d2,%a0 7662306a36Sopenharmony_ci movel %a0@,%a1 /* save top of frame */ 7762306a36Sopenharmony_ci movel %sp,%a1@(TASK_THREAD+THREAD_ESP0) 7862306a36Sopenharmony_ci btst #(TIF_SYSCALL_TRACE%8),%a0@(TINFO_FLAGS+(31-TIF_SYSCALL_TRACE)/8) 7962306a36Sopenharmony_ci bnes 1f 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci movel %d3,%a0 8262306a36Sopenharmony_ci jbsr %a0@ 8362306a36Sopenharmony_ci movel %d0,%sp@(PT_OFF_D0) /* save the return value */ 8462306a36Sopenharmony_ci jra ret_from_exception 8562306a36Sopenharmony_ci1: 8662306a36Sopenharmony_ci movel #-ENOSYS,%d2 /* strace needs -ENOSYS in PT_OFF_D0 */ 8762306a36Sopenharmony_ci movel %d2,PT_OFF_D0(%sp) /* on syscall entry */ 8862306a36Sopenharmony_ci subql #4,%sp 8962306a36Sopenharmony_ci SAVE_SWITCH_STACK 9062306a36Sopenharmony_ci jbsr syscall_trace_enter 9162306a36Sopenharmony_ci RESTORE_SWITCH_STACK 9262306a36Sopenharmony_ci addql #4,%sp 9362306a36Sopenharmony_ci addql #1,%d0 9462306a36Sopenharmony_ci jeq ret_from_exception 9562306a36Sopenharmony_ci movel %d3,%a0 9662306a36Sopenharmony_ci jbsr %a0@ 9762306a36Sopenharmony_ci movel %d0,%sp@(PT_OFF_D0) /* save the return value */ 9862306a36Sopenharmony_ci subql #4,%sp /* dummy return address */ 9962306a36Sopenharmony_ci SAVE_SWITCH_STACK 10062306a36Sopenharmony_ci jbsr syscall_trace_leave 10162306a36Sopenharmony_ci RESTORE_SWITCH_STACK 10262306a36Sopenharmony_ci addql #4,%sp 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ciret_from_exception: 10562306a36Sopenharmony_ci move #0x2700,%sr /* disable intrs */ 10662306a36Sopenharmony_ci btst #5,%sp@(PT_OFF_SR) /* check if returning to kernel */ 10762306a36Sopenharmony_ci jeq Luser_return /* if so, skip resched, signals */ 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci#ifdef CONFIG_PREEMPTION 11062306a36Sopenharmony_ci movel %sp,%d1 /* get thread_info pointer */ 11162306a36Sopenharmony_ci andl #-THREAD_SIZE,%d1 /* at base of kernel stack */ 11262306a36Sopenharmony_ci movel %d1,%a0 11362306a36Sopenharmony_ci movel %a0@(TINFO_FLAGS),%d1 /* get thread_info->flags */ 11462306a36Sopenharmony_ci andl #(1<<TIF_NEED_RESCHED),%d1 11562306a36Sopenharmony_ci jeq Lkernel_return 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci movel %a0@(TINFO_PREEMPT),%d1 11862306a36Sopenharmony_ci cmpl #0,%d1 11962306a36Sopenharmony_ci jne Lkernel_return 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci pea Lkernel_return 12262306a36Sopenharmony_ci jmp preempt_schedule_irq /* preempt the kernel */ 12362306a36Sopenharmony_ci#endif 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ciLkernel_return: 12662306a36Sopenharmony_ci moveml %sp@,%d1-%d5/%a0-%a2 12762306a36Sopenharmony_ci lea %sp@(32),%sp /* space for 8 regs */ 12862306a36Sopenharmony_ci movel %sp@+,%d0 12962306a36Sopenharmony_ci addql #4,%sp /* orig d0 */ 13062306a36Sopenharmony_ci addl %sp@+,%sp /* stk adj */ 13162306a36Sopenharmony_ci rte 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ciLuser_return: 13462306a36Sopenharmony_ci movel %sp,%d1 /* get thread_info pointer */ 13562306a36Sopenharmony_ci andl #-THREAD_SIZE,%d1 /* at base of kernel stack */ 13662306a36Sopenharmony_ci movel %d1,%a0 13762306a36Sopenharmony_ci moveb %a0@(TINFO_FLAGS+3),%d1 /* thread_info->flags (low 8 bits) */ 13862306a36Sopenharmony_ci jne Lwork_to_do /* still work to do */ 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ciLreturn: 14162306a36Sopenharmony_ci RESTORE_USER 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ciLwork_to_do: 14462306a36Sopenharmony_ci movel %a0@(TINFO_FLAGS),%d1 /* get thread_info->flags */ 14562306a36Sopenharmony_ci move #0x2000,%sr /* enable intrs again */ 14662306a36Sopenharmony_ci btst #TIF_NEED_RESCHED,%d1 14762306a36Sopenharmony_ci jne reschedule 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ciLsignal_return: 15062306a36Sopenharmony_ci subql #4,%sp /* dummy return address */ 15162306a36Sopenharmony_ci SAVE_SWITCH_STACK 15262306a36Sopenharmony_ci pea %sp@(SWITCH_STACK_SIZE) 15362306a36Sopenharmony_ci jsr do_notify_resume 15462306a36Sopenharmony_ci addql #4,%sp 15562306a36Sopenharmony_ci RESTORE_SWITCH_STACK 15662306a36Sopenharmony_ci addql #4,%sp 15762306a36Sopenharmony_ci jmp Luser_return 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci/* 16062306a36Sopenharmony_ci * This is the generic interrupt handler (for all hardware interrupt 16162306a36Sopenharmony_ci * sources). Calls up to high level code to do all the work. 16262306a36Sopenharmony_ci */ 16362306a36Sopenharmony_ciENTRY(inthandler) 16462306a36Sopenharmony_ci SAVE_ALL_INT 16562306a36Sopenharmony_ci GET_CURRENT(%d2) 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci movew %sp@(PT_OFF_FORMATVEC),%d0 /* put exception # in d0 */ 16862306a36Sopenharmony_ci andl #0x03fc,%d0 /* mask out vector only */ 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci movel %sp,%sp@- /* push regs arg */ 17162306a36Sopenharmony_ci lsrl #2,%d0 /* calculate real vector # */ 17262306a36Sopenharmony_ci movel %d0,%sp@- /* push vector number */ 17362306a36Sopenharmony_ci jbsr do_IRQ /* call high level irq handler */ 17462306a36Sopenharmony_ci lea %sp@(8),%sp /* pop args off stack */ 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci bra ret_from_exception 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci/* 17962306a36Sopenharmony_ci * Beware - when entering resume, prev (the current task) is 18062306a36Sopenharmony_ci * in a0, next (the new task) is in a1, so don't change these 18162306a36Sopenharmony_ci * registers until their contents are no longer needed. 18262306a36Sopenharmony_ci */ 18362306a36Sopenharmony_ciENTRY(resume) 18462306a36Sopenharmony_ci movew %sr,%d1 /* save current status */ 18562306a36Sopenharmony_ci movew %d1,%a0@(TASK_THREAD+THREAD_SR) 18662306a36Sopenharmony_ci movel %a0,%d1 /* get prev thread in d1 */ 18762306a36Sopenharmony_ci SAVE_SWITCH_STACK 18862306a36Sopenharmony_ci movel %sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack pointer */ 18962306a36Sopenharmony_ci RDUSP /* movel %usp,%a3 */ 19062306a36Sopenharmony_ci movel %a3,%a0@(TASK_THREAD+THREAD_USP) /* save thread user stack */ 19162306a36Sopenharmony_ci#ifdef CONFIG_MMU 19262306a36Sopenharmony_ci movel %a1,%a2 /* set new current */ 19362306a36Sopenharmony_ci#endif 19462306a36Sopenharmony_ci movel %a1@(TASK_THREAD+THREAD_USP),%a3 /* restore thread user stack */ 19562306a36Sopenharmony_ci WRUSP /* movel %a3,%usp */ 19662306a36Sopenharmony_ci movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new kernel stack */ 19762306a36Sopenharmony_ci movew %a1@(TASK_THREAD+THREAD_SR),%d7 /* restore new status */ 19862306a36Sopenharmony_ci movew %d7,%sr 19962306a36Sopenharmony_ci RESTORE_SWITCH_STACK 20062306a36Sopenharmony_ci rts 20162306a36Sopenharmony_ci 202