/* SPDX-License-Identifier: GPL-2.01*2* Copyright (C) 1999, 2000, 2002 Niibe Yutaka3* Copyright (C) 2003 - 2008 Paul Mundt4*/56! NOTE:7! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address8! to be jumped is too far, but it causes illegal slot exception.910/*11* entry.S contains the system-call and fault low-level handling routines.12* This also contains the timer-interrupt handler, as well as all interrupts13* and faults that can result in a task-switch.14*15* NOTE: This code handles signal-recognition, which happens every time16* after a timer-interrupt and after each system call.17*18* NOTE: This code uses a convention that instructions in the delay slot19* of a transfer-control instruction are indented by an extra space, thus:20*21* jmp @k0 ! control-transfer instruction22* ldc k1, ssr ! delay slot23*24* Stack layout in 'ret_from_syscall':25* ptrace needs to have all regs on the stack.26* if the order here is changed, it needs to be27* updated in ptrace.c and ptrace.h28*29* r030* ...31* r15 = stack pointer32* spc33* pr34* ssr35* gbr36* mach37* macl38* syscall #39*40*/41#include <asm/dwarf.h>4243#if defined(CONFIG_PREEMPTION)44# define preempt_stop() cli ; TRACE_IRQS_OFF45#else46# define preempt_stop()47# define resume_kernel __restore_all48#endif495051.align 252ENTRY(exception_error)53!54TRACE_IRQS_ON55sti56mov.l 1f, r057jmp @r058nop5960.align 2611: .long do_exception_error6263.align 264ret_from_exception:65CFI_STARTPROC simple66CFI_DEF_CFA r14, 067CFI_REL_OFFSET 17, 6468CFI_REL_OFFSET 15, 6069CFI_REL_OFFSET 14, 5670CFI_REL_OFFSET 13, 5271CFI_REL_OFFSET 12, 4872CFI_REL_OFFSET 11, 4473CFI_REL_OFFSET 10, 4074CFI_REL_OFFSET 9, 3675CFI_REL_OFFSET 8, 3276preempt_stop()77ENTRY(ret_from_irq)78!79mov #OFF_SR, r080mov.l @(r0,r15), r0 ! get status register81shll r082shll r0 ! kernel space?83get_current_thread_info r8, r084bt resume_kernel ! Yes, it's from kernel, go back soon8586#ifdef CONFIG_PREEMPTION87bra resume_userspace88nop89ENTRY(resume_kernel)90cli91TRACE_IRQS_OFF92mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count93tst r0, r094bf noresched95need_resched:96mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags97tst #_TIF_NEED_RESCHED, r0 ! need_resched set?98bt noresched99100mov #OFF_SR, r0101mov.l @(r0,r15), r0 ! get status register102shlr r0103and #(0xf0>>1), r0 ! interrupts off (exception path)?104cmp/eq #(0xf0>>1), r0105bt noresched106mov.l 1f, r0107jsr @r0 ! call preempt_schedule_irq108nop109bra need_resched110nop111112noresched:113bra __restore_all114nop115116.align 21171: .long preempt_schedule_irq118#endif119120ENTRY(resume_userspace)121! r8: current_thread_info122cli123TRACE_IRQS_OFF124mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags125tst #(_TIF_WORK_MASK & 0xff), r0126bt/s __restore_all127tst #_TIF_NEED_RESCHED, r0128129.align 2130work_pending:131! r0: current_thread_info->flags132! r8: current_thread_info133! t: result of "tst #_TIF_NEED_RESCHED, r0"134bf/s work_resched135tst #(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME), r0136work_notifysig:137bt/s __restore_all138mov r15, r4139mov r12, r5 ! set arg1(save_r0)140mov r0, r6141sti142mov.l 2f, r1143mov.l 3f, r0144jmp @r1145lds r0, pr146work_resched:147mov.l 1f, r1148jsr @r1 ! schedule149nop150cli151TRACE_IRQS_OFF152!153mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags154tst #(_TIF_WORK_MASK & 0xff), r0155bt __restore_all156bra work_pending157tst #_TIF_NEED_RESCHED, r0158159.align 21601: .long schedule1612: .long do_notify_resume1623: .long resume_userspace163164.align 2165syscall_exit_work:166! r0: current_thread_info->flags167! r8: current_thread_info168tst #(_TIF_WORK_SYSCALL_MASK & 0xff), r0169bt/s work_pending170tst #_TIF_NEED_RESCHED, r0171TRACE_IRQS_ON172sti173mov r15, r4174mov.l 8f, r0 ! do_syscall_trace_leave175jsr @r0176nop177bra resume_userspace178nop179180__restore_all:181mov #OFF_SR, r0182mov.l @(r0,r15), r0 ! get status register183184shlr2 r0185and #0x3c, r0186cmp/eq #0x3c, r0187bt 1f188TRACE_IRQS_ON189bra 2f190nop1911:192TRACE_IRQS_OFF1932:194mov.l 3f, r0195jmp @r0196nop197198.align 21993: .long restore_all200201.align 2202syscall_badsys: ! Bad syscall number203get_current_thread_info r8, r0204mov #-ENOSYS, r0205bra resume_userspace206mov.l r0, @(OFF_R0,r15) ! Return value207208/*209* The main debug trap handler.210*211* r8=TRA (not the trap number!)212*213* Note: This assumes that the trapa value is left in its original214* form (without the shlr2 shift) so the calculation for the jump215* call table offset remains a simple in place mask.216*/217debug_trap:218mov r8, r0219and #(0xf << 2), r0220mov.l 1f, r8221add r0, r8222mov.l @r8, r8223jsr @r8224nop225bra ret_from_exception226nop227CFI_ENDPROC228229.align 22301: .long debug_trap_table231232/*233* Syscall interface:234*235* Syscall #: R3236* Arguments #0 to #3: R4--R7237* Arguments #4 to #6: R0, R1, R2238* TRA: See following table.239*240* (TRA>>2) Purpose241* -------- -------242* 0x00-0x0f original SH-3/4 syscall ABI (not in general use).243* 0x10-0x1f general SH-3/4 syscall ABI.244* 0x1f unified SH-2/3/4 syscall ABI (preferred).245* 0x20-0x2f original SH-2 syscall ABI.246* 0x30-0x3f debug traps used by the kernel.247* 0x40-0xff Not supported by all parts, so left unhandled.248*249* For making system calls, any trap number in the range for the250* given cpu model may be used, but the unified trap number 0x1f is251* preferred for compatibility with all models.252*253* The low bits of the trap number were once documented as matching254* the number of arguments, but they were never actually used as such255* by the kernel. SH-2 originally used its own separate trap range256* because several hardware exceptions fell in the range used for the257* SH-3/4 syscall ABI.258*259* This code also handles delegating other traps to the BIOS/gdb stub.260*261* Note: When we're first called, the TRA value must be shifted262* right 2 bits in order to get the value that was used as the "trapa"263* argument.264*/265266.align 2267.globl ret_from_fork268ret_from_fork:269mov.l 1f, r8270jsr @r8271mov r0, r4272bra syscall_exit273nop274275.align 2276.globl ret_from_kernel_thread277ret_from_kernel_thread:278mov.l 1f, r8279jsr @r8280mov r0, r4281mov.l @(OFF_R5,r15), r5 ! fn282jsr @r5283mov.l @(OFF_R4,r15), r4 ! arg284bra syscall_exit285nop286287.align 22881: .long schedule_tail289290/*291* The poorly named main trapa decode and dispatch routine, for292* system calls and debug traps through their respective jump tables.293*/294ENTRY(system_call)295setup_frame_reg296#if !defined(CONFIG_CPU_SH2)297mov.l 1f, r9298mov.l @r9, r8 ! Read from TRA (Trap Address) Register299#endif300301mov #OFF_TRA, r10302add r15, r10303mov.l r8, @r10 ! set TRA value to tra304305/*306* Check the trap type307*/308mov #((0x20 << 2) - 1), r9309cmp/hi r9, r8310bt/s debug_trap ! it's a debug trap..311nop312313TRACE_IRQS_ON314sti315316!317get_current_thread_info r8, r10318mov.l @(TI_FLAGS,r8), r8319mov #(_TIF_WORK_SYSCALL_MASK & 0xff), r10320mov #(_TIF_WORK_SYSCALL_MASK >> 8), r9321tst r10, r8322shll8 r9323bf syscall_trace_entry324tst r9, r8325bf syscall_trace_entry326!327mov.l 6f, r8 ! Number of syscalls328cmp/hs r8, r3329bt syscall_badsys330!331syscall_call:332shll2 r3 ! x4333mov.l 3f, r8 ! Load the address of sys_call_table334add r8, r3335mov.l @r3, r8336mov.l @(OFF_R2,r15), r2337mov.l @(OFF_R1,r15), r1338mov.l @(OFF_R0,r15), r0339mov.l r2, @-r15340mov.l r1, @-r15341mov.l r0, @-r15342jsr @r8 ! jump to specific syscall handler343nop344add #12, r15345mov.l @(OFF_R0,r15), r12 ! save r0346mov.l r0, @(OFF_R0,r15) ! save the return value347!348syscall_exit:349cli350TRACE_IRQS_OFF351!352get_current_thread_info r8, r0353mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags354tst #(_TIF_ALLWORK_MASK & 0xff), r0355mov #(_TIF_ALLWORK_MASK >> 8), r1356bf syscall_exit_work357shlr8 r0358tst r0, r1359bf syscall_exit_work360bra __restore_all361nop362363.align 2364syscall_trace_entry:365! Yes it is traced.366mov r15, r4367mov.l 7f, r11 ! Call do_syscall_trace_enter which notifies368jsr @r11 ! superior (will chomp R[0-7])369nop370cmp/eq #-1, r0371bt syscall_exit372! Reload R0-R4 from kernel stack, where the373! parent may have modified them using374! ptrace(POKEUSR). (Note that R0-R2 are375! reloaded from the kernel stack by syscall_call376! below, so don't need to be reloaded here.)377! This allows the parent to rewrite system calls378! and args on the fly.379mov.l @(OFF_R4,r15), r4 ! arg0380mov.l @(OFF_R5,r15), r5381mov.l @(OFF_R6,r15), r6382mov.l @(OFF_R7,r15), r7 ! arg3383mov.l @(OFF_R3,r15), r3 ! syscall_nr384!385mov.l 6f, r10 ! Number of syscalls386cmp/hs r10, r3387bf syscall_call388mov #-ENOSYS, r0389bra syscall_exit390mov.l r0, @(OFF_R0,r15) ! Return value391392.align 2393#if !defined(CONFIG_CPU_SH2)3941: .long TRA395#endif3966: .long NR_syscalls3973: .long sys_call_table3987: .long do_syscall_trace_enter3998: .long do_syscall_trace_leave400401402