entry.S 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Common Low Level Interrupts/Traps/Exceptions(non-TLB) Handling for ARC
  4. * (included from entry-<isa>.S
  5. *
  6. * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
  7. * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  8. */
  9. /*------------------------------------------------------------------
  10. * Function ABI
  11. *------------------------------------------------------------------
  12. *
  13. * Arguments r0 - r7
  14. * Caller Saved Registers r0 - r12
  15. * Callee Saved Registers r13- r25
  16. * Global Pointer (gp) r26
  17. * Frame Pointer (fp) r27
  18. * Stack Pointer (sp) r28
  19. * Branch link register (blink) r31
  20. *------------------------------------------------------------------
  21. */
  22. ;################### Special Sys Call Wrappers ##########################
  23. ENTRY(sys_clone_wrapper)
  24. SAVE_CALLEE_SAVED_USER
  25. bl @sys_clone
  26. DISCARD_CALLEE_SAVED_USER
  27. GET_CURR_THR_INFO_FLAGS r10
  28. and.f 0, r10, _TIF_SYSCALL_WORK
  29. bnz tracesys_exit
  30. b .Lret_from_system_call
  31. END(sys_clone_wrapper)
  32. ENTRY(sys_clone3_wrapper)
  33. SAVE_CALLEE_SAVED_USER
  34. bl @sys_clone3
  35. DISCARD_CALLEE_SAVED_USER
  36. GET_CURR_THR_INFO_FLAGS r10
  37. and.f 0, r10, _TIF_SYSCALL_WORK
  38. bnz tracesys_exit
  39. b .Lret_from_system_call
  40. END(sys_clone3_wrapper)
  41. ENTRY(ret_from_fork)
  42. ; when the forked child comes here from the __switch_to function
  43. ; r0 has the last task pointer.
  44. ; put last task in scheduler queue
  45. jl @schedule_tail
  46. ld r9, [sp, PT_status32]
  47. brne r9, 0, 1f
  48. jl.d [r14] ; kernel thread entry point
  49. mov r0, r13 ; (see PF_KTHREAD block in copy_thread)
  50. 1:
  51. ; Return to user space
  52. ; 1. Any forked task (Reach here via BRne above)
  53. ; 2. First ever init task (Reach here via return from JL above)
  54. ; This is the historic "kernel_execve" use-case, to return to init
  55. ; user mode, in a round about way since that is always done from
  56. ; a kernel thread which is executed via JL above but always returns
  57. ; out whenever kernel_execve (now inline do_fork()) is involved
  58. b ret_from_exception
  59. END(ret_from_fork)
  60. ;################### Non TLB Exception Handling #############################
  61. ; ---------------------------------------------
  62. ; Instruction Error Exception Handler
  63. ; ---------------------------------------------
  64. ENTRY(instr_service)
  65. EXCEPTION_PROLOGUE
  66. bl do_insterror_or_kprobe
  67. b ret_from_exception
  68. END(instr_service)
  69. ; ---------------------------------------------
  70. ; Machine Check Exception Handler
  71. ; ---------------------------------------------
  72. ENTRY(EV_MachineCheck)
  73. EXCEPTION_PROLOGUE_KEEP_AE ; ECR returned in r10
  74. lr r0, [efa]
  75. mov r1, sp
  76. ; MC exceptions disable MMU
  77. ARC_MMU_REENABLE r3
  78. lsr r3, r10, 8
  79. bmsk r3, r3, 7
  80. brne r3, ECR_C_MCHK_DUP_TLB, 1f
  81. bl do_tlb_overlap_fault
  82. b ret_from_exception
  83. 1:
  84. ; DEAD END: can't do much, display Regs and HALT
  85. SAVE_CALLEE_SAVED_USER
  86. GET_CURR_TASK_FIELD_PTR TASK_THREAD, r10
  87. st sp, [r10, THREAD_CALLEE_REG]
  88. j do_machine_check_fault
  89. END(EV_MachineCheck)
  90. ; ---------------------------------------------
  91. ; Privilege Violation Exception Handler
  92. ; ---------------------------------------------
  93. ENTRY(EV_PrivilegeV)
  94. EXCEPTION_PROLOGUE
  95. bl do_privilege_fault
  96. b ret_from_exception
  97. END(EV_PrivilegeV)
  98. ; ---------------------------------------------
  99. ; Extension Instruction Exception Handler
  100. ; ---------------------------------------------
  101. ENTRY(EV_Extension)
  102. EXCEPTION_PROLOGUE
  103. bl do_extension_fault
  104. b ret_from_exception
  105. END(EV_Extension)
  106. ;################ Trap Handling (Syscall, Breakpoint) ##################
  107. ; ---------------------------------------------
  108. ; syscall Tracing
  109. ; ---------------------------------------------
  110. tracesys:
  111. ; safekeep EFA (r12) if syscall tracer wanted PC
  112. ; for traps, ERET is pre-commit so points to next-PC
  113. GET_CURR_TASK_FIELD_PTR TASK_THREAD, r11
  114. st r12, [r11, THREAD_FAULT_ADDR] ; thread.fault_address
  115. ; PRE syscall trace hook
  116. mov r0, sp ; pt_regs
  117. bl @syscall_trace_enter
  118. ; Tracing code now returns the syscall num (orig or modif)
  119. mov r8, r0
  120. ; Do the Sys Call as we normally would.
  121. cmp r8, NR_syscalls - 1
  122. mov.hi r0, -ENOSYS
  123. bhi tracesys_exit
  124. ; Restore the sys-call args. Mere invocation of the hook abv could have
  125. ; clobbered them (since they are in scratch regs). The tracer could also
  126. ; have deliberately changed the syscall args: r0-r7
  127. ld r0, [sp, PT_r0]
  128. ld r1, [sp, PT_r1]
  129. ld r2, [sp, PT_r2]
  130. ld r3, [sp, PT_r3]
  131. ld r4, [sp, PT_r4]
  132. ld r5, [sp, PT_r5]
  133. ld r6, [sp, PT_r6]
  134. ld r7, [sp, PT_r7]
  135. ld.as r9, [sys_call_table, r8]
  136. jl [r9]
  137. tracesys_exit:
  138. st r0, [sp, PT_r0]
  139. ; POST syscall trace hook
  140. mov r0, sp ; pt_regs needed
  141. bl @syscall_trace_exit
  142. ; don't call ret_from_system_call as it saves r0, already done above
  143. b ret_from_exception
  144. ; ---------------------------------------------
  145. ; Breakpoint TRAP
  146. ; ---------------------------------------------
  147. trap_with_param:
  148. mov r0, r12 ; EFA in case ptracer/gdb wants stop_pc
  149. mov r1, sp ; pt_regs
  150. ; save callee regs in case tracer/gdb wants to peek
  151. SAVE_CALLEE_SAVED_USER
  152. ; safekeep ref to callee regs
  153. GET_CURR_TASK_FIELD_PTR TASK_THREAD, r10
  154. st sp, [r10, THREAD_CALLEE_REG]
  155. ; call the non syscall trap handler
  156. bl do_non_swi_trap
  157. ; unwind stack to discard callee regs
  158. DISCARD_CALLEE_SAVED_USER
  159. b ret_from_exception
  160. ; ---------------------------------------------
  161. ; syscall TRAP
  162. ; ABI: (r0-r7) up to 8 args, (r8) syscall number
  163. ; ---------------------------------------------
  164. ENTRY(EV_Trap)
  165. EXCEPTION_PROLOGUE_KEEP_AE
  166. lr r12, [efa]
  167. FAKE_RET_FROM_EXCPN
  168. ;============ TRAP N : breakpoints, kprobes etc
  169. bmsk.f 0, r10, 7
  170. bnz trap_with_param
  171. ;============ TRAP 0 (no param): syscall
  172. ; syscall tracing ongoing, invoke pre-post-hooks around syscall
  173. GET_CURR_THR_INFO_FLAGS r10
  174. and.f 0, r10, _TIF_SYSCALL_WORK
  175. bnz tracesys ; this never comes back
  176. ;============ Normal syscall case
  177. cmp r8, NR_syscalls - 1
  178. mov.hi r0, -ENOSYS
  179. bhi .Lret_from_system_call
  180. ld.as r9,[sys_call_table, r8]
  181. jl [r9]
  182. .Lret_from_system_call:
  183. st r0, [sp, PT_r0] ; sys call return value in pt_regs
  184. ; fall through to ret_from_exception
  185. END(EV_Trap)
  186. ;############# Return from Intr/Excp/Trap (Linux Specifics) ##############
  187. ;
  188. ; If ret to user mode do we need to handle signals, schedule() et al.
  189. ENTRY(ret_from_exception)
  190. ; Pre-{IRQ,Trap,Exception} K/U mode from pt_regs->status32
  191. ld r8, [sp, PT_status32] ; returning to User/Kernel Mode
  192. bbit0 r8, STATUS_U_BIT, resume_kernel_mode
  193. ; Before returning to User mode check-for-and-complete any pending work
  194. ; such as rescheduling/signal-delivery etc.
  195. resume_user_mode_begin:
  196. ; Disable IRQs to ensures that chk for pending work itself is atomic
  197. ; (and we don't end up missing a NEED_RESCHED/SIGPENDING due to an
  198. ; interim IRQ).
  199. IRQ_DISABLE r10
  200. ; Fast Path return to user mode if no pending work
  201. GET_CURR_THR_INFO_FLAGS r9
  202. and.f 0, r9, _TIF_WORK_MASK
  203. bz .Lrestore_regs
  204. ; --- (Slow Path #1) task preemption ---
  205. bbit0 r9, TIF_NEED_RESCHED, .Lchk_pend_signals
  206. mov blink, resume_user_mode_begin ; tail-call to U mode ret chks
  207. j @schedule ; BTST+Bnz causes relo error in link
  208. .Lchk_pend_signals:
  209. IRQ_ENABLE r10
  210. ; --- (Slow Path #2) pending signal ---
  211. mov r0, sp ; pt_regs for arg to do_signal()/do_notify_resume()
  212. GET_CURR_THR_INFO_FLAGS r9
  213. and.f 0, r9, _TIF_SIGPENDING|_TIF_NOTIFY_SIGNAL
  214. bz .Lchk_notify_resume
  215. ; Normal Trap/IRQ entry only saves Scratch (caller-saved) regs
  216. ; in pt_reg since the "C" ABI (kernel code) will automatically
  217. ; save/restore callee-saved regs.
  218. ;
  219. ; However, here we need to explicitly save callee regs because
  220. ; (i) If this signal causes coredump - full regfile needed
  221. ; (ii) If signal is SIGTRAP/SIGSTOP, task is being traced thus
  222. ; tracer might call PEEKUSR(CALLEE reg)
  223. ;
  224. ; NOTE: SP will grow up by size of CALLEE Reg-File
  225. SAVE_CALLEE_SAVED_USER
  226. ; save location of saved Callee Regs @ thread_struct->callee
  227. GET_CURR_TASK_FIELD_PTR TASK_THREAD, r10
  228. st sp, [r10, THREAD_CALLEE_REG]
  229. bl @do_signal
  230. ; Ideally we want to discard the Callee reg above, however if this was
  231. ; a tracing signal, tracer could have done a POKEUSR(CALLEE reg)
  232. RESTORE_CALLEE_SAVED_USER
  233. b resume_user_mode_begin ; loop back to start of U mode ret
  234. ; --- (Slow Path #3) notify_resume ---
  235. .Lchk_notify_resume:
  236. btst r9, TIF_NOTIFY_RESUME
  237. blnz @do_notify_resume
  238. b resume_user_mode_begin ; unconditionally back to U mode ret chks
  239. ; for single exit point from this block
  240. resume_kernel_mode:
  241. ; Disable Interrupts from this point on
  242. ; CONFIG_PREEMPTION: This is a must for preempt_schedule_irq()
  243. ; !CONFIG_PREEMPTION: To ensure restore_regs is intr safe
  244. IRQ_DISABLE r9
  245. #ifdef CONFIG_PREEMPTION
  246. ; Can't preempt if preemption disabled
  247. GET_CURR_THR_INFO_FROM_SP r10
  248. ld r8, [r10, THREAD_INFO_PREEMPT_COUNT]
  249. brne r8, 0, .Lrestore_regs
  250. ; check if this task's NEED_RESCHED flag set
  251. ld r9, [r10, THREAD_INFO_FLAGS]
  252. bbit0 r9, TIF_NEED_RESCHED, .Lrestore_regs
  253. ; Invoke PREEMPTION
  254. jl preempt_schedule_irq
  255. ; preempt_schedule_irq() always returns with IRQ disabled
  256. #endif
  257. b .Lrestore_regs
  258. ##### DONT ADD CODE HERE - .Lrestore_regs actually follows in entry-<isa>.S