11da177e4SLinus Torvalds/* 21da177e4SLinus Torvalds * linux/arch/arm/kernel/entry-common.S 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 2000 Russell King 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 71da177e4SLinus Torvalds * it under the terms of the GNU General Public License version 2 as 81da177e4SLinus Torvalds * published by the Free Software Foundation. 91da177e4SLinus Torvalds */ 101da177e4SLinus Torvalds 116ebbf2ceSRussell King#include <asm/assembler.h> 121da177e4SLinus Torvalds#include <asm/unistd.h> 13395a59d0SAbhishek Sagar#include <asm/ftrace.h> 14c4c5716eSCatalin Marinas#include <asm/unwind.h> 151da177e4SLinus Torvalds 1613a5045dSRob Herring#ifdef CONFIG_NEED_RET_TO_USER 1713a5045dSRob Herring#include <mach/entry-macro.S> 1813a5045dSRob Herring#else 1913a5045dSRob Herring .macro arch_ret_to_user, tmp1, tmp2 2013a5045dSRob Herring .endm 2113a5045dSRob Herring#endif 2213a5045dSRob Herring 231da177e4SLinus Torvalds#include "entry-header.S" 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds .align 5 271da177e4SLinus Torvalds/* 281da177e4SLinus Torvalds * This is the fast syscall return path. We do as little as 291da177e4SLinus Torvalds * possible here, and this includes saving r0 back into the SVC 301da177e4SLinus Torvalds * stack. 311da177e4SLinus Torvalds */ 321da177e4SLinus Torvaldsret_fast_syscall: 33c4c5716eSCatalin Marinas UNWIND(.fnstart ) 34c4c5716eSCatalin Marinas UNWIND(.cantunwind ) 351ec42c0cSRussell King disable_irq @ disable interrupts 361da177e4SLinus Torvalds ldr r1, [tsk, #TI_FLAGS] 371da177e4SLinus Torvalds tst r1, #_TIF_WORK_MASK 381da177e4SLinus Torvalds bne fast_work_pending 39d13e5eddSTodd Android Poynor asm_trace_hardirqs_on 40f4dc9a4cSRussell King 41f80dff9dSDan Williams /* perform architecture specific actions before user return */ 42f80dff9dSDan Williams arch_ret_to_user r1, lr 43b0088480SKevin Hilman ct_user_enter 44f80dff9dSDan Williams 45b86040a5SCatalin Marinas restore_user_regs fast = 1, offset = S_OFF 46c4c5716eSCatalin Marinas UNWIND(.fnend ) 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds/* 491da177e4SLinus Torvalds * Ok, we need to do extra processing, enter the slow path. 501da177e4SLinus Torvalds */ 511da177e4SLinus Torvaldsfast_work_pending: 521da177e4SLinus Torvalds str r0, [sp, #S_R0+S_OFF]! @ returned r0 531da177e4SLinus Torvaldswork_pending: 541da177e4SLinus Torvalds mov r0, sp @ 'regs' 551da177e4SLinus Torvalds mov r2, why @ 'syscall' 560a267fa6SAl Viro bl do_work_pending 5766285217SAl Viro cmp r0, #0 5881783786SAl Viro beq no_work_pending 5966285217SAl Viro movlt scno, #(__NR_restart_syscall - __NR_SYSCALL_BASE) 6081783786SAl Viro ldmia sp, {r0 - r6} @ have to reload r0 - r6 6181783786SAl Viro b local_restart @ ... and off we go 6281783786SAl Viro 631da177e4SLinus Torvalds/* 641da177e4SLinus Torvalds * "slow" syscall return path. "why" tells us if this was a real syscall. 651da177e4SLinus Torvalds */ 661da177e4SLinus TorvaldsENTRY(ret_to_user) 671da177e4SLinus Torvaldsret_slow_syscall: 681ec42c0cSRussell King disable_irq @ disable interrupts 699fc2552aSMing LeiENTRY(ret_to_user_from_irq) 701da177e4SLinus Torvalds ldr r1, [tsk, #TI_FLAGS] 711da177e4SLinus Torvalds tst r1, #_TIF_WORK_MASK 721da177e4SLinus Torvalds bne work_pending 731da177e4SLinus Torvaldsno_work_pending: 74d13e5eddSTodd Android Poynor asm_trace_hardirqs_on 75651e9499SRussell King 76f80dff9dSDan Williams /* perform architecture specific actions before user return */ 77f80dff9dSDan Williams arch_ret_to_user r1, lr 78b0088480SKevin Hilman ct_user_enter save = 0 79f80dff9dSDan Williams 80b86040a5SCatalin Marinas restore_user_regs fast = 0, offset = 0 819fc2552aSMing LeiENDPROC(ret_to_user_from_irq) 8293ed3970SCatalin MarinasENDPROC(ret_to_user) 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds/* 851da177e4SLinus Torvalds * This is how we return from a fork. 861da177e4SLinus Torvalds */ 871da177e4SLinus TorvaldsENTRY(ret_from_fork) 881da177e4SLinus Torvalds bl schedule_tail 899fff2fa0SAl Viro cmp r5, #0 909fff2fa0SAl Viro movne r0, r4 9168687c84SRussell King adrne lr, BSYM(1f) 926ebbf2ceSRussell King retne r5 9368687c84SRussell King1: get_thread_info tsk 941da177e4SLinus Torvalds b ret_slow_syscall 9593ed3970SCatalin MarinasENDPROC(ret_from_fork) 961da177e4SLinus Torvalds 97fa1b4f91SAl Viro .equ NR_syscalls,0 98fa1b4f91SAl Viro#define CALL(x) .equ NR_syscalls,NR_syscalls+1 991da177e4SLinus Torvalds#include "calls.S" 1001f66e06fSWade Farnsworth 1011f66e06fSWade Farnsworth/* 1021f66e06fSWade Farnsworth * Ensure that the system call table is equal to __NR_syscalls, 1031f66e06fSWade Farnsworth * which is the value the rest of the system sees 1041f66e06fSWade Farnsworth */ 1051f66e06fSWade Farnsworth.ifne NR_syscalls - __NR_syscalls 1061f66e06fSWade Farnsworth.error "__NR_syscalls is not equal to the size of the syscall table" 1071f66e06fSWade Farnsworth.endif 1081f66e06fSWade Farnsworth 109fa1b4f91SAl Viro#undef CALL 110fa1b4f91SAl Viro#define CALL(x) .long x 1111da177e4SLinus Torvalds 112606576ceSSteven Rostedt#ifdef CONFIG_FUNCTION_TRACER 113686ff228SRabin Vincent/* 114686ff228SRabin Vincent * When compiling with -pg, gcc inserts a call to the mcount routine at the 115686ff228SRabin Vincent * start of every function. In mcount, apart from the function's address (in 116686ff228SRabin Vincent * lr), we need to get hold of the function's caller's address. 117686ff228SRabin Vincent * 118686ff228SRabin Vincent * Older GCCs (pre-4.4) inserted a call to a routine called mcount like this: 119686ff228SRabin Vincent * 120686ff228SRabin Vincent * bl mcount 121686ff228SRabin Vincent * 122686ff228SRabin Vincent * These versions have the limitation that in order for the mcount routine to 123686ff228SRabin Vincent * be able to determine the function's caller's address, an APCS-style frame 124686ff228SRabin Vincent * pointer (which is set up with something like the code below) is required. 125686ff228SRabin Vincent * 126686ff228SRabin Vincent * mov ip, sp 127686ff228SRabin Vincent * push {fp, ip, lr, pc} 128686ff228SRabin Vincent * sub fp, ip, #4 129686ff228SRabin Vincent * 130686ff228SRabin Vincent * With EABI, these frame pointers are not available unless -mapcs-frame is 131686ff228SRabin Vincent * specified, and if building as Thumb-2, not even then. 132686ff228SRabin Vincent * 133686ff228SRabin Vincent * Newer GCCs (4.4+) solve this problem by introducing a new version of mcount, 134686ff228SRabin Vincent * with call sites like: 135686ff228SRabin Vincent * 136686ff228SRabin Vincent * push {lr} 137686ff228SRabin Vincent * bl __gnu_mcount_nc 138686ff228SRabin Vincent * 139686ff228SRabin Vincent * With these compilers, frame pointers are not necessary. 140686ff228SRabin Vincent * 141686ff228SRabin Vincent * mcount can be thought of as a function called in the middle of a subroutine 142686ff228SRabin Vincent * call. As such, it needs to be transparent for both the caller and the 143686ff228SRabin Vincent * callee: the original lr needs to be restored when leaving mcount, and no 144686ff228SRabin Vincent * registers should be clobbered. (In the __gnu_mcount_nc implementation, we 145686ff228SRabin Vincent * clobber the ip register. This is OK because the ARM calling convention 146686ff228SRabin Vincent * allows it to be clobbered in subroutines and doesn't use it to hold 147686ff228SRabin Vincent * parameters.) 1483b6c223bSRabin Vincent * 1493b6c223bSRabin Vincent * When using dynamic ftrace, we patch out the mcount call by a "mov r0, r0" 1503b6c223bSRabin Vincent * for the mcount case, and a "pop {lr}" for the __gnu_mcount_nc case (see 1513b6c223bSRabin Vincent * arch/arm/kernel/ftrace.c). 152686ff228SRabin Vincent */ 15309bfafacSRabin Vincent 15409bfafacSRabin Vincent#ifndef CONFIG_OLD_MCOUNT 15509bfafacSRabin Vincent#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) 15609bfafacSRabin Vincent#error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0. 15709bfafacSRabin Vincent#endif 15809bfafacSRabin Vincent#endif 15909bfafacSRabin Vincent 160d68133b5SRabin Vincent.macro mcount_adjust_addr rd, rn 161d68133b5SRabin Vincent bic \rd, \rn, #1 @ clear the Thumb bit if present 162d68133b5SRabin Vincent sub \rd, \rd, #MCOUNT_INSN_SIZE 163d68133b5SRabin Vincent.endm 164d68133b5SRabin Vincent 165d3b9dc9dSRabin Vincent.macro __mcount suffix 166d3b9dc9dSRabin Vincent mcount_enter 167181f817eSUwe Kleine-König ldr r0, =ftrace_trace_function 168181f817eSUwe Kleine-König ldr r2, [r0] 169a3ba87a6SRabin Vincent adr r0, .Lftrace_stub 170181f817eSUwe Kleine-König cmp r0, r2 171d3b9dc9dSRabin Vincent bne 1f 172181f817eSUwe Kleine-König 173376cfa87STim Bird#ifdef CONFIG_FUNCTION_GRAPH_TRACER 174376cfa87STim Bird ldr r1, =ftrace_graph_return 175376cfa87STim Bird ldr r2, [r1] 176376cfa87STim Bird cmp r0, r2 177376cfa87STim Bird bne ftrace_graph_caller\suffix 178376cfa87STim Bird 179376cfa87STim Bird ldr r1, =ftrace_graph_entry 180376cfa87STim Bird ldr r2, [r1] 181376cfa87STim Bird ldr r0, =ftrace_graph_entry_stub 182376cfa87STim Bird cmp r0, r2 183376cfa87STim Bird bne ftrace_graph_caller\suffix 184376cfa87STim Bird#endif 185376cfa87STim Bird 186d3b9dc9dSRabin Vincent mcount_exit 187181f817eSUwe Kleine-König 188d3b9dc9dSRabin Vincent1: mcount_get_lr r1 @ lr of instrumented func 189d68133b5SRabin Vincent mcount_adjust_addr r0, lr @ instrumented function 190d3b9dc9dSRabin Vincent adr lr, BSYM(2f) 191181f817eSUwe Kleine-König mov pc, r2 192d3b9dc9dSRabin Vincent2: mcount_exit 193d3b9dc9dSRabin Vincent.endm 194d3b9dc9dSRabin Vincent 195d3b9dc9dSRabin Vincent.macro __ftrace_caller suffix 196d3b9dc9dSRabin Vincent mcount_enter 197d3b9dc9dSRabin Vincent 198d3b9dc9dSRabin Vincent mcount_get_lr r1 @ lr of instrumented func 199d68133b5SRabin Vincent mcount_adjust_addr r0, lr @ instrumented function 200d3b9dc9dSRabin Vincent 201d3b9dc9dSRabin Vincent .globl ftrace_call\suffix 202d3b9dc9dSRabin Vincentftrace_call\suffix: 203d3b9dc9dSRabin Vincent bl ftrace_stub 204d3b9dc9dSRabin Vincent 205dd686eb1SRabin Vincent#ifdef CONFIG_FUNCTION_GRAPH_TRACER 206dd686eb1SRabin Vincent .globl ftrace_graph_call\suffix 207dd686eb1SRabin Vincentftrace_graph_call\suffix: 208dd686eb1SRabin Vincent mov r0, r0 209dd686eb1SRabin Vincent#endif 210dd686eb1SRabin Vincent 211d3b9dc9dSRabin Vincent mcount_exit 212d3b9dc9dSRabin Vincent.endm 213181f817eSUwe Kleine-König 214376cfa87STim Bird.macro __ftrace_graph_caller 215376cfa87STim Bird sub r0, fp, #4 @ &lr of instrumented routine (&parent) 216dd686eb1SRabin Vincent#ifdef CONFIG_DYNAMIC_FTRACE 217dd686eb1SRabin Vincent @ called from __ftrace_caller, saved in mcount_enter 218dd686eb1SRabin Vincent ldr r1, [sp, #16] @ instrumented routine (func) 219d68133b5SRabin Vincent mcount_adjust_addr r1, r1 220dd686eb1SRabin Vincent#else 221dd686eb1SRabin Vincent @ called from __mcount, untouched in lr 222d68133b5SRabin Vincent mcount_adjust_addr r1, lr @ instrumented routine (func) 223dd686eb1SRabin Vincent#endif 224376cfa87STim Bird mov r2, fp @ frame pointer 225376cfa87STim Bird bl prepare_ftrace_return 226376cfa87STim Bird mcount_exit 227376cfa87STim Bird.endm 228014c257cSAbhishek Sagar 22909bfafacSRabin Vincent#ifdef CONFIG_OLD_MCOUNT 23009bfafacSRabin Vincent/* 231d3b9dc9dSRabin Vincent * mcount 23209bfafacSRabin Vincent */ 233014c257cSAbhishek Sagar 234d3b9dc9dSRabin Vincent.macro mcount_enter 235d3b9dc9dSRabin Vincent stmdb sp!, {r0-r3, lr} 236d3b9dc9dSRabin Vincent.endm 237d3b9dc9dSRabin Vincent 238d3b9dc9dSRabin Vincent.macro mcount_get_lr reg 239d3b9dc9dSRabin Vincent ldr \reg, [fp, #-4] 240d3b9dc9dSRabin Vincent.endm 241d3b9dc9dSRabin Vincent 242d3b9dc9dSRabin Vincent.macro mcount_exit 243d3b9dc9dSRabin Vincent ldr lr, [fp, #-4] 244014c257cSAbhishek Sagar ldmia sp!, {r0-r3, pc} 245d3b9dc9dSRabin Vincent.endm 246d3b9dc9dSRabin Vincent 247d3b9dc9dSRabin VincentENTRY(mcount) 248d3b9dc9dSRabin Vincent#ifdef CONFIG_DYNAMIC_FTRACE 249d3b9dc9dSRabin Vincent stmdb sp!, {lr} 250d3b9dc9dSRabin Vincent ldr lr, [fp, #-4] 251d3b9dc9dSRabin Vincent ldmia sp!, {pc} 252d3b9dc9dSRabin Vincent#else 253d3b9dc9dSRabin Vincent __mcount _old 254d3b9dc9dSRabin Vincent#endif 25572fa62faSRabin VincentENDPROC(mcount) 256d3b9dc9dSRabin Vincent 257d3b9dc9dSRabin Vincent#ifdef CONFIG_DYNAMIC_FTRACE 258d3b9dc9dSRabin VincentENTRY(ftrace_caller_old) 259d3b9dc9dSRabin Vincent __ftrace_caller _old 260d3b9dc9dSRabin VincentENDPROC(ftrace_caller_old) 26109bfafacSRabin Vincent#endif 262014c257cSAbhishek Sagar 263376cfa87STim Bird#ifdef CONFIG_FUNCTION_GRAPH_TRACER 264376cfa87STim BirdENTRY(ftrace_graph_caller_old) 265376cfa87STim Bird __ftrace_graph_caller 266376cfa87STim BirdENDPROC(ftrace_graph_caller_old) 267376cfa87STim Bird#endif 268376cfa87STim Bird 269d3b9dc9dSRabin Vincent.purgem mcount_enter 270d3b9dc9dSRabin Vincent.purgem mcount_get_lr 271d3b9dc9dSRabin Vincent.purgem mcount_exit 272d3b9dc9dSRabin Vincent#endif 273d3b9dc9dSRabin Vincent 274d3b9dc9dSRabin Vincent/* 275d3b9dc9dSRabin Vincent * __gnu_mcount_nc 276d3b9dc9dSRabin Vincent */ 277d3b9dc9dSRabin Vincent 278d3b9dc9dSRabin Vincent.macro mcount_enter 279b21e023bSRabin Vincent/* 280b21e023bSRabin Vincent * This pad compensates for the push {lr} at the call site. Note that we are 281b21e023bSRabin Vincent * unable to unwind through a function which does not otherwise save its lr. 282b21e023bSRabin Vincent */ 283b21e023bSRabin Vincent UNWIND(.pad #4) 284d3b9dc9dSRabin Vincent stmdb sp!, {r0-r3, lr} 285b21e023bSRabin Vincent UNWIND(.save {r0-r3, lr}) 286d3b9dc9dSRabin Vincent.endm 287d3b9dc9dSRabin Vincent 288d3b9dc9dSRabin Vincent.macro mcount_get_lr reg 289d3b9dc9dSRabin Vincent ldr \reg, [sp, #20] 290d3b9dc9dSRabin Vincent.endm 291d3b9dc9dSRabin Vincent 292d3b9dc9dSRabin Vincent.macro mcount_exit 293d3b9dc9dSRabin Vincent ldmia sp!, {r0-r3, ip, lr} 2946ebbf2ceSRussell King ret ip 295d3b9dc9dSRabin Vincent.endm 296d3b9dc9dSRabin Vincent 297d3b9dc9dSRabin VincentENTRY(__gnu_mcount_nc) 298b21e023bSRabin VincentUNWIND(.fnstart) 299d3b9dc9dSRabin Vincent#ifdef CONFIG_DYNAMIC_FTRACE 300d3b9dc9dSRabin Vincent mov ip, lr 301d3b9dc9dSRabin Vincent ldmia sp!, {lr} 3026ebbf2ceSRussell King ret ip 303d3b9dc9dSRabin Vincent#else 304d3b9dc9dSRabin Vincent __mcount 305d3b9dc9dSRabin Vincent#endif 306b21e023bSRabin VincentUNWIND(.fnend) 307d3b9dc9dSRabin VincentENDPROC(__gnu_mcount_nc) 308d3b9dc9dSRabin Vincent 309d3b9dc9dSRabin Vincent#ifdef CONFIG_DYNAMIC_FTRACE 310d3b9dc9dSRabin VincentENTRY(ftrace_caller) 311b21e023bSRabin VincentUNWIND(.fnstart) 312d3b9dc9dSRabin Vincent __ftrace_caller 313b21e023bSRabin VincentUNWIND(.fnend) 314d3b9dc9dSRabin VincentENDPROC(ftrace_caller) 315d3b9dc9dSRabin Vincent#endif 316d3b9dc9dSRabin Vincent 317376cfa87STim Bird#ifdef CONFIG_FUNCTION_GRAPH_TRACER 318376cfa87STim BirdENTRY(ftrace_graph_caller) 319b21e023bSRabin VincentUNWIND(.fnstart) 320376cfa87STim Bird __ftrace_graph_caller 321b21e023bSRabin VincentUNWIND(.fnend) 322376cfa87STim BirdENDPROC(ftrace_graph_caller) 323376cfa87STim Bird#endif 324376cfa87STim Bird 325d3b9dc9dSRabin Vincent.purgem mcount_enter 326d3b9dc9dSRabin Vincent.purgem mcount_get_lr 327d3b9dc9dSRabin Vincent.purgem mcount_exit 328014c257cSAbhishek Sagar 329376cfa87STim Bird#ifdef CONFIG_FUNCTION_GRAPH_TRACER 330376cfa87STim Bird .globl return_to_handler 331376cfa87STim Birdreturn_to_handler: 332376cfa87STim Bird stmdb sp!, {r0-r3} 333376cfa87STim Bird mov r0, fp @ frame pointer 334376cfa87STim Bird bl ftrace_return_to_handler 335376cfa87STim Bird mov lr, r0 @ r0 has real ret addr 336376cfa87STim Bird ldmia sp!, {r0-r3} 3376ebbf2ceSRussell King ret lr 338376cfa87STim Bird#endif 339014c257cSAbhishek Sagar 34072fa62faSRabin VincentENTRY(ftrace_stub) 341a3ba87a6SRabin Vincent.Lftrace_stub: 3426ebbf2ceSRussell King ret lr 34372fa62faSRabin VincentENDPROC(ftrace_stub) 344014c257cSAbhishek Sagar 345606576ceSSteven Rostedt#endif /* CONFIG_FUNCTION_TRACER */ 346014c257cSAbhishek Sagar 3471da177e4SLinus Torvalds/*============================================================================= 3481da177e4SLinus Torvalds * SWI handler 3491da177e4SLinus Torvalds *----------------------------------------------------------------------------- 3501da177e4SLinus Torvalds */ 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds .align 5 3531da177e4SLinus TorvaldsENTRY(vector_swi) 35419c4d593SUwe Kleine-König#ifdef CONFIG_CPU_V7M 35519c4d593SUwe Kleine-König v7m_exception_entry 35619c4d593SUwe Kleine-König#else 357f4dc9a4cSRussell King sub sp, sp, #S_FRAME_SIZE 358f4dc9a4cSRussell King stmia sp, {r0 - r12} @ Calling r0 - r12 359b86040a5SCatalin Marinas ARM( add r8, sp, #S_PC ) 360b86040a5SCatalin Marinas ARM( stmdb r8, {sp, lr}^ ) @ Calling sp, lr 361b86040a5SCatalin Marinas THUMB( mov r8, sp ) 362b86040a5SCatalin Marinas THUMB( store_user_sp_lr r8, r10, S_SP ) @ calling sp, lr 363f4dc9a4cSRussell King mrs r8, spsr @ called from non-FIQ mode, so ok. 364f4dc9a4cSRussell King str lr, [sp, #S_PC] @ Save calling PC 365f4dc9a4cSRussell King str r8, [sp, #S_PSR] @ Save CPSR 366f4dc9a4cSRussell King str r0, [sp, #S_OLD_R0] @ Save OLD_R0 36719c4d593SUwe Kleine-König#endif 3681da177e4SLinus Torvalds zero_fp 3698229c54fSRussell King alignment_trap ip, __cr_alignment 3701aa2b3b7SWill Deacon enable_irq 3711aa2b3b7SWill Deacon ct_user_exit 3721aa2b3b7SWill Deacon get_thread_info tsk 3731aa2b3b7SWill Deacon 374e0f9f4a6SRussell King /* 375e0f9f4a6SRussell King * Get the system call number. 376e0f9f4a6SRussell King */ 3773f2829a3SNicolas Pitre 378dd35afc2SNicolas Pitre#if defined(CONFIG_OABI_COMPAT) 3793f2829a3SNicolas Pitre 380dd35afc2SNicolas Pitre /* 381dd35afc2SNicolas Pitre * If we have CONFIG_OABI_COMPAT then we need to look at the swi 382dd35afc2SNicolas Pitre * value to determine if it is an EABI or an old ABI call. 383dd35afc2SNicolas Pitre */ 384dd35afc2SNicolas Pitre#ifdef CONFIG_ARM_THUMB 385dd35afc2SNicolas Pitre tst r8, #PSR_T_BIT 386dd35afc2SNicolas Pitre movne r10, #0 @ no thumb OABI emulation 3871aa2b3b7SWill Deacon USER( ldreq r10, [lr, #-4] ) @ get SWI instruction 388dd35afc2SNicolas Pitre#else 3891aa2b3b7SWill Deacon USER( ldr r10, [lr, #-4] ) @ get SWI instruction 390dd35afc2SNicolas Pitre#endif 391457c2403SBen Dooks ARM_BE8(rev r10, r10) @ little endian instruction 392dd35afc2SNicolas Pitre 393dd35afc2SNicolas Pitre#elif defined(CONFIG_AEABI) 394dd35afc2SNicolas Pitre 395dd35afc2SNicolas Pitre /* 396dd35afc2SNicolas Pitre * Pure EABI user space always put syscall number into scno (r7). 397dd35afc2SNicolas Pitre */ 3983f2829a3SNicolas Pitre#elif defined(CONFIG_ARM_THUMB) 399dd35afc2SNicolas Pitre /* Legacy ABI only, possibly thumb mode. */ 400e0f9f4a6SRussell King tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs 401e0f9f4a6SRussell King addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in 4021aa2b3b7SWill Deacon USER( ldreq scno, [lr, #-4] ) 403dd35afc2SNicolas Pitre 404e0f9f4a6SRussell King#else 405dd35afc2SNicolas Pitre /* Legacy ABI only. */ 4061aa2b3b7SWill Deacon USER( ldr scno, [lr, #-4] ) @ get SWI instruction 407e0f9f4a6SRussell King#endif 4081da177e4SLinus Torvalds 409dd35afc2SNicolas Pitre adr tbl, sys_call_table @ load syscall table pointer 410dd35afc2SNicolas Pitre 411dd35afc2SNicolas Pitre#if defined(CONFIG_OABI_COMPAT) 412dd35afc2SNicolas Pitre /* 413dd35afc2SNicolas Pitre * If the swi argument is zero, this is an EABI call and we do nothing. 414dd35afc2SNicolas Pitre * 415dd35afc2SNicolas Pitre * If this is an old ABI call, get the syscall number into scno and 416dd35afc2SNicolas Pitre * get the old ABI syscall table address. 417dd35afc2SNicolas Pitre */ 418dd35afc2SNicolas Pitre bics r10, r10, #0xff000000 419dd35afc2SNicolas Pitre eorne scno, r10, #__NR_OABI_SYSCALL_BASE 420dd35afc2SNicolas Pitre ldrne tbl, =sys_oabi_call_table 421dd35afc2SNicolas Pitre#elif !defined(CONFIG_AEABI) 4221da177e4SLinus Torvalds bic scno, scno, #0xff000000 @ mask off SWI op-code 423e0f9f4a6SRussell King eor scno, scno, #__NR_SYSCALL_BASE @ check OS number 4243f2829a3SNicolas Pitre#endif 425dd35afc2SNicolas Pitre 42681783786SAl Virolocal_restart: 42770c70d97SNicolas Pitre ldr r10, [tsk, #TI_FLAGS] @ check for syscall tracing 4283f2829a3SNicolas Pitre stmdb sp!, {r4, r5} @ push fifth and sixth args 42970c70d97SNicolas Pitre 43029ef73b7SNathaniel Husted tst r10, #_TIF_SYSCALL_WORK @ are we tracing syscalls? 4311da177e4SLinus Torvalds bne __sys_trace 4321da177e4SLinus Torvalds 4331da177e4SLinus Torvalds cmp scno, #NR_syscalls @ check upper syscall limit 434b86040a5SCatalin Marinas adr lr, BSYM(ret_fast_syscall) @ return address 4351da177e4SLinus Torvalds ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine 4361da177e4SLinus Torvalds 4371da177e4SLinus Torvalds add r1, sp, #S_OFF 438d95bc250SWill Deacon2: cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE) 439e0f9f4a6SRussell King eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back 4401da177e4SLinus Torvalds bcs arm_syscall 441d95bc250SWill Deacon mov why, #0 @ no longer a real syscall 4421da177e4SLinus Torvalds b sys_ni_syscall @ not private func 4431aa2b3b7SWill Deacon 4441aa2b3b7SWill Deacon#if defined(CONFIG_OABI_COMPAT) || !defined(CONFIG_AEABI) 4451aa2b3b7SWill Deacon /* 4461aa2b3b7SWill Deacon * We failed to handle a fault trying to access the page 4471aa2b3b7SWill Deacon * containing the swi instruction, but we're not really in a 4481aa2b3b7SWill Deacon * position to return -EFAULT. Instead, return back to the 4491aa2b3b7SWill Deacon * instruction and re-enter the user fault handling path trying 4501aa2b3b7SWill Deacon * to page it in. This will likely result in sending SEGV to the 4511aa2b3b7SWill Deacon * current task. 4521aa2b3b7SWill Deacon */ 4531aa2b3b7SWill Deacon9001: 4541aa2b3b7SWill Deacon sub lr, lr, #4 4551aa2b3b7SWill Deacon str lr, [sp, #S_PC] 4561aa2b3b7SWill Deacon b ret_fast_syscall 4571aa2b3b7SWill Deacon#endif 45893ed3970SCatalin MarinasENDPROC(vector_swi) 4591da177e4SLinus Torvalds 4601da177e4SLinus Torvalds /* 4611da177e4SLinus Torvalds * This is the really slow path. We're going to be doing 4621da177e4SLinus Torvalds * context switches, and waiting for our parent to respond. 4631da177e4SLinus Torvalds */ 4641da177e4SLinus Torvalds__sys_trace: 465ad722541SWill Deacon mov r1, scno 466ad722541SWill Deacon add r0, sp, #S_OFF 467ad722541SWill Deacon bl syscall_trace_enter 4681da177e4SLinus Torvalds 469b86040a5SCatalin Marinas adr lr, BSYM(__sys_trace_return) @ return address 4703f471126SNicolas Pitre mov scno, r0 @ syscall number (possibly new) 4711da177e4SLinus Torvalds add r1, sp, #S_R0 + S_OFF @ pointer to regs 4721da177e4SLinus Torvalds cmp scno, #NR_syscalls @ check upper syscall limit 473c7aa00dbSWill Deacon ldmccia r1, {r0 - r6} @ have to reload r0 - r6 474c7aa00dbSWill Deacon stmccia sp, {r4, r5} @ and update the stack args 4751da177e4SLinus Torvalds ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine 476ad75b514SKees Cook cmp scno, #-1 @ skip the syscall? 477ad75b514SKees Cook bne 2b 478ad75b514SKees Cook add sp, sp, #S_OFF @ restore stack 479ad75b514SKees Cook b ret_slow_syscall 4801da177e4SLinus Torvalds 4811da177e4SLinus Torvalds__sys_trace_return: 4821da177e4SLinus Torvalds str r0, [sp, #S_R0 + S_OFF]! @ save returned r0 483ad722541SWill Deacon mov r0, sp 484ad722541SWill Deacon bl syscall_trace_exit 4851da177e4SLinus Torvalds b ret_slow_syscall 4861da177e4SLinus Torvalds 4871da177e4SLinus Torvalds .align 5 4881da177e4SLinus Torvalds#ifdef CONFIG_ALIGNMENT_TRAP 4891da177e4SLinus Torvalds .type __cr_alignment, #object 4901da177e4SLinus Torvalds__cr_alignment: 4911da177e4SLinus Torvalds .word cr_alignment 4921da177e4SLinus Torvalds#endif 493dd35afc2SNicolas Pitre .ltorg 494dd35afc2SNicolas Pitre 495dd35afc2SNicolas Pitre/* 496dd35afc2SNicolas Pitre * This is the syscall table declaration for native ABI syscalls. 497dd35afc2SNicolas Pitre * With EABI a couple syscalls are obsolete and defined as sys_ni_syscall. 498dd35afc2SNicolas Pitre */ 499dd35afc2SNicolas Pitre#define ABI(native, compat) native 500dd35afc2SNicolas Pitre#ifdef CONFIG_AEABI 501dd35afc2SNicolas Pitre#define OBSOLETE(syscall) sys_ni_syscall 502dd35afc2SNicolas Pitre#else 503dd35afc2SNicolas Pitre#define OBSOLETE(syscall) syscall 504dd35afc2SNicolas Pitre#endif 5051da177e4SLinus Torvalds 5061da177e4SLinus Torvalds .type sys_call_table, #object 5071da177e4SLinus TorvaldsENTRY(sys_call_table) 5081da177e4SLinus Torvalds#include "calls.S" 509dd35afc2SNicolas Pitre#undef ABI 510dd35afc2SNicolas Pitre#undef OBSOLETE 5111da177e4SLinus Torvalds 5121da177e4SLinus Torvalds/*============================================================================ 5131da177e4SLinus Torvalds * Special system call wrappers 5141da177e4SLinus Torvalds */ 5151da177e4SLinus Torvalds@ r0 = syscall number 516567bd980SRussell King@ r8 = syscall table 5171da177e4SLinus Torvaldssys_syscall: 5185247593cSPaul Brook bic scno, r0, #__NR_OABI_SYSCALL_BASE 5191da177e4SLinus Torvalds cmp scno, #__NR_syscall - __NR_SYSCALL_BASE 5201da177e4SLinus Torvalds cmpne scno, #NR_syscalls @ check range 5211da177e4SLinus Torvalds stmloia sp, {r5, r6} @ shuffle args 5221da177e4SLinus Torvalds movlo r0, r1 5231da177e4SLinus Torvalds movlo r1, r2 5241da177e4SLinus Torvalds movlo r2, r3 5251da177e4SLinus Torvalds movlo r3, r4 5261da177e4SLinus Torvalds ldrlo pc, [tbl, scno, lsl #2] 5271da177e4SLinus Torvalds b sys_ni_syscall 52893ed3970SCatalin MarinasENDPROC(sys_syscall) 5291da177e4SLinus Torvalds 5301da177e4SLinus Torvaldssys_sigreturn_wrapper: 5311da177e4SLinus Torvalds add r0, sp, #S_OFF 532653d48b2SAl Viro mov why, #0 @ prevent syscall restart handling 5331da177e4SLinus Torvalds b sys_sigreturn 53493ed3970SCatalin MarinasENDPROC(sys_sigreturn_wrapper) 5351da177e4SLinus Torvalds 5361da177e4SLinus Torvaldssys_rt_sigreturn_wrapper: 5371da177e4SLinus Torvalds add r0, sp, #S_OFF 538653d48b2SAl Viro mov why, #0 @ prevent syscall restart handling 5391da177e4SLinus Torvalds b sys_rt_sigreturn 54093ed3970SCatalin MarinasENDPROC(sys_rt_sigreturn_wrapper) 5411da177e4SLinus Torvalds 542713c4815SNicolas Pitresys_statfs64_wrapper: 543713c4815SNicolas Pitre teq r1, #88 544713c4815SNicolas Pitre moveq r1, #84 545713c4815SNicolas Pitre b sys_statfs64 54693ed3970SCatalin MarinasENDPROC(sys_statfs64_wrapper) 547713c4815SNicolas Pitre 548713c4815SNicolas Pitresys_fstatfs64_wrapper: 549713c4815SNicolas Pitre teq r1, #88 550713c4815SNicolas Pitre moveq r1, #84 551713c4815SNicolas Pitre b sys_fstatfs64 55293ed3970SCatalin MarinasENDPROC(sys_fstatfs64_wrapper) 553713c4815SNicolas Pitre 5541da177e4SLinus Torvalds/* 5551da177e4SLinus Torvalds * Note: off_4k (r5) is always units of 4K. If we can't do the requested 5561da177e4SLinus Torvalds * offset, we return EINVAL. 5571da177e4SLinus Torvalds */ 5581da177e4SLinus Torvaldssys_mmap2: 5591da177e4SLinus Torvalds#if PAGE_SHIFT > 12 5601da177e4SLinus Torvalds tst r5, #PGOFF_MASK 5611da177e4SLinus Torvalds moveq r5, r5, lsr #PAGE_SHIFT - 12 5621da177e4SLinus Torvalds streq r5, [sp, #4] 563f8b72560SAl Viro beq sys_mmap_pgoff 5641da177e4SLinus Torvalds mov r0, #-EINVAL 5656ebbf2ceSRussell King ret lr 5661da177e4SLinus Torvalds#else 5671da177e4SLinus Torvalds str r5, [sp, #4] 568f8b72560SAl Viro b sys_mmap_pgoff 5691da177e4SLinus Torvalds#endif 57093ed3970SCatalin MarinasENDPROC(sys_mmap2) 571687ad019SNicolas Pitre 572687ad019SNicolas Pitre#ifdef CONFIG_OABI_COMPAT 573dd35afc2SNicolas Pitre 574687ad019SNicolas Pitre/* 575687ad019SNicolas Pitre * These are syscalls with argument register differences 576687ad019SNicolas Pitre */ 577687ad019SNicolas Pitre 578687ad019SNicolas Pitresys_oabi_pread64: 579687ad019SNicolas Pitre stmia sp, {r3, r4} 580687ad019SNicolas Pitre b sys_pread64 58193ed3970SCatalin MarinasENDPROC(sys_oabi_pread64) 582687ad019SNicolas Pitre 583687ad019SNicolas Pitresys_oabi_pwrite64: 584687ad019SNicolas Pitre stmia sp, {r3, r4} 585687ad019SNicolas Pitre b sys_pwrite64 58693ed3970SCatalin MarinasENDPROC(sys_oabi_pwrite64) 587687ad019SNicolas Pitre 588687ad019SNicolas Pitresys_oabi_truncate64: 589687ad019SNicolas Pitre mov r3, r2 590687ad019SNicolas Pitre mov r2, r1 591687ad019SNicolas Pitre b sys_truncate64 59293ed3970SCatalin MarinasENDPROC(sys_oabi_truncate64) 593687ad019SNicolas Pitre 594687ad019SNicolas Pitresys_oabi_ftruncate64: 595687ad019SNicolas Pitre mov r3, r2 596687ad019SNicolas Pitre mov r2, r1 597687ad019SNicolas Pitre b sys_ftruncate64 59893ed3970SCatalin MarinasENDPROC(sys_oabi_ftruncate64) 599687ad019SNicolas Pitre 600687ad019SNicolas Pitresys_oabi_readahead: 601687ad019SNicolas Pitre str r3, [sp] 602687ad019SNicolas Pitre mov r3, r2 603687ad019SNicolas Pitre mov r2, r1 604687ad019SNicolas Pitre b sys_readahead 60593ed3970SCatalin MarinasENDPROC(sys_oabi_readahead) 606687ad019SNicolas Pitre 607dd35afc2SNicolas Pitre/* 608dd35afc2SNicolas Pitre * Let's declare a second syscall table for old ABI binaries 609dd35afc2SNicolas Pitre * using the compatibility syscall entries. 610dd35afc2SNicolas Pitre */ 611dd35afc2SNicolas Pitre#define ABI(native, compat) compat 612dd35afc2SNicolas Pitre#define OBSOLETE(syscall) syscall 613dd35afc2SNicolas Pitre 614dd35afc2SNicolas Pitre .type sys_oabi_call_table, #object 615dd35afc2SNicolas PitreENTRY(sys_oabi_call_table) 616dd35afc2SNicolas Pitre#include "calls.S" 617dd35afc2SNicolas Pitre#undef ABI 618dd35afc2SNicolas Pitre#undef OBSOLETE 619dd35afc2SNicolas Pitre 620687ad019SNicolas Pitre#endif 621687ad019SNicolas Pitre 622