1 /* SPDX-License-Identifier: GPL-2.0-only */ !! 1 /* SPDX-License-Identifier: GPL-2.0-or-later 2 /* !! 2 * -*- mode: asm -*- 3 * Common Low Level Interrupts/Traps/Exception !! 3 * 4 * (included from entry-<isa>.S !! 4 * linux/arch/m68k/kernel/entry.S >> 5 * >> 6 * Copyright (C) 1991, 1992 Linus Torvalds >> 7 * >> 8 * Linux/m68k support by Hamish Macdonald >> 9 * >> 10 * 68060 fixes by Jesper Skov 5 * 11 * 6 * Copyright (C) 2014-15 Synopsys, Inc. (www.s << 7 * Copyright (C) 2004, 2007-2010, 2011-2012 Sy << 8 */ 12 */ 9 13 10 /*-------------------------------------------- !! 14 /* 11 * Function ABI !! 15 * entry.S contains the system-call and fault low-level handling routines. 12 *-------------------------------------------- !! 16 * This also contains the timer-interrupt handler, as well as all interrupts >> 17 * and faults that can result in a task-switch. >> 18 * >> 19 * NOTE: This code handles signal-recognition, which happens every time >> 20 * after a timer-interrupt and after each system call. 13 * 21 * 14 * Arguments r0 - r << 15 * Caller Saved Registers r0 - r << 16 * Callee Saved Registers r13- r << 17 * Global Pointer (gp) r26 << 18 * Frame Pointer (fp) r27 << 19 * Stack Pointer (sp) r28 << 20 * Branch link register (blink) r31 << 21 *-------------------------------------------- << 22 */ 22 */ 23 23 24 ;################### Special Sys Call Wrappers !! 24 /* 25 !! 25 * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so 26 ENTRY(sys_clone_wrapper) !! 26 * all pointers that used to be 'current' are now entry 27 SAVE_CALLEE_SAVED_USER !! 27 * number 0 in the 'current_set' list. 28 bl @sys_clone !! 28 * 29 DISCARD_CALLEE_SAVED_USER !! 29 * 6/05/00 RZ: addedd writeback completion after return from sighandler 30 !! 30 * for 68040 31 GET_CURR_THR_INFO_FLAGS r10 !! 31 */ 32 and.f 0, r10, _TIF_SYSCALL_WORK << 33 bnz tracesys_exit << 34 << 35 b .Lret_from_system_call << 36 END(sys_clone_wrapper) << 37 << 38 ENTRY(sys_clone3_wrapper) << 39 SAVE_CALLEE_SAVED_USER << 40 bl @sys_clone3 << 41 DISCARD_CALLEE_SAVED_USER << 42 << 43 GET_CURR_THR_INFO_FLAGS r10 << 44 and.f 0, r10, _TIF_SYSCALL_WORK << 45 bnz tracesys_exit << 46 << 47 b .Lret_from_system_call << 48 END(sys_clone3_wrapper) << 49 << 50 ENTRY(ret_from_fork) << 51 ; when the forked child comes here fro << 52 ; r0 has the last task pointer. << 53 ; put last task in scheduler queue << 54 jl @schedule_tail << 55 << 56 ld r9, [sp, PT_status32] << 57 brne r9, 0, 1f << 58 << 59 jl.d [r14] ; kernel threa << 60 mov r0, r13 ; (see PF_KTHR << 61 << 62 1: << 63 ; Return to user space << 64 ; 1. Any forked task (Reach here via B << 65 ; 2. First ever init task (Reach here << 66 ; This is the historic "kernel_exec << 67 ; user mode, in a round about way s << 68 ; a kernel thread which is executed << 69 ; out whenever kernel_execve (now i << 70 b ret_from_exception << 71 END(ret_from_fork) << 72 << 73 ;################### Non TLB Exception Handlin << 74 << 75 ; -------------------------------------------- << 76 ; Instruction Error Exception Handler << 77 ; -------------------------------------------- << 78 << 79 ENTRY(instr_service) << 80 << 81 EXCEPTION_PROLOGUE << 82 << 83 bl do_insterror_or_kprobe << 84 b ret_from_exception << 85 END(instr_service) << 86 << 87 ; -------------------------------------------- << 88 ; Machine Check Exception Handler << 89 ; -------------------------------------------- << 90 << 91 ENTRY(EV_MachineCheck) << 92 << 93 EXCEPTION_PROLOGUE_KEEP_AE ; ECR << 94 << 95 lr r0, [efa] << 96 mov r1, sp << 97 << 98 ; MC exceptions disable MMU << 99 ARC_MMU_REENABLE r3 << 100 << 101 lsr r3, r10, 8 << 102 bmsk r3, r3, 7 << 103 brne r3, ECR_C_MCHK_DUP_TLB, 1f << 104 32 105 bl do_tlb_overlap_fault !! 33 #include <linux/linkage.h> 106 b ret_from_exception !! 34 #include <asm/errno.h> >> 35 #include <asm/setup.h> >> 36 #include <asm/traps.h> >> 37 #include <asm/unistd.h> >> 38 #include <asm/asm-offsets.h> >> 39 #include <asm/entry.h> >> 40 >> 41 .globl system_call, buserr, trap, resume >> 42 .globl sys_call_table >> 43 .globl __sys_fork, __sys_clone, __sys_vfork >> 44 .globl bad_interrupt >> 45 .globl auto_irqhandler_fixup >> 46 .globl user_irqvec_fixup >> 47 >> 48 .text >> 49 ENTRY(__sys_fork) >> 50 SAVE_SWITCH_STACK >> 51 jbsr sys_fork >> 52 lea %sp@(24),%sp >> 53 rts >> 54 >> 55 ENTRY(__sys_clone) >> 56 SAVE_SWITCH_STACK >> 57 pea %sp@(SWITCH_STACK_SIZE) >> 58 jbsr m68k_clone >> 59 lea %sp@(28),%sp >> 60 rts >> 61 >> 62 ENTRY(__sys_vfork) >> 63 SAVE_SWITCH_STACK >> 64 jbsr sys_vfork >> 65 lea %sp@(24),%sp >> 66 rts >> 67 >> 68 ENTRY(__sys_clone3) >> 69 SAVE_SWITCH_STACK >> 70 pea %sp@(SWITCH_STACK_SIZE) >> 71 jbsr m68k_clone3 >> 72 lea %sp@(28),%sp >> 73 rts >> 74 >> 75 ENTRY(sys_sigreturn) >> 76 SAVE_SWITCH_STACK >> 77 movel %sp,%a1 | switch_stack pointer >> 78 lea %sp@(SWITCH_STACK_SIZE),%a0 | pt_regs pointer >> 79 lea %sp@(-84),%sp | leave a gap >> 80 movel %a1,%sp@- >> 81 movel %a0,%sp@- >> 82 jbsr do_sigreturn >> 83 jra 1f | shared with rt_sigreturn() >> 84 >> 85 ENTRY(sys_rt_sigreturn) >> 86 SAVE_SWITCH_STACK >> 87 movel %sp,%a1 | switch_stack pointer >> 88 lea %sp@(SWITCH_STACK_SIZE),%a0 | pt_regs pointer >> 89 lea %sp@(-84),%sp | leave a gap >> 90 movel %a1,%sp@- >> 91 movel %a0,%sp@- >> 92 | stack contents: >> 93 | [original pt_regs address] [original switch_stack address] >> 94 | [gap] [switch_stack] [pt_regs] [exception frame] >> 95 jbsr do_rt_sigreturn 107 96 108 1: 97 1: 109 ; DEAD END: can't do much, display Reg !! 98 | stack contents now: 110 SAVE_CALLEE_SAVED_USER !! 99 | [original pt_regs address] [original switch_stack address] 111 !! 100 | [unused part of the gap] [moved switch_stack] [moved pt_regs] 112 GET_CURR_TASK_FIELD_PTR TASK_THREAD, !! 101 | [replacement exception frame] 113 st sp, [r10, THREAD_CALLEE_REG] !! 102 | return value of do_{rt_,}sigreturn() points to moved switch_stack. 114 !! 103 115 j do_machine_check_fault !! 104 movel %d0,%sp | discard the leftover junk 116 !! 105 RESTORE_SWITCH_STACK 117 END(EV_MachineCheck) !! 106 | stack contents now is just [syscall return address] [pt_regs] [frame] 118 !! 107 | return pt_regs.d0 119 ; -------------------------------------------- !! 108 movel %sp@(PT_OFF_D0+4),%d0 120 ; Privilege Violation Exception Handler !! 109 rts 121 ; -------------------------------------------- !! 110 122 ENTRY(EV_PrivilegeV) !! 111 ENTRY(buserr) 123 !! 112 SAVE_ALL_INT 124 EXCEPTION_PROLOGUE !! 113 GET_CURRENT(%d0) 125 !! 114 movel %sp,%sp@- | stack frame pointer argument 126 bl do_privilege_fault !! 115 jbsr buserr_c 127 b ret_from_exception !! 116 addql #4,%sp 128 END(EV_PrivilegeV) !! 117 jra ret_from_exception 129 !! 118 130 ; -------------------------------------------- !! 119 ENTRY(trap) 131 ; Extension Instruction Exception Handler !! 120 SAVE_ALL_INT 132 ; -------------------------------------------- !! 121 GET_CURRENT(%d0) 133 ENTRY(EV_Extension) !! 122 movel %sp,%sp@- | stack frame pointer argument 134 !! 123 jbsr trap_c 135 EXCEPTION_PROLOGUE !! 124 addql #4,%sp 136 !! 125 jra ret_from_exception 137 bl do_extension_fault !! 126 138 b ret_from_exception !! 127 | After a fork we jump here directly from resume, 139 END(EV_Extension) !! 128 | so that %d1 contains the previous task 140 !! 129 | schedule_tail now used regardless of CONFIG_SMP 141 ;################ Trap Handling (Syscall, Brea !! 130 ENTRY(ret_from_fork) 142 !! 131 movel %d1,%sp@- 143 ; -------------------------------------------- !! 132 jsr schedule_tail 144 ; syscall Tracing !! 133 addql #4,%sp 145 ; -------------------------------------------- !! 134 jra ret_from_exception 146 tracesys: !! 135 147 ; safekeep EFA (r12) if syscall tracer !! 136 ENTRY(ret_from_kernel_thread) 148 ; for traps, ERET is pre-commit so poi !! 137 | a3 contains the kernel thread payload, d7 - its argument 149 GET_CURR_TASK_FIELD_PTR TASK_THREAD, !! 138 movel %d1,%sp@- 150 st r12, [r11, THREAD_FAULT_ADDR] !! 139 jsr schedule_tail 151 !! 140 movel %d7,(%sp) 152 ; PRE syscall trace hook !! 141 jsr %a3@ 153 mov r0, sp !! 142 addql #4,%sp 154 bl @syscall_trace_enter !! 143 jra ret_from_exception 155 !! 144 156 ; Tracing code now returns the syscall !! 145 #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) 157 mov r8, r0 !! 146 158 !! 147 #ifdef TRAP_DBG_INTERRUPT 159 ; Do the Sys Call as we normally would !! 148 160 cmp r8, NR_syscalls - 1 !! 149 .globl dbginterrupt 161 mov.hi r0, -ENOSYS !! 150 ENTRY(dbginterrupt) 162 bhi tracesys_exit !! 151 SAVE_ALL_INT 163 !! 152 GET_CURRENT(%d0) 164 ; Restore the sys-call args. Mere invo !! 153 movel %sp,%sp@- /* stack frame pointer argument */ 165 ; clobbered them (since they are in sc !! 154 jsr dbginterrupt_c 166 ; have deliberately changed the syscal !! 155 addql #4,%sp 167 ld r0, [sp, PT_r0] !! 156 jra ret_from_exception 168 ld r1, [sp, PT_r1] !! 157 #endif 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 << 210 ; -------------------------------------------- << 211 ; syscall TRAP << 212 ; ABI: (r0-r7) up to 8 args, (r8) syscall numb << 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 158 246 ; fall through to ret_from_exception !! 159 ENTRY(reschedule) 247 END(EV_Trap) !! 160 /* save top of frame */ >> 161 pea %sp@ >> 162 jbsr set_esp0 >> 163 addql #4,%sp >> 164 pea ret_from_exception >> 165 jmp schedule >> 166 >> 167 ENTRY(ret_from_user_signal) >> 168 moveq #__NR_sigreturn,%d0 >> 169 trap #0 >> 170 >> 171 ENTRY(ret_from_user_rt_signal) >> 172 movel #__NR_rt_sigreturn,%d0 >> 173 trap #0 >> 174 >> 175 #else >> 176 >> 177 do_trace_entry: >> 178 movel #-ENOSYS,%sp@(PT_OFF_D0)| needed for strace >> 179 subql #4,%sp >> 180 SAVE_SWITCH_STACK >> 181 jbsr syscall_trace_enter >> 182 RESTORE_SWITCH_STACK >> 183 addql #4,%sp >> 184 addql #1,%d0 | optimization for cmpil #-1,%d0 >> 185 jeq ret_from_syscall >> 186 movel %sp@(PT_OFF_ORIG_D0),%d0 >> 187 cmpl #NR_syscalls,%d0 >> 188 jcs syscall >> 189 jra ret_from_syscall >> 190 badsys: >> 191 movel #-ENOSYS,%sp@(PT_OFF_D0) >> 192 jra ret_from_syscall >> 193 >> 194 do_trace_exit: >> 195 subql #4,%sp >> 196 SAVE_SWITCH_STACK >> 197 jbsr syscall_trace_leave >> 198 RESTORE_SWITCH_STACK >> 199 addql #4,%sp >> 200 jra .Lret_from_exception >> 201 >> 202 ENTRY(system_call) >> 203 SAVE_ALL_SYS >> 204 >> 205 GET_CURRENT(%d1) >> 206 movel %d1,%a1 >> 207 >> 208 | save top of frame >> 209 movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) >> 210 >> 211 | syscall trace? >> 212 tstb %a1@(TINFO_FLAGS+2) >> 213 jmi do_trace_entry >> 214 | seccomp filter active? >> 215 btst #5,%a1@(TINFO_FLAGS+2) >> 216 bnes do_trace_entry >> 217 cmpl #NR_syscalls,%d0 >> 218 jcc badsys >> 219 syscall: >> 220 jbsr @(sys_call_table,%d0:l:4)@(0) >> 221 movel %d0,%sp@(PT_OFF_D0) | save the return value >> 222 ret_from_syscall: >> 223 |oriw #0x0700,%sr >> 224 movel %curptr@(TASK_STACK),%a1 >> 225 movew %a1@(TINFO_FLAGS+2),%d0 >> 226 jne syscall_exit_work >> 227 1: RESTORE_ALL >> 228 >> 229 syscall_exit_work: >> 230 btst #5,%sp@(PT_OFF_SR) | check if returning to kernel >> 231 bnes 1b | if so, skip resched, signals >> 232 lslw #1,%d0 >> 233 jcs do_trace_exit >> 234 jmi do_delayed_trace >> 235 lslw #8,%d0 >> 236 jne do_signal_return >> 237 pea resume_userspace >> 238 jra schedule 248 239 249 ;############# Return from Intr/Excp/Trap (Lin << 250 ; << 251 ; If ret to user mode do we need to handle sig << 252 240 253 ENTRY(ret_from_exception) 241 ENTRY(ret_from_exception) 254 !! 242 .Lret_from_exception: 255 ; Pre-{IRQ,Trap,Exception} K/U mode fr !! 243 btst #5,%sp@(PT_OFF_SR) | check if returning to kernel 256 ld r8, [sp, PT_status32] ; returnin !! 244 bnes 1f | if so, skip resched, signals 257 !! 245 | only allow interrupts when we are really the last one on the 258 bbit0 r8, STATUS_U_BIT, resume_kernel !! 246 | kernel stack, otherwise stack overflow can occur during 259 !! 247 | heavy interrupt load 260 ; Before returning to User mode check- !! 248 andw #ALLOWINT,%sr 261 ; such as rescheduling/signal-delivery !! 249 262 resume_user_mode_begin: !! 250 resume_userspace: 263 !! 251 movel %curptr@(TASK_STACK),%a1 264 ; Disable IRQs to ensures that chk for !! 252 moveb %a1@(TINFO_FLAGS+3),%d0 265 ; (and we don't end up missing a NEED_ !! 253 jne exit_work 266 ; interim IRQ). !! 254 1: RESTORE_ALL 267 IRQ_DISABLE r10 !! 255 268 !! 256 exit_work: 269 ; Fast Path return to user mode if no !! 257 | save top of frame 270 GET_CURR_THR_INFO_FLAGS r9 !! 258 movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) 271 and.f 0, r9, _TIF_WORK_MASK !! 259 lslb #1,%d0 272 bz .Lrestore_regs !! 260 jne do_signal_return 273 !! 261 pea resume_userspace 274 ; --- (Slow Path #1) task preemption - !! 262 jra schedule 275 bbit0 r9, TIF_NEED_RESCHED, .Lchk_pen !! 263 276 mov blink, resume_user_mode_begin !! 264 277 j @schedule ; BTST+Bnz cau !! 265 do_signal_return: 278 !! 266 |andw #ALLOWINT,%sr 279 .Lchk_pend_signals: !! 267 subql #4,%sp | dummy return address 280 IRQ_ENABLE r10 !! 268 SAVE_SWITCH_STACK 281 !! 269 pea %sp@(SWITCH_STACK_SIZE) 282 ; --- (Slow Path #2) pending signal - !! 270 bsrl do_notify_resume 283 mov r0, sp ; pt_regs for arg to d !! 271 addql #4,%sp 284 !! 272 RESTORE_SWITCH_STACK 285 GET_CURR_THR_INFO_FLAGS r9 !! 273 addql #4,%sp 286 and.f 0, r9, _TIF_SIGPENDING|_TIF_NO !! 274 jbra resume_userspace 287 bz .Lchk_notify_resume !! 275 288 !! 276 do_delayed_trace: 289 ; Normal Trap/IRQ entry only saves Scr !! 277 bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR 290 ; in pt_reg since the "C" ABI (kernel !! 278 pea 1 | send SIGTRAP 291 ; save/restore callee-saved regs. !! 279 movel %curptr,%sp@- 292 ; !! 280 pea LSIGTRAP 293 ; However, here we need to explicitly !! 281 jbsr send_sig 294 ; (i) If this signal causes coredump !! 282 addql #8,%sp 295 ; (ii) If signal is SIGTRAP/SIGSTOP, t !! 283 addql #4,%sp 296 ; tracer might call PEEKUSR(CALLE !! 284 jbra resume_userspace 297 ; !! 285 298 ; NOTE: SP will grow up by size of CAL !! 286 299 SAVE_CALLEE_SAVED_USER !! 287 /* This is the main interrupt handler for autovector interrupts */ 300 !! 288 301 ; save location of saved Callee Regs @ !! 289 ENTRY(auto_inthandler) 302 GET_CURR_TASK_FIELD_PTR TASK_THREAD, !! 290 SAVE_ALL_INT 303 st sp, [r10, THREAD_CALLEE_REG] !! 291 GET_CURRENT(%d0) 304 !! 292 | put exception # in d0 305 bl @do_signal !! 293 bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0 306 !! 294 subw #VEC_SPUR,%d0 307 ; Ideally we want to discard the Calle !! 295 308 ; a tracing signal, tracer could have !! 296 movel %sp,%sp@- 309 RESTORE_CALLEE_SAVED_USER !! 297 movel %d0,%sp@- | put vector # on stack 310 !! 298 auto_irqhandler_fixup = . + 2 311 b resume_user_mode_begin ; loop !! 299 jsr do_IRQ | process the IRQ 312 !! 300 addql #8,%sp | pop parameters off stack 313 ; --- (Slow Path #3) notify_resume --- !! 301 jra ret_from_exception 314 .Lchk_notify_resume: !! 302 315 btst r9, TIF_NOTIFY_RESUME !! 303 /* Handler for user defined interrupt vectors */ 316 blnz @do_notify_resume !! 304 317 b resume_user_mode_begin ; unco !! 305 ENTRY(user_inthandler) 318 ; for !! 306 SAVE_ALL_INT 319 !! 307 GET_CURRENT(%d0) 320 resume_kernel_mode: !! 308 | put exception # in d0 321 !! 309 bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0 322 ; Disable Interrupts from this point o !! 310 user_irqvec_fixup = . + 2 323 ; CONFIG_PREEMPTION: This is a must fo !! 311 subw #VEC_USER,%d0 324 ; !CONFIG_PREEMPTION: To ensure restor !! 312 325 IRQ_DISABLE r9 !! 313 movel %sp,%sp@- 326 !! 314 movel %d0,%sp@- | put vector # on stack 327 #ifdef CONFIG_PREEMPTION !! 315 jsr do_IRQ | process the IRQ 328 !! 316 addql #8,%sp | pop parameters off stack 329 ; Can't preempt if preemption disabled !! 317 jra ret_from_exception 330 GET_CURR_THR_INFO_FROM_SP r10 !! 318 331 ld r8, [r10, THREAD_INFO_PREEMPT_COUN !! 319 /* Handler for uninitialized and spurious interrupts */ 332 brne r8, 0, .Lrestore_regs !! 320 333 !! 321 ENTRY(bad_inthandler) 334 ; check if this task's NEED_RESCHED fl !! 322 SAVE_ALL_INT 335 ld r9, [r10, THREAD_INFO_FLAGS] !! 323 GET_CURRENT(%d0) 336 bbit0 r9, TIF_NEED_RESCHED, .Lrestore !! 324 337 !! 325 movel %sp,%sp@- 338 ; Invoke PREEMPTION !! 326 jsr handle_badint 339 jl preempt_schedule_irq !! 327 addql #4,%sp 340 !! 328 jra ret_from_exception 341 ; preempt_schedule_irq() always return !! 329 >> 330 resume: >> 331 /* >> 332 * Beware - when entering resume, prev (the current task) is >> 333 * in a0, next (the new task) is in a1,so don't change these >> 334 * registers until their contents are no longer needed. >> 335 */ >> 336 >> 337 /* save sr */ >> 338 movew %sr,%a0@(TASK_THREAD+THREAD_SR) >> 339 >> 340 /* save fs (sfc,%dfc) (may be pointing to kernel memory) */ >> 341 movec %sfc,%d0 >> 342 movew %d0,%a0@(TASK_THREAD+THREAD_FC) >> 343 >> 344 /* save usp */ >> 345 /* it is better to use a movel here instead of a movew 8*) */ >> 346 movec %usp,%d0 >> 347 movel %d0,%a0@(TASK_THREAD+THREAD_USP) >> 348 >> 349 /* save non-scratch registers on stack */ >> 350 SAVE_SWITCH_STACK >> 351 >> 352 /* save current kernel stack pointer */ >> 353 movel %sp,%a0@(TASK_THREAD+THREAD_KSP) >> 354 >> 355 /* save floating point context */ >> 356 #ifndef CONFIG_M68KFPU_EMU_ONLY >> 357 #ifdef CONFIG_M68KFPU_EMU >> 358 tstl m68k_fputype >> 359 jeq 3f 342 #endif 360 #endif >> 361 fsave %a0@(TASK_THREAD+THREAD_FPSTATE) 343 362 344 b .Lrestore_regs !! 363 #if defined(CONFIG_M68060) >> 364 #if !defined(CPU_M68060_ONLY) >> 365 btst #3,m68k_cputype+3 >> 366 beqs 1f >> 367 #endif >> 368 /* The 060 FPU keeps status in bits 15-8 of the first longword */ >> 369 tstb %a0@(TASK_THREAD+THREAD_FPSTATE+2) >> 370 jeq 3f >> 371 #if !defined(CPU_M68060_ONLY) >> 372 jra 2f >> 373 #endif >> 374 #endif /* CONFIG_M68060 */ >> 375 #if !defined(CPU_M68060_ONLY) >> 376 1: tstb %a0@(TASK_THREAD+THREAD_FPSTATE) >> 377 jeq 3f >> 378 #endif >> 379 2: fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG) >> 380 fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL) >> 381 3: >> 382 #endif /* CONFIG_M68KFPU_EMU_ONLY */ >> 383 /* Return previous task in %d1 */ >> 384 movel %curptr,%d1 >> 385 >> 386 /* switch to new task (a1 contains new task) */ >> 387 movel %a1,%curptr >> 388 >> 389 /* restore floating point context */ >> 390 #ifndef CONFIG_M68KFPU_EMU_ONLY >> 391 #ifdef CONFIG_M68KFPU_EMU >> 392 tstl m68k_fputype >> 393 jeq 4f >> 394 #endif >> 395 #if defined(CONFIG_M68060) >> 396 #if !defined(CPU_M68060_ONLY) >> 397 btst #3,m68k_cputype+3 >> 398 beqs 1f >> 399 #endif >> 400 /* The 060 FPU keeps status in bits 15-8 of the first longword */ >> 401 tstb %a1@(TASK_THREAD+THREAD_FPSTATE+2) >> 402 jeq 3f >> 403 #if !defined(CPU_M68060_ONLY) >> 404 jra 2f >> 405 #endif >> 406 #endif /* CONFIG_M68060 */ >> 407 #if !defined(CPU_M68060_ONLY) >> 408 1: tstb %a1@(TASK_THREAD+THREAD_FPSTATE) >> 409 jeq 3f >> 410 #endif >> 411 2: fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7 >> 412 fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar >> 413 3: frestore %a1@(TASK_THREAD+THREAD_FPSTATE) >> 414 4: >> 415 #endif /* CONFIG_M68KFPU_EMU_ONLY */ >> 416 >> 417 /* restore the kernel stack pointer */ >> 418 movel %a1@(TASK_THREAD+THREAD_KSP),%sp >> 419 >> 420 /* restore non-scratch registers */ >> 421 RESTORE_SWITCH_STACK >> 422 >> 423 /* restore user stack pointer */ >> 424 movel %a1@(TASK_THREAD+THREAD_USP),%a0 >> 425 movel %a0,%usp >> 426 >> 427 /* restore fs (sfc,%dfc) */ >> 428 movew %a1@(TASK_THREAD+THREAD_FC),%a0 >> 429 movec %a0,%sfc >> 430 movec %a0,%dfc >> 431 >> 432 /* restore status register */ >> 433 movew %a1@(TASK_THREAD+THREAD_SR),%d0 >> 434 oriw #0x0700,%d0 >> 435 movew %d0,%sr 345 436 346 ##### DONT ADD CODE HERE - .Lrestore_regs actu !! 437 rts 347 438 >> 439 #endif /* CONFIG_MMU && !CONFIG_COLDFIRE */
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.