From aa70719a9cf4ee6ca2d95049e84a28c10cb0d5a9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 23 Dec 2012 02:43:08 -0500 Subject: [PATCH] --- yaml --- r: 356685 b: refs/heads/master c: 1e974c21661db89b30eb13040fc9ab99a83b6492 h: refs/heads/master i: 356683: dd0b79378675acc082a3154b5d3792f40fa5ccc8 v: v3 --- [refs] | 2 +- trunk/arch/h8300/Kconfig | 3 -- trunk/arch/h8300/include/asm/signal.h | 7 +++ trunk/arch/h8300/kernel/signal.c | 72 ++++++++++++++++++++++++--- trunk/arch/h8300/kernel/syscalls.S | 15 ++++++ trunk/arch/hexagon/Kconfig | 1 + trunk/arch/hexagon/kernel/signal.c | 15 +----- 7 files changed, 89 insertions(+), 26 deletions(-) diff --git a/[refs] b/[refs] index be19da7209c6..524b7e3520db 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: b0375744f1c74b39a2677fc29045ad1cb6f4c6cd +refs/heads/master: 1e974c21661db89b30eb13040fc9ab99a83b6492 diff --git a/trunk/arch/h8300/Kconfig b/trunk/arch/h8300/Kconfig index 0b0176ce2c35..2d2efb653ee0 100644 --- a/trunk/arch/h8300/Kconfig +++ b/trunk/arch/h8300/Kconfig @@ -9,9 +9,6 @@ config H8300 select GENERIC_IRQ_SHOW select GENERIC_CPU_DEVICES select MODULES_USE_ELF_RELA - select GENERIC_SIGALTSTACK - select OLD_SIGSUSPEND3 - select OLD_SIGACTION config SYMBOL_PREFIX string diff --git a/trunk/arch/h8300/include/asm/signal.h b/trunk/arch/h8300/include/asm/signal.h index 6341e36386f8..9b18a0959461 100644 --- a/trunk/arch/h8300/include/asm/signal.h +++ b/trunk/arch/h8300/include/asm/signal.h @@ -16,6 +16,13 @@ typedef struct { unsigned long sig[_NSIG_WORDS]; } sigset_t; +struct old_sigaction { + __sighandler_t sa_handler; + old_sigset_t sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(void); +}; + #define __ARCH_HAS_SA_RESTORER #include diff --git a/trunk/arch/h8300/kernel/signal.c b/trunk/arch/h8300/kernel/signal.c index a65ff3b76326..0e81b96c642f 100644 --- a/trunk/arch/h8300/kernel/signal.c +++ b/trunk/arch/h8300/kernel/signal.c @@ -46,6 +46,56 @@ #include #include +/* + * Atomically swap in the new signal mask, and wait for a signal. + */ +asmlinkage int +sys_sigsuspend(int unused1, int unused2, old_sigset_t mask) +{ + sigset_t blocked; + siginitset(&blocked, mask); + return sigsuspend(&blocked); +} + +asmlinkage int +sys_sigaction(int sig, const struct old_sigaction *act, + struct old_sigaction *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_sigset_t mask; + if (!access_ok(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags) || + __get_user(mask, &act->sa_mask)) + return -EFAULT; + siginitset(&new_ka.sa.sa_mask, mask); + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) + return -EFAULT; + } + + return ret; +} + +asmlinkage int +sys_sigaltstack(const stack_t *uss, stack_t *uoss) +{ + return do_sigaltstack(uss, uoss, rdusp()); +} + + /* * Do a signal return; undo the signal stack. * @@ -86,9 +136,9 @@ struct rt_sigframe } __attribute__((aligned(2),packed)); static inline int -restore_sigcontext(struct sigcontext *usc, int *pd0) +restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, + int *pd0) { - struct pt_regs *regs = current_pt_regs(); int err = 0; unsigned int ccr; unsigned int usp; @@ -117,8 +167,9 @@ restore_sigcontext(struct sigcontext *usc, int *pd0) return err; } -asmlinkage int sys_sigreturn(void) +asmlinkage int do_sigreturn(unsigned long __unused,...) { + struct pt_regs *regs = (struct pt_regs *) (&__unused - 1); unsigned long usp = rdusp(); struct sigframe *frame = (struct sigframe *)(usp - 4); sigset_t set; @@ -134,7 +185,7 @@ asmlinkage int sys_sigreturn(void) set_current_blocked(&set); - if (restore_sigcontext(&frame->sc, &er0)) + if (restore_sigcontext(regs, &frame->sc, &er0)) goto badframe; return er0; @@ -143,8 +194,9 @@ asmlinkage int sys_sigreturn(void) return 0; } -asmlinkage int sys_rt_sigreturn(void) +asmlinkage int do_rt_sigreturn(unsigned long __unused,...) { + struct pt_regs *regs = (struct pt_regs *) &__unused; unsigned long usp = rdusp(); struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4); sigset_t set; @@ -157,10 +209,10 @@ asmlinkage int sys_rt_sigreturn(void) set_current_blocked(&set); - if (restore_sigcontext(&frame->uc.uc_mcontext, &er0)) + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0)) goto badframe; - if (restore_altstack(&frame->uc.uc_stack)) + if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT) goto badframe; return er0; @@ -306,7 +358,11 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); - err |= __save_altstack(&frame->uc.uc_stack, rdusp()); + err |= __put_user((void *)current->sas_ss_sp, + &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(rdusp()), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) diff --git a/trunk/arch/h8300/kernel/syscalls.S b/trunk/arch/h8300/kernel/syscalls.S index 5c2168fb9b9e..b74dd0ade58d 100644 --- a/trunk/arch/h8300/kernel/syscalls.S +++ b/trunk/arch/h8300/kernel/syscalls.S @@ -334,3 +334,18 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_getcpu) .long SYMBOL_NAME(sys_ni_syscall) /* sys_epoll_pwait */ .long SYMBOL_NAME(sys_setns) /* 320 */ + + .macro call_sp addr + mov.l #SYMBOL_NAME(\addr),er6 + bra SYMBOL_NAME(syscall_trampoline):8 + .endm + +SYMBOL_NAME_LABEL(sys_sigreturn) + call_sp do_sigreturn + +SYMBOL_NAME_LABEL(sys_rt_sigreturn) + call_sp do_rt_sigreturn + +SYMBOL_NAME_LABEL(syscall_trampoline) + mov.l sp,er0 + jmp @er6 diff --git a/trunk/arch/hexagon/Kconfig b/trunk/arch/hexagon/Kconfig index 0744f7d7b1fd..3e6e27c11f93 100644 --- a/trunk/arch/hexagon/Kconfig +++ b/trunk/arch/hexagon/Kconfig @@ -31,6 +31,7 @@ config HEXAGON select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS_BROADCAST select MODULES_USE_ELF_RELA + select GENERIC_SIGALTSTACK ---help--- Qualcomm Hexagon is a processor architecture designed for high performance and low power across a wide variety of applications. diff --git a/trunk/arch/hexagon/kernel/signal.c b/trunk/arch/hexagon/kernel/signal.c index fe0d1373165d..46ebd4794663 100644 --- a/trunk/arch/hexagon/kernel/signal.c +++ b/trunk/arch/hexagon/kernel/signal.c @@ -247,12 +247,6 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) /* * Architecture-specific wrappers for signal-related system calls */ -asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) -{ - struct pt_regs *regs = current_pt_regs(); - - return do_sigaltstack(uss, uoss, regs->r29); -} asmlinkage int sys_rt_sigreturn(void) { @@ -288,14 +282,7 @@ asmlinkage int sys_rt_sigreturn(void) */ regs->syscall_nr = __NR_rt_sigreturn; - /* - * If we were meticulous, we'd only call this if we knew that - * we were actually going to use an alternate stack, and we'd - * consider any error to be fatal. What we do here, in common - * with many other architectures, is call it blindly and only - * consider the -EFAULT return case to be proof of a problem. - */ - if (do_sigaltstack(&frame->uc.uc_stack, NULL, pt_psp(regs)) == -EFAULT) + if (restore_altstack(&frame->uc.uc_stack)) goto badframe; return 0;