0001
0002
0003
0004
0005
0006
0007
0008 #include <asm/assembler.h>
0009 #include <asm/unistd.h>
0010 #include <asm/ftrace.h>
0011 #include <asm/unwind.h>
0012 #include <asm/memory.h>
0013 #ifdef CONFIG_AEABI
0014 #include <asm/unistd-oabi.h>
0015 #endif
0016
0017 .equ NR_syscalls, __NR_syscalls
0018
0019 .macro arch_ret_to_user, tmp
0020 #ifdef CONFIG_ARCH_IOP32X
0021 mrc p15, 0, \tmp, c15, c1, 0
0022 tst \tmp, #(1 << 6)
0023 bicne \tmp, \tmp, #(1 << 6)
0024 mcrne p15, 0, \tmp, c15, c1, 0 @ Disable cp6 access
0025 #endif
0026 .endm
0027
0028 #include "entry-header.S"
0029
0030 saved_psr .req r8
0031 #if defined(CONFIG_TRACE_IRQFLAGS) || defined(CONFIG_CONTEXT_TRACKING_USER)
0032 saved_pc .req r9
0033 #define TRACE(x...) x
0034 #else
0035 saved_pc .req lr
0036 #define TRACE(x...)
0037 #endif
0038
0039 .section .entry.text,"ax",%progbits
0040 .align 5
0041 #if !(IS_ENABLED(CONFIG_TRACE_IRQFLAGS) || IS_ENABLED(CONFIG_CONTEXT_TRACKING_USER) || \
0042 IS_ENABLED(CONFIG_DEBUG_RSEQ))
0043
0044
0045
0046
0047
0048
0049 ret_fast_syscall:
0050 __ret_fast_syscall:
0051 UNWIND(.fnstart )
0052 UNWIND(.cantunwind )
0053 disable_irq_notrace @ disable interrupts
0054 ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
0055 movs r1, r1, lsl #16
0056 bne fast_work_pending
0057
0058
0059
0060 arch_ret_to_user r1
0061
0062 restore_user_regs fast = 1, offset = S_OFF
0063 UNWIND(.fnend )
0064 ENDPROC(ret_fast_syscall)
0065
0066
0067 fast_work_pending:
0068 str r0, [sp, #S_R0+S_OFF]! @ returned r0
0069
0070 #else
0071
0072
0073
0074
0075
0076
0077 ret_fast_syscall:
0078 __ret_fast_syscall:
0079 UNWIND(.fnstart )
0080 UNWIND(.cantunwind )
0081 str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
0082 #if IS_ENABLED(CONFIG_DEBUG_RSEQ)
0083
0084 mov r0, sp @ 'regs'
0085 bl do_rseq_syscall
0086 #endif
0087 disable_irq_notrace @ disable interrupts
0088 ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
0089 movs r1, r1, lsl #16
0090 beq no_work_pending
0091 UNWIND(.fnend )
0092 ENDPROC(ret_fast_syscall)
0093
0094
0095 #endif
0096
0097 tst r1, #_TIF_SYSCALL_WORK
0098 bne __sys_trace_return_nosave
0099 slow_work_pending:
0100 mov r0, sp @ 'regs'
0101 mov r2, why @ 'syscall'
0102 bl do_work_pending
0103 cmp r0, #0
0104 beq no_work_pending
0105 movlt scno, #(__NR_restart_syscall - __NR_SYSCALL_BASE)
0106 ldmia sp, {r0 - r6} @ have to reload r0 - r6
0107 b local_restart @ ... and off we go
0108 ENDPROC(ret_fast_syscall)
0109
0110
0111
0112
0113
0114
0115
0116 ENTRY(ret_to_user)
0117 ret_slow_syscall:
0118 #if IS_ENABLED(CONFIG_DEBUG_RSEQ)
0119
0120 enable_irq_notrace @ enable interrupts
0121 mov r0, sp @ 'regs'
0122 bl do_rseq_syscall
0123 #endif
0124 disable_irq_notrace @ disable interrupts
0125 ENTRY(ret_to_user_from_irq)
0126 ldr r1, [tsk, #TI_FLAGS]
0127 movs r1, r1, lsl #16
0128 bne slow_work_pending
0129 no_work_pending:
0130 asm_trace_hardirqs_on save = 0
0131
0132
0133 arch_ret_to_user r1
0134 ct_user_enter save = 0
0135
0136 restore_user_regs fast = 0, offset = 0
0137 ENDPROC(ret_to_user_from_irq)
0138 ENDPROC(ret_to_user)
0139
0140
0141
0142
0143 ENTRY(ret_from_fork)
0144 bl schedule_tail
0145 cmp r5, #0
0146 movne r0, r4
0147 badrne lr, 1f
0148 retne r5
0149 1: get_thread_info tsk
0150 b ret_slow_syscall
0151 ENDPROC(ret_from_fork)
0152
0153
0154
0155
0156
0157
0158 .align 5
0159 #ifdef CONFIG_HARDEN_BRANCH_HISTORY
0160 ENTRY(vector_bhb_loop8_swi)
0161 sub sp, sp, #PT_REGS_SIZE
0162 stmia sp, {r0 - r12}
0163 mov r8, #8
0164 1: b 2f
0165 2: subs r8, r8, #1
0166 bne 1b
0167 dsb nsh
0168 isb
0169 b 3f
0170 ENDPROC(vector_bhb_loop8_swi)
0171
0172 .align 5
0173 ENTRY(vector_bhb_bpiall_swi)
0174 sub sp, sp, #PT_REGS_SIZE
0175 stmia sp, {r0 - r12}
0176 mcr p15, 0, r8, c7, c5, 6 @ BPIALL
0177 isb
0178 b 3f
0179 ENDPROC(vector_bhb_bpiall_swi)
0180 #endif
0181 .align 5
0182 ENTRY(vector_swi)
0183 #ifdef CONFIG_CPU_V7M
0184 v7m_exception_entry
0185 #else
0186 sub sp, sp, #PT_REGS_SIZE
0187 stmia sp, {r0 - r12} @ Calling r0 - r12
0188 3:
0189 ARM( add r8, sp, #S_PC )
0190 ARM( stmdb r8, {sp, lr}^ ) @ Calling sp, lr
0191 THUMB( mov r8, sp )
0192 THUMB( store_user_sp_lr r8, r10, S_SP ) @ calling sp, lr
0193 mrs saved_psr, spsr @ called from non-FIQ mode, so ok.
0194 TRACE( mov saved_pc, lr )
0195 str saved_pc, [sp, #S_PC] @ Save calling PC
0196 str saved_psr, [sp, #S_PSR] @ Save CPSR
0197 str r0, [sp, #S_OLD_R0] @ Save OLD_R0
0198 #endif
0199 reload_current r10, ip
0200 zero_fp
0201 alignment_trap r10, ip, cr_alignment
0202 asm_trace_hardirqs_on save=0
0203 enable_irq_notrace
0204 ct_user_exit save=0
0205
0206
0207
0208
0209
0210 #if defined(CONFIG_OABI_COMPAT)
0211
0212
0213
0214
0215
0216 #ifdef CONFIG_ARM_THUMB
0217 tst saved_psr, #PSR_T_BIT
0218 movne r10, #0 @ no thumb OABI emulation
0219 USER( ldreq r10, [saved_pc, #-4] ) @ get SWI instruction
0220 #else
0221 USER( ldr r10, [saved_pc, #-4] ) @ get SWI instruction
0222 #endif
0223 ARM_BE8(rev r10, r10) @ little endian instruction
0224
0225 #elif defined(CONFIG_AEABI)
0226
0227
0228
0229
0230 #elif defined(CONFIG_ARM_THUMB)
0231
0232 tst saved_psr, #PSR_T_BIT @ this is SPSR from save_user_regs
0233 addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in
0234 USER( ldreq scno, [saved_pc, #-4] )
0235
0236 #else
0237
0238 USER( ldr scno, [saved_pc, #-4] ) @ get SWI instruction
0239 #endif
0240
0241
0242
0243 uaccess_disable tbl
0244 get_thread_info tsk
0245
0246 adr tbl, sys_call_table @ load syscall table pointer
0247
0248 #if defined(CONFIG_OABI_COMPAT)
0249
0250
0251
0252
0253
0254
0255 bics r10, r10, #0xff000000
0256 strne r10, [tsk, #TI_ABI_SYSCALL]
0257 streq scno, [tsk, #TI_ABI_SYSCALL]
0258 eorne scno, r10, #__NR_OABI_SYSCALL_BASE
0259 ldrne tbl, =sys_oabi_call_table
0260 #elif !defined(CONFIG_AEABI)
0261 bic scno, scno, #0xff000000 @ mask off SWI op-code
0262 str scno, [tsk, #TI_ABI_SYSCALL]
0263 eor scno, scno, #__NR_SYSCALL_BASE @ check OS number
0264 #else
0265 str scno, [tsk, #TI_ABI_SYSCALL]
0266 #endif
0267
0268
0269
0270
0271 TRACE( ldmia sp, {r0 - r3} )
0272
0273 local_restart:
0274 ldr r10, [tsk, #TI_FLAGS] @ check for syscall tracing
0275 stmdb sp!, {r4, r5} @ push fifth and sixth args
0276
0277 tst r10, #_TIF_SYSCALL_WORK @ are we tracing syscalls?
0278 bne __sys_trace
0279
0280 invoke_syscall tbl, scno, r10, __ret_fast_syscall
0281
0282 add r1, sp, #S_OFF
0283 2: cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
0284 eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back
0285 bcs arm_syscall
0286 mov why, #0 @ no longer a real syscall
0287 b sys_ni_syscall @ not private func
0288
0289 #if defined(CONFIG_OABI_COMPAT) || !defined(CONFIG_AEABI)
0290
0291
0292
0293
0294
0295
0296
0297
0298 9001:
0299 sub lr, saved_pc, #4
0300 str lr, [sp, #S_PC]
0301 get_thread_info tsk
0302 b ret_fast_syscall
0303 #endif
0304 ENDPROC(vector_swi)
0305 .ltorg
0306
0307
0308
0309
0310
0311 __sys_trace:
0312 add r0, sp, #S_OFF
0313 bl syscall_trace_enter
0314 mov scno, r0
0315 invoke_syscall tbl, scno, r10, __sys_trace_return, reload=1
0316 cmp scno, #-1 @ skip the syscall?
0317 bne 2b
0318 add sp, sp, #S_OFF @ restore stack
0319
0320 __sys_trace_return_nosave:
0321 enable_irq_notrace
0322 mov r0, sp
0323 bl syscall_trace_exit
0324 b ret_slow_syscall
0325
0326 __sys_trace_return:
0327 str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
0328 mov r0, sp
0329 bl syscall_trace_exit
0330 b ret_slow_syscall
0331
0332 .macro syscall_table_start, sym
0333 .equ __sys_nr, 0
0334 .type \sym, #object
0335 ENTRY(\sym)
0336 .endm
0337
0338 .macro syscall, nr, func
0339 .ifgt __sys_nr - \nr
0340 .error "Duplicated/unorded system call entry"
0341 .endif
0342 .rept \nr - __sys_nr
0343 .long sys_ni_syscall
0344 .endr
0345 .long \func
0346 .equ __sys_nr, \nr + 1
0347 .endm
0348
0349 .macro syscall_table_end, sym
0350 .ifgt __sys_nr - __NR_syscalls
0351 .error "System call table too big"
0352 .endif
0353 .rept __NR_syscalls - __sys_nr
0354 .long sys_ni_syscall
0355 .endr
0356 .size \sym, . - \sym
0357 .endm
0358
0359 #define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native)
0360 #define __SYSCALL(nr, func) syscall nr, func
0361
0362
0363
0364
0365
0366 syscall_table_start sys_call_table
0367 #ifdef CONFIG_AEABI
0368 #include <calls-eabi.S>
0369 #else
0370 #include <calls-oabi.S>
0371 #endif
0372 syscall_table_end sys_call_table
0373
0374
0375
0376
0377 @ r0 = syscall number
0378 @ r8 = syscall table
0379 sys_syscall:
0380 bic scno, r0, #__NR_OABI_SYSCALL_BASE
0381 cmp scno, #__NR_syscall - __NR_SYSCALL_BASE
0382 cmpne scno, #NR_syscalls @ check range
0383 #ifdef CONFIG_CPU_SPECTRE
0384 movhs scno, #0
0385 csdb
0386 #endif
0387 stmialo sp, {r5, r6} @ shuffle args
0388 movlo r0, r1
0389 movlo r1, r2
0390 movlo r2, r3
0391 movlo r3, r4
0392 ldrlo pc, [tbl, scno, lsl #2]
0393 b sys_ni_syscall
0394 ENDPROC(sys_syscall)
0395
0396 sys_sigreturn_wrapper:
0397 add r0, sp, #S_OFF
0398 mov why, #0 @ prevent syscall restart handling
0399 b sys_sigreturn
0400 ENDPROC(sys_sigreturn_wrapper)
0401
0402 sys_rt_sigreturn_wrapper:
0403 add r0, sp, #S_OFF
0404 mov why, #0 @ prevent syscall restart handling
0405 b sys_rt_sigreturn
0406 ENDPROC(sys_rt_sigreturn_wrapper)
0407
0408 sys_statfs64_wrapper:
0409 teq r1, #88
0410 moveq r1, #84
0411 b sys_statfs64
0412 ENDPROC(sys_statfs64_wrapper)
0413
0414 sys_fstatfs64_wrapper:
0415 teq r1, #88
0416 moveq r1, #84
0417 b sys_fstatfs64
0418 ENDPROC(sys_fstatfs64_wrapper)
0419
0420
0421
0422
0423
0424 sys_mmap2:
0425 str r5, [sp, #4]
0426 b sys_mmap_pgoff
0427 ENDPROC(sys_mmap2)
0428
0429 #ifdef CONFIG_OABI_COMPAT
0430
0431
0432
0433
0434
0435 sys_oabi_pread64:
0436 stmia sp, {r3, r4}
0437 b sys_pread64
0438 ENDPROC(sys_oabi_pread64)
0439
0440 sys_oabi_pwrite64:
0441 stmia sp, {r3, r4}
0442 b sys_pwrite64
0443 ENDPROC(sys_oabi_pwrite64)
0444
0445 sys_oabi_truncate64:
0446 mov r3, r2
0447 mov r2, r1
0448 b sys_truncate64
0449 ENDPROC(sys_oabi_truncate64)
0450
0451 sys_oabi_ftruncate64:
0452 mov r3, r2
0453 mov r2, r1
0454 b sys_ftruncate64
0455 ENDPROC(sys_oabi_ftruncate64)
0456
0457 sys_oabi_readahead:
0458 str r3, [sp]
0459 mov r3, r2
0460 mov r2, r1
0461 b sys_readahead
0462 ENDPROC(sys_oabi_readahead)
0463
0464
0465
0466
0467
0468 syscall_table_start sys_oabi_call_table
0469 #undef __SYSCALL_WITH_COMPAT
0470 #define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, compat)
0471 #include <calls-oabi.S>
0472 syscall_table_end sys_oabi_call_table
0473
0474 #endif
0475