diff options
-rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_32.S | 167 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 214 | ||||
-rw-r--r-- | arch/powerpc/kernel/signal_32.c | 59 | ||||
-rw-r--r-- | arch/powerpc/kernel/signal_64.c | 23 | ||||
-rw-r--r-- | arch/powerpc/kernel/systbl.S | 10 | ||||
-rw-r--r-- | include/asm-powerpc/ptrace.h | 2 | ||||
-rw-r--r-- | include/asm-powerpc/thread_info.h | 12 |
8 files changed, 269 insertions, 222 deletions
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 91538d2445bf..3bf89d1a2de6 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -92,9 +92,9 @@ int main(void) | |||
92 | 92 | ||
93 | DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); | 93 | DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); |
94 | DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); | 94 | DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); |
95 | DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror)); | 95 | DEFINE(TI_SIGFRAME, offsetof(struct thread_info, nvgprs_frame)); |
96 | #ifdef CONFIG_PPC32 | ||
97 | DEFINE(TI_TASK, offsetof(struct thread_info, task)); | 96 | DEFINE(TI_TASK, offsetof(struct thread_info, task)); |
97 | #ifdef CONFIG_PPC32 | ||
98 | DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain)); | 98 | DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain)); |
99 | DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); | 99 | DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); |
100 | #endif /* CONFIG_PPC32 */ | 100 | #endif /* CONFIG_PPC32 */ |
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 2e99ae41723c..8fed9538f188 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -200,8 +200,6 @@ _GLOBAL(DoSyscall) | |||
200 | bl do_show_syscall | 200 | bl do_show_syscall |
201 | #endif /* SHOW_SYSCALLS */ | 201 | #endif /* SHOW_SYSCALLS */ |
202 | rlwinm r10,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ | 202 | rlwinm r10,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ |
203 | li r11,0 | ||
204 | stb r11,TI_SC_NOERR(r10) | ||
205 | lwz r11,TI_FLAGS(r10) | 203 | lwz r11,TI_FLAGS(r10) |
206 | andi. r11,r11,_TIF_SYSCALL_T_OR_A | 204 | andi. r11,r11,_TIF_SYSCALL_T_OR_A |
207 | bne- syscall_dotrace | 205 | bne- syscall_dotrace |
@@ -222,25 +220,21 @@ ret_from_syscall: | |||
222 | bl do_show_syscall_exit | 220 | bl do_show_syscall_exit |
223 | #endif | 221 | #endif |
224 | mr r6,r3 | 222 | mr r6,r3 |
225 | li r11,-_LAST_ERRNO | ||
226 | cmplw 0,r3,r11 | ||
227 | rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ | 223 | rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ |
228 | blt+ 30f | ||
229 | lbz r11,TI_SC_NOERR(r12) | ||
230 | cmpwi r11,0 | ||
231 | bne 30f | ||
232 | neg r3,r3 | ||
233 | lwz r10,_CCR(r1) /* Set SO bit in CR */ | ||
234 | oris r10,r10,0x1000 | ||
235 | stw r10,_CCR(r1) | ||
236 | |||
237 | /* disable interrupts so current_thread_info()->flags can't change */ | 224 | /* disable interrupts so current_thread_info()->flags can't change */ |
238 | 30: LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ | 225 | LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ |
239 | SYNC | 226 | SYNC |
240 | MTMSRD(r10) | 227 | MTMSRD(r10) |
241 | lwz r9,TI_FLAGS(r12) | 228 | lwz r9,TI_FLAGS(r12) |
242 | andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED) | 229 | li r8,-_LAST_ERRNO |
230 | andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL) | ||
243 | bne- syscall_exit_work | 231 | bne- syscall_exit_work |
232 | cmplw 0,r3,r8 | ||
233 | blt+ syscall_exit_cont | ||
234 | lwz r11,_CCR(r1) /* Load CR */ | ||
235 | neg r3,r3 | ||
236 | oris r11,r11,0x1000 /* Set SO bit in CR */ | ||
237 | stw r11,_CCR(r1) | ||
244 | syscall_exit_cont: | 238 | syscall_exit_cont: |
245 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) | 239 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) |
246 | /* If the process has its own DBCR0 value, load it up. The single | 240 | /* If the process has its own DBCR0 value, load it up. The single |
@@ -292,46 +286,113 @@ syscall_dotrace: | |||
292 | b syscall_dotrace_cont | 286 | b syscall_dotrace_cont |
293 | 287 | ||
294 | syscall_exit_work: | 288 | syscall_exit_work: |
295 | stw r6,RESULT(r1) /* Save result */ | 289 | andi. r0,r9,_TIF_RESTOREALL |
290 | bne- 2f | ||
291 | cmplw 0,r3,r8 | ||
292 | blt+ 1f | ||
293 | andi. r0,r9,_TIF_NOERROR | ||
294 | bne- 1f | ||
295 | lwz r11,_CCR(r1) /* Load CR */ | ||
296 | neg r3,r3 | ||
297 | oris r11,r11,0x1000 /* Set SO bit in CR */ | ||
298 | stw r11,_CCR(r1) | ||
299 | |||
300 | 1: stw r6,RESULT(r1) /* Save result */ | ||
296 | stw r3,GPR3(r1) /* Update return value */ | 301 | stw r3,GPR3(r1) /* Update return value */ |
297 | andi. r0,r9,_TIF_SYSCALL_T_OR_A | 302 | 2: andi. r0,r9,(_TIF_PERSYSCALL_MASK) |
298 | beq 5f | 303 | beq 4f |
299 | ori r10,r10,MSR_EE | 304 | |
300 | SYNC | 305 | /* Clear per-syscall TIF flags if any are set, but _leave_ |
301 | MTMSRD(r10) /* re-enable interrupts */ | 306 | _TIF_SAVE_NVGPRS set in r9 since we haven't dealt with that |
307 | yet. */ | ||
308 | |||
309 | li r11,_TIF_PERSYSCALL_MASK | ||
310 | addi r12,r12,TI_FLAGS | ||
311 | 3: lwarx r8,0,r12 | ||
312 | andc r8,r8,r11 | ||
313 | #ifdef CONFIG_IBM405_ERR77 | ||
314 | dcbt 0,r12 | ||
315 | #endif | ||
316 | stwcx. r8,0,r12 | ||
317 | bne- 3b | ||
318 | subi r12,r12,TI_FLAGS | ||
319 | |||
320 | 4: /* Anything which requires enabling interrupts? */ | ||
321 | andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SAVE_NVGPRS) | ||
322 | beq 7f | ||
323 | |||
324 | /* Save NVGPRS if they're not saved already */ | ||
302 | lwz r4,_TRAP(r1) | 325 | lwz r4,_TRAP(r1) |
303 | andi. r4,r4,1 | 326 | andi. r4,r4,1 |
304 | beq 4f | 327 | beq 5f |
305 | SAVE_NVGPRS(r1) | 328 | SAVE_NVGPRS(r1) |
306 | li r4,0xc00 | 329 | li r4,0xc00 |
307 | stw r4,_TRAP(r1) | 330 | stw r4,_TRAP(r1) |
308 | 4: | 331 | |
332 | /* Re-enable interrupts */ | ||
333 | 5: ori r10,r10,MSR_EE | ||
334 | SYNC | ||
335 | MTMSRD(r10) | ||
336 | |||
337 | andi. r0,r9,_TIF_SAVE_NVGPRS | ||
338 | bne save_user_nvgprs | ||
339 | |||
340 | save_user_nvgprs_cont: | ||
341 | andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) | ||
342 | beq 7f | ||
343 | |||
309 | addi r3,r1,STACK_FRAME_OVERHEAD | 344 | addi r3,r1,STACK_FRAME_OVERHEAD |
310 | bl do_syscall_trace_leave | 345 | bl do_syscall_trace_leave |
311 | REST_NVGPRS(r1) | 346 | REST_NVGPRS(r1) |
312 | 2: | 347 | |
313 | lwz r3,GPR3(r1) | 348 | 6: lwz r3,GPR3(r1) |
314 | LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ | 349 | LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ |
315 | SYNC | 350 | SYNC |
316 | MTMSRD(r10) /* disable interrupts again */ | 351 | MTMSRD(r10) /* disable interrupts again */ |
317 | rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ | 352 | rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ |
318 | lwz r9,TI_FLAGS(r12) | 353 | lwz r9,TI_FLAGS(r12) |
319 | 5: | 354 | 7: |
320 | andi. r0,r9,_TIF_NEED_RESCHED | 355 | andi. r0,r9,_TIF_NEED_RESCHED |
321 | bne 1f | 356 | bne 8f |
322 | lwz r5,_MSR(r1) | 357 | lwz r5,_MSR(r1) |
323 | andi. r5,r5,MSR_PR | 358 | andi. r5,r5,MSR_PR |
324 | beq syscall_exit_cont | 359 | beq ret_from_except |
325 | andi. r0,r9,_TIF_SIGPENDING | 360 | andi. r0,r9,_TIF_SIGPENDING |
326 | beq syscall_exit_cont | 361 | beq ret_from_except |
327 | b do_user_signal | 362 | b do_user_signal |
328 | 1: | 363 | 8: |
329 | ori r10,r10,MSR_EE | 364 | ori r10,r10,MSR_EE |
330 | SYNC | 365 | SYNC |
331 | MTMSRD(r10) /* re-enable interrupts */ | 366 | MTMSRD(r10) /* re-enable interrupts */ |
332 | bl schedule | 367 | bl schedule |
333 | b 2b | 368 | b 6b |
369 | |||
370 | save_user_nvgprs: | ||
371 | ld r8,TI_SIGFRAME(r12) | ||
372 | |||
373 | .macro savewords start, end | ||
374 | 1: stw \start,4*(\start)(r8) | ||
375 | .section __ex_table,"a" | ||
376 | .align 2 | ||
377 | .long 1b,save_user_nvgprs_fault | ||
378 | .previous | ||
379 | .if \end - \start | ||
380 | savewords "(\start+1)",\end | ||
381 | .endif | ||
382 | .endm | ||
383 | savewords 14,31 | ||
384 | b save_user_nvgprs_cont | ||
385 | |||
386 | |||
387 | save_user_nvgprs_fault: | ||
388 | li r3,11 /* SIGSEGV */ | ||
389 | ld r4,TI_TASK(r12) | ||
390 | bl force_sigsegv | ||
334 | 391 | ||
392 | rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ | ||
393 | ld r9,TI_FLAGS(r12) | ||
394 | b save_user_nvgprs_cont | ||
395 | |||
335 | #ifdef SHOW_SYSCALLS | 396 | #ifdef SHOW_SYSCALLS |
336 | do_show_syscall: | 397 | do_show_syscall: |
337 | #ifdef SHOW_SYSCALLS_TASK | 398 | #ifdef SHOW_SYSCALLS_TASK |
@@ -401,28 +462,10 @@ show_syscalls_task: | |||
401 | #endif /* SHOW_SYSCALLS */ | 462 | #endif /* SHOW_SYSCALLS */ |
402 | 463 | ||
403 | /* | 464 | /* |
404 | * The sigsuspend and rt_sigsuspend system calls can call do_signal | 465 | * The fork/clone functions need to copy the full register set into |
405 | * and thus put the process into the stopped state where we might | 466 | * the child process. Therefore we need to save all the nonvolatile |
406 | * want to examine its user state with ptrace. Therefore we need | 467 | * registers (r13 - r31) before calling the C code. |
407 | * to save all the nonvolatile registers (r13 - r31) before calling | ||
408 | * the C code. | ||
409 | */ | 468 | */ |
410 | .globl ppc_sigsuspend | ||
411 | ppc_sigsuspend: | ||
412 | SAVE_NVGPRS(r1) | ||
413 | lwz r0,_TRAP(r1) | ||
414 | rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */ | ||
415 | stw r0,_TRAP(r1) /* register set saved */ | ||
416 | b sys_sigsuspend | ||
417 | |||
418 | .globl ppc_rt_sigsuspend | ||
419 | ppc_rt_sigsuspend: | ||
420 | SAVE_NVGPRS(r1) | ||
421 | lwz r0,_TRAP(r1) | ||
422 | rlwinm r0,r0,0,0,30 | ||
423 | stw r0,_TRAP(r1) | ||
424 | b sys_rt_sigsuspend | ||
425 | |||
426 | .globl ppc_fork | 469 | .globl ppc_fork |
427 | ppc_fork: | 470 | ppc_fork: |
428 | SAVE_NVGPRS(r1) | 471 | SAVE_NVGPRS(r1) |
@@ -447,14 +490,6 @@ ppc_clone: | |||
447 | stw r0,_TRAP(r1) /* register set saved */ | 490 | stw r0,_TRAP(r1) /* register set saved */ |
448 | b sys_clone | 491 | b sys_clone |
449 | 492 | ||
450 | .globl ppc_swapcontext | ||
451 | ppc_swapcontext: | ||
452 | SAVE_NVGPRS(r1) | ||
453 | lwz r0,_TRAP(r1) | ||
454 | rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */ | ||
455 | stw r0,_TRAP(r1) /* register set saved */ | ||
456 | b sys_swapcontext | ||
457 | |||
458 | /* | 493 | /* |
459 | * Top-level page fault handling. | 494 | * Top-level page fault handling. |
460 | * This is in assembler because if do_page_fault tells us that | 495 | * This is in assembler because if do_page_fault tells us that |
@@ -626,16 +661,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_601) | |||
626 | .long ret_from_except | 661 | .long ret_from_except |
627 | #endif | 662 | #endif |
628 | 663 | ||
629 | .globl sigreturn_exit | ||
630 | sigreturn_exit: | ||
631 | subi r1,r3,STACK_FRAME_OVERHEAD | ||
632 | rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ | ||
633 | lwz r9,TI_FLAGS(r12) | ||
634 | andi. r0,r9,_TIF_SYSCALL_T_OR_A | ||
635 | beq+ ret_from_except_full | ||
636 | bl do_syscall_trace_leave | ||
637 | /* fall through */ | ||
638 | |||
639 | .globl ret_from_except_full | 664 | .globl ret_from_except_full |
640 | ret_from_except_full: | 665 | ret_from_except_full: |
641 | REST_NVGPRS(r1) | 666 | REST_NVGPRS(r1) |
@@ -658,7 +683,7 @@ user_exc_return: /* r10 contains MSR_KERNEL here */ | |||
658 | /* Check current_thread_info()->flags */ | 683 | /* Check current_thread_info()->flags */ |
659 | rlwinm r9,r1,0,0,(31-THREAD_SHIFT) | 684 | rlwinm r9,r1,0,0,(31-THREAD_SHIFT) |
660 | lwz r9,TI_FLAGS(r9) | 685 | lwz r9,TI_FLAGS(r9) |
661 | andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED) | 686 | andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL) |
662 | bne do_work | 687 | bne do_work |
663 | 688 | ||
664 | restore_user: | 689 | restore_user: |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index bce33a38399f..0bff31f166dd 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 |
121 | syscall_dotrace_cont: | 119 | syscall_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 | ||
146 | syscall_exit: | 144 | syscall_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 | ||
158 | syscall_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 | ||
164 | syscall_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 | ||
168 | syscall_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 | ||
196 | syscall_enosys: | 187 | syscall_error: |
197 | li r3,-ENOSYS | ||
198 | std r3,RESULT(r1) | ||
199 | clrrdi r12,r1,THREAD_SHIFT | ||
200 | ld r5,_CCR(r1) | ||
201 | |||
202 | syscall_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 */ |
212 | syscall_dotrace: | 194 | syscall_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 | ||
228 | syscall_exit_trace: | 210 | syscall_enosys: |
229 | std r3,GPR3(r1) | 211 | li r3,-ENOSYS |
230 | bl .save_nvgprs | 212 | b syscall_exit |
213 | |||
214 | syscall_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) | ||
228 | 1: std r3,GPR3(r1) | ||
229 | 2: 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 | ||
238 | 3: ldarx r10,0,r12 | ||
239 | andc r10,r10,r11 | ||
240 | stdcx. r10,0,r12 | ||
241 | bne- 3b | ||
242 | subi r12,r12,TI_FLAGS | ||
243 | |||
244 | 4: 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 */ | ||
258 | save_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 */ |
240 | syscall_exit_work: | 268 | 5: 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 | |||
286 | save_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 | |||
306 | save_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 | |||
322 | save_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 | ||
276 | 70: 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 | |||
329 | 80: 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 | ||
337 | 81: 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) |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 5a2eba60dd39..c9d02751127f 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -76,7 +76,6 @@ | |||
76 | * registers from *regs. This is what we need | 76 | * registers from *regs. This is what we need |
77 | * to do when a signal has been delivered. | 77 | * to do when a signal has been delivered. |
78 | */ | 78 | */ |
79 | #define sigreturn_exit(regs) return 0 | ||
80 | 79 | ||
81 | #define GP_REGS_SIZE min(sizeof(elf_gregset_t32), sizeof(struct pt_regs32)) | 80 | #define GP_REGS_SIZE min(sizeof(elf_gregset_t32), sizeof(struct pt_regs32)) |
82 | #undef __SIGNAL_FRAMESIZE | 81 | #undef __SIGNAL_FRAMESIZE |
@@ -156,9 +155,17 @@ static inline int save_general_regs(struct pt_regs *regs, | |||
156 | elf_greg_t64 *gregs = (elf_greg_t64 *)regs; | 155 | elf_greg_t64 *gregs = (elf_greg_t64 *)regs; |
157 | int i; | 156 | int i; |
158 | 157 | ||
159 | for (i = 0; i <= PT_RESULT; i ++) | 158 | if (!FULL_REGS(regs)) { |
159 | set_thread_flag(TIF_SAVE_NVGPRS); | ||
160 | current_thread_info()->nvgprs_frame = frame->mc_gregs; | ||
161 | } | ||
162 | |||
163 | for (i = 0; i <= PT_RESULT; i ++) { | ||
164 | if (i == 14 && !FULL_REGS(regs)) | ||
165 | i = 32; | ||
160 | if (__put_user((unsigned int)gregs[i], &frame->mc_gregs[i])) | 166 | if (__put_user((unsigned int)gregs[i], &frame->mc_gregs[i])) |
161 | return -EFAULT; | 167 | return -EFAULT; |
168 | } | ||
162 | return 0; | 169 | return 0; |
163 | } | 170 | } |
164 | 171 | ||
@@ -179,8 +186,6 @@ static inline int restore_general_regs(struct pt_regs *regs, | |||
179 | 186 | ||
180 | #else /* CONFIG_PPC64 */ | 187 | #else /* CONFIG_PPC64 */ |
181 | 188 | ||
182 | extern void sigreturn_exit(struct pt_regs *); | ||
183 | |||
184 | #define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs)) | 189 | #define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs)) |
185 | 190 | ||
186 | static inline int put_sigset_t(sigset_t __user *uset, sigset_t *set) | 191 | static inline int put_sigset_t(sigset_t __user *uset, sigset_t *set) |
@@ -256,8 +261,10 @@ long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, | |||
256 | while (1) { | 261 | while (1) { |
257 | current->state = TASK_INTERRUPTIBLE; | 262 | current->state = TASK_INTERRUPTIBLE; |
258 | schedule(); | 263 | schedule(); |
259 | if (do_signal(&saveset, regs)) | 264 | if (do_signal(&saveset, regs)) { |
260 | sigreturn_exit(regs); | 265 | set_thread_flag(TIF_RESTOREALL); |
266 | return 0; | ||
267 | } | ||
261 | } | 268 | } |
262 | } | 269 | } |
263 | 270 | ||
@@ -292,8 +299,10 @@ long sys_rt_sigsuspend( | |||
292 | while (1) { | 299 | while (1) { |
293 | current->state = TASK_INTERRUPTIBLE; | 300 | current->state = TASK_INTERRUPTIBLE; |
294 | schedule(); | 301 | schedule(); |
295 | if (do_signal(&saveset, regs)) | 302 | if (do_signal(&saveset, regs)) { |
296 | sigreturn_exit(regs); | 303 | set_thread_flag(TIF_RESTOREALL); |
304 | return 0; | ||
305 | } | ||
297 | } | 306 | } |
298 | } | 307 | } |
299 | 308 | ||
@@ -391,9 +400,6 @@ struct rt_sigframe { | |||
391 | static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, | 400 | static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, |
392 | int sigret) | 401 | int sigret) |
393 | { | 402 | { |
394 | #ifdef CONFIG_PPC32 | ||
395 | CHECK_FULL_REGS(regs); | ||
396 | #endif | ||
397 | /* Make sure floating point registers are stored in regs */ | 403 | /* Make sure floating point registers are stored in regs */ |
398 | flush_fp_to_thread(current); | 404 | flush_fp_to_thread(current); |
399 | 405 | ||
@@ -828,12 +834,6 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka, | |||
828 | regs->gpr[6] = (unsigned long) rt_sf; | 834 | regs->gpr[6] = (unsigned long) rt_sf; |
829 | regs->nip = (unsigned long) ka->sa.sa_handler; | 835 | regs->nip = (unsigned long) ka->sa.sa_handler; |
830 | regs->trap = 0; | 836 | regs->trap = 0; |
831 | #ifdef CONFIG_PPC64 | ||
832 | regs->result = 0; | ||
833 | |||
834 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
835 | ptrace_notify(SIGTRAP); | ||
836 | #endif | ||
837 | return 1; | 837 | return 1; |
838 | 838 | ||
839 | badframe: | 839 | badframe: |
@@ -911,8 +911,8 @@ long sys_swapcontext(struct ucontext __user *old_ctx, | |||
911 | */ | 911 | */ |
912 | if (do_setcontext(new_ctx, regs, 0)) | 912 | if (do_setcontext(new_ctx, regs, 0)) |
913 | do_exit(SIGSEGV); | 913 | do_exit(SIGSEGV); |
914 | sigreturn_exit(regs); | 914 | |
915 | /* doesn't actually return back to here */ | 915 | set_thread_flag(TIF_RESTOREALL); |
916 | return 0; | 916 | return 0; |
917 | } | 917 | } |
918 | 918 | ||
@@ -945,12 +945,11 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, | |||
945 | * nobody does any... | 945 | * nobody does any... |
946 | */ | 946 | */ |
947 | compat_sys_sigaltstack((u32)(u64)&rt_sf->uc.uc_stack, 0, 0, 0, 0, 0, regs); | 947 | compat_sys_sigaltstack((u32)(u64)&rt_sf->uc.uc_stack, 0, 0, 0, 0, 0, regs); |
948 | return (int)regs->result; | ||
949 | #else | 948 | #else |
950 | do_sigaltstack(&rt_sf->uc.uc_stack, NULL, regs->gpr[1]); | 949 | do_sigaltstack(&rt_sf->uc.uc_stack, NULL, regs->gpr[1]); |
951 | sigreturn_exit(regs); /* doesn't return here */ | ||
952 | return 0; | ||
953 | #endif | 950 | #endif |
951 | set_thread_flag(TIF_RESTOREALL); | ||
952 | return 0; | ||
954 | 953 | ||
955 | bad: | 954 | bad: |
956 | force_sig(SIGSEGV, current); | 955 | force_sig(SIGSEGV, current); |
@@ -1041,9 +1040,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
1041 | */ | 1040 | */ |
1042 | do_sigaltstack(&ctx->uc_stack, NULL, regs->gpr[1]); | 1041 | do_sigaltstack(&ctx->uc_stack, NULL, regs->gpr[1]); |
1043 | 1042 | ||
1044 | sigreturn_exit(regs); | 1043 | set_thread_flag(TIF_RESTOREALL); |
1045 | /* doesn't actually return back to here */ | ||
1046 | |||
1047 | out: | 1044 | out: |
1048 | return 0; | 1045 | return 0; |
1049 | } | 1046 | } |
@@ -1107,12 +1104,6 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
1107 | regs->gpr[4] = (unsigned long) sc; | 1104 | regs->gpr[4] = (unsigned long) sc; |
1108 | regs->nip = (unsigned long) ka->sa.sa_handler; | 1105 | regs->nip = (unsigned long) ka->sa.sa_handler; |
1109 | regs->trap = 0; | 1106 | regs->trap = 0; |
1110 | #ifdef CONFIG_PPC64 | ||
1111 | regs->result = 0; | ||
1112 | |||
1113 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
1114 | ptrace_notify(SIGTRAP); | ||
1115 | #endif | ||
1116 | 1107 | ||
1117 | return 1; | 1108 | return 1; |
1118 | 1109 | ||
@@ -1160,12 +1151,8 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, | |||
1160 | || restore_user_regs(regs, sr, 1)) | 1151 | || restore_user_regs(regs, sr, 1)) |
1161 | goto badframe; | 1152 | goto badframe; |
1162 | 1153 | ||
1163 | #ifdef CONFIG_PPC64 | 1154 | set_thread_flag(TIF_RESTOREALL); |
1164 | return (int)regs->result; | ||
1165 | #else | ||
1166 | sigreturn_exit(regs); /* doesn't return */ | ||
1167 | return 0; | 1155 | return 0; |
1168 | #endif | ||
1169 | 1156 | ||
1170 | badframe: | 1157 | badframe: |
1171 | force_sig(SIGSEGV, current); | 1158 | force_sig(SIGSEGV, current); |
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 1decf2785530..5462bef898f6 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
@@ -96,8 +96,10 @@ long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, int p3, int | |||
96 | while (1) { | 96 | while (1) { |
97 | current->state = TASK_INTERRUPTIBLE; | 97 | current->state = TASK_INTERRUPTIBLE; |
98 | schedule(); | 98 | schedule(); |
99 | if (do_signal(&saveset, regs)) | 99 | if (do_signal(&saveset, regs)) { |
100 | set_thread_flag(TIF_RESTOREALL); | ||
100 | return 0; | 101 | return 0; |
102 | } | ||
101 | } | 103 | } |
102 | } | 104 | } |
103 | 105 | ||
@@ -152,6 +154,14 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | |||
152 | err |= __put_user(0, &sc->v_regs); | 154 | err |= __put_user(0, &sc->v_regs); |
153 | #endif /* CONFIG_ALTIVEC */ | 155 | #endif /* CONFIG_ALTIVEC */ |
154 | err |= __put_user(&sc->gp_regs, &sc->regs); | 156 | err |= __put_user(&sc->gp_regs, &sc->regs); |
157 | if (!FULL_REGS(regs)) { | ||
158 | /* Zero out the unsaved GPRs to avoid information | ||
159 | leak, and set TIF_SAVE_NVGPRS to ensure that the | ||
160 | registers do actually get saved later. */ | ||
161 | memset(®s->gpr[14], 0, 18 * sizeof(unsigned long)); | ||
162 | set_thread_flag(TIF_SAVE_NVGPRS); | ||
163 | current_thread_info()->nvgprs_frame = &sc->gp_regs; | ||
164 | } | ||
155 | err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE); | 165 | err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE); |
156 | err |= __copy_to_user(&sc->fp_regs, ¤t->thread.fpr, FP_REGS_SIZE); | 166 | err |= __copy_to_user(&sc->fp_regs, ¤t->thread.fpr, FP_REGS_SIZE); |
157 | err |= __put_user(signr, &sc->signal); | 167 | err |= __put_user(signr, &sc->signal); |
@@ -340,6 +350,7 @@ int sys_swapcontext(struct ucontext __user *old_ctx, | |||
340 | do_exit(SIGSEGV); | 350 | do_exit(SIGSEGV); |
341 | 351 | ||
342 | /* This returns like rt_sigreturn */ | 352 | /* This returns like rt_sigreturn */ |
353 | set_thread_flag(TIF_RESTOREALL); | ||
343 | return 0; | 354 | return 0; |
344 | } | 355 | } |
345 | 356 | ||
@@ -372,7 +383,8 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, | |||
372 | */ | 383 | */ |
373 | do_sigaltstack(&uc->uc_stack, NULL, regs->gpr[1]); | 384 | do_sigaltstack(&uc->uc_stack, NULL, regs->gpr[1]); |
374 | 385 | ||
375 | return regs->result; | 386 | set_thread_flag(TIF_RESTOREALL); |
387 | return 0; | ||
376 | 388 | ||
377 | badframe: | 389 | badframe: |
378 | #if DEBUG_SIG | 390 | #if DEBUG_SIG |
@@ -454,9 +466,6 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
454 | if (err) | 466 | if (err) |
455 | goto badframe; | 467 | goto badframe; |
456 | 468 | ||
457 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
458 | ptrace_notify(SIGTRAP); | ||
459 | |||
460 | return 1; | 469 | return 1; |
461 | 470 | ||
462 | badframe: | 471 | badframe: |
@@ -502,6 +511,8 @@ static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) | |||
502 | * we only get here if there is a handler, we dont restart. | 511 | * we only get here if there is a handler, we dont restart. |
503 | */ | 512 | */ |
504 | regs->result = -EINTR; | 513 | regs->result = -EINTR; |
514 | regs->gpr[3] = EINTR; | ||
515 | regs->ccr |= 0x10000000; | ||
505 | break; | 516 | break; |
506 | case -ERESTARTSYS: | 517 | case -ERESTARTSYS: |
507 | /* ERESTARTSYS means to restart the syscall if there is no | 518 | /* ERESTARTSYS means to restart the syscall if there is no |
@@ -509,6 +520,8 @@ static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) | |||
509 | */ | 520 | */ |
510 | if (!(ka->sa.sa_flags & SA_RESTART)) { | 521 | if (!(ka->sa.sa_flags & SA_RESTART)) { |
511 | regs->result = -EINTR; | 522 | regs->result = -EINTR; |
523 | regs->gpr[3] = EINTR; | ||
524 | regs->ccr |= 0x10000000; | ||
512 | break; | 525 | break; |
513 | } | 526 | } |
514 | /* fallthrough */ | 527 | /* fallthrough */ |
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index 65eaea91b499..4bb3650420b4 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S | |||
@@ -113,7 +113,7 @@ SYSCALL(sgetmask) | |||
113 | COMPAT_SYS(ssetmask) | 113 | COMPAT_SYS(ssetmask) |
114 | SYSCALL(setreuid) | 114 | SYSCALL(setreuid) |
115 | SYSCALL(setregid) | 115 | SYSCALL(setregid) |
116 | SYSX(sys_ni_syscall,ppc32_sigsuspend,ppc_sigsuspend) | 116 | SYS32ONLY(sigsuspend) |
117 | COMPAT_SYS(sigpending) | 117 | COMPAT_SYS(sigpending) |
118 | COMPAT_SYS(sethostname) | 118 | COMPAT_SYS(sethostname) |
119 | COMPAT_SYS(setrlimit) | 119 | COMPAT_SYS(setrlimit) |
@@ -160,7 +160,7 @@ SYSCALL(swapoff) | |||
160 | COMPAT_SYS(sysinfo) | 160 | COMPAT_SYS(sysinfo) |
161 | COMPAT_SYS(ipc) | 161 | COMPAT_SYS(ipc) |
162 | SYSCALL(fsync) | 162 | SYSCALL(fsync) |
163 | SYSX(sys_ni_syscall,ppc32_sigreturn,sys_sigreturn) | 163 | SYS32ONLY(sigreturn) |
164 | PPC_SYS(clone) | 164 | PPC_SYS(clone) |
165 | COMPAT_SYS(setdomainname) | 165 | COMPAT_SYS(setdomainname) |
166 | PPC_SYS(newuname) | 166 | PPC_SYS(newuname) |
@@ -213,13 +213,13 @@ COMPAT_SYS(nfsservctl) | |||
213 | SYSCALL(setresgid) | 213 | SYSCALL(setresgid) |
214 | SYSCALL(getresgid) | 214 | SYSCALL(getresgid) |
215 | COMPAT_SYS(prctl) | 215 | COMPAT_SYS(prctl) |
216 | SYSX(ppc64_rt_sigreturn,ppc32_rt_sigreturn,sys_rt_sigreturn) | 216 | COMPAT_SYS(rt_sigreturn) |
217 | COMPAT_SYS(rt_sigaction) | 217 | COMPAT_SYS(rt_sigaction) |
218 | COMPAT_SYS(rt_sigprocmask) | 218 | COMPAT_SYS(rt_sigprocmask) |
219 | COMPAT_SYS(rt_sigpending) | 219 | COMPAT_SYS(rt_sigpending) |
220 | COMPAT_SYS(rt_sigtimedwait) | 220 | COMPAT_SYS(rt_sigtimedwait) |
221 | COMPAT_SYS(rt_sigqueueinfo) | 221 | COMPAT_SYS(rt_sigqueueinfo) |
222 | SYSX(ppc64_rt_sigsuspend,ppc32_rt_sigsuspend,ppc_rt_sigsuspend) | 222 | COMPAT_SYS(rt_sigsuspend) |
223 | COMPAT_SYS(pread64) | 223 | COMPAT_SYS(pread64) |
224 | COMPAT_SYS(pwrite64) | 224 | COMPAT_SYS(pwrite64) |
225 | SYSCALL(chown) | 225 | SYSCALL(chown) |
@@ -290,7 +290,7 @@ COMPAT_SYS(clock_settime) | |||
290 | COMPAT_SYS(clock_gettime) | 290 | COMPAT_SYS(clock_gettime) |
291 | COMPAT_SYS(clock_getres) | 291 | COMPAT_SYS(clock_getres) |
292 | COMPAT_SYS(clock_nanosleep) | 292 | COMPAT_SYS(clock_nanosleep) |
293 | SYSX(ppc64_swapcontext,ppc32_swapcontext,ppc_swapcontext) | 293 | COMPAT_SYS(swapcontext) |
294 | COMPAT_SYS(tgkill) | 294 | COMPAT_SYS(tgkill) |
295 | COMPAT_SYS(utimes) | 295 | COMPAT_SYS(utimes) |
296 | COMPAT_SYS(statfs64) | 296 | COMPAT_SYS(statfs64) |
diff --git a/include/asm-powerpc/ptrace.h b/include/asm-powerpc/ptrace.h index 1f7ecdb0b6ce..9c550b314823 100644 --- a/include/asm-powerpc/ptrace.h +++ b/include/asm-powerpc/ptrace.h | |||
@@ -87,7 +87,7 @@ extern unsigned long profile_pc(struct pt_regs *regs); | |||
87 | 87 | ||
88 | #define force_successful_syscall_return() \ | 88 | #define force_successful_syscall_return() \ |
89 | do { \ | 89 | do { \ |
90 | current_thread_info()->syscall_noerror = 1; \ | 90 | set_thread_flag(TIF_NOERROR); \ |
91 | } while(0) | 91 | } while(0) |
92 | 92 | ||
93 | /* | 93 | /* |
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h index e525f49bd179..ac1e80e6033e 100644 --- a/include/asm-powerpc/thread_info.h +++ b/include/asm-powerpc/thread_info.h | |||
@@ -37,8 +37,7 @@ struct thread_info { | |||
37 | int preempt_count; /* 0 => preemptable, | 37 | int preempt_count; /* 0 => preemptable, |
38 | <0 => BUG */ | 38 | <0 => BUG */ |
39 | struct restart_block restart_block; | 39 | struct restart_block restart_block; |
40 | /* set by force_successful_syscall_return */ | 40 | void *nvgprs_frame; |
41 | unsigned char syscall_noerror; | ||
42 | /* low level flags - has atomic operations done on it */ | 41 | /* low level flags - has atomic operations done on it */ |
43 | unsigned long flags ____cacheline_aligned_in_smp; | 42 | unsigned long flags ____cacheline_aligned_in_smp; |
44 | }; | 43 | }; |
@@ -123,6 +122,9 @@ static inline struct thread_info *current_thread_info(void) | |||
123 | #define TIF_SINGLESTEP 9 /* singlestepping active */ | 122 | #define TIF_SINGLESTEP 9 /* singlestepping active */ |
124 | #define TIF_MEMDIE 10 | 123 | #define TIF_MEMDIE 10 |
125 | #define TIF_SECCOMP 11 /* secure computing */ | 124 | #define TIF_SECCOMP 11 /* secure computing */ |
125 | #define TIF_RESTOREALL 12 /* Restore all regs (implies NOERROR) */ | ||
126 | #define TIF_SAVE_NVGPRS 13 /* Save r14-r31 in signal frame */ | ||
127 | #define TIF_NOERROR 14 /* Force successful syscall return */ | ||
126 | 128 | ||
127 | /* as above, but as bit values */ | 129 | /* as above, but as bit values */ |
128 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) | 130 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) |
@@ -136,10 +138,14 @@ static inline struct thread_info *current_thread_info(void) | |||
136 | #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) | 138 | #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) |
137 | #define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) | 139 | #define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) |
138 | #define _TIF_SECCOMP (1<<TIF_SECCOMP) | 140 | #define _TIF_SECCOMP (1<<TIF_SECCOMP) |
141 | #define _TIF_RESTOREALL (1<<TIF_RESTOREALL) | ||
142 | #define _TIF_SAVE_NVGPRS (1<<TIF_SAVE_NVGPRS) | ||
143 | #define _TIF_NOERROR (1<<TIF_NOERROR) | ||
139 | #define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP) | 144 | #define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP) |
140 | 145 | ||
141 | #define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \ | 146 | #define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \ |
142 | _TIF_NEED_RESCHED) | 147 | _TIF_NEED_RESCHED | _TIF_RESTOREALL) |
148 | #define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR|_TIF_SAVE_NVGPRS) | ||
143 | 149 | ||
144 | #endif /* __KERNEL__ */ | 150 | #endif /* __KERNEL__ */ |
145 | 151 | ||