diff options
Diffstat (limited to 'arch/powerpc/kernel/entry_64.S')
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 101 |
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 */ | ||
173 | 1: ld r2,GPR2(r1) | 175 | 1: 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 | ||
222 | 0: 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: | |||
227 | 2: andi. r0,r9,(_TIF_PERSYSCALL_MASK) | 231 | 2: 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 | ||
242 | 4: bl .save_nvgprs | 244 | 4: /* 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 */ | ||
256 | save_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 */ | ||
266 | 5: 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 | |||
284 | save_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 | |||
304 | save_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 | |||
320 | save_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) |
540 | 1: | 491 | 1: |
541 | ld r3,_CTR(r1) | 492 | ld r3,_CTR(r1) |