aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/signal_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/signal_32.c')
-rw-r--r--arch/sh/kernel/signal_32.c69
1 files changed, 41 insertions, 28 deletions
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c
index 51689d29ad45..69d09c0b3498 100644
--- a/arch/sh/kernel/signal_32.c
+++ b/arch/sh/kernel/signal_32.c
@@ -30,6 +30,7 @@
30#include <asm/uaccess.h> 30#include <asm/uaccess.h>
31#include <asm/pgtable.h> 31#include <asm/pgtable.h>
32#include <asm/cacheflush.h> 32#include <asm/cacheflush.h>
33#include <asm/syscalls.h>
33#include <asm/fpu.h> 34#include <asm/fpu.h>
34 35
35#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 36#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -215,6 +216,9 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
215 sigset_t set; 216 sigset_t set;
216 int r0; 217 int r0;
217 218
219 /* Always make any pending restarted system calls return -EINTR */
220 current_thread_info()->restart_block.fn = do_no_restart_syscall;
221
218 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 222 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
219 goto badframe; 223 goto badframe;
220 224
@@ -247,9 +251,11 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
247 struct pt_regs *regs = RELOC_HIDE(&__regs, 0); 251 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
248 struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->regs[15]; 252 struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->regs[15];
249 sigset_t set; 253 sigset_t set;
250 stack_t st;
251 int r0; 254 int r0;
252 255
256 /* Always make any pending restarted system calls return -EINTR */
257 current_thread_info()->restart_block.fn = do_no_restart_syscall;
258
253 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 259 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
254 goto badframe; 260 goto badframe;
255 261
@@ -265,11 +271,9 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
265 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) 271 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
266 goto badframe; 272 goto badframe;
267 273
268 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) 274 if (do_sigaltstack(&frame->uc.uc_stack, NULL,
275 regs->regs[15]) == -EFAULT)
269 goto badframe; 276 goto badframe;
270 /* It is more difficult to avoid calling this function than to
271 call it and ignore errors. */
272 do_sigaltstack((const stack_t __user *)&st, NULL, (unsigned long)frame);
273 277
274 return r0; 278 return r0;
275 279
@@ -429,7 +433,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
429 433
430 /* Create the ucontext. */ 434 /* Create the ucontext. */
431 err |= __put_user(0, &frame->uc.uc_flags); 435 err |= __put_user(0, &frame->uc.uc_flags);
432 err |= __put_user(0, &frame->uc.uc_link); 436 err |= __put_user(NULL, &frame->uc.uc_link);
433 err |= __put_user((void *)current->sas_ss_sp, 437 err |= __put_user((void *)current->sas_ss_sp,
434 &frame->uc.uc_stack.ss_sp); 438 &frame->uc.uc_stack.ss_sp);
435 err |= __put_user(sas_ss_flags(regs->regs[15]), 439 err |= __put_user(sas_ss_flags(regs->regs[15]),
@@ -492,37 +496,43 @@ give_sigsegv:
492 return -EFAULT; 496 return -EFAULT;
493} 497}
494 498
499static inline void
500handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs,
501 struct sigaction *sa)
502{
503 /* If we're not from a syscall, bail out */
504 if (regs->tra < 0)
505 return;
506
507 /* check for system call restart.. */
508 switch (regs->regs[0]) {
509 case -ERESTART_RESTARTBLOCK:
510 case -ERESTARTNOHAND:
511 no_system_call_restart:
512 regs->regs[0] = -EINTR;
513 regs->sr |= 1;
514 break;
515
516 case -ERESTARTSYS:
517 if (!(sa->sa_flags & SA_RESTART))
518 goto no_system_call_restart;
519 /* fallthrough */
520 case -ERESTARTNOINTR:
521 regs->regs[0] = save_r0;
522 regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
523 break;
524 }
525}
526
495/* 527/*
496 * OK, we're invoking a handler 528 * OK, we're invoking a handler
497 */ 529 */
498
499static int 530static int
500handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, 531handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
501 sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0) 532 sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0)
502{ 533{
503 int ret; 534 int ret;
504 535
505 /* Are we from a system call? */
506 if (regs->tra >= 0) {
507 /* If so, check system call restarting.. */
508 switch (regs->regs[0]) {
509 case -ERESTART_RESTARTBLOCK:
510 case -ERESTARTNOHAND:
511 no_system_call_restart:
512 regs->regs[0] = -EINTR;
513 break;
514
515 case -ERESTARTSYS:
516 if (!(ka->sa.sa_flags & SA_RESTART))
517 goto no_system_call_restart;
518 /* fallthrough */
519 case -ERESTARTNOINTR:
520 regs->regs[0] = save_r0;
521 regs->pc -= instruction_size(
522 ctrl_inw(regs->pc - 4));
523 break;
524 }
525 }
526 536
527 /* Set up the stack frame */ 537 /* Set up the stack frame */
528 if (ka->sa.sa_flags & SA_SIGINFO) 538 if (ka->sa.sa_flags & SA_SIGINFO)
@@ -580,6 +590,9 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
580 590
581 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 591 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
582 if (signr > 0) { 592 if (signr > 0) {
593 if (regs->sr & 1)
594 handle_syscall_restart(save_r0, regs, &ka.sa);
595
583 /* Whee! Actually deliver the signal. */ 596 /* Whee! Actually deliver the signal. */
584 if (handle_signal(signr, &ka, &info, oldset, 597 if (handle_signal(signr, &ka, &info, oldset,
585 regs, save_r0) == 0) { 598 regs, save_r0) == 0) {