#include /*============================================================================ * All exits to user mode from the kernel go through this code. */ /* * Define to favour ARM8, ARM9 and StrongARM cpus. This says that it is * cheaper to use two LDR instructions than a two-register LDM, if the * latter would entail calculating an address specially. */ #if defined(CONFIG_CPU_SA110) #define HARVARD_CACHE #endif .globl ret_from_sys_call .align 5 fast_syscall_return: str r0, [sp, #S_R0 + 4] @ returned r0 slow_syscall_return: add sp, sp, #4 ret_from_sys_call: #ifdef HARVARD_CACHE ldr r0, bh_data ldr r4, bh_data+4 #else adr r0, bh_data ldmia r0, {r0, r4} #endif ldr r0, [r0] ldr r1, [r4] tst r0, r1 blne SYMBOL_NAME(do_bottom_half) ret_with_reschedule: get_current_task r5 ldr r0, [r5, #TSK_NEED_RESCHED] ldr r1, [r5, #TSK_SIGPENDING] teq r0, #0 bne ret_reschedule teq r1, #0 @ check for signals bne ret_signal ret_from_all: restore_user_regs ret_signal: mov r1, sp adrsvc al, lr, ret_from_all mov r2, r4 b SYMBOL_NAME(do_signal) ret_reschedule: adrsvc al, lr, ret_with_reschedule b SYMBOL_NAME(schedule) .globl ret_from_exception ret_from_exception: #ifdef HARVARD_CACHE ldr r0, bh_data ldr r1, bh_data + 4 #else adr r0, bh_data ldmia r0, {r0, r1} #endif ldr r0, [r0] ldr r1, [r1] mov r4, #0 tst r0, r1 blne SYMBOL_NAME(do_bottom_half) ldr r0, [sp, #S_PSR] tst r0, #3 @ returning to user mode? beq ret_with_reschedule b ret_from_all #include "calls.S" /*============================================================================= * SWI handler *----------------------------------------------------------------------------- * * We now handle sys-call tracing, and the errno in the task structure. * Still have a problem with >4 arguments for functions. Theres only * a couple of functions in the code that have 5 arguments, so Im not * too worried. */ .align 5 vector_swi: save_user_regs mask_pc lr, lr mov fp, #0 ldr r6, [lr, #-4] @ get SWI instruction arm700_bug_check r6, r7 #ifdef CONFIG_ALIGNMENT_TRAP ldr r7, .LCswi ldr r7, [r7] mcr p15, 0, r7, c1, c0 #endif enable_irqs r7 str r4, [sp, #-4]! @ new style: (r0 = arg1, r4 = arg5) adrsvc al, lr, fast_syscall_return bic r6, r6, #0xff000000 @ mask off SWI op-code eor r6, r6, #OS_NUMBER<<20 @ check OS number cmp r6, #NR_syscalls @ check upper syscall limit bcs 2f get_current_task r7 ldr ip, [r7, #TSK_FLAGS] @ check for syscall tracing adr r5, SYMBOL_NAME(sys_call_table) tst ip, #PF_TRACESYS ldreq pc, [r5, r6, lsl #2] @ call sys routine ldr r7, [sp, #S_IP + 4] @ save old IP mov r0, #0 str r0, [sp, #S_IP + 4] @ trace entry [IP = 0] bl SYMBOL_NAME(syscall_trace) str r7, [sp, #S_IP + 4] ldmib sp, {r0 - r3} @ have to reload r0 - r3 mov lr, pc ldr pc, [r5, r6, lsl #2] @ call sys routine str r0, [sp, #S_R0 + 4] @ returned r0 mov r0, #1 str r0, [sp, #S_IP + 4] @ trace exit [IP = 1] bl SYMBOL_NAME(syscall_trace) str r7, [sp, #S_IP + 4] b slow_syscall_return 2: add r1, sp, #4 tst r6, #0x00f00000 @ is it a Unix SWI? bne 3f subs r0, r6, #(KSWI_SYS_BASE - KSWI_BASE) bcs SYMBOL_NAME(arm_syscall) b SYMBOL_NAME(sys_ni_syscall) @ not private func 3: eor r0, r6, #OS_NUMBER <<20 @ Put OS number back adrsvc al, lr, slow_syscall_return b SYMBOL_NAME(deferred) .align 5 bh_data: .word SYMBOL_NAME(bh_mask) .word SYMBOL_NAME(bh_active) ENTRY(sys_call_table) #include "calls.S" /*============================================================================ * Special system call wrappers */ @ r0 = syscall number @ r5 = syscall table SYMBOL_NAME(sys_syscall): eor r6, r0, #OS_NUMBER << 20 cmp r6, #NR_syscalls @ check range add ip, sp, #4 ldmleib ip, {r0 - r4} @ get our args strle r4, [sp] @ Put our arg on the stack ldrle pc, [r5, r6, lsl #2] mov r0, #-ENOSYS mov pc, lr sys_fork_wrapper: add r0, sp, #4 b SYMBOL_NAME(sys_fork) sys_vfork_wrapper: add r0, sp, #4 b SYMBOL_NAME(sys_vfork) sys_execve_wrapper: add r3, sp, #4 b SYMBOL_NAME(sys_execve) sys_mount_wrapper: mov r6, lr add r5, sp, #4 str r5, [sp] str r4, [sp, #-4]! bl SYMBOL_NAME(sys_compat_mount) add sp, sp, #4 RETINSTR(mov,pc,r6) sys_clone_wapper: add r2, sp, #4 b SYMBOL_NAME(sys_clone) sys_llseek_wrapper: mov r6, lr add r5, sp, #4 str r5, [sp] str r4, [sp, #-4]! bl SYMBOL_NAME(sys_compat_llseek) add sp, sp, #4 RETINSTR(mov,pc,r6) sys_sigsuspend_wrapper: add r3, sp, #4 b SYMBOL_NAME(sys_sigsuspend) sys_rt_sigsuspend_wrapper: add r2, sp, #4 b SYMBOL_NAME(sys_rt_sigsuspend) sys_sigreturn_wrapper: add r0, sp, #4 b SYMBOL_NAME(sys_sigreturn) sys_rt_sigreturn_wrapper: add r0, sp, #4 b SYMBOL_NAME(sys_rt_sigreturn) sys_sigaltstack_wrapper: ldr r2, [sp, #4 + S_SP] b do_sigaltstack .data ENTRY(fp_enter) .word fpe_not_present