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/*------------------------------------------------------------------ 11 * Function ABI 12 *------------------------------------------------------------------ 13 * 14 * Arguments r0 - r7 15 * Caller Saved Registers r0 - r12 16 * Callee Saved Registers r13- r25 17 * Global Pointer (gp) r26 18 * Frame Pointer (fp) r27 19 * Stack Pointer (sp) r28 20 * Branch link register (blink) r31 21 *------------------------------------------------------------------ 22 */ 23 24;################### Special Sys Call Wrappers ########################## 25 26ENTRY(sys_clone_wrapper) 27 SAVE_CALLEE_SAVED_USER 28 bl @sys_clone 29 DISCARD_CALLEE_SAVED_USER 30 31 GET_CURR_THR_INFO_FLAGS r10 32 btst r10, TIF_SYSCALL_TRACE 33 bnz tracesys_exit 34 35 b .Lret_from_system_call 36END(sys_clone_wrapper) 37 38ENTRY(ret_from_fork) 39 ; when the forked child comes here from the __switch_to function 40 ; r0 has the last task pointer. 41 ; put last task in scheduler queue 42 jl @schedule_tail 43 44 ld r9, [sp, PT_status32] 45 brne r9, 0, 1f 46 47 jl.d [r14] ; kernel thread entry point 48 mov r0, r13 ; (see PF_KTHREAD block in copy_thread) 49 501: 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 59END(ret_from_fork) 60 61;################### Non TLB Exception Handling ############################# 62 63; --------------------------------------------- 64; Instruction Error Exception Handler 65; --------------------------------------------- 66 67ENTRY(instr_service) 68 69 EXCEPTION_PROLOGUE 70 71 lr r0, [efa] 72 mov r1, sp 73 74 FAKE_RET_FROM_EXCPN 75 76 bl do_insterror_or_kprobe 77 b ret_from_exception 78END(instr_service) 79 80; --------------------------------------------- 81; Machine Check Exception Handler 82; --------------------------------------------- 83 84ENTRY(EV_MachineCheck) 85 86 EXCEPTION_PROLOGUE 87 88 lr r2, [ecr] 89 lr r0, [efa] 90 mov r1, sp 91 92 ; hardware auto-disables MMU, re-enable it to allow kernel vaddr 93 ; access for say stack unwinding of modules for crash dumps 94 lr r3, [ARC_REG_PID] 95 or r3, r3, MMU_ENABLE 96 sr r3, [ARC_REG_PID] 97 98 lsr r3, r2, 8 99 bmsk r3, r3, 7 100 brne r3, ECR_C_MCHK_DUP_TLB, 1f 101 102 bl do_tlb_overlap_fault 103 b ret_from_exception 104 1051: 106 ; DEAD END: can't do much, display Regs and HALT 107 SAVE_CALLEE_SAVED_USER 108 109 GET_CURR_TASK_FIELD_PTR TASK_THREAD, r10 110 st sp, [r10, THREAD_CALLEE_REG] 111 112 j do_machine_check_fault 113 114END(EV_MachineCheck) 115 116; --------------------------------------------- 117; Privilege Violation Exception Handler 118; --------------------------------------------- 119ENTRY(EV_PrivilegeV) 120 121 EXCEPTION_PROLOGUE 122 123 lr r0, [efa] 124 mov r1, sp 125 126 FAKE_RET_FROM_EXCPN 127 128 bl do_privilege_fault 129 b ret_from_exception 130END(EV_PrivilegeV) 131 132; --------------------------------------------- 133; Extension Instruction Exception Handler 134; --------------------------------------------- 135ENTRY(EV_Extension) 136 137 EXCEPTION_PROLOGUE 138 139 lr r0, [efa] 140 mov r1, sp 141 142 FAKE_RET_FROM_EXCPN 143 144 bl do_extension_fault 145 b ret_from_exception 146END(EV_Extension) 147 148;################ Trap Handling (Syscall, Breakpoint) ################## 149 150; --------------------------------------------- 151; syscall Tracing 152; --------------------------------------------- 153tracesys: 154 ; save EFA in case tracer wants the PC of traced task 155 ; using ERET won't work since next-PC has already committed 156 lr r12, [efa] 157 GET_CURR_TASK_FIELD_PTR TASK_THREAD, r11 158 st r12, [r11, THREAD_FAULT_ADDR] ; thread.fault_address 159 160 ; PRE Sys Call Ptrace hook 161 mov r0, sp ; pt_regs needed 162 bl @syscall_trace_entry 163 164 ; Tracing code now returns the syscall num (orig or modif) 165 mov r8, r0 166 167 ; Do the Sys Call as we normally would. 168 ; Validate the Sys Call number 169 cmp r8, NR_syscalls 170 mov.hi r0, -ENOSYS 171 bhi tracesys_exit 172 173 ; Restore the sys-call args. Mere invocation of the hook abv could have 174 ; clobbered them (since they are in scratch regs). The tracer could also 175 ; have deliberately changed the syscall args: r0-r7 176 ld r0, [sp, PT_r0] 177 ld r1, [sp, PT_r1] 178 ld r2, [sp, PT_r2] 179 ld r3, [sp, PT_r3] 180 ld r4, [sp, PT_r4] 181 ld r5, [sp, PT_r5] 182 ld r6, [sp, PT_r6] 183 ld r7, [sp, PT_r7] 184 ld.as r9, [sys_call_table, r8] 185 jl [r9] ; Entry into Sys Call Handler 186 187tracesys_exit: 188 st r0, [sp, PT_r0] ; sys call return value in pt_regs 189 190 ;POST Sys Call Ptrace Hook 191 bl @syscall_trace_exit 192 b ret_from_exception ; NOT ret_from_system_call at is saves r0 which 193 ; we'd done before calling post hook above 194 195; --------------------------------------------- 196; Breakpoint TRAP 197; --------------------------------------------- 198trap_with_param: 199 200 ; stop_pc info by gdb needs this info 201 lr r0, [efa] 202 mov r1, sp 203 204 ; Now that we have read EFA, it is safe to do "fake" rtie 205 ; and get out of CPU exception mode 206 FAKE_RET_FROM_EXCPN 207 208 ; Save callee regs in case gdb wants to have a look 209 ; SP will grow up by size of CALLEE Reg-File 210 ; NOTE: clobbers r12 211 SAVE_CALLEE_SAVED_USER 212 213 ; save location of saved Callee Regs @ thread_struct->pc 214 GET_CURR_TASK_FIELD_PTR TASK_THREAD, r10 215 st sp, [r10, THREAD_CALLEE_REG] 216 217 ; Call the trap handler 218 bl do_non_swi_trap 219 220 ; unwind stack to discard Callee saved Regs 221 DISCARD_CALLEE_SAVED_USER 222 223 b ret_from_exception 224 225; --------------------------------------------- 226; syscall TRAP 227; ABI: (r0-r7) upto 8 args, (r8) syscall number 228; --------------------------------------------- 229 230ENTRY(EV_Trap) 231 232 EXCEPTION_PROLOGUE 233 234 ;============ TRAP 1 :breakpoints 235 ; Check ECR for trap with arg (PROLOGUE ensures r10 has ECR) 236 bmsk.f 0, r10, 7 237 bnz trap_with_param 238 239 ;============ TRAP (no param): syscall top level 240 241 ; First return from Exception to pure K mode (Exception/IRQs renabled) 242 FAKE_RET_FROM_EXCPN 243 244 ; If syscall tracing ongoing, invoke pre-post-hooks 245 GET_CURR_THR_INFO_FLAGS r10 246 btst r10, TIF_SYSCALL_TRACE 247 bnz tracesys ; this never comes back 248 249 ;============ Normal syscall case 250 251 ; syscall num shd not exceed the total system calls avail 252 cmp r8, NR_syscalls 253 mov.hi r0, -ENOSYS 254 bhi .Lret_from_system_call 255 256 ; Offset into the syscall_table and call handler 257 ld.as r9,[sys_call_table, r8] 258 jl [r9] ; Entry into Sys Call Handler 259 260.Lret_from_system_call: 261 262 st r0, [sp, PT_r0] ; sys call return value in pt_regs 263 264 ; fall through to ret_from_exception 265END(EV_Trap) 266 267;############# Return from Intr/Excp/Trap (Linux Specifics) ############## 268; 269; If ret to user mode do we need to handle signals, schedule() et al. 270 271ENTRY(ret_from_exception) 272 273 ; Pre-{IRQ,Trap,Exception} K/U mode from pt_regs->status32 274 ld r8, [sp, PT_status32] ; returning to User/Kernel Mode 275 276 bbit0 r8, STATUS_U_BIT, resume_kernel_mode 277 278 ; Before returning to User mode check-for-and-complete any pending work 279 ; such as rescheduling/signal-delivery etc. 280resume_user_mode_begin: 281 282 ; Disable IRQs to ensures that chk for pending work itself is atomic 283 ; (and we don't end up missing a NEED_RESCHED/SIGPENDING due to an 284 ; interim IRQ). 285 IRQ_DISABLE r10 286 287 ; Fast Path return to user mode if no pending work 288 GET_CURR_THR_INFO_FLAGS r9 289 and.f 0, r9, _TIF_WORK_MASK 290 bz .Lrestore_regs 291 292 ; --- (Slow Path #1) task preemption --- 293 bbit0 r9, TIF_NEED_RESCHED, .Lchk_pend_signals 294 mov blink, resume_user_mode_begin ; tail-call to U mode ret chks 295 j @schedule ; BTST+Bnz causes relo error in link 296 297.Lchk_pend_signals: 298 IRQ_ENABLE r10 299 300 ; --- (Slow Path #2) pending signal --- 301 mov r0, sp ; pt_regs for arg to do_signal()/do_notify_resume() 302 303 GET_CURR_THR_INFO_FLAGS r9 304 bbit0 r9, TIF_SIGPENDING, .Lchk_notify_resume 305 306 ; Normal Trap/IRQ entry only saves Scratch (caller-saved) regs 307 ; in pt_reg since the "C" ABI (kernel code) will automatically 308 ; save/restore callee-saved regs. 309 ; 310 ; However, here we need to explicitly save callee regs because 311 ; (i) If this signal causes coredump - full regfile needed 312 ; (ii) If signal is SIGTRAP/SIGSTOP, task is being traced thus 313 ; tracer might call PEEKUSR(CALLEE reg) 314 ; 315 ; NOTE: SP will grow up by size of CALLEE Reg-File 316 SAVE_CALLEE_SAVED_USER ; clobbers r12 317 318 ; save location of saved Callee Regs @ thread_struct->callee 319 GET_CURR_TASK_FIELD_PTR TASK_THREAD, r10 320 st sp, [r10, THREAD_CALLEE_REG] 321 322 bl @do_signal 323 324 ; Ideally we want to discard the Callee reg above, however if this was 325 ; a tracing signal, tracer could have done a POKEUSR(CALLEE reg) 326 RESTORE_CALLEE_SAVED_USER 327 328 b resume_user_mode_begin ; loop back to start of U mode ret 329 330 ; --- (Slow Path #3) notify_resume --- 331.Lchk_notify_resume: 332 btst r9, TIF_NOTIFY_RESUME 333 blnz @do_notify_resume 334 b resume_user_mode_begin ; unconditionally back to U mode ret chks 335 ; for single exit point from this block 336 337resume_kernel_mode: 338 339 ; Disable Interrupts from this point on 340 ; CONFIG_PREEMPT: This is a must for preempt_schedule_irq() 341 ; !CONFIG_PREEMPT: To ensure restore_regs is intr safe 342 IRQ_DISABLE r9 343 344#ifdef CONFIG_PREEMPT 345 346 ; Can't preempt if preemption disabled 347 GET_CURR_THR_INFO_FROM_SP r10 348 ld r8, [r10, THREAD_INFO_PREEMPT_COUNT] 349 brne r8, 0, .Lrestore_regs 350 351 ; check if this task's NEED_RESCHED flag set 352 ld r9, [r10, THREAD_INFO_FLAGS] 353 bbit0 r9, TIF_NEED_RESCHED, .Lrestore_regs 354 355 ; Invoke PREEMPTION 356 jl preempt_schedule_irq 357 358 ; preempt_schedule_irq() always returns with IRQ disabled 359#endif 360 361 b .Lrestore_regs 362 363##### DONT ADD CODE HERE - .Lrestore_regs actually follows in entry-<isa>.S 364 365