diff options
Diffstat (limited to 'arch/microblaze/kernel/signal.c')
| -rw-r--r-- | arch/microblaze/kernel/signal.c | 109 | 
1 files changed, 21 insertions, 88 deletions
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 40d36931e36..4c0e6521b11 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -152,8 +152,8 @@ struct rt_sigframe {  	unsigned long tramp[2];	/* signal trampoline */  }; -static int -restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *rval_p) +static int restore_sigcontext(struct pt_regs *regs, +				struct sigcontext __user *sc, int *rval_p)  {  	unsigned int err = 0; @@ -211,11 +211,10 @@ badframe:  asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)  { -	struct rt_sigframe *frame = -			(struct rt_sigframe *)(regs->r1 + STATE_SAVE_ARG_SPACE); +	struct rt_sigframe __user *frame = +		(struct rt_sigframe __user *)(regs->r1 + STATE_SAVE_ARG_SPACE);  	sigset_t set; -	stack_t st;  	int rval;  	if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) @@ -233,11 +232,10 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)  	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))  		goto badframe; -	if (__copy_from_user((void *)&st, &frame->uc.uc_stack, sizeof(st))) -		goto badframe;  	/* It is more difficult to avoid calling this function than to  	 call it and ignore errors. */ -	do_sigaltstack(&st, NULL, regs->r1); +	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->r1)) +		goto badframe;  	return rval; @@ -251,7 +249,7 @@ badframe:   */  static int -setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, +setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,  		unsigned long mask)  {  	int err = 0; @@ -278,7 +276,7 @@ setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,  /*   * Determine which stack to use..   */ -static inline void * +static inline void __user *  get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)  {  	/* Default to using normal stack */ @@ -287,87 +285,13 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)  	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp))  		sp = current->sas_ss_sp + current->sas_ss_size; -	return (void *)((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); +	return (void __user *)((sp - frame_size) & -8UL);  }  static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,  			sigset_t *set, struct pt_regs *regs)  { -	struct rt_sigframe *frame; +	struct rt_sigframe __user *frame;  	int err = 0;  	int signal; @@ -382,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); @@ -463,7 +388,15 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)  	case -ERESTARTNOINTR:  do_restart:  		/* offset of 4 bytes to re-execute trap (brki) instruction */ +#ifndef CONFIG_MMU  		regs->pc -= 4; +#else +		/* offset of 8 bytes required = 4 for rtbd +		   offset, plus 4 for size of +			"brki r14,8" +		   instruction. */ +		regs->pc -= 8; +#endif  		break;  	}  } @@ -480,7 +413,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;  |