aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/signal_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/signal_64.c')
-rw-r--r--arch/powerpc/kernel/signal_64.c23
1 files changed, 18 insertions, 5 deletions
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(&regs->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, &current->thread.fpr, FP_REGS_SIZE); 166 err |= __copy_to_user(&sc->fp_regs, &current->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
377badframe: 389badframe:
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
462badframe: 471badframe:
@@ -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 */