From: Michal Simek Date: Tue, 12 May 2009 10:10:52 +0000 (+0200) Subject: microblaze: prepare signal handling for generic unistd.h X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=a6029d1c8cfc9ac2609195f31c2e70b584d3496e;p=deliverable%2Flinux.git microblaze: prepare signal handling for generic unistd.h We need to define set_restore_sigmask() in order to get pselect and ppoll. Also, the setup_frame function can not be used when __NR_sigreturn is not defined. Signed-off-by: Arnd Bergmann Signed-off-by: Michal Simek --- diff --git a/arch/microblaze/include/asm/syscalls.h b/arch/microblaze/include/asm/syscalls.h index 9cb4ff0edeb2..ddea9eb31f8d 100644 --- a/arch/microblaze/include/asm/syscalls.h +++ b/arch/microblaze/include/asm/syscalls.h @@ -34,6 +34,9 @@ asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, asmlinkage int sys_sigaction(int sig, const struct old_sigaction *act, struct old_sigaction *oact); +asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, + struct sigaction __user *oact, size_t sigsetsize); + asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, struct pt_regs *regs); diff --git a/arch/microblaze/include/asm/thread_info.h b/arch/microblaze/include/asm/thread_info.h index 4c3943e3f403..a0401d2ef8d5 100644 --- a/arch/microblaze/include/asm/thread_info.h +++ b/arch/microblaze/include/asm/thread_info.h @@ -154,6 +154,17 @@ static inline struct thread_info *current_thread_info(void) */ /* FPU was used by this task this quantum (SMP) */ #define TS_USEDFPU 0x0001 +#define TS_RESTORE_SIGMASK 0x0002 + +#ifndef __ASSEMBLY__ +#define HAVE_SET_RESTORE_SIGMASK 1 +static inline void set_restore_sigmask(void) +{ + struct thread_info *ti = current_thread_info(); + ti->status |= TS_RESTORE_SIGMASK; + set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags); +} +#endif #endif /* __KERNEL__ */ #endif /* _ASM_MICROBLAZE_THREAD_INFO_H */ diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 804a074a94a8..3cdcbfe41295 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -288,80 +288,6 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) return (void __user *)((sp - frame_size) & -8UL); } -static void setup_frame(int sig, struct k_sigaction *ka, - sigset_t *set, struct pt_regs *regs) -{ - struct sigframe *frame; - int err = 0; - int signal; - - frame = get_sigframe(ka, regs, sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; - - signal = current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig; - - err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); - - if (_NSIG_WORDS > 1) { - err |= __copy_to_user(frame->extramask, &set->sig[1], - sizeof(frame->extramask)); - } - - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - /* minus 8 is offset to cater for "rtsd r15,8" offset */ - if (ka->sa.sa_flags & SA_RESTORER) { - regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8; - } else { - /* Note, these encodings are _big endian_! */ - - /* addi r12, r0, __NR_sigreturn */ - err |= __put_user(0x31800000 | __NR_sigreturn , - frame->tramp + 0); - /* brki r14, 0x8 */ - err |= __put_user(0xb9cc0008, frame->tramp + 1); - - /* Return from sighandler will jump to the tramp. - Negative 8 offset because return is rtsd r15, 8 */ - regs->r15 = ((unsigned long)frame->tramp)-8; - - __invalidate_cache_sigtramp((unsigned long)frame->tramp); - } - - if (err) - goto give_sigsegv; - - /* Set up registers for signal handler */ - regs->r1 = (unsigned long) frame - STATE_SAVE_ARG_SPACE; - - /* Signal handler args: */ - regs->r5 = signal; /* Arg 0: signum */ - regs->r6 = (unsigned long) &frame->sc; /* arg 1: sigcontext */ - - /* Offset of 4 to handle microblaze rtid r14, 0 */ - regs->pc = (unsigned long)ka->sa.sa_handler; - - set_fs(USER_DS); - -#ifdef DEBUG_SIG - printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n", - current->comm, current->pid, frame, regs->pc); -#endif - - return; - -give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); -} - static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { @@ -380,7 +306,8 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ? current_thread_info()->exec_domain->signal_invmap[sig] : sig; - err |= copy_siginfo_to_user(&frame->info, info); + if (info) + err |= copy_siginfo_to_user(&frame->info, info); /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); @@ -478,7 +405,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, if (ka->sa.sa_flags & SA_SIGINFO) setup_rt_frame(sig, ka, info, oldset, regs); else - setup_frame(sig, ka, oldset, regs); + setup_rt_frame(sig, ka, NULL, oldset, regs); if (ka->sa.sa_flags & SA_ONESHOT) ka->sa.sa_handler = SIG_DFL;