1 /* !! 1 /* SPDX-License-Identifier: GPL-2.0-or-later 2 * linux/arch/nios2/kernel/entry.S !! 2 * -*- mode: asm -*- 3 * << 4 * Copyright (C) 2013-2014 Altera Corporation << 5 * Copyright (C) 2009, Wind River Systems Inc << 6 * << 7 * Implemented by fredrik.markstrom@gmail.com << 8 * 3 * 9 * Copyright (C) 1999-2002, Greg Ungerer (ger !! 4 * linux/arch/m68k/kernel/entry.S 10 * Copyright (C) 1998 D. Jeff Dionne <jeff@li << 11 * Kenneth Albanowski <kja << 12 * Copyright (C) 2000 Lineo Inc. (www.lineo. << 13 * Copyright (C) 2004 Microtronix Datacom Lt << 14 * 5 * 15 * This file is subject to the terms and condi !! 6 * Copyright (C) 1991, 1992 Linus Torvalds 16 * License. See the file "COPYING" in the mai << 17 * for more details. << 18 * 7 * 19 * Linux/m68k support by Hamish Macdonald 8 * Linux/m68k support by Hamish Macdonald 20 * 9 * 21 * 68060 fixes by Jesper Skov 10 * 68060 fixes by Jesper Skov 22 * ColdFire support by Greg Ungerer (gerg@snap !! 11 * 23 * 5307 fixes by David W. Miller !! 12 */ 24 * linux 2.4 support David McCullough <davidm@s !! 13 >> 14 /* >> 15 * entry.S contains the system-call and fault low-level handling routines. >> 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. >> 21 * >> 22 */ >> 23 >> 24 /* >> 25 * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so >> 26 * all pointers that used to be 'current' are now entry >> 27 * number 0 in the 'current_set' list. >> 28 * >> 29 * 6/05/00 RZ: addedd writeback completion after return from sighandler >> 30 * for 68040 25 */ 31 */ 26 32 27 #include <linux/sys.h> << 28 #include <linux/linkage.h> 33 #include <linux/linkage.h> 29 #include <asm/asm-offsets.h> << 30 #include <asm/asm-macros.h> << 31 #include <asm/thread_info.h> << 32 #include <asm/errno.h> 34 #include <asm/errno.h> 33 #include <asm/setup.h> 35 #include <asm/setup.h> 34 #include <asm/entry.h> !! 36 #include <asm/traps.h> 35 #include <asm/unistd.h> 37 #include <asm/unistd.h> 36 #include <asm/processor.h> !! 38 #include <asm/asm-offsets.h> 37 !! 39 #include <asm/entry.h> 38 .macro GET_THREAD_INFO reg << 39 .if THREAD_SIZE & 0xffff0000 << 40 andhi \reg, sp, %hi(~(THREAD_SIZE-1) << 41 .else << 42 addi \reg, r0, %lo(~(THREAD_SIZE-1) << 43 and \reg, \reg, sp << 44 .endif << 45 .endm << 46 << 47 .macro kuser_cmpxchg_check << 48 /* << 49 * Make sure our user space atomic hel << 50 * interrupted in a critical region. << 51 * ea-4 = address of interrupted insn << 52 * sp = saved regs. << 53 * cmpxchg_ldw = first critical insn, << 54 * If ea <= cmpxchg_stw and ea > cmpxc << 55 * cmpxchg_ldw + 4. << 56 */ << 57 /* et = cmpxchg_stw + 4 */ << 58 movui et, (KUSER_BASE + 4 + (cmpxchg << 59 bgtu ea, et, 1f << 60 << 61 subi et, et, (cmpxchg_stw - cmpxchg << 62 bltu ea, et, 1f << 63 stw et, PT_EA(sp) /* fix up EA * << 64 mov ea, et << 65 1: << 66 .endm << 67 40 68 .section .rodata !! 41 .globl system_call, buserr, trap, resume 69 .align 4 !! 42 .globl sys_call_table 70 exception_table: !! 43 .globl __sys_fork, __sys_clone, __sys_vfork 71 .word unhandled_exception /* 0 - !! 44 .globl bad_interrupt 72 .word unhandled_exception /* 1 - !! 45 .globl auto_irqhandler_fixup 73 .word external_interrupt /* 2 - !! 46 .globl user_irqvec_fixup 74 .word handle_trap /* 3 - << 75 << 76 .word instruction_trap /* 4 - << 77 .word handle_illegal /* 5 - << 78 .word handle_unaligned /* 6 - << 79 .word handle_unaligned /* 7 - << 80 << 81 .word handle_diverror /* 8 - << 82 .word protection_exception_ba /* 9 - << 83 .word protection_exception_instr /* 10 << 84 .word protection_exception_ba /* 11 << 85 << 86 .word unhandled_exception /* 12 << 87 .word protection_exception_pte /* 13 << 88 .word protection_exception_pte /* 14 << 89 .word protection_exception_pte /* 15 << 90 << 91 .word unhandled_exception /* 16 << 92 << 93 trap_table: << 94 .word handle_system_call /* 0 << 95 .word handle_trap_1 /* 1 << 96 .word handle_trap_2 /* 2 << 97 .word handle_trap_3 /* 3 << 98 .word handle_trap_reserved /* 4 << 99 .word handle_trap_reserved /* 5 << 100 .word handle_trap_reserved /* 6 << 101 .word handle_trap_reserved /* 7 << 102 .word handle_trap_reserved /* 8 << 103 .word handle_trap_reserved /* 9 << 104 .word handle_trap_reserved /* 10 << 105 .word handle_trap_reserved /* 11 << 106 .word handle_trap_reserved /* 12 << 107 .word handle_trap_reserved /* 13 << 108 .word handle_trap_reserved /* 14 << 109 .word handle_trap_reserved /* 15 << 110 .word handle_trap_reserved /* 16 << 111 .word handle_trap_reserved /* 17 << 112 .word handle_trap_reserved /* 18 << 113 .word handle_trap_reserved /* 19 << 114 .word handle_trap_reserved /* 20 << 115 .word handle_trap_reserved /* 21 << 116 .word handle_trap_reserved /* 22 << 117 .word handle_trap_reserved /* 23 << 118 .word handle_trap_reserved /* 24 << 119 .word handle_trap_reserved /* 25 << 120 .word handle_trap_reserved /* 26 << 121 .word handle_trap_reserved /* 27 << 122 .word handle_trap_reserved /* 28 << 123 .word handle_trap_reserved /* 29 << 124 #ifdef CONFIG_KGDB << 125 .word handle_kgdb_breakpoint /* 30 << 126 #else << 127 .word instruction_trap << 128 #endif << 129 .word handle_breakpoint /* 31 << 130 47 131 .text 48 .text 132 .set noat !! 49 ENTRY(__sys_fork) 133 .set nobreak !! 50 SAVE_SWITCH_STACK 134 !! 51 jbsr sys_fork 135 ENTRY(inthandler) !! 52 lea %sp@(24),%sp 136 SAVE_ALL !! 53 rts 137 << 138 kuser_cmpxchg_check << 139 54 140 /* Clear EH bit before we get a new ex !! 55 ENTRY(__sys_clone) 141 * and after we have saved it to the e !! 56 SAVE_SWITCH_STACK 142 * whether it's trap, tlb-miss or inte !! 57 pea %sp@(SWITCH_STACK_SIZE) 143 * estatus is not updated the next exc !! 58 jbsr m68k_clone 144 */ !! 59 lea %sp@(28),%sp 145 rdctl r24, status !! 60 rts 146 movi r9, %lo(~STATUS_EH) << 147 and r24, r24, r9 << 148 wrctl status, r24 << 149 << 150 /* Read cause and vector and branch to << 151 mov r4, sp << 152 rdctl r5, exception << 153 movia r9, exception_table << 154 add r24, r9, r5 << 155 ldw r24, 0(r24) << 156 jmp r24 << 157 << 158 << 159 /********************************************* << 160 * Handle traps << 161 ********************************************* << 162 */ << 163 ENTRY(handle_trap) << 164 ldwio r24, -4(ea) /* instruction << 165 srli r24, r24, 4 << 166 andi r24, r24, 0x7c << 167 movia r9,trap_table << 168 add r24, r24, r9 << 169 ldw r24, 0(r24) << 170 jmp r24 << 171 61 >> 62 ENTRY(__sys_vfork) >> 63 SAVE_SWITCH_STACK >> 64 jbsr sys_vfork >> 65 lea %sp@(24),%sp >> 66 rts 172 67 173 /********************************************* !! 68 ENTRY(__sys_clone3) 174 * Handle system calls << 175 ********************************************* << 176 */ << 177 ENTRY(handle_system_call) << 178 /* Enable interrupts */ << 179 rdctl r10, status << 180 ori r10, r10, STATUS_PIE << 181 wrctl status, r10 << 182 << 183 /* Reload registers destroyed by commo << 184 ldw r4, PT_R4(sp) << 185 ldw r5, PT_R5(sp) << 186 << 187 local_restart: << 188 stw r2, PT_ORIG_R2(sp) << 189 /* Check that the requested system cal << 190 movui r1, __NR_syscalls << 191 bgeu r2, r1, ret_invsyscall << 192 slli r1, r2, 2 << 193 movhi r11, %hiadj(sys_call_table) << 194 add r1, r1, r11 << 195 ldw r1, %lo(sys_call_table)(r1) << 196 << 197 /* Check if we are being traced */ << 198 GET_THREAD_INFO r11 << 199 ldw r11,TI_FLAGS(r11) << 200 BTBNZ r11,r11,TIF_SYSCALL_TRACE,trac << 201 << 202 /* Execute the system call */ << 203 callr r1 << 204 << 205 /* If the syscall returns a negative r << 206 * Set r7 to 1 to indicate error, << 207 * Negate r2 to get a positive error << 208 * If the syscall returns zero or a po << 209 * Set r7 to 0. << 210 * The sigreturn system calls will ski << 211 * adding to register ra. To avoid des << 212 */ << 213 translate_rc_and_ret: << 214 movi r1, 0 << 215 bge r2, zero, 3f << 216 ldw r1, PT_ORIG_R2(sp) << 217 addi r1, r1, 1 << 218 beq r1, zero, 3f << 219 sub r2, zero, r2 << 220 movi r1, 1 << 221 3: << 222 stw r2, PT_R2(sp) << 223 stw r1, PT_R7(sp) << 224 end_translate_rc_and_ret: << 225 << 226 ret_from_exception: << 227 ldw r1, PT_ESTATUS(sp) << 228 /* if so, skip resched, signals */ << 229 TSTBNZ r1, r1, ESTATUS_EU, Luser_retu << 230 << 231 restore_all: << 232 rdctl r10, status << 233 andi r10, r10, %lo(~STATUS_PIE) << 234 wrctl status, r10 << 235 RESTORE_ALL << 236 eret << 237 << 238 /* If the syscall number was invalid r << 239 ret_invsyscall: << 240 movi r2, -ENOSYS << 241 br translate_rc_and_ret << 242 << 243 /* This implements the same as above, << 244 * do_syscall_trace_enter and do_sysca << 245 * syscall in order for utilities like << 246 */ << 247 traced_system_call: << 248 SAVE_SWITCH_STACK 69 SAVE_SWITCH_STACK 249 call do_syscall_trace_enter !! 70 pea %sp@(SWITCH_STACK_SIZE) 250 RESTORE_SWITCH_STACK !! 71 jbsr m68k_clone3 >> 72 lea %sp@(28),%sp >> 73 rts 251 74 252 /* Create system call register argumen !! 75 ENTRY(sys_sigreturn) 253 arguments on stack are already in p << 254 of pt_regs. */ << 255 ldw r2, PT_R2(sp) << 256 ldw r4, PT_R4(sp) << 257 ldw r5, PT_R5(sp) << 258 ldw r6, PT_R6(sp) << 259 ldw r7, PT_R7(sp) << 260 << 261 /* Fetch the syscall function. */ << 262 movui r1, __NR_syscalls << 263 bgeu r2, r1, traced_invsyscall << 264 slli r1, r2, 2 << 265 movhi r11,%hiadj(sys_call_table) << 266 add r1, r1, r11 << 267 ldw r1, %lo(sys_call_table)(r1) << 268 << 269 callr r1 << 270 << 271 /* If the syscall returns a negative r << 272 * Set r7 to 1 to indicate error, << 273 * Negate r2 to get a positive error << 274 * If the syscall returns zero or a po << 275 * Set r7 to 0. << 276 * The sigreturn system calls will ski << 277 * adding to register ra. To avoid des << 278 */ << 279 translate_rc_and_ret2: << 280 movi r1, 0 << 281 bge r2, zero, 4f << 282 ldw r1, PT_ORIG_R2(sp) << 283 addi r1, r1, 1 << 284 beq r1, zero, 4f << 285 sub r2, zero, r2 << 286 movi r1, 1 << 287 4: << 288 stw r2, PT_R2(sp) << 289 stw r1, PT_R7(sp) << 290 end_translate_rc_and_ret2: << 291 SAVE_SWITCH_STACK 76 SAVE_SWITCH_STACK 292 call do_syscall_trace_exit !! 77 movel %sp,%a1 | switch_stack pointer 293 RESTORE_SWITCH_STACK !! 78 lea %sp@(SWITCH_STACK_SIZE),%a0 | pt_regs pointer 294 br ret_from_exception !! 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() 295 84 296 /* If the syscall number was invalid r !! 85 ENTRY(sys_rt_sigreturn) 297 traced_invsyscall: << 298 movi r2, -ENOSYS << 299 br translate_rc_and_ret2 << 300 << 301 Luser_return: << 302 GET_THREAD_INFO r11 << 303 ldw r10, TI_FLAGS(r11) << 304 ANDI32 r11, r10, _TIF_WORK_MASK << 305 beq r11, r0, restore_all << 306 BTBZ r1, r10, TIF_NEED_RESCHED, Lsi << 307 << 308 /* Reschedule work */ << 309 call schedule << 310 br ret_from_exception << 311 << 312 Lsignal_return: << 313 ANDI32 r1, r10, _TIF_SIGPENDING | _TI << 314 beq r1, r0, restore_all << 315 mov r4, sp /* pt_ << 316 SAVE_SWITCH_STACK 86 SAVE_SWITCH_STACK 317 call do_notify_resume !! 87 movel %sp,%a1 | switch_stack pointer 318 beq r2, r0, no_work_pending !! 88 lea %sp@(SWITCH_STACK_SIZE),%a0 | pt_regs pointer 319 RESTORE_SWITCH_STACK !! 89 lea %sp@(-84),%sp | leave a gap 320 /* prepare restart syscall here withou !! 90 movel %a1,%sp@- 321 ldw r2, PT_R2(sp) /* reload sysc !! 91 movel %a0,%sp@- 322 ldw r4, PT_R4(sp) /* reload sysc !! 92 | stack contents: 323 ldw r5, PT_R5(sp) !! 93 | [original pt_regs address] [original switch_stack address] 324 ldw r6, PT_R6(sp) !! 94 | [gap] [switch_stack] [pt_regs] [exception frame] 325 ldw r7, PT_R7(sp) !! 95 jbsr do_rt_sigreturn 326 ldw r8, PT_R8(sp) !! 96 327 ldw r9, PT_R9(sp) !! 97 1: 328 br local_restart /* restart sys !! 98 | stack contents now: >> 99 | [original pt_regs address] [original switch_stack address] >> 100 | [unused part of the gap] [moved switch_stack] [moved pt_regs] >> 101 | [replacement exception frame] >> 102 | return value of do_{rt_,}sigreturn() points to moved switch_stack. 329 103 330 no_work_pending: !! 104 movel %d0,%sp | discard the leftover junk 331 RESTORE_SWITCH_STACK 105 RESTORE_SWITCH_STACK 332 br ret_from_exception !! 106 | stack contents now is just [syscall return address] [pt_regs] [frame] >> 107 | return pt_regs.d0 >> 108 movel %sp@(PT_OFF_D0+4),%d0 >> 109 rts >> 110 >> 111 ENTRY(buserr) >> 112 SAVE_ALL_INT >> 113 GET_CURRENT(%d0) >> 114 movel %sp,%sp@- | stack frame pointer argument >> 115 jbsr buserr_c >> 116 addql #4,%sp >> 117 jra ret_from_exception >> 118 >> 119 ENTRY(trap) >> 120 SAVE_ALL_INT >> 121 GET_CURRENT(%d0) >> 122 movel %sp,%sp@- | stack frame pointer argument >> 123 jbsr trap_c >> 124 addql #4,%sp >> 125 jra ret_from_exception >> 126 >> 127 | After a fork we jump here directly from resume, >> 128 | so that %d1 contains the previous task >> 129 | schedule_tail now used regardless of CONFIG_SMP >> 130 ENTRY(ret_from_fork) >> 131 movel %d1,%sp@- >> 132 jsr schedule_tail >> 133 addql #4,%sp >> 134 jra ret_from_exception 333 135 334 /********************************************* !! 136 ENTRY(ret_from_kernel_thread) 335 * Handle external interrupts. !! 137 | a3 contains the kernel thread payload, d7 - its argument 336 ********************************************* !! 138 movel %d1,%sp@- 337 */ !! 139 jsr schedule_tail 338 /* !! 140 movel %d7,(%sp) 339 * This is the generic interrupt handler (for !! 141 jsr %a3@ 340 * sources). It figures out the vector number !! 142 addql #4,%sp 341 * interrupt service routine directly. !! 143 jra ret_from_exception 342 */ !! 144 343 external_interrupt: !! 145 #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) 344 rdctl r12, ipending !! 146 345 rdctl r9, ienable !! 147 #ifdef TRAP_DBG_INTERRUPT 346 and r12, r12, r9 !! 148 347 /* skip if no interrupt is pending */ !! 149 .globl dbginterrupt 348 beq r12, r0, ret_from_interrupt !! 150 ENTRY(dbginterrupt) >> 151 SAVE_ALL_INT >> 152 GET_CURRENT(%d0) >> 153 movel %sp,%sp@- /* stack frame pointer argument */ >> 154 jsr dbginterrupt_c >> 155 addql #4,%sp >> 156 jra ret_from_exception >> 157 #endif 349 158 350 /* !! 159 ENTRY(reschedule) 351 * Process an external hardware interr !! 160 /* save top of frame */ 352 */ !! 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 353 174 354 addi ea, ea, -4 /* re-issue th !! 175 #else 355 stw ea, PT_EA(sp) << 356 2: movi r4, %lo(-1) /* Start from << 357 highes << 358 /* This is the << 359 1: andi r10, r12, 1 /* Isolate bit << 360 srli r12, r12, 1 /* shift count << 361 multip << 362 addi r4, r4, 1 << 363 beq r10, r0, 1b << 364 mov r5, sp /* Setup pt_re << 365 call do_IRQ << 366 rdctl r12, ipending /* check again << 367 rdctl r9, ienable /* Isolate pos << 368 and r12, r12, r9 << 369 bne r12, r0, 2b << 370 /* br ret_from_interrupt */ /* fall << 371 << 372 ENTRY(ret_from_interrupt) << 373 ldw r1, PT_ESTATUS(sp) /* che << 374 TSTBNZ r1, r1, ESTATUS_EU, Luser_retu << 375 << 376 #ifdef CONFIG_PREEMPTION << 377 GET_THREAD_INFO r1 << 378 ldw r4, TI_PREEMPT_COUNT(r1) << 379 bne r4, r0, restore_all << 380 ldw r4, TI_FLAGS(r1) << 381 BTBZ r10, r4, TIF_NEED_RESCHED, res << 382 ldw r4, PT_ESTATUS(sp) /* ? I << 383 andi r10, r4, ESTATUS_EPIE << 384 beq r10, r0, restore_all << 385 call preempt_schedule_irq << 386 #endif << 387 br restore_all << 388 176 389 /********************************************* !! 177 do_trace_entry: 390 * A few syscall wrappers !! 178 movel #-ENOSYS,%sp@(PT_OFF_D0)| needed for strace 391 ********************************************* !! 179 subql #4,%sp 392 */ << 393 /* << 394 * int clone(unsigned long clone_flags, unsign << 395 * int __user * parent_tidptr, in << 396 * int tls_val) << 397 */ << 398 ENTRY(sys_clone) << 399 SAVE_SWITCH_STACK 180 SAVE_SWITCH_STACK 400 subi sp, sp, 4 /* make space for tl !! 181 jbsr syscall_trace_enter 401 stw r8, 0(sp) /* pass tls pointer << 402 call nios2_clone << 403 addi sp, sp, 4 << 404 RESTORE_SWITCH_STACK 182 RESTORE_SWITCH_STACK 405 ret !! 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 406 193 407 ENTRY(sys_rt_sigreturn) !! 194 do_trace_exit: >> 195 subql #4,%sp 408 SAVE_SWITCH_STACK 196 SAVE_SWITCH_STACK 409 mov r4, sp !! 197 jbsr syscall_trace_leave 410 call do_rt_sigreturn << 411 RESTORE_SWITCH_STACK 198 RESTORE_SWITCH_STACK 412 addi ra, ra, (end_translate_rc_and_ !! 199 addql #4,%sp 413 ret !! 200 jra .Lret_from_exception 414 201 415 /********************************************* !! 202 ENTRY(system_call) 416 * A few other wrappers and stubs !! 203 SAVE_ALL_SYS 417 ********************************************* !! 204 418 */ !! 205 GET_CURRENT(%d1) 419 protection_exception_pte: !! 206 movel %d1,%a1 420 rdctl r6, pteaddr << 421 slli r6, r6, 10 << 422 call do_page_fault << 423 br ret_from_exception << 424 << 425 protection_exception_ba: << 426 rdctl r6, badaddr << 427 call do_page_fault << 428 br ret_from_exception << 429 << 430 protection_exception_instr: << 431 call handle_supervisor_instr << 432 br ret_from_exception << 433 << 434 handle_breakpoint: << 435 call breakpoint_c << 436 br ret_from_exception << 437 207 438 #ifdef CONFIG_NIOS2_ALIGNMENT_TRAP !! 208 | save top of frame 439 handle_unaligned: !! 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 >> 239 >> 240 >> 241 ENTRY(ret_from_exception) >> 242 .Lret_from_exception: >> 243 btst #5,%sp@(PT_OFF_SR) | check if returning to kernel >> 244 bnes 1f | if so, skip resched, signals >> 245 | only allow interrupts when we are really the last one on the >> 246 | kernel stack, otherwise stack overflow can occur during >> 247 | heavy interrupt load >> 248 andw #ALLOWINT,%sr >> 249 >> 250 resume_userspace: >> 251 movel %curptr@(TASK_STACK),%a1 >> 252 moveb %a1@(TINFO_FLAGS+3),%d0 >> 253 jne exit_work >> 254 1: RESTORE_ALL >> 255 >> 256 exit_work: >> 257 | save top of frame >> 258 movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) >> 259 lslb #1,%d0 >> 260 jne do_signal_return >> 261 pea resume_userspace >> 262 jra schedule >> 263 >> 264 >> 265 do_signal_return: >> 266 |andw #ALLOWINT,%sr >> 267 subql #4,%sp | dummy return address 440 SAVE_SWITCH_STACK 268 SAVE_SWITCH_STACK 441 call handle_unaligned_c !! 269 pea %sp@(SWITCH_STACK_SIZE) >> 270 bsrl do_notify_resume >> 271 addql #4,%sp 442 RESTORE_SWITCH_STACK 272 RESTORE_SWITCH_STACK 443 br ret_from_exception !! 273 addql #4,%sp 444 #else !! 274 jbra resume_userspace 445 handle_unaligned: << 446 call handle_unaligned_c << 447 br ret_from_exception << 448 #endif << 449 275 450 handle_illegal: !! 276 do_delayed_trace: 451 call handle_illegal_c !! 277 bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR 452 br ret_from_exception !! 278 pea 1 | send SIGTRAP 453 !! 279 movel %curptr,%sp@- 454 handle_diverror: !! 280 pea LSIGTRAP 455 call handle_diverror_c !! 281 jbsr send_sig 456 br ret_from_exception !! 282 addql #8,%sp 457 !! 283 addql #4,%sp 458 #ifdef CONFIG_KGDB !! 284 jbra resume_userspace 459 handle_kgdb_breakpoint: !! 285 460 call kgdb_breakpoint_c !! 286 461 br ret_from_exception !! 287 /* This is the main interrupt handler for autovector interrupts */ 462 #endif !! 288 >> 289 ENTRY(auto_inthandler) >> 290 SAVE_ALL_INT >> 291 GET_CURRENT(%d0) >> 292 | put exception # in d0 >> 293 bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0 >> 294 subw #VEC_SPUR,%d0 >> 295 >> 296 movel %sp,%sp@- >> 297 movel %d0,%sp@- | put vector # on stack >> 298 auto_irqhandler_fixup = . + 2 >> 299 jsr do_IRQ | process the IRQ >> 300 addql #8,%sp | pop parameters off stack >> 301 jra ret_from_exception >> 302 >> 303 /* Handler for user defined interrupt vectors */ >> 304 >> 305 ENTRY(user_inthandler) >> 306 SAVE_ALL_INT >> 307 GET_CURRENT(%d0) >> 308 | put exception # in d0 >> 309 bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0 >> 310 user_irqvec_fixup = . + 2 >> 311 subw #VEC_USER,%d0 >> 312 >> 313 movel %sp,%sp@- >> 314 movel %d0,%sp@- | put vector # on stack >> 315 jsr do_IRQ | process the IRQ >> 316 addql #8,%sp | pop parameters off stack >> 317 jra ret_from_exception >> 318 >> 319 /* Handler for uninitialized and spurious interrupts */ >> 320 >> 321 ENTRY(bad_inthandler) >> 322 SAVE_ALL_INT >> 323 GET_CURRENT(%d0) >> 324 >> 325 movel %sp,%sp@- >> 326 jsr handle_badint >> 327 addql #4,%sp >> 328 jra ret_from_exception 463 329 464 handle_trap_1: !! 330 resume: 465 call handle_trap_1_c !! 331 /* 466 br ret_from_exception !! 332 * Beware - when entering resume, prev (the current task) is 467 !! 333 * in a0, next (the new task) is in a1,so don't change these 468 handle_trap_2: !! 334 * registers until their contents are no longer needed. 469 call handle_trap_2_c !! 335 */ 470 br ret_from_exception << 471 << 472 handle_trap_3: << 473 handle_trap_reserved: << 474 call handle_trap_3_c << 475 br ret_from_exception << 476 << 477 /* << 478 * Beware - when entering resume, prev (the cu << 479 * in r4, next (the new task) is in r5, don't << 480 * registers. << 481 */ << 482 ENTRY(resume) << 483 336 484 rdctl r7, status !! 337 /* save sr */ 485 stw r7, TASK_THREAD + THREAD_KPSR( !! 338 movew %sr,%a0@(TASK_THREAD+THREAD_SR) 486 339 487 andi r7, r7, %lo(~STATUS_PIE) !! 340 /* save fs (sfc,%dfc) (may be pointing to kernel memory) */ 488 wrctl status, r7 !! 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) 489 348 >> 349 /* save non-scratch registers on stack */ 490 SAVE_SWITCH_STACK 350 SAVE_SWITCH_STACK 491 stw sp, TASK_THREAD + THREAD_KSP(r << 492 ldw sp, TASK_THREAD + THREAD_KSP(r << 493 movia r24, _current_thread << 494 GET_THREAD_INFO r1 << 495 stw r1, 0(r24) << 496 RESTORE_SWITCH_STACK << 497 << 498 ldw r7, TASK_THREAD + THREAD_KPSR( << 499 wrctl status, r7 << 500 ret << 501 351 502 ENTRY(ret_from_fork) !! 352 /* save current kernel stack pointer */ 503 call schedule_tail !! 353 movel %sp,%a0@(TASK_THREAD+THREAD_KSP) 504 br ret_from_exception << 505 354 506 ENTRY(ret_from_kernel_thread) !! 355 /* save floating point context */ 507 call schedule_tail !! 356 #ifndef CONFIG_M68KFPU_EMU_ONLY 508 mov r4,r17 /* arg */ !! 357 #ifdef CONFIG_M68KFPU_EMU 509 callr r16 /* function */ !! 358 tstl m68k_fputype 510 br ret_from_exception !! 359 jeq 3f >> 360 #endif >> 361 fsave %a0@(TASK_THREAD+THREAD_FPSTATE) 511 362 512 /* !! 363 #if defined(CONFIG_M68060) 513 * Kernel user helpers. !! 364 #if !defined(CPU_M68060_ONLY) 514 * !! 365 btst #3,m68k_cputype+3 515 * Each segment is 64-byte aligned and will be !! 366 beqs 1f 516 * New segments (if ever needed) must be added !! 367 #endif 517 * This mechanism should be used only for thin !! 368 /* The 060 FPU keeps status in bits 15-8 of the first longword */ 518 * justified, and not be abused freely. !! 369 tstb %a0@(TASK_THREAD+THREAD_FPSTATE+2) 519 * !! 370 jeq 3f 520 */ !! 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 */ 521 416 522 /* Filling pads with undefined instructions. !! 417 /* restore the kernel stack pointer */ 523 .macro kuser_pad sym size !! 418 movel %a1@(TASK_THREAD+THREAD_KSP),%sp 524 .if ((. - \sym) & 3) << 525 .rept (4 - (. - \sym) & 3) << 526 .byte 0 << 527 .endr << 528 .endif << 529 .rept ((\size - (. - \sym)) / 4) << 530 .word 0xdeadbeef << 531 .endr << 532 .endm << 533 << 534 .align 6 << 535 .globl __kuser_helper_start << 536 __kuser_helper_start: << 537 419 538 __kuser_helper_version: !! 420 /* restore non-scratch registers */ 539 .word ((__kuser_helper_end - __kuser !! 421 RESTORE_SWITCH_STACK 540 422 541 __kuser_cmpxchg: !! 423 /* restore user stack pointer */ 542 /* !! 424 movel %a1@(TASK_THREAD+THREAD_USP),%a0 543 * r4 pointer to exchange variable !! 425 movel %a0,%usp 544 * r5 old value !! 426 545 * r6 new value !! 427 /* restore fs (sfc,%dfc) */ 546 */ !! 428 movew %a1@(TASK_THREAD+THREAD_FC),%a0 547 cmpxchg_ldw: !! 429 movec %a0,%sfc 548 ldw r2, 0(r4) !! 430 movec %a0,%dfc 549 sub r2, r2, r5 !! 431 550 bne r2, zero, cmpxchg_ret !! 432 /* restore status register */ 551 !! 433 movew %a1@(TASK_THREAD+THREAD_SR),%d0 552 /* We had a match, store the new value !! 434 oriw #0x0700,%d0 553 cmpxchg_stw: !! 435 movew %d0,%sr 554 stw r6, 0(r4) << 555 cmpxchg_ret: << 556 ret << 557 << 558 kuser_pad __kuser_cmpxchg, 64 << 559 << 560 .globl __kuser_sigtramp << 561 __kuser_sigtramp: << 562 movi r2, __NR_rt_sigreturn << 563 trap << 564 436 565 kuser_pad __kuser_sigtramp, 64 !! 437 rts 566 438 567 .globl __kuser_helper_end !! 439 #endif /* CONFIG_MMU && !CONFIG_COLDFIRE */ 568 __kuser_helper_end: <<
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.