1 /* 1 /* 2 * linux/arch/nios2/kernel/entry.S !! 2 * PowerPC version >> 3 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) >> 4 * Rewritten by Cort Dougan (cort@fsmlabs.com) for PReP >> 5 * Copyright (C) 1996 Cort Dougan <cort@fsmlabs.com> >> 6 * Adapted for Power Macintosh by Paul Mackerras. >> 7 * Low-level exception handlers and MMU support >> 8 * rewritten by Paul Mackerras. >> 9 * Copyright (C) 1996 Paul Mackerras. >> 10 * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net). 3 * 11 * 4 * Copyright (C) 2013-2014 Altera Corporation !! 12 * This file contains the system call entry code, context switch 5 * Copyright (C) 2009, Wind River Systems Inc !! 13 * code, and exception/interrupt return code for PowerPC. 6 * 14 * 7 * Implemented by fredrik.markstrom@gmail.com !! 15 * This program is free software; you can redistribute it and/or >> 16 * modify it under the terms of the GNU General Public License >> 17 * as published by the Free Software Foundation; either version >> 18 * 2 of the License, or (at your option) any later version. 8 * 19 * 9 * Copyright (C) 1999-2002, Greg Ungerer (ger << 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 * << 15 * This file is subject to the terms and condi << 16 * License. See the file "COPYING" in the mai << 17 * for more details. << 18 * << 19 * Linux/m68k support by Hamish Macdonald << 20 * << 21 * 68060 fixes by Jesper Skov << 22 * ColdFire support by Greg Ungerer (gerg@snap << 23 * 5307 fixes by David W. Miller << 24 * linux 2.4 support David McCullough <davidm@s << 25 */ 20 */ 26 21 >> 22 #include <linux/config.h> >> 23 #include <linux/errno.h> 27 #include <linux/sys.h> 24 #include <linux/sys.h> 28 #include <linux/linkage.h> !! 25 #include <linux/threads.h> 29 #include <asm/asm-offsets.h> << 30 #include <asm/asm-macros.h> << 31 #include <asm/thread_info.h> << 32 #include <asm/errno.h> << 33 #include <asm/setup.h> << 34 #include <asm/entry.h> << 35 #include <asm/unistd.h> << 36 #include <asm/processor.h> 26 #include <asm/processor.h> 37 !! 27 #include <asm/page.h> 38 .macro GET_THREAD_INFO reg !! 28 #include <asm/mmu.h> 39 .if THREAD_SIZE & 0xffff0000 !! 29 #include <asm/cputable.h> 40 andhi \reg, sp, %hi(~(THREAD_SIZE-1) !! 30 #include <asm/ppc_asm.h> 41 .else !! 31 #include "ppc_defs.h" 42 addi \reg, r0, %lo(~(THREAD_SIZE-1) !! 32 43 and \reg, \reg, sp !! 33 #undef SHOW_SYSCALLS 44 .endif !! 34 #undef SHOW_SYSCALLS_TASK 45 .endm !! 35 46 !! 36 #ifdef SHOW_SYSCALLS_TASK 47 .macro kuser_cmpxchg_check !! 37 .data 48 /* !! 38 show_syscalls_task: 49 * Make sure our user space atomic hel !! 39 .long -1 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 << 68 .section .rodata << 69 .align 4 << 70 exception_table: << 71 .word unhandled_exception /* 0 - << 72 .word unhandled_exception /* 1 - << 73 .word external_interrupt /* 2 - << 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 40 #endif 129 .word handle_breakpoint /* 31 << 130 << 131 .text << 132 .set noat << 133 .set nobreak << 134 << 135 ENTRY(inthandler) << 136 SAVE_ALL << 137 41 138 kuser_cmpxchg_check !! 42 /* 139 !! 43 * Handle a system call. 140 /* Clear EH bit before we get a new ex << 141 * and after we have saved it to the e << 142 * whether it's trap, tlb-miss or inte << 143 * estatus is not updated the next exc << 144 */ << 145 rdctl r24, status << 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 */ 44 */ 163 ENTRY(handle_trap) !! 45 .text 164 ldwio r24, -4(ea) /* instruction !! 46 .stabs "arch/ppc/kernel/",N_SO,0,0,0f 165 srli r24, r24, 4 !! 47 .stabs "entry.S",N_SO,0,0,0f 166 andi r24, r24, 0x7c !! 48 0: 167 movia r9,trap_table !! 49 168 add r24, r24, r9 !! 50 _GLOBAL(DoSyscall) 169 ldw r24, 0(r24) !! 51 stw r0,THREAD+LAST_SYSCALL(r2) 170 jmp r24 !! 52 lwz r11,_CCR(r1) /* Clear SO bit in CR */ 171 !! 53 lis r10,0x1000 >> 54 andc r11,r11,r10 >> 55 stw r11,_CCR(r1) >> 56 #ifdef SHOW_SYSCALLS >> 57 #ifdef SHOW_SYSCALLS_TASK >> 58 lis r31,show_syscalls_task@ha >> 59 lwz r31,show_syscalls_task@l(r31) >> 60 cmp 0,r2,r31 >> 61 bne 1f >> 62 #endif >> 63 lis r3,7f@ha >> 64 addi r3,r3,7f@l >> 65 lwz r4,GPR0(r1) >> 66 lwz r5,GPR3(r1) >> 67 lwz r6,GPR4(r1) >> 68 lwz r7,GPR5(r1) >> 69 lwz r8,GPR6(r1) >> 70 lwz r9,GPR7(r1) >> 71 bl printk >> 72 lis r3,77f@ha >> 73 addi r3,r3,77f@l >> 74 lwz r4,GPR8(r1) >> 75 lwz r5,GPR9(r1) >> 76 mr r6,r2 >> 77 bl printk >> 78 lwz r0,GPR0(r1) >> 79 lwz r3,GPR3(r1) >> 80 lwz r4,GPR4(r1) >> 81 lwz r5,GPR5(r1) >> 82 lwz r6,GPR6(r1) >> 83 lwz r7,GPR7(r1) >> 84 lwz r8,GPR8(r1) >> 85 1: >> 86 #endif /* SHOW_SYSCALLS */ >> 87 cmpi 0,r0,0x7777 /* Special case for 'sys_sigreturn' */ >> 88 beq- 10f >> 89 cmpi 0,r0,0x6666 /* Special case for 'sys_rt_sigreturn' */ >> 90 beq- 16f >> 91 lwz r10,TASK_PTRACE(r2) >> 92 andi. r10,r10,PT_TRACESYS >> 93 bne- 50f >> 94 cmpli 0,r0,NR_syscalls >> 95 bge- 66f >> 96 lis r10,sys_call_table@h >> 97 ori r10,r10,sys_call_table@l >> 98 slwi r0,r0,2 >> 99 lwzx r10,r10,r0 /* Fetch system call handler [ptr] */ >> 100 cmpi 0,r10,0 >> 101 beq- 66f >> 102 mtlr r10 >> 103 addi r9,r1,STACK_FRAME_OVERHEAD >> 104 blrl /* Call handler */ >> 105 .globl ret_from_syscall_1 >> 106 ret_from_syscall_1: >> 107 20: stw r3,RESULT(r1) /* Save result */ >> 108 #ifdef SHOW_SYSCALLS >> 109 #ifdef SHOW_SYSCALLS_TASK >> 110 cmp 0,r2,r31 >> 111 bne 91f >> 112 #endif >> 113 mr r4,r3 >> 114 lis r3,79f@ha >> 115 addi r3,r3,79f@l >> 116 bl printk >> 117 lwz r3,RESULT(r1) >> 118 91: >> 119 #endif >> 120 li r10,-_LAST_ERRNO >> 121 cmpl 0,r3,r10 >> 122 blt 30f >> 123 neg r3,r3 >> 124 cmpi 0,r3,ERESTARTNOHAND >> 125 bne 22f >> 126 li r3,EINTR >> 127 22: lwz r10,_CCR(r1) /* Set SO bit in CR */ >> 128 oris r10,r10,0x1000 >> 129 stw r10,_CCR(r1) >> 130 30: stw r3,GPR3(r1) /* Update return value */ >> 131 b ret_from_except >> 132 66: li r3,ENOSYS >> 133 b 22b >> 134 /* sys_sigreturn */ >> 135 10: addi r3,r1,STACK_FRAME_OVERHEAD >> 136 bl sys_sigreturn >> 137 cmpi 0,r3,0 /* Check for restarted system call */ >> 138 bge ret_from_except >> 139 b 20b >> 140 /* sys_rt_sigreturn */ >> 141 16: addi r3,r1,STACK_FRAME_OVERHEAD >> 142 bl sys_rt_sigreturn >> 143 cmpi 0,r3,0 /* Check for restarted system call */ >> 144 bge ret_from_except >> 145 b 20b >> 146 /* Traced system call support */ >> 147 50: bl syscall_trace >> 148 lwz r0,GPR0(r1) /* Restore original registers */ >> 149 lwz r3,GPR3(r1) >> 150 lwz r4,GPR4(r1) >> 151 lwz r5,GPR5(r1) >> 152 lwz r6,GPR6(r1) >> 153 lwz r7,GPR7(r1) >> 154 lwz r8,GPR8(r1) >> 155 lwz r9,GPR9(r1) >> 156 cmpli 0,r0,NR_syscalls >> 157 bge- 66f >> 158 lis r10,sys_call_table@h >> 159 ori r10,r10,sys_call_table@l >> 160 slwi r0,r0,2 >> 161 lwzx r10,r10,r0 /* Fetch system call handler [ptr] */ >> 162 cmpi 0,r10,0 >> 163 beq- 66f >> 164 mtlr r10 >> 165 addi r9,r1,STACK_FRAME_OVERHEAD >> 166 blrl /* Call handler */ >> 167 .globl ret_from_syscall_2 >> 168 ret_from_syscall_2: >> 169 stw r3,RESULT(r1) /* Save result */ >> 170 li r10,-_LAST_ERRNO >> 171 cmpl 0,r3,r10 >> 172 blt 60f >> 173 neg r3,r3 >> 174 cmpi 0,r3,ERESTARTNOHAND >> 175 bne 52f >> 176 li r3,EINTR >> 177 52: lwz r10,_CCR(r1) /* Set SO bit in CR */ >> 178 oris r10,r10,0x1000 >> 179 stw r10,_CCR(r1) >> 180 60: stw r3,GPR3(r1) /* Update return value */ >> 181 bl syscall_trace >> 182 b ret_from_except >> 183 66: li r3,ENOSYS >> 184 b 52b >> 185 #ifdef SHOW_SYSCALLS >> 186 7: .string "syscall %d(%x, %x, %x, %x, %x, " >> 187 77: .string "%x, %x), current=%p\n" >> 188 79: .string " -> %x\n" >> 189 .align 2,0 >> 190 #endif 172 191 173 /********************************************* << 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 << 249 call do_syscall_trace_enter << 250 RESTORE_SWITCH_STACK << 251 << 252 /* Create system call register argumen << 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 << 292 call do_syscall_trace_exit << 293 RESTORE_SWITCH_STACK << 294 br ret_from_exception << 295 << 296 /* If the syscall number was invalid r << 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 << 317 call do_notify_resume << 318 beq r2, r0, no_work_pending << 319 RESTORE_SWITCH_STACK << 320 /* prepare restart syscall here withou << 321 ldw r2, PT_R2(sp) /* reload sysc << 322 ldw r4, PT_R4(sp) /* reload sysc << 323 ldw r5, PT_R5(sp) << 324 ldw r6, PT_R6(sp) << 325 ldw r7, PT_R7(sp) << 326 ldw r8, PT_R8(sp) << 327 ldw r9, PT_R9(sp) << 328 br local_restart /* restart sys << 329 << 330 no_work_pending: << 331 RESTORE_SWITCH_STACK << 332 br ret_from_exception << 333 << 334 /********************************************* << 335 * Handle external interrupts. << 336 ********************************************* << 337 */ << 338 /* 192 /* 339 * This is the generic interrupt handler (for !! 193 * This routine switches between two different tasks. The process 340 * sources). It figures out the vector number !! 194 * state of one is saved on its kernel stack. Then the state 341 * interrupt service routine directly. !! 195 * of the other is restored from its kernel stack. The memory >> 196 * management hardware is updated to the second process's state. >> 197 * Finally, we can return to the second process. >> 198 * On entry, r3 points to the THREAD for the current task, r4 >> 199 * points to the THREAD for the new task. >> 200 * >> 201 * Note: there are two ways to get to the "going out" portion >> 202 * of this code; either by coming in via the entry (_switch) >> 203 * or via "fork" which must set up an environment equivalent >> 204 * to the "_switch" path. If you change this , you'll have to >> 205 * change the fork code also. >> 206 * >> 207 * The code which creates the new task context is in 'copy_thread' >> 208 * in arch/ppc/kernel/process.c 342 */ 209 */ 343 external_interrupt: !! 210 _GLOBAL(_switch) 344 rdctl r12, ipending !! 211 stwu r1,-INT_FRAME_SIZE(r1) 345 rdctl r9, ienable !! 212 stw r0,GPR0(r1) 346 and r12, r12, r9 !! 213 lwz r0,0(r1) 347 /* skip if no interrupt is pending */ !! 214 stw r0,GPR1(r1) 348 beq r12, r0, ret_from_interrupt !! 215 /* r3-r13 are caller saved -- Cort */ >> 216 SAVE_GPR(2, r1) >> 217 SAVE_8GPRS(14, r1) >> 218 SAVE_10GPRS(22, r1) >> 219 mflr r20 /* Return to switch caller */ >> 220 stw r20,INT_FRAME_SIZE+4(r1) >> 221 mfmsr r22 >> 222 li r0,MSR_FP /* Disable floating-point */ >> 223 #ifdef CONFIG_ALTIVEC >> 224 BEGIN_FTR_SECTION >> 225 oris r0,r0,MSR_VEC@h /* Disable altivec */ >> 226 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) >> 227 #endif /* CONFIG_ALTIVEC */ >> 228 and. r0,r0,r22 /* FP or altivec enabled? */ >> 229 beq+ 1f >> 230 andc r22,r22,r0 >> 231 mtmsr r22 >> 232 isync >> 233 1: stw r20,_NIP(r1) >> 234 stw r22,_MSR(r1) >> 235 stw r20,_LINK(r1) >> 236 mfcr r20 >> 237 mfctr r22 >> 238 mfspr r23,XER >> 239 stw r20,_CCR(r1) >> 240 stw r22,_CTR(r1) >> 241 stw r23,_XER(r1) >> 242 li r0,0x0ff0 >> 243 stw r0,TRAP(r1) >> 244 stw r1,KSP(r3) /* Set old stack pointer */ >> 245 >> 246 tophys(r0,r4) >> 247 CLR_TOP32(r0) >> 248 mtspr SPRG3,r0 /* Update current THREAD phys addr */ >> 249 lwz r1,KSP(r4) /* Load new stack pointer */ >> 250 /* save the old current 'last' for return value */ >> 251 mr r3,r2 >> 252 addi r2,r4,-THREAD /* Update current */ >> 253 lwz r0,_CCR(r1) >> 254 mtcrf 0xFF,r0 >> 255 /* r3-r13 are destroyed -- Cort */ >> 256 REST_2GPRS(14, r1) >> 257 REST_8GPRS(16, r1) >> 258 REST_8GPRS(24, r1) >> 259 >> 260 lwz r4,_NIP(r1) /* Return to _switch caller in new task */ >> 261 mtlr r4 >> 262 addi r1,r1,INT_FRAME_SIZE >> 263 blr >> 264 >> 265 .globl syscall_direct_return >> 266 syscall_direct_return: >> 267 addi r1,r3,-STACK_FRAME_OVERHEAD >> 268 lwz r10,TASK_PTRACE(r2) >> 269 andi. r10,r10,PT_TRACESYS >> 270 beq+ ret_from_except >> 271 bl syscall_trace >> 272 b ret_from_except >> 273 >> 274 .globl ret_from_fork >> 275 ret_from_fork: >> 276 bl schedule_tail >> 277 lwz r0,TASK_PTRACE(r2) >> 278 andi. r0,r0,PT_TRACESYS >> 279 bnel- syscall_trace >> 280 b ret_from_except 349 281 >> 282 .globl ret_from_intercept >> 283 ret_from_intercept: 350 /* 284 /* 351 * Process an external hardware interr !! 285 * We may be returning from RTL and cannot do the normal checks >> 286 * -- Cort 352 */ 287 */ >> 288 cmpi 0,r3,0 >> 289 beq restore >> 290 .globl ret_from_except >> 291 ret_from_except: >> 292 lwz r3,_MSR(r1) /* Returning to user mode? */ >> 293 andi. r3,r3,MSR_PR >> 294 beq+ do_signal_ret /* if so, check need_resched and signals */ >> 295 lwz r3,NEED_RESCHED(r2) >> 296 cmpi 0,r3,0 /* check need_resched flag */ >> 297 beq+ 7f >> 298 bl schedule >> 299 7: lwz r5,SIGPENDING(r2) /* Check for pending unblocked signals */ >> 300 cmpwi 0,r5,0 >> 301 beq+ do_signal_ret >> 302 li r3,0 >> 303 addi r4,r1,STACK_FRAME_OVERHEAD >> 304 bl do_signal >> 305 .globl do_signal_ret >> 306 do_signal_ret: >> 307 .globl ret_to_user_hook >> 308 ret_to_user_hook: >> 309 nop >> 310 restore: >> 311 lwz r3,_XER(r1) >> 312 mtspr XER,r3 >> 313 REST_10GPRS(9,r1) >> 314 REST_10GPRS(19,r1) >> 315 REST_2GPRS(29,r1) >> 316 REST_GPR(31,r1) 353 317 354 addi ea, ea, -4 /* re-issue th !! 318 /* make sure we hard disable here, even if rtl is active, to protect 355 stw ea, PT_EA(sp) !! 319 * SRR[01] and SPRG2 -- Cort 356 2: movi r4, %lo(-1) /* Start from !! 320 */ 357 highes !! 321 mfmsr r0 /* Get current interrupt state */ 358 /* This is the !! 322 rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */ 359 1: andi r10, r12, 1 /* Isolate bit !! 323 #ifdef CONFIG_4xx 360 srli r12, r12, 1 /* shift count !! 324 rlwinm r0,r0,0,23,21 /* clear MSR_DE in r0 */ 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 325 #endif 387 br restore_all !! 326 SYNC /* Some chip revs have problems here... */ >> 327 mtmsr r0 /* Update machine state */ 388 328 389 /********************************************* !! 329 PPC405_ERR77(0,r1) 390 * A few syscall wrappers !! 330 stwcx. r0,0,r1 /* to clear the reservation */ 391 ********************************************* << 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 << 400 subi sp, sp, 4 /* make space for tl << 401 stw r8, 0(sp) /* pass tls pointer << 402 call nios2_clone << 403 addi sp, sp, 4 << 404 RESTORE_SWITCH_STACK << 405 ret << 406 << 407 ENTRY(sys_rt_sigreturn) << 408 SAVE_SWITCH_STACK << 409 mov r4, sp << 410 call do_rt_sigreturn << 411 RESTORE_SWITCH_STACK << 412 addi ra, ra, (end_translate_rc_and_ << 413 ret << 414 << 415 /********************************************* << 416 * A few other wrappers and stubs << 417 ********************************************* << 418 */ << 419 protection_exception_pte: << 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 << 438 #ifdef CONFIG_NIOS2_ALIGNMENT_TRAP << 439 handle_unaligned: << 440 SAVE_SWITCH_STACK << 441 call handle_unaligned_c << 442 RESTORE_SWITCH_STACK << 443 br ret_from_exception << 444 #else << 445 handle_unaligned: << 446 call handle_unaligned_c << 447 br ret_from_exception << 448 #endif << 449 331 450 handle_illegal: !! 332 /* if returning to user mode, set new sprg2 and save kernel SP */ 451 call handle_illegal_c !! 333 lwz r0,_MSR(r1) 452 br ret_from_exception !! 334 andi. r0,r0,MSR_PR 453 !! 335 beq+ 1f 454 handle_diverror: !! 336 #ifdef CONFIG_ALTIVEC 455 call handle_diverror_c !! 337 BEGIN_FTR_SECTION 456 br ret_from_exception !! 338 lwz r0,THREAD+THREAD_VRSAVE(r2) 457 !! 339 mtspr SPRN_VRSAVE,r0 /* if G4, restore VRSAVE reg */ 458 #ifdef CONFIG_KGDB !! 340 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) 459 handle_kgdb_breakpoint: !! 341 #endif /* CONFIG_ALTIVEC */ 460 call kgdb_breakpoint_c !! 342 #if defined(CONFIG_4xx) && !defined(CONFIG_BDI_SWITCH) 461 br ret_from_exception !! 343 /* Restore the processor debugging state of the thread. Only do >> 344 * this if we aren't using an Abatron BDI JTAG debugger. It doesn't >> 345 * tolerate others mucking with the debug registers. >> 346 */ >> 347 lwz r0,THREAD+THREAD_DBCR0(r2) >> 348 mtspr SPRN_DBCR0,r0 462 #endif 349 #endif >> 350 addi r0,r1,INT_FRAME_SIZE /* size of frame */ >> 351 stw r0,THREAD+KSP(r2) /* save kernel stack pointer */ >> 352 tophys(r8,r1) >> 353 CLR_TOP32(r8) >> 354 mtspr SPRG2,r8 /* phys exception stack pointer */ >> 355 1: >> 356 lwz r3,_CTR(r1) >> 357 lwz r0,_LINK(r1) >> 358 mtctr r3 >> 359 mtlr r0 >> 360 REST_4GPRS(3, r1) >> 361 REST_2GPRS(7, r1) >> 362 >> 363 #ifndef CONFIG_SMP >> 364 /* We have to "dummy" load from the context save area in case >> 365 * these instructions cause an MMU fault. If this happens >> 366 * after we load SRR0/SRR1, our return context is hosed. -- Dan >> 367 * >> 368 * This workaround is not enough, we must also make sure the >> 369 * actual code for this routine is in the TLB or BAT mapped. >> 370 * For 6xx/Power3, we know the code is in a BAT, so this should >> 371 * be enough in UP. In SMP, I limit lowmem to the amount of >> 372 * RAM that can be BAT mapped. Other CPUs may need additional >> 373 * tweaks, especially if used SMP or if the code for this routine >> 374 * crosses page boundaries. The TLB pin down for 4xx should help >> 375 * for example. --BenH. >> 376 */ >> 377 lwz r0,GPR0(r1) >> 378 lwz r0,GPR2(r1) >> 379 lwz r0,GPR1(r1) >> 380 #endif /* ndef CONFIG_SMP */ >> 381 >> 382 /* We re-use r3,r4 here (the load above was to cause the MMU >> 383 * fault if necessary). Using r3,r4 removes the need to "dummy" >> 384 * load the CCR and NIP. Since we load them we may as well >> 385 * use them. >> 386 */ >> 387 lwz r3,_CCR(r1) >> 388 lwz r4,_NIP(r1) >> 389 >> 390 lwz r0,_MSR(r1) >> 391 FIX_SRR1(r0,r2) >> 392 mtspr SRR1,r0 >> 393 mtcrf 0xFF,r3 >> 394 mtspr SRR0,r4 >> 395 lwz r0,GPR0(r1) >> 396 lwz r2,GPR2(r1) >> 397 lwz r3,GPR3(r1) >> 398 lwz r4,GPR4(r1) >> 399 lwz r1,GPR1(r1) >> 400 SYNC >> 401 PPC405_ERR77_SYNC >> 402 RFI 463 403 464 handle_trap_1: << 465 call handle_trap_1_c << 466 br ret_from_exception << 467 << 468 handle_trap_2: << 469 call handle_trap_2_c << 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 404 477 /* 405 /* 478 * Beware - when entering resume, prev (the cu !! 406 * PROM code for specific machines follows. Put it 479 * in r4, next (the new task) is in r5, don't !! 407 * here so it's easy to add arch-specific sections later. 480 * registers. !! 408 * -- Cort 481 */ 409 */ 482 ENTRY(resume) !! 410 #if defined(CONFIG_ALL_PPC) 483 << 484 rdctl r7, status << 485 stw r7, TASK_THREAD + THREAD_KPSR( << 486 << 487 andi r7, r7, %lo(~STATUS_PIE) << 488 wrctl status, r7 << 489 << 490 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 << 502 ENTRY(ret_from_fork) << 503 call schedule_tail << 504 br ret_from_exception << 505 << 506 ENTRY(ret_from_kernel_thread) << 507 call schedule_tail << 508 mov r4,r17 /* arg */ << 509 callr r16 /* function */ << 510 br ret_from_exception << 511 << 512 /* 411 /* 513 * Kernel user helpers. !! 412 * On CHRP, the Run-Time Abstraction Services (RTAS) have to be 514 * !! 413 * called with the MMU off. 515 * Each segment is 64-byte aligned and will be << 516 * New segments (if ever needed) must be added << 517 * This mechanism should be used only for thin << 518 * justified, and not be abused freely. << 519 * << 520 */ 414 */ 521 !! 415 .globl enter_rtas 522 /* Filling pads with undefined instructions. !! 416 enter_rtas: 523 .macro kuser_pad sym size !! 417 mflr r0 524 .if ((. - \sym) & 3) !! 418 stw r0,20(r1) 525 .rept (4 - (. - \sym) & 3) !! 419 lis r4,rtas_data@ha 526 .byte 0 !! 420 lwz r4,rtas_data@l(r4) 527 .endr !! 421 lis r6,1f@ha /* physical return address for rtas */ 528 .endif !! 422 addi r6,r6,1f@l 529 .rept ((\size - (. - \sym)) / 4) !! 423 addis r6,r6,-KERNELBASE@h 530 .word 0xdeadbeef !! 424 subi r7,r1,INT_FRAME_SIZE 531 .endr !! 425 addis r7,r7,-KERNELBASE@h 532 .endm !! 426 lis r8,rtas_entry@ha 533 !! 427 lwz r8,rtas_entry@l(r8) 534 .align 6 !! 428 mfmsr r9 535 .globl __kuser_helper_start !! 429 stw r9,8(r1) 536 __kuser_helper_start: !! 430 li r0,0 537 !! 431 ori r0,r0,MSR_EE|MSR_SE|MSR_BE|MSR_FE0|MSR_FE1 538 __kuser_helper_version: !! 432 andc r0,r9,r0 539 .word ((__kuser_helper_end - __kuser !! 433 li r10,MSR_IR|MSR_DR|MSR_FP 540 !! 434 andc r9,r0,r10 541 __kuser_cmpxchg: !! 435 SYNC /* disable interrupts so SRR0/1 */ 542 /* !! 436 mtmsr r0 /* don't get trashed */ 543 * r4 pointer to exchange variable !! 437 mtlr r6 544 * r5 old value !! 438 CLR_TOP32(r7) 545 * r6 new value !! 439 mtspr SPRG2,r7 546 */ !! 440 mtspr SRR0,r8 547 cmpxchg_ldw: !! 441 mtspr SRR1,r9 548 ldw r2, 0(r4) !! 442 RFI 549 sub r2, r2, r5 !! 443 1: addis r9,r1,-KERNELBASE@h 550 bne r2, zero, cmpxchg_ret !! 444 lwz r8,20(r9) /* get return address */ 551 !! 445 lwz r9,8(r9) /* original msr value */ 552 /* We had a match, store the new value !! 446 FIX_SRR1(r9,r0) 553 cmpxchg_stw: !! 447 li r0,0 554 stw r6, 0(r4) !! 448 mtspr SPRG2,r0 555 cmpxchg_ret: !! 449 mtspr SRR0,r8 556 ret !! 450 mtspr SRR1,r9 557 !! 451 RFI /* return to caller */ 558 kuser_pad __kuser_cmpxchg, 64 !! 452 #endif /* CONFIG_ALL_PPC */ 559 << 560 .globl __kuser_sigtramp << 561 __kuser_sigtramp: << 562 movi r2, __NR_rt_sigreturn << 563 trap << 564 << 565 kuser_pad __kuser_sigtramp, 64 << 566 << 567 .globl __kuser_helper_end << 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.