1 /* SPDX-License-Identifier: GPL-2.0-only */ << 2 /* 1 /* 3 * Common Low Level Interrupts/Traps/Exception !! 2 * arch/alpha/kernel/entry.S 4 * (included from entry-<isa>.S << 5 * 3 * 6 * Copyright (C) 2014-15 Synopsys, Inc. (www.s !! 4 * Kernel entry-points. 7 * Copyright (C) 2004, 2007-2010, 2011-2012 Sy << 8 */ 5 */ 9 6 10 /*-------------------------------------------- !! 7 #include <asm/asm-offsets.h> 11 * Function ABI !! 8 #include <asm/thread_info.h> 12 *-------------------------------------------- !! 9 #include <asm/pal.h> >> 10 #include <asm/errno.h> >> 11 #include <asm/unistd.h> >> 12 >> 13 .text >> 14 .set noat >> 15 .cfi_sections .debug_frame >> 16 >> 17 /* Stack offsets. */ >> 18 #define SP_OFF 184 >> 19 #define SWITCH_STACK_SIZE 320 >> 20 >> 21 .macro CFI_START_OSF_FRAME func >> 22 .align 4 >> 23 .globl \func >> 24 .type \func,@function >> 25 \func: >> 26 .cfi_startproc simple >> 27 .cfi_return_column 64 >> 28 .cfi_def_cfa $sp, 48 >> 29 .cfi_rel_offset 64, 8 >> 30 .cfi_rel_offset $gp, 16 >> 31 .cfi_rel_offset $16, 24 >> 32 .cfi_rel_offset $17, 32 >> 33 .cfi_rel_offset $18, 40 >> 34 .endm >> 35 >> 36 .macro CFI_END_OSF_FRAME func >> 37 .cfi_endproc >> 38 .size \func, . - \func >> 39 .endm >> 40 >> 41 /* >> 42 * This defines the normal kernel pt-regs layout. 13 * 43 * 14 * Arguments r0 - r !! 44 * regs 9-15 preserved by C code 15 * Caller Saved Registers r0 - r !! 45 * regs 16-18 saved by PAL-code 16 * Callee Saved Registers r13- r !! 46 * regs 29-30 saved and set up by PAL-code 17 * Global Pointer (gp) r26 !! 47 * JRP - Save regs 16-18 in a special area of the stack, so that 18 * Frame Pointer (fp) r27 !! 48 * the palcode-provided values are available to the signal handler. 19 * Stack Pointer (sp) r28 << 20 * Branch link register (blink) r31 << 21 *-------------------------------------------- << 22 */ 49 */ 23 50 24 ;################### Special Sys Call Wrappers !! 51 .macro SAVE_ALL 25 !! 52 subq $sp, SP_OFF, $sp 26 ENTRY(sys_clone_wrapper) !! 53 .cfi_adjust_cfa_offset SP_OFF 27 SAVE_CALLEE_SAVED_USER !! 54 stq $0, 0($sp) 28 bl @sys_clone !! 55 stq $1, 8($sp) 29 DISCARD_CALLEE_SAVED_USER !! 56 stq $2, 16($sp) 30 !! 57 stq $3, 24($sp) 31 GET_CURR_THR_INFO_FLAGS r10 !! 58 stq $4, 32($sp) 32 and.f 0, r10, _TIF_SYSCALL_WORK !! 59 stq $28, 144($sp) 33 bnz tracesys_exit !! 60 .cfi_rel_offset $0, 0 34 !! 61 .cfi_rel_offset $1, 8 35 b .Lret_from_system_call !! 62 .cfi_rel_offset $2, 16 36 END(sys_clone_wrapper) !! 63 .cfi_rel_offset $3, 24 37 !! 64 .cfi_rel_offset $4, 32 38 ENTRY(sys_clone3_wrapper) !! 65 .cfi_rel_offset $28, 144 39 SAVE_CALLEE_SAVED_USER !! 66 lda $2, alpha_mv 40 bl @sys_clone3 !! 67 stq $5, 40($sp) 41 DISCARD_CALLEE_SAVED_USER !! 68 stq $6, 48($sp) 42 !! 69 stq $7, 56($sp) 43 GET_CURR_THR_INFO_FLAGS r10 !! 70 stq $8, 64($sp) 44 and.f 0, r10, _TIF_SYSCALL_WORK !! 71 stq $19, 72($sp) 45 bnz tracesys_exit !! 72 stq $20, 80($sp) 46 !! 73 stq $21, 88($sp) 47 b .Lret_from_system_call !! 74 ldq $2, HAE_CACHE($2) 48 END(sys_clone3_wrapper) !! 75 stq $22, 96($sp) 49 !! 76 stq $23, 104($sp) 50 ENTRY(ret_from_fork) !! 77 stq $24, 112($sp) 51 ; when the forked child comes here fro !! 78 stq $25, 120($sp) 52 ; r0 has the last task pointer. !! 79 stq $26, 128($sp) 53 ; put last task in scheduler queue !! 80 stq $27, 136($sp) 54 jl @schedule_tail !! 81 stq $2, 152($sp) 55 !! 82 stq $16, 160($sp) 56 ld r9, [sp, PT_status32] !! 83 stq $17, 168($sp) 57 brne r9, 0, 1f !! 84 stq $18, 176($sp) 58 !! 85 .cfi_rel_offset $5, 40 59 jl.d [r14] ; kernel threa !! 86 .cfi_rel_offset $6, 48 60 mov r0, r13 ; (see PF_KTHR !! 87 .cfi_rel_offset $7, 56 61 !! 88 .cfi_rel_offset $8, 64 62 1: !! 89 .cfi_rel_offset $19, 72 63 ; Return to user space !! 90 .cfi_rel_offset $20, 80 64 ; 1. Any forked task (Reach here via B !! 91 .cfi_rel_offset $21, 88 65 ; 2. First ever init task (Reach here !! 92 .cfi_rel_offset $22, 96 66 ; This is the historic "kernel_exec !! 93 .cfi_rel_offset $23, 104 67 ; user mode, in a round about way s !! 94 .cfi_rel_offset $24, 112 68 ; a kernel thread which is executed !! 95 .cfi_rel_offset $25, 120 69 ; out whenever kernel_execve (now i !! 96 .cfi_rel_offset $26, 128 70 b ret_from_exception !! 97 .cfi_rel_offset $27, 136 71 END(ret_from_fork) !! 98 .endm 72 !! 99 73 ;################### Non TLB Exception Handlin !! 100 .macro RESTORE_ALL 74 !! 101 lda $19, alpha_mv 75 ; -------------------------------------------- !! 102 ldq $0, 0($sp) 76 ; Instruction Error Exception Handler !! 103 ldq $1, 8($sp) 77 ; -------------------------------------------- !! 104 ldq $2, 16($sp) 78 !! 105 ldq $3, 24($sp) 79 ENTRY(instr_service) !! 106 ldq $21, 152($sp) 80 !! 107 ldq $20, HAE_CACHE($19) 81 EXCEPTION_PROLOGUE !! 108 ldq $4, 32($sp) 82 !! 109 ldq $5, 40($sp) 83 bl do_insterror_or_kprobe !! 110 ldq $6, 48($sp) 84 b ret_from_exception !! 111 ldq $7, 56($sp) 85 END(instr_service) !! 112 subq $20, $21, $20 86 !! 113 ldq $8, 64($sp) 87 ; -------------------------------------------- !! 114 beq $20, 99f 88 ; Machine Check Exception Handler !! 115 ldq $20, HAE_REG($19) 89 ; -------------------------------------------- !! 116 stq $21, HAE_CACHE($19) 90 !! 117 stq $21, 0($20) 91 ENTRY(EV_MachineCheck) !! 118 99: ldq $19, 72($sp) 92 !! 119 ldq $20, 80($sp) 93 EXCEPTION_PROLOGUE_KEEP_AE ; ECR !! 120 ldq $21, 88($sp) 94 !! 121 ldq $22, 96($sp) 95 lr r0, [efa] !! 122 ldq $23, 104($sp) 96 mov r1, sp !! 123 ldq $24, 112($sp) 97 !! 124 ldq $25, 120($sp) 98 ; MC exceptions disable MMU !! 125 ldq $26, 128($sp) 99 ARC_MMU_REENABLE r3 !! 126 ldq $27, 136($sp) 100 !! 127 ldq $28, 144($sp) 101 lsr r3, r10, 8 !! 128 addq $sp, SP_OFF, $sp 102 bmsk r3, r3, 7 !! 129 .cfi_restore $0 103 brne r3, ECR_C_MCHK_DUP_TLB, 1f !! 130 .cfi_restore $1 104 !! 131 .cfi_restore $2 105 bl do_tlb_overlap_fault !! 132 .cfi_restore $3 106 b ret_from_exception !! 133 .cfi_restore $4 107 !! 134 .cfi_restore $5 108 1: !! 135 .cfi_restore $6 109 ; DEAD END: can't do much, display Reg !! 136 .cfi_restore $7 110 SAVE_CALLEE_SAVED_USER !! 137 .cfi_restore $8 111 !! 138 .cfi_restore $19 112 GET_CURR_TASK_FIELD_PTR TASK_THREAD, !! 139 .cfi_restore $20 113 st sp, [r10, THREAD_CALLEE_REG] !! 140 .cfi_restore $21 114 !! 141 .cfi_restore $22 115 j do_machine_check_fault !! 142 .cfi_restore $23 116 !! 143 .cfi_restore $24 117 END(EV_MachineCheck) !! 144 .cfi_restore $25 118 !! 145 .cfi_restore $26 119 ; -------------------------------------------- !! 146 .cfi_restore $27 120 ; Privilege Violation Exception Handler !! 147 .cfi_restore $28 121 ; -------------------------------------------- !! 148 .cfi_adjust_cfa_offset -SP_OFF 122 ENTRY(EV_PrivilegeV) !! 149 .endm 123 !! 150 124 EXCEPTION_PROLOGUE !! 151 .macro DO_SWITCH_STACK 125 !! 152 bsr $1, do_switch_stack 126 bl do_privilege_fault !! 153 .cfi_adjust_cfa_offset SWITCH_STACK_SIZE 127 b ret_from_exception !! 154 .cfi_rel_offset $9, 0 128 END(EV_PrivilegeV) !! 155 .cfi_rel_offset $10, 8 129 !! 156 .cfi_rel_offset $11, 16 130 ; -------------------------------------------- !! 157 .cfi_rel_offset $12, 24 131 ; Extension Instruction Exception Handler !! 158 .cfi_rel_offset $13, 32 132 ; -------------------------------------------- !! 159 .cfi_rel_offset $14, 40 133 ENTRY(EV_Extension) !! 160 .cfi_rel_offset $15, 48 134 !! 161 /* We don't really care about the FP registers for debugging. */ 135 EXCEPTION_PROLOGUE !! 162 .endm 136 !! 163 137 bl do_extension_fault !! 164 .macro UNDO_SWITCH_STACK 138 b ret_from_exception !! 165 bsr $1, undo_switch_stack 139 END(EV_Extension) !! 166 .cfi_restore $9 140 !! 167 .cfi_restore $10 141 ;################ Trap Handling (Syscall, Brea !! 168 .cfi_restore $11 142 !! 169 .cfi_restore $12 143 ; -------------------------------------------- !! 170 .cfi_restore $13 144 ; syscall Tracing !! 171 .cfi_restore $14 145 ; -------------------------------------------- !! 172 .cfi_restore $15 146 tracesys: !! 173 .cfi_adjust_cfa_offset -SWITCH_STACK_SIZE 147 ; safekeep EFA (r12) if syscall tracer !! 174 .endm 148 ; for traps, ERET is pre-commit so poi << 149 GET_CURR_TASK_FIELD_PTR TASK_THREAD, << 150 st r12, [r11, THREAD_FAULT_ADDR] << 151 << 152 ; PRE syscall trace hook << 153 mov r0, sp << 154 bl @syscall_trace_enter << 155 << 156 ; Tracing code now returns the syscall << 157 mov r8, r0 << 158 << 159 ; Do the Sys Call as we normally would << 160 cmp r8, NR_syscalls - 1 << 161 mov.hi r0, -ENOSYS << 162 bhi tracesys_exit << 163 << 164 ; Restore the sys-call args. Mere invo << 165 ; clobbered them (since they are in sc << 166 ; have deliberately changed the syscal << 167 ld r0, [sp, PT_r0] << 168 ld r1, [sp, PT_r1] << 169 ld r2, [sp, PT_r2] << 170 ld r3, [sp, PT_r3] << 171 ld r4, [sp, PT_r4] << 172 ld r5, [sp, PT_r5] << 173 ld r6, [sp, PT_r6] << 174 ld r7, [sp, PT_r7] << 175 ld.as r9, [sys_call_table, r8] << 176 jl [r9] << 177 << 178 tracesys_exit: << 179 st r0, [sp, PT_r0] << 180 << 181 ; POST syscall trace hook << 182 mov r0, sp ; pt_regs need << 183 bl @syscall_trace_exit << 184 << 185 ; don't call ret_from_system_call as i << 186 b ret_from_exception << 187 << 188 ; -------------------------------------------- << 189 ; Breakpoint TRAP << 190 ; -------------------------------------------- << 191 trap_with_param: << 192 mov r0, r12 ; EFA in case ptracer/ << 193 mov r1, sp ; pt_regs << 194 << 195 ; save callee regs in case tracer/gdb << 196 SAVE_CALLEE_SAVED_USER << 197 << 198 ; safekeep ref to callee regs << 199 GET_CURR_TASK_FIELD_PTR TASK_THREAD, << 200 st sp, [r10, THREAD_CALLEE_REG] << 201 << 202 ; call the non syscall trap handler << 203 bl do_non_swi_trap << 204 << 205 ; unwind stack to discard callee regs << 206 DISCARD_CALLEE_SAVED_USER << 207 << 208 b ret_from_exception << 209 175 210 ; -------------------------------------------- !! 176 /* 211 ; syscall TRAP !! 177 * Non-syscall kernel entry points. 212 ; ABI: (r0-r7) up to 8 args, (r8) syscall numb !! 178 */ 213 ; -------------------------------------------- << 214 << 215 ENTRY(EV_Trap) << 216 << 217 EXCEPTION_PROLOGUE_KEEP_AE << 218 << 219 lr r12, [efa] << 220 << 221 FAKE_RET_FROM_EXCPN << 222 << 223 ;============ TRAP N : breakpoints, kp << 224 bmsk.f 0, r10, 7 << 225 bnz trap_with_param << 226 << 227 ;============ TRAP 0 (no param): sysca << 228 << 229 ; syscall tracing ongoing, invoke pre- << 230 GET_CURR_THR_INFO_FLAGS r10 << 231 and.f 0, r10, _TIF_SYSCALL_WORK << 232 bnz tracesys ; this never comes bac << 233 << 234 ;============ Normal syscall case << 235 << 236 cmp r8, NR_syscalls - 1 << 237 mov.hi r0, -ENOSYS << 238 bhi .Lret_from_system_call << 239 << 240 ld.as r9,[sys_call_table, r8] << 241 jl [r9] << 242 << 243 .Lret_from_system_call: << 244 st r0, [sp, PT_r0] ; sys call ret << 245 << 246 ; fall through to ret_from_exception << 247 END(EV_Trap) << 248 << 249 ;############# Return from Intr/Excp/Trap (Lin << 250 ; << 251 ; If ret to user mode do we need to handle sig << 252 << 253 ENTRY(ret_from_exception) << 254 << 255 ; Pre-{IRQ,Trap,Exception} K/U mode fr << 256 ld r8, [sp, PT_status32] ; returnin << 257 << 258 bbit0 r8, STATUS_U_BIT, resume_kernel << 259 << 260 ; Before returning to User mode check- << 261 ; such as rescheduling/signal-delivery << 262 resume_user_mode_begin: << 263 << 264 ; Disable IRQs to ensures that chk for << 265 ; (and we don't end up missing a NEED_ << 266 ; interim IRQ). << 267 IRQ_DISABLE r10 << 268 << 269 ; Fast Path return to user mode if no << 270 GET_CURR_THR_INFO_FLAGS r9 << 271 and.f 0, r9, _TIF_WORK_MASK << 272 bz .Lrestore_regs << 273 << 274 ; --- (Slow Path #1) task preemption - << 275 bbit0 r9, TIF_NEED_RESCHED, .Lchk_pen << 276 mov blink, resume_user_mode_begin << 277 j @schedule ; BTST+Bnz cau << 278 << 279 .Lchk_pend_signals: << 280 IRQ_ENABLE r10 << 281 << 282 ; --- (Slow Path #2) pending signal - << 283 mov r0, sp ; pt_regs for arg to d << 284 << 285 GET_CURR_THR_INFO_FLAGS r9 << 286 and.f 0, r9, _TIF_SIGPENDING|_TIF_NO << 287 bz .Lchk_notify_resume << 288 << 289 ; Normal Trap/IRQ entry only saves Scr << 290 ; in pt_reg since the "C" ABI (kernel << 291 ; save/restore callee-saved regs. << 292 ; << 293 ; However, here we need to explicitly << 294 ; (i) If this signal causes coredump << 295 ; (ii) If signal is SIGTRAP/SIGSTOP, t << 296 ; tracer might call PEEKUSR(CALLE << 297 ; << 298 ; NOTE: SP will grow up by size of CAL << 299 SAVE_CALLEE_SAVED_USER << 300 << 301 ; save location of saved Callee Regs @ << 302 GET_CURR_TASK_FIELD_PTR TASK_THREAD, << 303 st sp, [r10, THREAD_CALLEE_REG] << 304 << 305 bl @do_signal << 306 179 307 ; Ideally we want to discard the Calle !! 180 CFI_START_OSF_FRAME entInt 308 ; a tracing signal, tracer could have !! 181 SAVE_ALL 309 RESTORE_CALLEE_SAVED_USER !! 182 lda $8, 0x3fff >> 183 lda $26, ret_from_sys_call >> 184 bic $sp, $8, $8 >> 185 mov $sp, $19 >> 186 jsr $31, do_entInt >> 187 CFI_END_OSF_FRAME entInt >> 188 >> 189 CFI_START_OSF_FRAME entArith >> 190 SAVE_ALL >> 191 lda $8, 0x3fff >> 192 lda $26, ret_from_sys_call >> 193 bic $sp, $8, $8 >> 194 mov $sp, $18 >> 195 jsr $31, do_entArith >> 196 CFI_END_OSF_FRAME entArith >> 197 >> 198 CFI_START_OSF_FRAME entMM >> 199 SAVE_ALL >> 200 /* save $9 - $15 so the inline exception code can manipulate them. */ >> 201 subq $sp, 56, $sp >> 202 .cfi_adjust_cfa_offset 56 >> 203 stq $9, 0($sp) >> 204 stq $10, 8($sp) >> 205 stq $11, 16($sp) >> 206 stq $12, 24($sp) >> 207 stq $13, 32($sp) >> 208 stq $14, 40($sp) >> 209 stq $15, 48($sp) >> 210 .cfi_rel_offset $9, 0 >> 211 .cfi_rel_offset $10, 8 >> 212 .cfi_rel_offset $11, 16 >> 213 .cfi_rel_offset $12, 24 >> 214 .cfi_rel_offset $13, 32 >> 215 .cfi_rel_offset $14, 40 >> 216 .cfi_rel_offset $15, 48 >> 217 addq $sp, 56, $19 >> 218 /* handle the fault */ >> 219 lda $8, 0x3fff >> 220 bic $sp, $8, $8 >> 221 jsr $26, do_page_fault >> 222 /* reload the registers after the exception code played. */ >> 223 ldq $9, 0($sp) >> 224 ldq $10, 8($sp) >> 225 ldq $11, 16($sp) >> 226 ldq $12, 24($sp) >> 227 ldq $13, 32($sp) >> 228 ldq $14, 40($sp) >> 229 ldq $15, 48($sp) >> 230 addq $sp, 56, $sp >> 231 .cfi_restore $9 >> 232 .cfi_restore $10 >> 233 .cfi_restore $11 >> 234 .cfi_restore $12 >> 235 .cfi_restore $13 >> 236 .cfi_restore $14 >> 237 .cfi_restore $15 >> 238 .cfi_adjust_cfa_offset -56 >> 239 /* finish up the syscall as normal. */ >> 240 br ret_from_sys_call >> 241 CFI_END_OSF_FRAME entMM >> 242 >> 243 CFI_START_OSF_FRAME entIF >> 244 SAVE_ALL >> 245 lda $8, 0x3fff >> 246 lda $26, ret_from_sys_call >> 247 bic $sp, $8, $8 >> 248 mov $sp, $17 >> 249 jsr $31, do_entIF >> 250 CFI_END_OSF_FRAME entIF >> 251 >> 252 CFI_START_OSF_FRAME entUna >> 253 lda $sp, -256($sp) >> 254 .cfi_adjust_cfa_offset 256 >> 255 stq $0, 0($sp) >> 256 .cfi_rel_offset $0, 0 >> 257 .cfi_remember_state >> 258 ldq $0, 256($sp) /* get PS */ >> 259 stq $1, 8($sp) >> 260 stq $2, 16($sp) >> 261 stq $3, 24($sp) >> 262 and $0, 8, $0 /* user mode? */ >> 263 stq $4, 32($sp) >> 264 bne $0, entUnaUser /* yup -> do user-level unaligned fault */ >> 265 stq $5, 40($sp) >> 266 stq $6, 48($sp) >> 267 stq $7, 56($sp) >> 268 stq $8, 64($sp) >> 269 stq $9, 72($sp) >> 270 stq $10, 80($sp) >> 271 stq $11, 88($sp) >> 272 stq $12, 96($sp) >> 273 stq $13, 104($sp) >> 274 stq $14, 112($sp) >> 275 stq $15, 120($sp) >> 276 /* 16-18 PAL-saved */ >> 277 stq $19, 152($sp) >> 278 stq $20, 160($sp) >> 279 stq $21, 168($sp) >> 280 stq $22, 176($sp) >> 281 stq $23, 184($sp) >> 282 stq $24, 192($sp) >> 283 stq $25, 200($sp) >> 284 stq $26, 208($sp) >> 285 stq $27, 216($sp) >> 286 stq $28, 224($sp) >> 287 mov $sp, $19 >> 288 stq $gp, 232($sp) >> 289 .cfi_rel_offset $1, 1*8 >> 290 .cfi_rel_offset $2, 2*8 >> 291 .cfi_rel_offset $3, 3*8 >> 292 .cfi_rel_offset $4, 4*8 >> 293 .cfi_rel_offset $5, 5*8 >> 294 .cfi_rel_offset $6, 6*8 >> 295 .cfi_rel_offset $7, 7*8 >> 296 .cfi_rel_offset $8, 8*8 >> 297 .cfi_rel_offset $9, 9*8 >> 298 .cfi_rel_offset $10, 10*8 >> 299 .cfi_rel_offset $11, 11*8 >> 300 .cfi_rel_offset $12, 12*8 >> 301 .cfi_rel_offset $13, 13*8 >> 302 .cfi_rel_offset $14, 14*8 >> 303 .cfi_rel_offset $15, 15*8 >> 304 .cfi_rel_offset $19, 19*8 >> 305 .cfi_rel_offset $20, 20*8 >> 306 .cfi_rel_offset $21, 21*8 >> 307 .cfi_rel_offset $22, 22*8 >> 308 .cfi_rel_offset $23, 23*8 >> 309 .cfi_rel_offset $24, 24*8 >> 310 .cfi_rel_offset $25, 25*8 >> 311 .cfi_rel_offset $26, 26*8 >> 312 .cfi_rel_offset $27, 27*8 >> 313 .cfi_rel_offset $28, 28*8 >> 314 .cfi_rel_offset $29, 29*8 >> 315 lda $8, 0x3fff >> 316 stq $31, 248($sp) >> 317 bic $sp, $8, $8 >> 318 jsr $26, do_entUna >> 319 ldq $0, 0($sp) >> 320 ldq $1, 8($sp) >> 321 ldq $2, 16($sp) >> 322 ldq $3, 24($sp) >> 323 ldq $4, 32($sp) >> 324 ldq $5, 40($sp) >> 325 ldq $6, 48($sp) >> 326 ldq $7, 56($sp) >> 327 ldq $8, 64($sp) >> 328 ldq $9, 72($sp) >> 329 ldq $10, 80($sp) >> 330 ldq $11, 88($sp) >> 331 ldq $12, 96($sp) >> 332 ldq $13, 104($sp) >> 333 ldq $14, 112($sp) >> 334 ldq $15, 120($sp) >> 335 /* 16-18 PAL-saved */ >> 336 ldq $19, 152($sp) >> 337 ldq $20, 160($sp) >> 338 ldq $21, 168($sp) >> 339 ldq $22, 176($sp) >> 340 ldq $23, 184($sp) >> 341 ldq $24, 192($sp) >> 342 ldq $25, 200($sp) >> 343 ldq $26, 208($sp) >> 344 ldq $27, 216($sp) >> 345 ldq $28, 224($sp) >> 346 ldq $gp, 232($sp) >> 347 lda $sp, 256($sp) >> 348 .cfi_restore $1 >> 349 .cfi_restore $2 >> 350 .cfi_restore $3 >> 351 .cfi_restore $4 >> 352 .cfi_restore $5 >> 353 .cfi_restore $6 >> 354 .cfi_restore $7 >> 355 .cfi_restore $8 >> 356 .cfi_restore $9 >> 357 .cfi_restore $10 >> 358 .cfi_restore $11 >> 359 .cfi_restore $12 >> 360 .cfi_restore $13 >> 361 .cfi_restore $14 >> 362 .cfi_restore $15 >> 363 .cfi_restore $19 >> 364 .cfi_restore $20 >> 365 .cfi_restore $21 >> 366 .cfi_restore $22 >> 367 .cfi_restore $23 >> 368 .cfi_restore $24 >> 369 .cfi_restore $25 >> 370 .cfi_restore $26 >> 371 .cfi_restore $27 >> 372 .cfi_restore $28 >> 373 .cfi_restore $29 >> 374 .cfi_adjust_cfa_offset -256 >> 375 call_pal PAL_rti >> 376 >> 377 .align 4 >> 378 entUnaUser: >> 379 .cfi_restore_state >> 380 ldq $0, 0($sp) /* restore original $0 */ >> 381 lda $sp, 256($sp) /* pop entUna's stack frame */ >> 382 .cfi_restore $0 >> 383 .cfi_adjust_cfa_offset -256 >> 384 SAVE_ALL /* setup normal kernel stack */ >> 385 lda $sp, -56($sp) >> 386 .cfi_adjust_cfa_offset 56 >> 387 stq $9, 0($sp) >> 388 stq $10, 8($sp) >> 389 stq $11, 16($sp) >> 390 stq $12, 24($sp) >> 391 stq $13, 32($sp) >> 392 stq $14, 40($sp) >> 393 stq $15, 48($sp) >> 394 .cfi_rel_offset $9, 0 >> 395 .cfi_rel_offset $10, 8 >> 396 .cfi_rel_offset $11, 16 >> 397 .cfi_rel_offset $12, 24 >> 398 .cfi_rel_offset $13, 32 >> 399 .cfi_rel_offset $14, 40 >> 400 .cfi_rel_offset $15, 48 >> 401 lda $8, 0x3fff >> 402 addq $sp, 56, $19 >> 403 bic $sp, $8, $8 >> 404 jsr $26, do_entUnaUser >> 405 ldq $9, 0($sp) >> 406 ldq $10, 8($sp) >> 407 ldq $11, 16($sp) >> 408 ldq $12, 24($sp) >> 409 ldq $13, 32($sp) >> 410 ldq $14, 40($sp) >> 411 ldq $15, 48($sp) >> 412 lda $sp, 56($sp) >> 413 .cfi_restore $9 >> 414 .cfi_restore $10 >> 415 .cfi_restore $11 >> 416 .cfi_restore $12 >> 417 .cfi_restore $13 >> 418 .cfi_restore $14 >> 419 .cfi_restore $15 >> 420 .cfi_adjust_cfa_offset -56 >> 421 br ret_from_sys_call >> 422 CFI_END_OSF_FRAME entUna >> 423 >> 424 CFI_START_OSF_FRAME entDbg >> 425 SAVE_ALL >> 426 lda $8, 0x3fff >> 427 lda $26, ret_from_sys_call >> 428 bic $sp, $8, $8 >> 429 mov $sp, $16 >> 430 jsr $31, do_entDbg >> 431 CFI_END_OSF_FRAME entDbg >> 432 >> 433 /* >> 434 * The system call entry point is special. Most importantly, it looks >> 435 * like a function call to userspace as far as clobbered registers. We >> 436 * do preserve the argument registers (for syscall restarts) and $26 >> 437 * (for leaf syscall functions). >> 438 * >> 439 * So much for theory. We don't take advantage of this yet. >> 440 * >> 441 * Note that a0-a2 are not saved by PALcode as with the other entry points. >> 442 */ 310 443 311 b resume_user_mode_begin ; loop !! 444 .align 4 >> 445 .globl entSys >> 446 .type entSys, @function >> 447 .cfi_startproc simple >> 448 .cfi_return_column 64 >> 449 .cfi_def_cfa $sp, 48 >> 450 .cfi_rel_offset 64, 8 >> 451 .cfi_rel_offset $gp, 16 >> 452 entSys: >> 453 SAVE_ALL >> 454 lda $8, 0x3fff >> 455 bic $sp, $8, $8 >> 456 lda $4, NR_SYSCALLS($31) >> 457 stq $16, SP_OFF+24($sp) >> 458 lda $5, sys_call_table >> 459 lda $27, sys_ni_syscall >> 460 cmpult $0, $4, $4 >> 461 ldl $3, TI_FLAGS($8) >> 462 stq $17, SP_OFF+32($sp) >> 463 s8addq $0, $5, $5 >> 464 stq $18, SP_OFF+40($sp) >> 465 .cfi_rel_offset $16, SP_OFF+24 >> 466 .cfi_rel_offset $17, SP_OFF+32 >> 467 .cfi_rel_offset $18, SP_OFF+40 >> 468 #ifdef CONFIG_AUDITSYSCALL >> 469 lda $6, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT >> 470 and $3, $6, $3 >> 471 #endif >> 472 bne $3, strace >> 473 beq $4, 1f >> 474 ldq $27, 0($5) >> 475 1: jsr $26, ($27), alpha_ni_syscall >> 476 ldgp $gp, 0($26) >> 477 blt $0, $syscall_error /* the call failed */ >> 478 stq $0, 0($sp) >> 479 stq $31, 72($sp) /* a3=0 => no error */ >> 480 >> 481 .align 4 >> 482 .globl ret_from_sys_call >> 483 ret_from_sys_call: >> 484 cmovne $26, 0, $18 /* $18 = 0 => non-restartable */ >> 485 ldq $0, SP_OFF($sp) >> 486 and $0, 8, $0 >> 487 beq $0, ret_to_kernel >> 488 ret_to_user: >> 489 /* Make sure need_resched and sigpending don't change between >> 490 sampling and the rti. */ >> 491 lda $16, 7 >> 492 call_pal PAL_swpipl >> 493 ldl $17, TI_FLAGS($8) >> 494 and $17, _TIF_WORK_MASK, $2 >> 495 bne $2, work_pending >> 496 restore_all: >> 497 .cfi_remember_state >> 498 RESTORE_ALL >> 499 call_pal PAL_rti >> 500 >> 501 ret_to_kernel: >> 502 .cfi_restore_state >> 503 lda $16, 7 >> 504 call_pal PAL_swpipl >> 505 br restore_all >> 506 >> 507 .align 3 >> 508 $syscall_error: >> 509 /* >> 510 * Some system calls (e.g., ptrace) can return arbitrary >> 511 * values which might normally be mistaken as error numbers. >> 512 * Those functions must zero $0 (v0) directly in the stack >> 513 * frame to indicate that a negative return value wasn't an >> 514 * error number.. >> 515 */ >> 516 ldq $18, 0($sp) /* old syscall nr (zero if success) */ >> 517 beq $18, $ret_success >> 518 >> 519 ldq $19, 72($sp) /* .. and this a3 */ >> 520 subq $31, $0, $0 /* with error in v0 */ >> 521 addq $31, 1, $1 /* set a3 for errno return */ >> 522 stq $0, 0($sp) >> 523 mov $31, $26 /* tell "ret_from_sys_call" we can restart */ >> 524 stq $1, 72($sp) /* a3 for return */ >> 525 br ret_from_sys_call >> 526 >> 527 $ret_success: >> 528 stq $0, 0($sp) >> 529 stq $31, 72($sp) /* a3=0 => no error */ >> 530 br ret_from_sys_call 312 531 313 ; --- (Slow Path #3) notify_resume --- !! 532 /* 314 .Lchk_notify_resume: !! 533 * Do all cleanup when returning from all interrupts and system calls. 315 btst r9, TIF_NOTIFY_RESUME !! 534 * 316 blnz @do_notify_resume !! 535 * Arguments: 317 b resume_user_mode_begin ; unco !! 536 * $8: current. 318 ; for !! 537 * $17: TI_FLAGS. >> 538 * $18: The old syscall number, or zero if this is not a return >> 539 * from a syscall that errored and is possibly restartable. >> 540 * $19: The old a3 value >> 541 */ 319 542 320 resume_kernel_mode: !! 543 .align 4 >> 544 .type work_pending, @function >> 545 work_pending: >> 546 and $17, _TIF_NOTIFY_RESUME | _TIF_SIGPENDING, $2 >> 547 bne $2, $work_notifysig >> 548 >> 549 $work_resched: >> 550 /* >> 551 * We can get here only if we returned from syscall without SIGPENDING >> 552 * or got through work_notifysig already. Either case means no syscall >> 553 * restarts for us, so let $18 and $19 burn. >> 554 */ >> 555 jsr $26, schedule >> 556 mov 0, $18 >> 557 br ret_to_user >> 558 >> 559 $work_notifysig: >> 560 mov $sp, $16 >> 561 DO_SWITCH_STACK >> 562 jsr $26, do_work_pending >> 563 UNDO_SWITCH_STACK >> 564 br restore_all 321 565 322 ; Disable Interrupts from this point o !! 566 /* 323 ; CONFIG_PREEMPTION: This is a must fo !! 567 * PTRACE syscall handler 324 ; !CONFIG_PREEMPTION: To ensure restor !! 568 */ 325 IRQ_DISABLE r9 << 326 569 327 #ifdef CONFIG_PREEMPTION !! 570 .align 4 >> 571 .type strace, @function >> 572 strace: >> 573 /* set up signal stack, call syscall_trace */ >> 574 DO_SWITCH_STACK >> 575 jsr $26, syscall_trace_enter /* returns the syscall number */ >> 576 UNDO_SWITCH_STACK >> 577 >> 578 /* get the arguments back.. */ >> 579 ldq $16, SP_OFF+24($sp) >> 580 ldq $17, SP_OFF+32($sp) >> 581 ldq $18, SP_OFF+40($sp) >> 582 ldq $19, 72($sp) >> 583 ldq $20, 80($sp) >> 584 ldq $21, 88($sp) >> 585 >> 586 /* get the system call pointer.. */ >> 587 lda $1, NR_SYSCALLS($31) >> 588 lda $2, sys_call_table >> 589 lda $27, alpha_ni_syscall >> 590 cmpult $0, $1, $1 >> 591 s8addq $0, $2, $2 >> 592 beq $1, 1f >> 593 ldq $27, 0($2) >> 594 1: jsr $26, ($27), sys_gettimeofday >> 595 ret_from_straced: >> 596 ldgp $gp, 0($26) >> 597 >> 598 /* check return.. */ >> 599 blt $0, $strace_error /* the call failed */ >> 600 stq $31, 72($sp) /* a3=0 => no error */ >> 601 $strace_success: >> 602 stq $0, 0($sp) /* save return value */ >> 603 >> 604 DO_SWITCH_STACK >> 605 jsr $26, syscall_trace_leave >> 606 UNDO_SWITCH_STACK >> 607 br $31, ret_from_sys_call >> 608 >> 609 .align 3 >> 610 $strace_error: >> 611 ldq $18, 0($sp) /* old syscall nr (zero if success) */ >> 612 beq $18, $strace_success >> 613 ldq $19, 72($sp) /* .. and this a3 */ >> 614 >> 615 subq $31, $0, $0 /* with error in v0 */ >> 616 addq $31, 1, $1 /* set a3 for errno return */ >> 617 stq $0, 0($sp) >> 618 stq $1, 72($sp) /* a3 for return */ >> 619 >> 620 DO_SWITCH_STACK >> 621 mov $18, $9 /* save old syscall number */ >> 622 mov $19, $10 /* save old a3 */ >> 623 jsr $26, syscall_trace_leave >> 624 mov $9, $18 >> 625 mov $10, $19 >> 626 UNDO_SWITCH_STACK >> 627 >> 628 mov $31, $26 /* tell "ret_from_sys_call" we can restart */ >> 629 br ret_from_sys_call >> 630 CFI_END_OSF_FRAME entSys >> 631 >> 632 /* >> 633 * Save and restore the switch stack -- aka the balance of the user context. >> 634 */ 328 635 329 ; Can't preempt if preemption disabled !! 636 .align 4 330 GET_CURR_THR_INFO_FROM_SP r10 !! 637 .type do_switch_stack, @function 331 ld r8, [r10, THREAD_INFO_PREEMPT_COUN !! 638 .cfi_startproc simple 332 brne r8, 0, .Lrestore_regs !! 639 .cfi_return_column 64 >> 640 .cfi_def_cfa $sp, 0 >> 641 .cfi_register 64, $1 >> 642 do_switch_stack: >> 643 lda $sp, -SWITCH_STACK_SIZE($sp) >> 644 .cfi_adjust_cfa_offset SWITCH_STACK_SIZE >> 645 stq $9, 0($sp) >> 646 stq $10, 8($sp) >> 647 stq $11, 16($sp) >> 648 stq $12, 24($sp) >> 649 stq $13, 32($sp) >> 650 stq $14, 40($sp) >> 651 stq $15, 48($sp) >> 652 stq $26, 56($sp) >> 653 stt $f0, 64($sp) >> 654 stt $f1, 72($sp) >> 655 stt $f2, 80($sp) >> 656 stt $f3, 88($sp) >> 657 stt $f4, 96($sp) >> 658 stt $f5, 104($sp) >> 659 stt $f6, 112($sp) >> 660 stt $f7, 120($sp) >> 661 stt $f8, 128($sp) >> 662 stt $f9, 136($sp) >> 663 stt $f10, 144($sp) >> 664 stt $f11, 152($sp) >> 665 stt $f12, 160($sp) >> 666 stt $f13, 168($sp) >> 667 stt $f14, 176($sp) >> 668 stt $f15, 184($sp) >> 669 stt $f16, 192($sp) >> 670 stt $f17, 200($sp) >> 671 stt $f18, 208($sp) >> 672 stt $f19, 216($sp) >> 673 stt $f20, 224($sp) >> 674 stt $f21, 232($sp) >> 675 stt $f22, 240($sp) >> 676 stt $f23, 248($sp) >> 677 stt $f24, 256($sp) >> 678 stt $f25, 264($sp) >> 679 stt $f26, 272($sp) >> 680 stt $f27, 280($sp) >> 681 mf_fpcr $f0 # get fpcr >> 682 stt $f28, 288($sp) >> 683 stt $f29, 296($sp) >> 684 stt $f30, 304($sp) >> 685 stt $f0, 312($sp) # save fpcr in slot of $f31 >> 686 ldt $f0, 64($sp) # dont let "do_switch_stack" change fp state. >> 687 ret $31, ($1), 1 >> 688 .cfi_endproc >> 689 .size do_switch_stack, .-do_switch_stack >> 690 >> 691 .align 4 >> 692 .type undo_switch_stack, @function >> 693 .cfi_startproc simple >> 694 .cfi_def_cfa $sp, 0 >> 695 .cfi_register 64, $1 >> 696 undo_switch_stack: >> 697 ldq $9, 0($sp) >> 698 ldq $10, 8($sp) >> 699 ldq $11, 16($sp) >> 700 ldq $12, 24($sp) >> 701 ldq $13, 32($sp) >> 702 ldq $14, 40($sp) >> 703 ldq $15, 48($sp) >> 704 ldq $26, 56($sp) >> 705 ldt $f30, 312($sp) # get saved fpcr >> 706 ldt $f0, 64($sp) >> 707 ldt $f1, 72($sp) >> 708 ldt $f2, 80($sp) >> 709 ldt $f3, 88($sp) >> 710 mt_fpcr $f30 # install saved fpcr >> 711 ldt $f4, 96($sp) >> 712 ldt $f5, 104($sp) >> 713 ldt $f6, 112($sp) >> 714 ldt $f7, 120($sp) >> 715 ldt $f8, 128($sp) >> 716 ldt $f9, 136($sp) >> 717 ldt $f10, 144($sp) >> 718 ldt $f11, 152($sp) >> 719 ldt $f12, 160($sp) >> 720 ldt $f13, 168($sp) >> 721 ldt $f14, 176($sp) >> 722 ldt $f15, 184($sp) >> 723 ldt $f16, 192($sp) >> 724 ldt $f17, 200($sp) >> 725 ldt $f18, 208($sp) >> 726 ldt $f19, 216($sp) >> 727 ldt $f20, 224($sp) >> 728 ldt $f21, 232($sp) >> 729 ldt $f22, 240($sp) >> 730 ldt $f23, 248($sp) >> 731 ldt $f24, 256($sp) >> 732 ldt $f25, 264($sp) >> 733 ldt $f26, 272($sp) >> 734 ldt $f27, 280($sp) >> 735 ldt $f28, 288($sp) >> 736 ldt $f29, 296($sp) >> 737 ldt $f30, 304($sp) >> 738 lda $sp, SWITCH_STACK_SIZE($sp) >> 739 ret $31, ($1), 1 >> 740 .cfi_endproc >> 741 .size undo_switch_stack, .-undo_switch_stack >> 742 >> 743 /* >> 744 * The meat of the context switch code. >> 745 */ 333 746 334 ; check if this task's NEED_RESCHED fl !! 747 .align 4 335 ld r9, [r10, THREAD_INFO_FLAGS] !! 748 .globl alpha_switch_to 336 bbit0 r9, TIF_NEED_RESCHED, .Lrestore !! 749 .type alpha_switch_to, @function >> 750 .cfi_startproc >> 751 alpha_switch_to: >> 752 DO_SWITCH_STACK >> 753 call_pal PAL_swpctx >> 754 lda $8, 0x3fff >> 755 UNDO_SWITCH_STACK >> 756 bic $sp, $8, $8 >> 757 mov $17, $0 >> 758 ret >> 759 .cfi_endproc >> 760 .size alpha_switch_to, .-alpha_switch_to 337 761 338 ; Invoke PREEMPTION !! 762 /* 339 jl preempt_schedule_irq !! 763 * New processes begin life here. >> 764 */ 340 765 341 ; preempt_schedule_irq() always return !! 766 .globl ret_from_fork 342 #endif !! 767 .align 4 >> 768 .ent ret_from_fork >> 769 ret_from_fork: >> 770 lda $26, ret_from_sys_call >> 771 mov $17, $16 >> 772 jmp $31, schedule_tail >> 773 .end ret_from_fork 343 774 344 b .Lrestore_regs !! 775 /* >> 776 * ... and new kernel threads - here >> 777 */ >> 778 .align 4 >> 779 .globl ret_from_kernel_thread >> 780 .ent ret_from_kernel_thread >> 781 ret_from_kernel_thread: >> 782 mov $17, $16 >> 783 jsr $26, schedule_tail >> 784 mov $9, $27 >> 785 mov $10, $16 >> 786 jsr $26, ($9) >> 787 mov $31, $19 /* to disable syscall restarts */ >> 788 br $31, ret_to_user >> 789 .end ret_from_kernel_thread 345 790 346 ##### DONT ADD CODE HERE - .Lrestore_regs actu !! 791 >> 792 /* >> 793 * Special system calls. Most of these are special in that they either >> 794 * have to play switch_stack games or in some way use the pt_regs struct. >> 795 */ 347 796 >> 797 .macro fork_like name >> 798 .align 4 >> 799 .globl alpha_\name >> 800 .ent alpha_\name >> 801 alpha_\name: >> 802 .prologue 0 >> 803 bsr $1, do_switch_stack >> 804 jsr $26, sys_\name >> 805 ldq $26, 56($sp) >> 806 lda $sp, SWITCH_STACK_SIZE($sp) >> 807 ret >> 808 .end alpha_\name >> 809 .endm >> 810 >> 811 fork_like fork >> 812 fork_like vfork >> 813 fork_like clone >> 814 >> 815 .align 4 >> 816 .globl sys_sigreturn >> 817 .ent sys_sigreturn >> 818 sys_sigreturn: >> 819 .prologue 0 >> 820 lda $9, ret_from_straced >> 821 cmpult $26, $9, $9 >> 822 lda $sp, -SWITCH_STACK_SIZE($sp) >> 823 jsr $26, do_sigreturn >> 824 bne $9, 1f >> 825 jsr $26, syscall_trace_leave >> 826 1: br $1, undo_switch_stack >> 827 br ret_from_sys_call >> 828 .end sys_sigreturn >> 829 >> 830 .align 4 >> 831 .globl sys_rt_sigreturn >> 832 .ent sys_rt_sigreturn >> 833 sys_rt_sigreturn: >> 834 .prologue 0 >> 835 lda $9, ret_from_straced >> 836 cmpult $26, $9, $9 >> 837 lda $sp, -SWITCH_STACK_SIZE($sp) >> 838 jsr $26, do_rt_sigreturn >> 839 bne $9, 1f >> 840 jsr $26, syscall_trace_leave >> 841 1: br $1, undo_switch_stack >> 842 br ret_from_sys_call >> 843 .end sys_rt_sigreturn >> 844 >> 845 .align 4 >> 846 .globl alpha_ni_syscall >> 847 .ent alpha_ni_syscall >> 848 alpha_ni_syscall: >> 849 .prologue 0 >> 850 /* Special because it also implements overflow handling via >> 851 syscall number 0. And if you recall, zero is a special >> 852 trigger for "not an error". Store large non-zero there. */ >> 853 lda $0, -ENOSYS >> 854 unop >> 855 stq $0, 0($sp) >> 856 ret >> 857 .end alpha_ni_syscall
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.