aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/entry_64.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/entry_64.S')
-rw-r--r--arch/powerpc/kernel/entry_64.S218
1 files changed, 117 insertions, 101 deletions
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index bce33a38399..aacebb33e98 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -113,9 +113,7 @@ system_call_common:
113 addi r9,r1,STACK_FRAME_OVERHEAD 113 addi r9,r1,STACK_FRAME_OVERHEAD
114#endif 114#endif
115 clrrdi r11,r1,THREAD_SHIFT 115 clrrdi r11,r1,THREAD_SHIFT
116 li r12,0
117 ld r10,TI_FLAGS(r11) 116 ld r10,TI_FLAGS(r11)
118 stb r12,TI_SC_NOERR(r11)
119 andi. r11,r10,_TIF_SYSCALL_T_OR_A 117 andi. r11,r10,_TIF_SYSCALL_T_OR_A
120 bne- syscall_dotrace 118 bne- syscall_dotrace
121syscall_dotrace_cont: 119syscall_dotrace_cont:
@@ -144,24 +142,12 @@ system_call: /* label this so stack traces look sane */
144 bctrl /* Call handler */ 142 bctrl /* Call handler */
145 143
146syscall_exit: 144syscall_exit:
145 std r3,RESULT(r1)
147#ifdef SHOW_SYSCALLS 146#ifdef SHOW_SYSCALLS
148 std r3,GPR3(r1)
149 bl .do_show_syscall_exit 147 bl .do_show_syscall_exit
150 ld r3,GPR3(r1) 148 ld r3,RESULT(r1)
151#endif 149#endif
152 std r3,RESULT(r1)
153 ld r5,_CCR(r1)
154 li r10,-_LAST_ERRNO
155 cmpld r3,r10
156 clrrdi r12,r1,THREAD_SHIFT 150 clrrdi r12,r1,THREAD_SHIFT
157 bge- syscall_error
158syscall_error_cont:
159
160 /* check for syscall tracing or audit */
161 ld r9,TI_FLAGS(r12)
162 andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
163 bne- syscall_exit_trace
164syscall_exit_trace_cont:
165 151
166 /* disable interrupts so current_thread_info()->flags can't change, 152 /* disable interrupts so current_thread_info()->flags can't change,
167 and so that we don't get interrupted after loading SRR0/1. */ 153 and so that we don't get interrupted after loading SRR0/1. */
@@ -173,8 +159,13 @@ syscall_exit_trace_cont:
173 rotldi r10,r10,16 159 rotldi r10,r10,16
174 mtmsrd r10,1 160 mtmsrd r10,1
175 ld r9,TI_FLAGS(r12) 161 ld r9,TI_FLAGS(r12)
176 andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED) 162 li r11,-_LAST_ERRNO
163 andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR)
177 bne- syscall_exit_work 164 bne- syscall_exit_work
165 cmpld r3,r11
166 ld r5,_CCR(r1)
167 bge- syscall_error
168syscall_error_cont:
178 ld r7,_NIP(r1) 169 ld r7,_NIP(r1)
179 stdcx. r0,0,r1 /* to clear the reservation */ 170 stdcx. r0,0,r1 /* to clear the reservation */
180 andi. r6,r8,MSR_PR 171 andi. r6,r8,MSR_PR
@@ -193,21 +184,12 @@ syscall_exit_trace_cont:
193 rfid 184 rfid
194 b . /* prevent speculative execution */ 185 b . /* prevent speculative execution */
195 186
196syscall_enosys: 187syscall_error:
197 li r3,-ENOSYS
198 std r3,RESULT(r1)
199 clrrdi r12,r1,THREAD_SHIFT
200 ld r5,_CCR(r1)
201
202syscall_error:
203 lbz r11,TI_SC_NOERR(r12)
204 cmpwi 0,r11,0
205 bne- syscall_error_cont
206 neg r3,r3
207 oris r5,r5,0x1000 /* Set SO bit in CR */ 188 oris r5,r5,0x1000 /* Set SO bit in CR */
189 neg r3,r3
208 std r5,_CCR(r1) 190 std r5,_CCR(r1)
209 b syscall_error_cont 191 b syscall_error_cont
210 192
211/* Traced system call support */ 193/* Traced system call support */
212syscall_dotrace: 194syscall_dotrace:
213 bl .save_nvgprs 195 bl .save_nvgprs
@@ -225,21 +207,69 @@ syscall_dotrace:
225 ld r10,TI_FLAGS(r10) 207 ld r10,TI_FLAGS(r10)
226 b syscall_dotrace_cont 208 b syscall_dotrace_cont
227 209
228syscall_exit_trace: 210syscall_enosys:
229 std r3,GPR3(r1) 211 li r3,-ENOSYS
230 bl .save_nvgprs 212 b syscall_exit
213
214syscall_exit_work:
215 /* If TIF_RESTOREALL is set, don't scribble on either r3 or ccr.
216 If TIF_NOERROR is set, just save r3 as it is. */
217
218 andi. r0,r9,_TIF_RESTOREALL
219 bne- 2f
220 cmpld r3,r11 /* r10 is -LAST_ERRNO */
221 blt+ 1f
222 andi. r0,r9,_TIF_NOERROR
223 bne- 1f
224 ld r5,_CCR(r1)
225 neg r3,r3
226 oris r5,r5,0x1000 /* Set SO bit in CR */
227 std r5,_CCR(r1)
2281: std r3,GPR3(r1)
2292: andi. r0,r9,(_TIF_PERSYSCALL_MASK)
230 beq 4f
231
232 /* Clear per-syscall TIF flags if any are set, but _leave_
233 _TIF_SAVE_NVGPRS set in r9 since we haven't dealt with that
234 yet. */
235
236 li r11,_TIF_PERSYSCALL_MASK
237 addi r12,r12,TI_FLAGS
2383: ldarx r10,0,r12
239 andc r10,r10,r11
240 stdcx. r10,0,r12
241 bne- 3b
242 subi r12,r12,TI_FLAGS
243
2444: bl .save_nvgprs
245 /* Anything else left to do? */
246 andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SAVE_NVGPRS)
247 beq .ret_from_except_lite
248
249 /* Re-enable interrupts */
250 mfmsr r10
251 ori r10,r10,MSR_EE
252 mtmsrd r10,1
253
254 andi. r0,r9,_TIF_SAVE_NVGPRS
255 bne save_user_nvgprs
256
257 /* If tracing, re-enable interrupts and do it */
258save_user_nvgprs_cont:
259 andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
260 beq 5f
261
231 addi r3,r1,STACK_FRAME_OVERHEAD 262 addi r3,r1,STACK_FRAME_OVERHEAD
232 bl .do_syscall_trace_leave 263 bl .do_syscall_trace_leave
233 REST_NVGPRS(r1) 264 REST_NVGPRS(r1)
234 ld r3,GPR3(r1)
235 ld r5,_CCR(r1)
236 clrrdi r12,r1,THREAD_SHIFT 265 clrrdi r12,r1,THREAD_SHIFT
237 b syscall_exit_trace_cont
238 266
239/* Stuff to do on exit from a system call. */ 267 /* Disable interrupts again and handle other work if any */
240syscall_exit_work: 2685: mfmsr r10
241 std r3,GPR3(r1) 269 rldicl r10,r10,48,1
242 std r5,_CCR(r1) 270 rotldi r10,r10,16
271 mtmsrd r10,1
272
243 b .ret_from_except_lite 273 b .ret_from_except_lite
244 274
245/* Save non-volatile GPRs, if not already saved. */ 275/* Save non-volatile GPRs, if not already saved. */
@@ -252,6 +282,52 @@ _GLOBAL(save_nvgprs)
252 std r0,_TRAP(r1) 282 std r0,_TRAP(r1)
253 blr 283 blr
254 284
285
286save_user_nvgprs:
287 ld r10,TI_SIGFRAME(r12)
288 andi. r0,r9,_TIF_32BIT
289 beq- save_user_nvgprs_64
290
291 /* 32-bit save to userspace */
292
293.macro savewords start, end
294 1: stw \start,4*(\start)(r10)
295 .section __ex_table,"a"
296 .align 3
297 .llong 1b,save_user_nvgprs_fault
298 .previous
299 .if \end - \start
300 savewords "(\start+1)",\end
301 .endif
302.endm
303 savewords 14,31
304 b save_user_nvgprs_cont
305
306save_user_nvgprs_64:
307 /* 64-bit save to userspace */
308
309.macro savelongs start, end
310 1: std \start,8*(\start)(r10)
311 .section __ex_table,"a"
312 .align 3
313 .llong 1b,save_user_nvgprs_fault
314 .previous
315 .if \end - \start
316 savelongs "(\start+1)",\end
317 .endif
318.endm
319 savelongs 14,31
320 b save_user_nvgprs_cont
321
322save_user_nvgprs_fault:
323 li r3,11 /* SIGSEGV */
324 ld r4,TI_TASK(r12)
325 bl .force_sigsegv
326
327 clrrdi r12,r1,THREAD_SHIFT
328 ld r9,TI_FLAGS(r12)
329 b save_user_nvgprs_cont
330
255/* 331/*
256 * The sigsuspend and rt_sigsuspend system calls can call do_signal 332 * The sigsuspend and rt_sigsuspend system calls can call do_signal
257 * and thus put the process into the stopped state where we might 333 * and thus put the process into the stopped state where we might
@@ -260,35 +336,6 @@ _GLOBAL(save_nvgprs)
260 * the C code. Similarly, fork, vfork and clone need the full 336 * the C code. Similarly, fork, vfork and clone need the full
261 * register state on the stack so that it can be copied to the child. 337 * register state on the stack so that it can be copied to the child.
262 */ 338 */
263_GLOBAL(ppc32_sigsuspend)
264 bl .save_nvgprs
265 bl .compat_sys_sigsuspend
266 b 70f
267
268_GLOBAL(ppc64_rt_sigsuspend)
269 bl .save_nvgprs
270 bl .sys_rt_sigsuspend
271 b 70f
272
273_GLOBAL(ppc32_rt_sigsuspend)
274 bl .save_nvgprs
275 bl .compat_sys_rt_sigsuspend
27670: cmpdi 0,r3,0
277 /* If it returned an error, we need to return via syscall_exit to set
278 the SO bit in cr0 and potentially stop for ptrace. */
279 bne syscall_exit
280 /* If sigsuspend() returns zero, we are going into a signal handler. We
281 may need to call audit_syscall_exit() to mark the exit from sigsuspend() */
282#ifdef CONFIG_AUDITSYSCALL
283 ld r3,PACACURRENT(r13)
284 ld r4,AUDITCONTEXT(r3)
285 cmpdi 0,r4,0
286 beq .ret_from_except /* No audit_context: Leave immediately. */
287 li r4, 2 /* AUDITSC_FAILURE */
288 li r5,-4 /* It's always -EINTR */
289 bl .audit_syscall_exit
290#endif
291 b .ret_from_except
292 339
293_GLOBAL(ppc_fork) 340_GLOBAL(ppc_fork)
294 bl .save_nvgprs 341 bl .save_nvgprs
@@ -305,37 +352,6 @@ _GLOBAL(ppc_clone)
305 bl .sys_clone 352 bl .sys_clone
306 b syscall_exit 353 b syscall_exit
307 354
308_GLOBAL(ppc32_swapcontext)
309 bl .save_nvgprs
310 bl .compat_sys_swapcontext
311 b 80f
312
313_GLOBAL(ppc64_swapcontext)
314 bl .save_nvgprs
315 bl .sys_swapcontext
316 b 80f
317
318_GLOBAL(ppc32_sigreturn)
319 bl .compat_sys_sigreturn
320 b 80f
321
322_GLOBAL(ppc32_rt_sigreturn)
323 bl .compat_sys_rt_sigreturn
324 b 80f
325
326_GLOBAL(ppc64_rt_sigreturn)
327 bl .sys_rt_sigreturn
328
32980: cmpdi 0,r3,0
330 blt syscall_exit
331 clrrdi r4,r1,THREAD_SHIFT
332 ld r4,TI_FLAGS(r4)
333 andi. r4,r4,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
334 beq+ 81f
335 addi r3,r1,STACK_FRAME_OVERHEAD
336 bl .do_syscall_trace_leave
33781: b .ret_from_except
338
339_GLOBAL(ret_from_fork) 355_GLOBAL(ret_from_fork)
340 bl .schedule_tail 356 bl .schedule_tail
341 REST_NVGPRS(r1) 357 REST_NVGPRS(r1)
@@ -674,7 +690,7 @@ _GLOBAL(enter_rtas)
674 690
675 /* Setup our real return addr */ 691 /* Setup our real return addr */
676 SET_REG_TO_LABEL(r4,.rtas_return_loc) 692 SET_REG_TO_LABEL(r4,.rtas_return_loc)
677 SET_REG_TO_CONST(r9,KERNELBASE) 693 SET_REG_TO_CONST(r9,PAGE_OFFSET)
678 sub r4,r4,r9 694 sub r4,r4,r9
679 mtlr r4 695 mtlr r4
680 696
@@ -702,7 +718,7 @@ _GLOBAL(enter_rtas)
702_STATIC(rtas_return_loc) 718_STATIC(rtas_return_loc)
703 /* relocation is off at this point */ 719 /* relocation is off at this point */
704 mfspr r4,SPRN_SPRG3 /* Get PACA */ 720 mfspr r4,SPRN_SPRG3 /* Get PACA */
705 SET_REG_TO_CONST(r5, KERNELBASE) 721 SET_REG_TO_CONST(r5, PAGE_OFFSET)
706 sub r4,r4,r5 /* RELOC the PACA base pointer */ 722 sub r4,r4,r5 /* RELOC the PACA base pointer */
707 723
708 mfmsr r6 724 mfmsr r6