diff options
Diffstat (limited to 'arch/blackfin/mach-common/entry.S')
| -rw-r--r-- | arch/blackfin/mach-common/entry.S | 1268 |
1 files changed, 881 insertions, 387 deletions
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 8eb0a902348..86b5a095c5a 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -1,81 +1,30 @@ /* - * File: arch/blackfin/mach-common/entry.S - * Based on: - * Author: Linus Torvalds + * 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. * - * Created: ? - * Description: 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. + * Copyright 2005-2009 Analog Devices Inc. * - * Modified: - * Copyright 2004-2006 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * Licensed under the GPL-2 or later. */ -/* - * 25-Dec-2004 - LG Soft India - * 1. Fix in return_from_int, to make sure any pending - * system call in ILAT for this process to get - * executed, otherwise in case context switch happens, - * system call of first process (i.e in ILAT) will be - * carried forward to the switched process. - * 2. Removed Constant references for the following - * a. IPEND - * b. EXCAUSE mask - * c. PAGE Mask - */ - -/* - * NOTE: This code handles signal-recognition, which happens every time +/* NOTE: This code handles signal-recognition, which happens every time * after a timer-interrupt and after each system call. */ - +#include <linux/init.h> #include <linux/linkage.h> +#include <linux/unistd.h> #include <asm/blackfin.h> -#include <asm/unistd.h> #include <asm/errno.h> +#include <asm/fixed_code.h> #include <asm/thread_info.h> /* TIF_NEED_RESCHED */ #include <asm/asm-offsets.h> +#include <asm/trace.h> +#include <asm/traps.h> -#include <asm/mach-common/context.S> +#include <asm/context.S> -#ifdef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE - /* - * TODO: this should be proper save/restore, but for now - * we'll just cheat and use 0x1/0x13 - */ -# define DEBUG_START_HWTRACE \ - P5.l = LO(TBUFCTL); \ - P5.h = HI(TBUFCTL); \ - R7 = 0x13; \ - [P5] = R7; -# define DEBUG_STOP_HWTRACE \ - P5.l = LO(TBUFCTL); \ - P5.h = HI(TBUFCTL); \ - R7 = 0x01; \ - [P5] = R7; -#else -# define DEBUG_START_HWTRACE -# define DEBUG_STOP_HWTRACE -#endif #ifdef CONFIG_EXCPT_IRQ_SYSC_L1 .section .l1.text @@ -87,246 +36,489 @@ * This one does not lower the level to IRQ5, and thus can be used to * patch up CPLB misses on the kernel stack. */ -ENTRY(_ex_dcplb) -#if defined(ANOMALY_05000261) +#if ANOMALY_05000261 +#define _ex_dviol _ex_workaround_261 +#define _ex_dmiss _ex_workaround_261 +#define _ex_dmult _ex_workaround_261 + +ENTRY(_ex_workaround_261) /* * Work around an anomaly: if we see a new DCPLB fault, return * without doing anything. Then, if we get the same fault again, * handle it. */ - p5.l = _last_cplb_fault_retx; - p5.h = _last_cplb_fault_retx; - r7 = [p5]; + P4 = R7; /* Store EXCAUSE */ + + GET_PDA(p5, r7); + r7 = [p5 + PDA_LFRETX]; r6 = retx; - [p5] = r6; + [p5 + PDA_LFRETX] = r6; cc = r6 == r7; - if !cc jump _return_from_exception; + if !cc jump _bfin_return_from_exception; /* fall through */ + R7 = P4; + R6 = VEC_CPLB_M; /* Data CPLB Miss */ + cc = R6 == R7; + if cc jump _ex_dcplb_miss (BP); +#ifdef CONFIG_MPU + R6 = VEC_CPLB_VL; /* Data CPLB Violation */ + cc = R6 == R7; + if cc jump _ex_dcplb_viol (BP); #endif + /* Handle Data CPLB Protection Violation + * and Data CPLB Multiple Hits - Linux Trap Zero + */ + jump _ex_trap_c; +ENDPROC(_ex_workaround_261) -ENTRY(_ex_icplb) - (R7:6,P5:4) = [sp++]; - ASTAT = [sp++]; - SAVE_ALL_SYS - call __cplb_hdr; - DEBUG_START_HWTRACE - RESTORE_ALL_SYS - SP = RETN; - rtx; +#else +#ifdef CONFIG_MPU +#define _ex_dviol _ex_dcplb_viol +#else +#define _ex_dviol _ex_trap_c +#endif +#define _ex_dmiss _ex_dcplb_miss +#define _ex_dmult _ex_trap_c +#endif -ENTRY(_ex_spinlock) - /* Transform this into a syscall - twiddle the syscall vector. */ - p5.l = lo(EVT15); - p5.h = hi(EVT15); - r7.l = _spinlock_bh; - r7.h = _spinlock_bh; - [p5] = r7; - csync; - /* Fall through. */ -ENTRY(_ex_syscall) - DEBUG_START_HWTRACE +ENTRY(_ex_dcplb_viol) +ENTRY(_ex_dcplb_miss) +ENTRY(_ex_icplb_miss) (R7:6,P5:4) = [sp++]; - ASTAT = [sp++]; - raise 15; /* invoked by TRAP #0, for sys call */ - sp = retn; - rtx + /* We leave the previously pushed ASTAT on the stack. */ + SAVE_CONTEXT_CPLB + + /* We must load R1 here, _before_ DEBUG_HWTRACE_SAVE, since that + * will change the stack pointer. */ + R0 = SEQSTAT; + R1 = SP; + + DEBUG_HWTRACE_SAVE(p5, r7) -ENTRY(_spinlock_bh) - SAVE_ALL_SYS - /* To end up here, vector 15 was changed - so we have to change it - * back. - */ - p0.l = lo(EVT15); - p0.h = hi(EVT15); - p1.l = _evt_system_call; - p1.h = _evt_system_call; - [p0] = p1; - csync; - r0 = [sp + PT_R0]; sp += -12; - call _sys_bfin_spinlock; + call _cplb_hdr; sp += 12; - [SP + PT_R0] = R0; - RESTORE_ALL_SYS - rti; + CC = R0 == 0; + IF !CC JUMP _handle_bad_cplb; -ENTRY(_ex_soft_bp) - r7 = retx; - r7 += -2; - retx = r7; - jump.s _ex_trap_c; +#ifdef CONFIG_DEBUG_DOUBLEFAULT + /* While we were processing this, did we double fault? */ + r7 = SEQSTAT; /* reason code is in bit 5:0 */ + r6.l = lo(SEQSTAT_EXCAUSE); + r6.h = hi(SEQSTAT_EXCAUSE); + r7 = r7 & r6; + r6 = 0x25; + CC = R7 == R6; + if CC JUMP _double_fault; +#endif + + DEBUG_HWTRACE_RESTORE(p5, r7) + RESTORE_CONTEXT_CPLB + ASTAT = [SP++]; + SP = EX_SCRATCH_REG; + rtx; +ENDPROC(_ex_icplb_miss) + +ENTRY(_ex_syscall) + raise 15; /* invoked by TRAP #0, for sys call */ + jump.s _bfin_return_from_exception; +ENDPROC(_ex_syscall) ENTRY(_ex_single_step) + /* If we just returned from an interrupt, the single step event is + for the RTI instruction. */ r7 = retx; r6 = reti; cc = r7 == r6; - if cc jump _return_from_exception - r7 = syscfg; - bitclr (r7, 0); - syscfg = R7; + if cc jump _bfin_return_from_exception; +#ifdef CONFIG_KGDB + /* Don't do single step in hardware exception handler */ + p5.l = lo(IPEND); + p5.h = hi(IPEND); + r6 = [p5]; + cc = bittst(r6, 4); + if cc jump _bfin_return_from_exception; + cc = bittst(r6, 5); + if cc jump _bfin_return_from_exception; + + /* skip single step if current interrupt priority is higher than + * that of the first instruction, from which gdb starts single step */ + r6 >>= 6; + r7 = 10; +.Lfind_priority_start: + cc = bittst(r6, 0); + if cc jump .Lfind_priority_done; + r6 >>= 1; + r7 += -1; + cc = r7 == 0; + if cc jump .Lfind_priority_done; + jump.s .Lfind_priority_start; +.Lfind_priority_done: + p4.l = _kgdb_single_step; + p4.h = _kgdb_single_step; + r6 = [p4]; + cc = r6 == 0; + if cc jump .Ldo_single_step; + r6 += -1; + cc = r6 < r7; + if cc jump 1f; +.Ldo_single_step: +#else + /* If we were in user mode, do the single step normally. */ p5.l = lo(IPEND); p5.h = hi(IPEND); r6 = [p5]; - cc = bittst(r6, 5); - if !cc jump _ex_trap_c; - p4.l = lo(EVT5); - p4.h = hi(EVT5); - r6.h = _exception_to_level5; - r6.l = _exception_to_level5; - r7 = [p4]; - cc = r6 == r7; - if !cc jump _ex_trap_c; + r7 = 0xffe0 (z); + r7 = r7 & r6; + cc = r7 == 0; + if !cc jump 1f; +#endif +#ifdef CONFIG_EXACT_HWERR + /* Read the ILAT, and to check to see if the process we are + * single stepping caused a previous hardware error + * If so, do not single step, (which lowers to IRQ5, and makes + * us miss the error). + */ + p5.l = lo(ILAT); + p5.h = hi(ILAT); + r7 = [p5]; + cc = bittst(r7, EVT_IVHW_P); + if cc jump 1f; +#endif + /* Single stepping only a single instruction, so clear the trace + * bit here. */ + r7 = syscfg; + bitclr (r7, SYSCFG_SSSTEP_P); + syscfg = R7; + jump _ex_trap_c; + +1: + /* + * We were in an interrupt handler. By convention, all of them save + * SYSCFG with their first instruction, so by checking whether our + * RETX points at the entry point, we can determine whether to allow + * a single step, or whether to clear SYSCFG. + * + * First, find out the interrupt level and the event vector for it. + */ + p5.l = lo(EVT0); + p5.h = hi(EVT0); + p5 += -4; +2: + r7 = rot r7 by -1; + p5 += 4; + if !cc jump 2b; + + /* What we actually do is test for the _second_ instruction in the + * IRQ handler. That way, if there are insns following the restore + * of SYSCFG after leaving the handler, we will not turn off SYSCFG + * for them. */ + + r7 = [p5]; + r7 += 2; + r6 = RETX; + cc = R7 == R6; + if !cc jump _bfin_return_from_exception; + + r7 = syscfg; + bitclr (r7, SYSCFG_SSSTEP_P); /* Turn off single step */ + syscfg = R7; + + /* Fall through to _bfin_return_from_exception. */ +ENDPROC(_ex_single_step) + +ENTRY(_bfin_return_from_exception) +#if ANOMALY_05000257 + R7=LC0; + LC0=R7; + R7=LC1; + LC1=R7; +#endif + +#ifdef CONFIG_DEBUG_DOUBLEFAULT + /* While we were processing the current exception, + * did we cause another, and double fault? + */ + r7 = SEQSTAT; /* reason code is in bit 5:0 */ + r6.l = lo(SEQSTAT_EXCAUSE); + r6.h = hi(SEQSTAT_EXCAUSE); + r7 = r7 & r6; + r6 = VEC_UNCOV; + CC = R7 == R6; + if CC JUMP _double_fault; +#endif -_return_from_exception: - DEBUG_START_HWTRACE (R7:6,P5:4) = [sp++]; ASTAT = [sp++]; - sp = retn; + sp = EX_SCRATCH_REG; rtx; +ENDPROC(_bfin_return_from_exception) ENTRY(_handle_bad_cplb) + DEBUG_HWTRACE_RESTORE(p5, r7) /* To get here, we just tried and failed to change a CPLB * so, handle things in trap_c (C code), by lowering to * IRQ5, just like we normally do. Since this is not a - * "normal" return path, we have a do alot of stuff to + * "normal" return path, we have a do a lot of stuff to * the stack to get ready so, we can fall through - we * need to make a CPLB exception look like a normal exception */ + RESTORE_CONTEXT_CPLB + /* ASTAT is still on the stack, where it is needed. */ + [--sp] = (R7:6,P5:4); - DEBUG_START_HWTRACE - RESTORE_ALL_SYS - [--sp] = ASTAT; - [--sp] = (R7:6, P5:4); +ENTRY(_ex_replaceable) + nop; ENTRY(_ex_trap_c) + /* The only thing that has been saved in this context is + * (R7:6,P5:4), ASTAT & SP - don't use anything else + */ + + GET_PDA(p5, r6); + + /* Make sure we are not in a double fault */ + p4.l = lo(IPEND); + p4.h = hi(IPEND); + r7 = [p4]; + CC = BITTST (r7, 5); + if CC jump _double_fault; + [p5 + PDA_EXIPEND] = r7; + /* Call C code (trap_c) to handle the exception, which most * likely involves sending a signal to the current process. * To avoid double faults, lower our priority to IRQ5 first. */ - P5.h = _exception_to_level5; - P5.l = _exception_to_level5; + r7.h = _exception_to_level5; + r7.l = _exception_to_level5; p4.l = lo(EVT5); p4.h = hi(EVT5); - [p4] = p5; + [p4] = r7; csync; - /* Disable all interrupts, but make sure level 5 is enabled so - * we can switch to that level. Save the old mask. */ + /* + * Save these registers, as they are only valid in exception context + * (where we are now - as soon as we defer to IRQ5, they can change) + * DCPLB_STATUS and ICPLB_STATUS are also only valid in EVT3, + * but they are not very interesting, so don't save them + */ + + p4.l = lo(DCPLB_FAULT_ADDR); + p4.h = hi(DCPLB_FAULT_ADDR); + r7 = [p4]; + [p5 + PDA_DCPLB] = r7; + + p4.l = lo(ICPLB_FAULT_ADDR); + p4.h = hi(ICPLB_FAULT_ADDR); + r6 = [p4]; + [p5 + PDA_ICPLB] = r6; + + r6 = retx; + [p5 + PDA_RETX] = r6; + + r6 = SEQSTAT; + [p5 + PDA_SEQSTAT] = r6; + + /* Save the state of single stepping */ + r6 = SYSCFG; + [p5 + PDA_SYSCFG] = r6; + /* Clear it while we handle the exception in IRQ5 mode */ + BITCLR(r6, SYSCFG_SSSTEP_P); + SYSCFG = r6; + + /* Save the current IMASK, since we change in order to jump to level 5 */ cli r6; - p4.l = _excpt_saved_imask; - p4.h = _excpt_saved_imask; - [p4] = r6; + [p5 + PDA_EXIMASK] = r6; + + p4.l = lo(SAFE_USER_INSTRUCTION); + p4.h = hi(SAFE_USER_INSTRUCTION); + retx = p4; + + /* Disable all interrupts, but make sure level 5 is enabled so + * we can switch to that level. + */ r6 = 0x3f; sti r6; - /* Save the excause into a circular buffer, in case the instruction - * which caused this excecptions causes others. + /* In case interrupts are disabled IPEND[4] (global interrupt disable bit) + * clear it (re-enabling interrupts again) by the special sequence of pushing + * RETI onto the stack. This way we can lower ourselves to IVG5 even if the + * exception was taken after the interrupt handler was called but before it + * got a chance to enable global interrupts itself. */ - P5.l = _in_ptr_excause; - P5.h = _in_ptr_excause; - R7 = [P5]; - R7 += 4; - R6 = 0xF; - R7 = R7 & R6; - [P5] = R7; - R6.l = _excause_circ_buf; - R6.h = _excause_circ_buf; - R7 = R7 + R6; - p5 = R7; - R6 = SEQSTAT; - [P5] = R6; - - DEBUG_START_HWTRACE + [--sp] = reti; + sp += 4; + + raise 5; + jump.s _bfin_return_from_exception; +ENDPROC(_ex_trap_c) + +/* We just realized we got an exception, while we were processing a different + * exception. This is a unrecoverable event, so crash. + * Note: this cannot be ENTRY() as we jump here with "if cc jump" ... + */ +ENTRY(_double_fault) + /* Turn caches & protection off, to ensure we don't get any more + * double exceptions + */ + + P4.L = LO(IMEM_CONTROL); + P4.H = HI(IMEM_CONTROL); + + R5 = [P4]; /* Control Register*/ + BITCLR(R5,ENICPLB_P); + CSYNC; /* Disabling of CPLBs should be proceeded by a CSYNC */ + [P4] = R5; + SSYNC; + + P4.L = LO(DMEM_CONTROL); + P4.H = HI(DMEM_CONTROL); + R5 = [P4]; + BITCLR(R5,ENDCPLB_P); + CSYNC; /* Disabling of CPLBs should be proceeded by a CSYNC */ + [P4] = R5; + SSYNC; + + /* Fix up the stack */ (R7:6,P5:4) = [sp++]; ASTAT = [sp++]; - SP = RETN; - raise 5; - rtx; + SP = EX_SCRATCH_REG; + + /* We should be out of the exception stack, and back down into + * kernel or user space stack + */ + SAVE_ALL_SYS + + /* The dumping functions expect the return address in the RETI + * slot. */ + r6 = retx; + [sp + PT_PC] = r6; + + r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ + SP += -12; + pseudo_long_call _double_fault_c, p5; + SP += 12; +.L_double_fault_panic: + JUMP .L_double_fault_panic + +ENDPROC(_double_fault) ENTRY(_exception_to_level5) SAVE_ALL_SYS - /* Restore interrupt mask. We haven't pushed RETI, so this - * doesn't enable interrupts until we return from this handler. */ - p4.l = _excpt_saved_imask; - p4.h = _excpt_saved_imask; - r6 = [p4]; - sti r6; + GET_PDA(p5, r7); /* Fetch current PDA */ + r6 = [p5 + PDA_RETX]; + [sp + PT_PC] = r6; + + r6 = [p5 + PDA_SYSCFG]; + [sp + PT_SYSCFG] = r6; + + r6 = [p5 + PDA_SEQSTAT]; /* Read back seqstat */ + [sp + PT_SEQSTAT] = r6; /* Restore the hardware error vector. */ - P5.h = _evt_ivhw; - P5.l = _evt_ivhw; + r7.h = _evt_ivhw; + r7.l = _evt_ivhw; p4.l = lo(EVT5); p4.h = hi(EVT5); - [p4] = p5; + [p4] = r7; csync; - p2.l = lo(IPEND); - p2.h = hi(IPEND); - csync; - r0 = [p2]; /* Read current IPEND */ - [sp + PT_IPEND] = r0; /* Store IPEND */ - - /* Pop the excause from the circular buffer and push it on the stack - * (in the right place - if you change the location of SEQSTAT, you - * must change this offset. +#ifdef CONFIG_DEBUG_DOUBLEFAULT + /* Now that we have the hardware error vector programmed properly + * we can re-enable interrupts (IPEND[4]), so if the _trap_c causes + * another hardware error, we can catch it (self-nesting). */ -.L_excep_to_5_again: - P5.l = _out_ptr_excause; - P5.h = _out_ptr_excause; - R7 = [P5]; - R7 += 4; - R6 = 0xF; - R7 = R7 & R6; - [P5] = R7; - R6.l = _excause_circ_buf; - R6.h = _excause_circ_buf; - R7 = R7 + R6; - P5 = R7; - R1 = [P5]; - [SP + 8] = r1; + [--sp] = reti; + sp += 4; +#endif + + r7 = [p5 + PDA_EXIPEND] /* Read the IPEND from the Exception state */ + [sp + PT_IPEND] = r7; /* Store IPEND onto the stack */ r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ SP += -12; - call _trap_c; + pseudo_long_call _trap_c, p4; SP += 12; - /* See if anything else is in the exception buffer - * if there is, process it + /* If interrupts were off during the exception (IPEND[4] = 1), turn them off + * before we return. */ - P5.l = _out_ptr_excause; - P5.h = _out_ptr_excause; - P4.l = _in_ptr_excause; - P4.h = _in_ptr_excause; - R6 = [P5]; - R7 = [P4]; - CC = R6 == R7; - if ! CC JUMP .L_excep_to_5_again + CC = BITTST(r7, EVT_IRPTEN_P) + if !CC jump 1f; + /* this will load a random value into the reti register - but that is OK, + * since we do restore it to the correct value in the 'RESTORE_ALL_SYS' macro + */ + sp += -4; + reti = [sp++]; +1: + /* restore the interrupt mask (IMASK) */ + r6 = [p5 + PDA_EXIMASK]; + sti r6; call _ret_from_exception; RESTORE_ALL_SYS rti; +ENDPROC(_exception_to_level5) ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ /* Since the kernel stack can be anywhere, it's not guaranteed to be * covered by a CPLB. Switch to an exception stack; use RETN as a * scratch register (for want of a better option). */ - retn = sp; - sp.l = _exception_stack_top; - sp.h = _exception_stack_top; + EX_SCRATCH_REG = sp; + GET_PDA_SAFE(sp); + sp = [sp + PDA_EXSTACK]; /* Try to deal with syscalls quickly. */ [--sp] = ASTAT; - [--sp] = (R7:6, P5:4); - DEBUG_STOP_HWTRACE + [--sp] = (R7:6,P5:4); + + ANOMALY_283_315_WORKAROUND(p5, r7) + +#ifdef CONFIG_EXACT_HWERR + /* Make sure all pending read/writes complete. This will ensure any + * accesses which could cause hardware errors completes, and signal + * the the hardware before we do something silly, like crash the + * kernel. We don't need to work around anomaly 05000312, since + * we are already atomic + */ + ssync; +#endif + +#ifdef CONFIG_DEBUG_DOUBLEFAULT + /* + * Save these registers, as they are only valid in exception context + * (where we are now - as soon as we defer to IRQ5, they can change) + * DCPLB_STATUS and ICPLB_STATUS are also only valid in EVT3, + * but they are not very interesting, so don't save them + */ + + GET_PDA(p5, r7); + p4.l = lo(DCPLB_FAULT_ADDR); + p4.h = hi(DCPLB_FAULT_ADDR); + r7 = [p4]; + [p5 + PDA_DF_DCPLB] = r7; + + p4.l = lo(ICPLB_FAULT_ADDR); + p4.h = hi(ICPLB_FAULT_ADDR); + r7 = [p4]; + [p5 + PDA_DF_ICPLB] = r7; + + r7 = retx; + [p5 + PDA_DF_RETX] = r7; + r7 = SEQSTAT; /* reason code is in bit 5:0 */ + [p5 + PDA_DF_SEQSTAT] = r7; +#else + r7 = SEQSTAT; /* reason code is in bit 5:0 */ +#endif r6.l = lo(SEQSTAT_EXCAUSE); r6.h = hi(SEQSTAT_EXCAUSE); r7 = r7 & r6; - p5.h = _extable; - p5.l = _extable; + p5.h = _ex_table; + p5.l = _ex_table; p4 = r7; p5 = p5 + (p4 << 2); p4 = [p5]; @@ -336,60 +528,7 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ r7 = -ENOSYS; /* signextending enough */ [sp + PT_R0] = r7; /* return value from system call */ jump .Lsyscall_really_exit; - -ENTRY(_kernel_execve) - link SIZEOF_PTREGS; - p0 = sp; - r3 = SIZEOF_PTREGS / 4; - r4 = 0(x); -0: - [p0++] = r4; - r3 += -1; - cc = r3 == 0; - if !cc jump 0b (bp); - - p0 = sp; - sp += -16; - [sp + 12] = p0; - call _do_execve; - SP += 16; - cc = r0 == 0; - if ! cc jump 1f; - /* Success. Copy our temporary pt_regs to the top of the kernel - * stack and do a normal exception return. - */ - r1 = sp; - r0 = (-KERNEL_STACK_SIZE) (x); - r1 = r1 & r0; - p2 = r1; - p3 = [p2]; - r0 = KERNEL_STACK_SIZE - 4 (z); - p1 = r0; - p1 = p1 + p2; - - p0 = fp; - r4 = [p0--]; - r3 = SIZEOF_PTREGS / 4; -0: - r4 = [p0--]; - [p1--] = r4; - r3 += -1; - cc = r3 == 0; - if ! cc jump 0b (bp); - - r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z); - p1 = r0; - p1 = p1 + p2; - sp = p1; - r0 = syscfg; - [SP + PT_SYSCFG] = r0; - [p3 + (TASK_THREAD + THREAD_KSP)] = sp; - - RESTORE_CONTEXT; - rti; -1: - unlink; - rts; +ENDPROC(_trap) ENTRY(_system_call) /* Store IPEND */ @@ -411,13 +550,19 @@ ENTRY(_system_call) p2 = [p2]; [p2+(TASK_THREAD+THREAD_KSP)] = sp; - - /* Check the System Call */ - r7 = __NR_syscall; - /* System call number is passed in P0 */ - r6 = p0; - cc = r6 < r7; - if ! cc jump .Lbadsys; +#ifdef CONFIG_IPIPE + r0 = sp; + SP += -12; + pseudo_long_call ___ipipe_syscall_root, p0; + SP += 12; + cc = r0 == 1; + if cc jump .Lsyscall_really_exit; + cc = r0 == -1; + if cc jump .Lresume_userspace; + r3 = [sp + PT_R3]; + r4 = [sp + PT_R4]; + p0 = [sp + PT_ORIG_P0]; +#endif /* CONFIG_IPIPE */ /* are we tracing syscalls?*/ r7 = sp; @@ -428,6 +573,14 @@ ENTRY(_system_call) r7 = [p2+TI_FLAGS]; CC = BITTST(r7,TIF_SYSCALL_TRACE); if CC JUMP _sys_trace; + CC = BITTST(r7,TIF_SINGLESTEP); + if CC JUMP _sys_trace; + + /* Make sure the system call # is valid */ + p4 = __NR_syscall; + /* System call number is passed in P0 */ + cc = p4 <= p0; + if cc jump .Lbadsys; /* Execute the appropriate system call */ @@ -465,45 +618,72 @@ ENTRY(_system_call) r7 = r7 & r4; .Lsyscall_resched: +#ifdef CONFIG_IPIPE + cc = BITTST(r7, TIF_IRQ_SYNC); + if !cc jump .Lsyscall_no_irqsync; + /* + * Clear IPEND[4] manually to undo what resume_userspace_1 just did; + * we need this so that high priority domain interrupts may still + * preempt the current domain while the pipeline log is being played + * back. + */ + [--sp] = reti; + SP += 4; /* don't merge with next insn to keep the pattern obvious */ + SP += -12; + pseudo_long_call ___ipipe_sync_root, p4; + SP += 12; + jump .Lresume_userspace_1; +.Lsyscall_no_irqsync: +#endif cc = BITTST(r7, TIF_NEED_RESCHED); if !cc jump .Lsyscall_sigpending; /* Reenable interrupts. */ [--sp] = reti; - r0 = [sp++]; + sp += 4; SP += -12; - call _schedule; + pseudo_long_call _schedule, p4; SP += 12; jump .Lresume_userspace_1; .Lsyscall_sigpending: - cc = BITTST(r7, TIF_RESTORE_SIGMASK); - if cc jump .Lsyscall_do_signals; cc = BITTST(r7, TIF_SIGPENDING); + if cc jump .Lsyscall_do_signals; + cc = BITTST(r7, TIF_NOTIFY_RESUME); if !cc jump .Lsyscall_really_exit; .Lsyscall_do_signals: /* Reenable interrupts. */ [--sp] = reti; - r0 = [sp++]; + sp += 4; r0 = sp; SP += -12; - call _do_signal; + pseudo_long_call _do_notify_resume, p5; SP += 12; .Lsyscall_really_exit: r5 = [sp + PT_RESERVED]; rets = r5; rts; +ENDPROC(_system_call) +/* Do not mark as ENTRY() to avoid error in assembler ... + * this symbol need not be global anyways, so ... + */ _sys_trace: - call _syscall_trace; - - /* Execute the appropriate system call */ + r0 = sp; + pseudo_long_call _syscall_trace_enter, p5; + /* Make sure the system call # is valid */ p4 = [SP + PT_P0]; + p3 = __NR_syscall; + cc = p3 <= p4; + r0 = -ENOSYS; + if cc jump .Lsys_trace_badsys; + + /* Execute the appropriate system call */ p5.l = _sys_call_table; p5.h = _sys_call_table; p5 = p5 + (p4 << 2); @@ -521,10 +701,13 @@ _sys_trace: SP += -12; call (p5); SP += 24; +.Lsys_trace_badsys: [sp + PT_R0] = r0; - call _syscall_trace; + r0 = sp; + pseudo_long_call _syscall_trace_leave, p5; jump .Lresume_userspace; +ENDPROC(_sys_trace) ENTRY(_resume) /* @@ -570,12 +753,22 @@ _new_old_task: rets = [sp++]; /* - * When we come out of resume, r0 carries "old" task, becuase we are + * When we come out of resume, r0 carries "old" task, because we are * in "new" task. */ rts; +ENDPROC(_resume) ENTRY(_ret_from_exception) +#ifdef CONFIG_IPIPE + p2.l = _ipipe_percpu_domain; + p2.h = _ipipe_percpu_domain; + r0.l = _ipipe_root; + r0.h = _ipipe_root; + r2 = [p2]; + cc = r0 == r2; + if !cc jump 4f; /* not on behalf of the root domain, get out */ +#endif /* CONFIG_IPIPE */ p2.l = lo(IPEND); p2.h = hi(IPEND); @@ -584,9 +777,7 @@ ENTRY(_ret_from_exception) [sp + PT_IPEND] = r0; 1: - r1 = 0x37(Z); - r2 = ~r1; - r2.h = 0; + r2 = LO(~0x37) (Z); r0 = r2 & r0; cc = r0 == 0; if !cc jump 4f; /* if not return to user mode, get out */ @@ -625,13 +816,148 @@ ENTRY(_ret_from_exception) p1.h = _schedule_and_signal; [p0] = p1; csync; - raise 15; /* raise evt14 to do signal or reschedule */ + raise 15; /* raise evt15 to do signal or reschedule */ 4: r0 = syscfg; - bitclr(r0, 0); + bitclr(r0, SYSCFG_SSSTEP_P); /* Turn off single step */ syscfg = r0; 5: rts; +ENDPROC(_ret_from_exception) + +#if defined(CONFIG_PREEMPT) + +ENTRY(_up_to_irq14) +#if ANOMALY_05000281 || ANOMALY_05000461 + r0.l = lo(SAFE_USER_INSTRUCTION); + r0.h = hi(SAFE_USER_INSTRUCTION); + reti = r0; +#endif + +#ifdef CONFIG_DEBUG_HWERR + /* enable irq14 & hwerr interrupt, until we transition to _evt_evt14 */ + r0 = (EVT_IVG14 | EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU); +#else + /* Only enable irq14 interrupt, until we transition to _evt_evt14 */ + r0 = (EVT_IVG14 | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU); +#endif + sti r0; + + p0.l = lo(EVT14); + p0.h = hi(EVT14); + p1.l = _evt_up_evt14; + p1.h = _evt_up_evt14; + [p0] = p1; + csync; + + raise 14; +1: + jump 1b; +ENDPROC(_up_to_irq14) + +ENTRY(_evt_up_evt14) +#ifdef CONFIG_DEBUG_HWERR + r0 = (EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU); + sti r0; +#else + cli r0; +#endif +#ifdef CONFIG_TRACE_IRQFLAGS + [--sp] = rets; + sp += -12; + call _trace_hardirqs_off; + sp += 12; + rets = [sp++]; +#endif + [--sp] = RETI; + SP += 4; + + /* restore normal evt14 */ + p0.l = lo(EVT14); + p0.h = hi(EVT14); + p1.l = _evt_evt14; + p1.h = _evt_evt14; + [p0] = p1; + csync; + + rts; +ENDPROC(_evt_up_evt14) + +#endif + +#ifdef CONFIG_IPIPE + +_resume_kernel_from_int: + r1 = LO(~0x8000) (Z); + r1 = r0 & r1; + r0 = 1; + r0 = r1 - r0; + r2 = r1 & r0; + cc = r2 == 0; + /* Sync the root stage only from the outer interrupt level. */ + if !cc jump .Lnosync; + r0.l = ___ipipe_sync_root; + r0.h = ___ipipe_sync_root; + [--sp] = reti; + [--sp] = rets; + [--sp] = ( r7:4, p5:3 ); + SP += -12; + call ___ipipe_call_irqtail + SP += 12; + ( r7:4, p5:3 ) = [sp++]; + rets = [sp++]; + reti = [sp++]; +.Lnosync: + rts +#elif defined(CONFIG_PREEMPT) + +_resume_kernel_from_int: + /* check preempt_count */ + r7 = sp; + r4.l = lo(ALIGN_PAGE_MASK); + r4.h = hi(ALIGN_PAGE_MASK); + r7 = r7 & r4; + p5 = r7; + r7 = [p5 + TI_PREEMPT]; + cc = r7 == 0x0; + if !cc jump .Lreturn_to_kernel; +.Lneed_schedule: + r7 = [p5 + TI_FLAGS]; + r4.l = lo(_TIF_WORK_MASK); + r4.h = hi(_TIF_WORK_MASK); + r7 = r7 & r4; + cc = BITTST(r7, TIF_NEED_RESCHED); + if !cc jump .Lreturn_to_kernel; + /* + * let schedule done at level 15, otherwise sheduled process will run + * at high level and block low level interrupt + */ + r6 = reti; /* save reti */ + r5.l = .Lkernel_schedule; + r5.h = .Lkernel_schedule; + reti = r5; + rti; +.Lkernel_schedule: + [--sp] = rets; + sp += -12; + pseudo_long_call _preempt_schedule_irq, p4; + sp += 12; + rets = [sp++]; + + [--sp] = rets; + sp += -12; + /* up to irq14 so that reti after restore_all can return to irq15(kernel) */ + pseudo_long_call _up_to_irq14, p4; + sp += 12; + rets = [sp++]; + + reti = r6; /* restore reti so that origin process can return to interrupted point */ + + jump .Lneed_schedule; +#else + +#define _resume_kernel_from_int .Lreturn_to_kernel +#endif ENTRY(_return_from_int) /* If someone else already raised IRQ 15, do nothing. */ @@ -640,7 +966,7 @@ ENTRY(_return_from_int) p2.h = hi(ILAT); r0 = [p2]; cc = bittst (r0, EVT_IVG15_P); - if cc jump 2f; + if cc jump .Lreturn_to_kernel; /* if not return to user mode, get out */ p2.l = lo(IPEND); @@ -654,7 +980,7 @@ ENTRY(_return_from_int) r1 = r0 - r1; r2 = r0 & r1; cc = r2 == 0; - if !cc jump 2f; + if !cc jump _resume_kernel_from_int; /* Lower the interrupt level to 15. */ p0.l = lo(EVT15); @@ -663,40 +989,58 @@ ENTRY(_return_from_int) p1.h = _schedule_and_signal_from_int; [p0] = p1; csync; -#if defined(ANOMALY_05000281) - r0.l = lo(CONFIG_BOOT_LOAD); - r0.h = hi(CONFIG_BOOT_LOAD); +#if ANOMALY_05000281 || ANOMALY_05000461 + r0.l = lo(SAFE_USER_INSTRUCTION); + r0.h = hi(SAFE_USER_INSTRUCTION); reti = r0; #endif r0 = 0x801f (z); STI r0; raise 15; /* raise evt15 to do signal or reschedule */ rti; -2: +.Lreturn_to_kernel: rts; +ENDPROC(_return_from_int) ENTRY(_lower_to_irq14) -#if defined(ANOMALY_05000281) - r0.l = lo(CONFIG_BOOT_LOAD); - r0.h = hi(CONFIG_BOOT_LOAD); +#if ANOMALY_05000281 || ANOMALY_05000461 + r0.l = lo(SAFE_USER_INSTRUCTION); + r0.h = hi(SAFE_USER_INSTRUCTION); reti = r0; #endif - r0 = 0x401f; + +#ifdef CONFIG_DEBUG_HWERR + /* enable irq14 & hwerr interrupt, until we transition to _evt_evt14 */ + r0 = (EVT_IVG14 | EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU); +#else + /* Only enable irq14 interrupt, until we transition to _evt_evt14 */ + r0 = (EVT_IVG14 | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU); +#endif sti r0; raise 14; rti; -ENTRY(_evt14_softirq) +ENDPROC(_lower_to_irq14) + +ENTRY(_evt_evt14) #ifdef CONFIG_DEBUG_HWERR - r0 = 0x3f; + r0 = (EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU); sti r0; #else cli r0; #endif +#ifdef CONFIG_TRACE_IRQFLAGS + [--sp] = rets; + sp += -12; + call _trace_hardirqs_off; + sp += 12; + rets = [sp++]; +#endif [--sp] = RETI; SP += 4; rts; +ENDPROC(_evt_evt14) -_schedule_and_signal_from_int: +ENTRY(_schedule_and_signal_from_int) /* To end up here, vector 15 was changed - so we have to change it * back. */ @@ -706,17 +1050,48 @@ _schedule_and_signal_from_int: p1.h = _evt_system_call; [p0] = p1; csync; + + /* Set orig_p0 to -1 to indicate this isn't the end of a syscall. */ + r0 = -1 (x); + [sp + PT_ORIG_P0] = r0; + p1 = rets; [sp + PT_RESERVED] = p1; - p0.l = _irq_flags; - p0.h = _irq_flags; +#ifdef CONFIG_TRACE_IRQFLAGS + /* trace_hardirqs_on() checks if all irqs are disabled. But here IRQ 15 + * is turned on, so disable all irqs. */ + cli r0; + sp += -12; + call _trace_hardirqs_on; + sp += 12; +#endif +#ifdef CONFIG_SMP + GET_PDA(p0, r0); /* Fetch current PDA (can't migrate to other CPU here) */ + r0 = [p0 + PDA_IRQFLAGS]; +#else + p0.l = _bfin_irq_flags; + p0.h = _bfin_irq_flags; r0 = [p0]; +#endif sti r0; + /* finish the userspace "atomic" functions for it */ + r1.l = lo(FIXED_CODE_END); + r1.h = hi(FIXED_CODE_END); + r2 = [sp + PT_PC]; + cc = r1 <= r2; + if cc jump .Lresume_userspace (bp); + + r0 = sp; + sp += -12; + + pseudo_long_call _finish_atomic_sections, p5; + sp += 12; jump.s .Lresume_userspace; +ENDPROC(_schedule_and_signal_from_int) -_schedule_and_signal: +ENTRY(_schedule_and_signal) SAVE_CONTEXT_SYSCALL /* To end up here, vector 15 was changed - so we have to change it * back. @@ -734,19 +1109,114 @@ _schedule_and_signal: 1: RESTORE_CONTEXT rti; +ENDPROC(_schedule_and_signal) -/* Make sure when we start, that the circular buffer is initialized properly - * R0 and P0 are call clobbered, so we can use them here. +/* We handle this 100% in exception space - to reduce overhead + * Only potiential problem is if the software buffer gets swapped out of the + * CPLB table - then double fault. - so we don't let this happen in other places */ -ENTRY(_init_exception_buff) - r0 = 0; - p0.h = _in_ptr_excause; - p0.l = _in_ptr_excause; - [p0] = r0; - p0.h = _out_ptr_excause; - p0.l = _out_ptr_excause; - [p0] = r0; - rts; +#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND +ENTRY(_ex_trace_buff_full) + [--sp] = P3; + [--sp] = P2; + [--sp] = LC0; + [--sp] = LT0; + [--sp] = LB0; + P5.L = _trace_buff_offset; + P5.H = _trace_buff_offset; + P3 = [P5]; /* trace_buff_offset */ + P5.L = lo(TBUFSTAT); + P5.H = hi(TBUFSTAT); + R7 = [P5]; + R7 <<= 1; /* double, since we need to read twice */ + LC0 = R7; + R7 <<= 2; /* need to shift over again, + * to get the number of bytes */ + P5.L = lo(TBUF); + P5.H = hi(TBUF); + R6 = ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN)*1024) - 1; + + P2 = R7; + P3 = P3 + P2; + R7 = P3; + R7 = R7 & R6; + P3 = R7; + P2.L = _trace_buff_offset; + P2.H = _trace_buff_offset; + [P2] = P3; + + P2.L = _software_trace_buff; + P2.H = _software_trace_buff; + + LSETUP (.Lstart, .Lend) LC0; +.Lstart: + R7 = [P5]; /* read TBUF */ + P4 = P3 + P2; + [P4] = R7; + P3 += -4; + R7 = P3; + R7 = R7 & R6; +.Lend: + P3 = R7; + + LB0 = [sp++]; + LT0 = [sp++]; + LC0 = [sp++]; + P2 = [sp++]; + P3 = [sp++]; + jump _bfin_return_from_exception; +ENDPROC(_ex_trace_buff_full) + +#if CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN == 4 +.data +#else +.section .l1.data.B +#endif /* CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN */ +ENTRY(_trace_buff_offset) + .long 0; +ALIGN +ENTRY(_software_trace_buff) + .rept ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN)*256); + .long 0 + .endr +#endif /* CONFIG_DEBUG_BFIN_HWTRACE_EXPAND */ + +#ifdef CONFIG_EARLY_PRINTK +__INIT +ENTRY(_early_trap) + SAVE_ALL_SYS + trace_buffer_stop(p0,r0); + + ANOMALY_283_315_WORKAROUND(p4, r5) + + /* Turn caches off, to ensure we don't get double exceptions */ + + P4.L = LO(IMEM_CONTROL); + P4.H = HI(IMEM_CONTROL); + + R5 = [P4]; /* Control Register*/ + BITCLR(R5,ENICPLB_P); + CSYNC; /* Disabling of CPLBs should be proceeded by a CSYNC */ + [P4] = R5; + SSYNC; + + P4.L = LO(DMEM_CONTROL); + P4.H = HI(DMEM_CONTROL); + R5 = [P4]; + BITCLR(R5,ENDCPLB_P); + CSYNC; /* Disabling of CPLBs should be proceeded by a CSYNC */ + [P4] = R5; + SSYNC; + + r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ + r1 = RETX; + + SP += -12; + call _early_trap_c; + SP += 12; +ENDPROC(_early_trap) +__FINIT +#endif /* CONFIG_EARLY_PRINTK */ /* * Put these in the kernel data section - that should always be covered by @@ -758,30 +1228,39 @@ ENTRY(_init_exception_buff) #else .data #endif -ALIGN -_extable: + +ENTRY(_ex_table) /* entry for each EXCAUSE[5:0] - * This table bmust be in sync with the table in ./kernel/traps.c + * This table must be in sync with the table in ./kernel/traps.c * EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined */ - .long _ex_syscall; /* 0x00 - User Defined - Linux Syscall */ - .long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */ - .long _ex_trap_c /* 0x02 - User Defined */ - .long _ex_trap_c /* 0x03 - User Defined - Atomic test and set service */ - .long _ex_spinlock /* 0x04 - User Defined */ - .long _ex_trap_c /* 0x05 - User Defined */ - .long _ex_trap_c /* 0x06 - User Defined */ - .long _ex_trap_c /* 0x07 - User Defined */ - .long _ex_trap_c /* 0x08 - User Defined */ - .long _ex_trap_c /* 0x09 - User Defined */ - .long _ex_trap_c /* 0x0A - User Defined */ - .long _ex_trap_c /* 0x0B - User Defined */ - .long _ex_trap_c /* 0x0C - User Defined */ - .long _ex_trap_c /* 0x0D - User Defined */ - .long _ex_trap_c /* 0x0E - User Defined */ - .long _ex_trap_c /* 0x0F - User Defined */ + .long _ex_syscall /* 0x00 - User Defined - Linux Syscall */ + .long _ex_trap_c /* 0x01 - User Defined - Software breakpoint */ +#ifdef CONFIG_KGDB + .long _ex_trap_c /* 0x02 - User Defined - KGDB initial connection + and break signal trap */ +#else + .long _ex_replaceable /* 0x02 - User Defined */ +#endif + .long _ex_trap_c /* 0x03 - User Defined - userspace stack overflow */ + .long _ex_trap_c /* 0x04 - User Defined - dump trace buffer */ + .long _ex_replaceable /* 0x05 - User Defined */ + .long _ex_replaceable /* 0x06 - User Defined */ + .long _ex_replaceable /* 0x07 - User Defined */ + .long _ex_replaceable /* 0x08 - User Defined */ + .long _ex_replaceable /* 0x09 - User Defined */ + .long _ex_replaceable /* 0x0A - User Defined */ + .long _ex_replaceable /* 0x0B - User Defined */ + .long _ex_replaceable /* 0x0C - User Defined */ + .long _ex_replaceable /* 0x0D - User Defined */ + .long _ex_replaceable /* 0x0E - User Defined */ + .long _ex_replaceable /* 0x0F - User Defined */ .long _ex_single_step /* 0x10 - HW Single step */ +#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND + .long _ex_trace_buff_full /* 0x11 - Trace Buffer Full */ +#else .long _ex_trap_c /* 0x11 - Trace Buffer Full */ +#endif .long _ex_trap_c /* 0x12 - Reserved */ .long _ex_trap_c /* 0x13 - Reserved */ .long _ex_trap_c /* 0x14 - Reserved */ @@ -799,16 +1278,16 @@ _extable: .long _ex_trap_c /* 0x20 - Reserved */ .long _ex_trap_c /* 0x21 - Undefined Instruction */ .long _ex_trap_c /* 0x22 - Illegal Instruction Combination */ - .long _ex_dcplb /* 0x23 - Data CPLB Protection Violation */ + .long _ex_dviol /* 0x23 - Data CPLB Protection Violation */ .long _ex_trap_c /* 0x24 - Data access misaligned */ .long _ex_trap_c /* 0x25 - Unrecoverable Event */ - .long _ex_dcplb /* 0x26 - Data CPLB Miss */ - .long _ex_trap_c /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero */ + .long _ex_dmiss /* 0x26 - Data CPLB Miss */ + .long _ex_dmult /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero */ .long _ex_trap_c /* 0x28 - Emulation Watchpoint */ .long _ex_trap_c /* 0x29 - Instruction fetch access error (535 only) */ .long _ex_trap_c /* 0x2A - Instruction fetch misaligned */ - .long _ex_icplb /* 0x2B - Instruction CPLB protection Violation */ - .long _ex_icplb /* 0x2C - Instruction CPLB miss */ + .long _ex_trap_c /* 0x2B - Instruction CPLB protection Violation */ + .long _ex_icplb_miss /* 0x2C - Instruction CPLB miss */ .long _ex_trap_c /* 0x2D - Instruction CPLB Multiple Hits */ .long _ex_trap_c /* 0x2E - Illegal use of Supervisor Resource */ .long _ex_trap_c /* 0x2E - Illegal use of Supervisor Resource */ @@ -829,12 +1308,12 @@ _extable: .long _ex_trap_c /* 0x3D - Reserved */ .long _ex_trap_c /* 0x3E - Reserved */ .long _ex_trap_c /* 0x3F - Reserved */ +END(_ex_table) -ALIGN ENTRY(_sys_call_table) - .long _sys_ni_syscall /* 0 - old "setup()" system call*/ + .long _sys_restart_syscall /* 0 */ .long _sys_exit - .long _sys_fork + .long _sys_ni_syscall /* fork */ .long _sys_read .long _sys_write .long _sys_open /* 5 */ @@ -952,12 +1431,12 @@ ENTRY(_sys_call_table) .long _sys_ni_syscall /* old sys_ipc */ .long _sys_fsync .long _sys_ni_syscall /* old sys_sigreturn */ - .long _sys_clone /* 120 */ + .long _bfin_clone /* 120 */ .long _sys_setdomainname .long _sys_newuname .long _sys_ni_syscall /* old sys_modify_ldt */ .long _sys_adjtimex - .long _sys_ni_syscall /* 125 */ /* sys_mprotect */ + .long _sys_mprotect /* 125 */ .long _sys_ni_syscall /* old sys_sigprocmask */ .long _sys_ni_syscall /* old "creat_module" */ .long _sys_init_module @@ -976,16 +1455,16 @@ ENTRY(_sys_call_table) .long _sys_getdents .long _sys_ni_syscall /* sys_select */ .long _sys_flock - .long _sys_ni_syscall /* sys_msync */ + .long _sys_msync .long _sys_readv /* 145 */ .long _sys_writev .long _sys_getsid .long _sys_fdatasync .long _sys_sysctl - .long _sys_ni_syscall /* 150 */ /* sys_mlock */ - .long _sys_ni_syscall /* sys_munlock */ - .long _sys_ni_syscall /* sys_mlockall */ - .long _sys_ni_syscall /* sys_munlockall */ + .long _sys_mlock /* 150 */ + .long _sys_munlock + .long _sys_mlockall + .long _sys_munlockall .long _sys_sched_setparam .long _sys_sched_getparam /* 155 */ .long _sys_sched_setscheduler @@ -995,13 +1474,13 @@ ENTRY(_sys_call_table) .long _sys_sched_get_priority_min /* 160 */ .long _sys_sched_rr_get_interval .long _sys_nanosleep - .long _sys_ni_syscall /* sys_mremap */ + .long _sys_mremap .long _sys_setresuid /* setresuid16 */ .long _sys_getresuid /* getresuid16 */ /* 165 */ .long _sys_ni_syscall /* for vm86 */ .long _sys_ni_syscall /* old "query_module" */ .long _sys_ni_syscall /* sys_poll */ - .long _sys_ni_syscall /* sys_nfsservctl */ + .long _sys_ni_syscall /* old nfsservctl */ .long _sys_setresgid /* setresgid16 */ /* 170 */ .long _sys_getresgid /* getresgid16 */ .long _sys_prctl @@ -1024,7 +1503,7 @@ ENTRY(_sys_call_table) .long _sys_ni_syscall /* streams2 */ .long _sys_vfork /* 190 */ .long _sys_getrlimit - .long _sys_mmap2 + .long _sys_mmap_pgoff .long _sys_truncate64 .long _sys_ftruncate64 .long _sys_stat64 /* 195 */ @@ -1050,14 +1529,14 @@ ENTRY(_sys_call_table) .long _sys_setfsuid /* 215 */ .long _sys_setfsgid .long _sys_pivot_root - .long _sys_ni_syscall /* sys_mincore */ - .long _sys_ni_syscall /* sys_madvise */ + .long _sys_mincore + .long _sys_madvise .long _sys_getdents64 /* 220 */ .long _sys_fcntl64 .long _sys_ni_syscall /* reserved for TUX */ .long _sys_ni_syscall .long _sys_gettid - .long _sys_ni_syscall /* 225 */ /* sys_readahead */ + .long _sys_readahead /* 225 */ .long _sys_setxattr .long _sys_lsetxattr .long _sys_fsetxattr @@ -1107,7 +1586,7 @@ ENTRY(_sys_call_table) .long _sys_utimes .long _sys_fadvise64_64 .long _sys_ni_syscall /* vserver */ - .long _sys_ni_syscall /* 275, mbind */ + .long _sys_mbind /* 275 */ .long _sys_ni_syscall /* get_mempolicy */ .long _sys_ni_syscall /* set_mempolicy */ .long _sys_mq_open @@ -1174,34 +1653,49 @@ ENTRY(_sys_call_table) .long _sys_shmctl .long _sys_shmdt /* 340 */ .long _sys_shmget + .long _sys_splice + .long _sys_sync_file_range + .long _sys_tee + .long _sys_vmsplice /* 345 */ + .long _sys_epoll_pwait + .long _sys_utimensat + .long _sys_signalfd + .long _sys_timerfd_create + .long _sys_eventfd /* 350 */ + .long _sys_pread64 + .long _sys_pwrite64 + .long _sys_fadvise64 + .long _sys_set_robust_list + .long _sys_get_robust_list /* 355 */ + .long _sys_fallocate + .long _sys_semtimedop + .long _sys_timerfd_settime + .long _sys_timerfd_gettime + .long _sys_signalfd4 /* 360 */ + .long _sys_eventfd2 + .long _sys_epoll_create1 + .long _sys_dup3 + .long _sys_pipe2 + .long _sys_inotify_init1 /* 365 */ + .long _sys_preadv + .long _sys_pwritev + .long _sys_rt_tgsigqueueinfo + .long _sys_perf_event_open + .long _sys_recvmmsg /* 370 */ + .long _sys_fanotify_init + .long _sys_fanotify_mark + .long _sys_prlimit64 + .long _sys_cacheflush + .long _sys_name_to_handle_at /* 375 */ + .long _sys_open_by_handle_at + .long _sys_clock_adjtime + .long _sys_syncfs + .long _sys_setns + .long _sys_sendmmsg /* 380 */ + .long _sys_process_vm_readv + .long _sys_process_vm_writev + .rept NR_syscalls-(.-_sys_call_table)/4 .long _sys_ni_syscall .endr -_excpt_saved_imask: - .long 0; - -_exception_stack: - .rept 1024 - .long 0; - .endr -_exception_stack_top: - -#if defined(ANOMALY_05000261) -/* Used by the assembly entry point to work around an anomaly. */ -_last_cplb_fault_retx: - .long 0; -#endif -/* - * Single instructions can have multiple faults, which need to be - * handled by traps.c, in irq5. We store the exception cause to ensure - * we don't miss a double fault condition - */ -ENTRY(_in_ptr_excause) - .long 0; -ENTRY(_out_ptr_excause) - .long 0; -ALIGN -ENTRY(_excause_circ_buf) - .rept 4 - .long 0 - .endr +END(_sys_call_table) |
