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.S101
1 files changed, 26 insertions, 75 deletions
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 79a0c910f0d8..1060155d84c3 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -61,6 +61,7 @@ system_call_common:
61 std r12,_MSR(r1) 61 std r12,_MSR(r1)
62 std r0,GPR0(r1) 62 std r0,GPR0(r1)
63 std r10,GPR1(r1) 63 std r10,GPR1(r1)
64 ACCOUNT_CPU_USER_ENTRY(r10, r11)
64 std r2,GPR2(r1) 65 std r2,GPR2(r1)
65 std r3,GPR3(r1) 66 std r3,GPR3(r1)
66 std r4,GPR4(r1) 67 std r4,GPR4(r1)
@@ -158,7 +159,7 @@ syscall_exit:
158 mtmsrd r10,1 159 mtmsrd r10,1
159 ld r9,TI_FLAGS(r12) 160 ld r9,TI_FLAGS(r12)
160 li r11,-_LAST_ERRNO 161 li r11,-_LAST_ERRNO
161 andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR|_TIF_RESTORE_SIGMASK) 162 andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK)
162 bne- syscall_exit_work 163 bne- syscall_exit_work
163 cmpld r3,r11 164 cmpld r3,r11
164 ld r5,_CCR(r1) 165 ld r5,_CCR(r1)
@@ -168,8 +169,9 @@ syscall_error_cont:
168 stdcx. r0,0,r1 /* to clear the reservation */ 169 stdcx. r0,0,r1 /* to clear the reservation */
169 andi. r6,r8,MSR_PR 170 andi. r6,r8,MSR_PR
170 ld r4,_LINK(r1) 171 ld r4,_LINK(r1)
171 beq- 1f /* only restore r13 if */ 172 beq- 1f
172 ld r13,GPR13(r1) /* returning to usermode */ 173 ACCOUNT_CPU_USER_EXIT(r11, r12)
174 ld r13,GPR13(r1) /* only restore r13 if returning to usermode */
1731: ld r2,GPR2(r1) 1751: ld r2,GPR2(r1)
174 li r12,MSR_RI 176 li r12,MSR_RI
175 andc r11,r10,r12 177 andc r11,r10,r12
@@ -214,8 +216,10 @@ syscall_exit_work:
214 If TIF_NOERROR is set, just save r3 as it is. */ 216 If TIF_NOERROR is set, just save r3 as it is. */
215 217
216 andi. r0,r9,_TIF_RESTOREALL 218 andi. r0,r9,_TIF_RESTOREALL
217 bne- 2f 219 beq+ 0f
218 cmpld r3,r11 /* r10 is -LAST_ERRNO */ 220 REST_NVGPRS(r1)
221 b 2f
2220: cmpld r3,r11 /* r10 is -LAST_ERRNO */
219 blt+ 1f 223 blt+ 1f
220 andi. r0,r9,_TIF_NOERROR 224 andi. r0,r9,_TIF_NOERROR
221 bne- 1f 225 bne- 1f
@@ -227,9 +231,7 @@ syscall_exit_work:
2272: andi. r0,r9,(_TIF_PERSYSCALL_MASK) 2312: andi. r0,r9,(_TIF_PERSYSCALL_MASK)
228 beq 4f 232 beq 4f
229 233
230 /* Clear per-syscall TIF flags if any are set, but _leave_ 234 /* Clear per-syscall TIF flags if any are set. */
231 _TIF_SAVE_NVGPRS set in r9 since we haven't dealt with that
232 yet. */
233 235
234 li r11,_TIF_PERSYSCALL_MASK 236 li r11,_TIF_PERSYSCALL_MASK
235 addi r12,r12,TI_FLAGS 237 addi r12,r12,TI_FLAGS
@@ -238,10 +240,9 @@ syscall_exit_work:
238 stdcx. r10,0,r12 240 stdcx. r10,0,r12
239 bne- 3b 241 bne- 3b
240 subi r12,r12,TI_FLAGS 242 subi r12,r12,TI_FLAGS
241 243
2424: bl .save_nvgprs 2444: /* Anything else left to do? */
243 /* Anything else left to do? */ 245 andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
244 andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SAVE_NVGPRS)
245 beq .ret_from_except_lite 246 beq .ret_from_except_lite
246 247
247 /* Re-enable interrupts */ 248 /* Re-enable interrupts */
@@ -249,26 +250,10 @@ syscall_exit_work:
249 ori r10,r10,MSR_EE 250 ori r10,r10,MSR_EE
250 mtmsrd r10,1 251 mtmsrd r10,1
251 252
252 andi. r0,r9,_TIF_SAVE_NVGPRS 253 bl .save_nvgprs
253 bne save_user_nvgprs
254
255 /* If tracing, re-enable interrupts and do it */
256save_user_nvgprs_cont:
257 andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
258 beq 5f
259
260 addi r3,r1,STACK_FRAME_OVERHEAD 254 addi r3,r1,STACK_FRAME_OVERHEAD
261 bl .do_syscall_trace_leave 255 bl .do_syscall_trace_leave
262 REST_NVGPRS(r1) 256 b .ret_from_except
263 clrrdi r12,r1,THREAD_SHIFT
264
265 /* Disable interrupts again and handle other work if any */
2665: mfmsr r10
267 rldicl r10,r10,48,1
268 rotldi r10,r10,16
269 mtmsrd r10,1
270
271 b .ret_from_except_lite
272 257
273/* Save non-volatile GPRs, if not already saved. */ 258/* Save non-volatile GPRs, if not already saved. */
274_GLOBAL(save_nvgprs) 259_GLOBAL(save_nvgprs)
@@ -280,51 +265,6 @@ _GLOBAL(save_nvgprs)
280 std r0,_TRAP(r1) 265 std r0,_TRAP(r1)
281 blr 266 blr
282 267
283
284save_user_nvgprs:
285 ld r10,TI_SIGFRAME(r12)
286 andi. r0,r9,_TIF_32BIT
287 beq- save_user_nvgprs_64
288
289 /* 32-bit save to userspace */
290
291.macro savewords start, end
292 1: stw \start,4*(\start)(r10)
293 .section __ex_table,"a"
294 .align 3
295 .llong 1b,save_user_nvgprs_fault
296 .previous
297 .if \end - \start
298 savewords "(\start+1)",\end
299 .endif
300.endm
301 savewords 14,31
302 b save_user_nvgprs_cont
303
304save_user_nvgprs_64:
305 /* 64-bit save to userspace */
306
307.macro savelongs start, end
308 1: std \start,8*(\start)(r10)
309 .section __ex_table,"a"
310 .align 3
311 .llong 1b,save_user_nvgprs_fault
312 .previous
313 .if \end - \start
314 savelongs "(\start+1)",\end
315 .endif
316.endm
317 savelongs 14,31
318 b save_user_nvgprs_cont
319
320save_user_nvgprs_fault:
321 li r3,11 /* SIGSEGV */
322 ld r4,TI_TASK(r12)
323 bl .force_sigsegv
324
325 clrrdi r12,r1,THREAD_SHIFT
326 ld r9,TI_FLAGS(r12)
327 b save_user_nvgprs_cont
328 268
329/* 269/*
330 * The sigsuspend and rt_sigsuspend system calls can call do_signal 270 * The sigsuspend and rt_sigsuspend system calls can call do_signal
@@ -350,6 +290,16 @@ _GLOBAL(ppc_clone)
350 bl .sys_clone 290 bl .sys_clone
351 b syscall_exit 291 b syscall_exit
352 292
293_GLOBAL(ppc32_swapcontext)
294 bl .save_nvgprs
295 bl .compat_sys_swapcontext
296 b syscall_exit
297
298_GLOBAL(ppc64_swapcontext)
299 bl .save_nvgprs
300 bl .sys_swapcontext
301 b syscall_exit
302
353_GLOBAL(ret_from_fork) 303_GLOBAL(ret_from_fork)
354 bl .schedule_tail 304 bl .schedule_tail
355 REST_NVGPRS(r1) 305 REST_NVGPRS(r1)
@@ -536,6 +486,7 @@ restore:
536 * userspace 486 * userspace
537 */ 487 */
538 beq 1f 488 beq 1f
489 ACCOUNT_CPU_USER_EXIT(r3, r4)
539 REST_GPR(13, r1) 490 REST_GPR(13, r1)
5401: 4911:
541 ld r3,_CTR(r1) 492 ld r3,_CTR(r1)