static int setup_rt_frame()

in kernel/signal.c [158:207]


static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
			  struct pt_regs *regs)
{
	struct rt_sigframe *frame;
	int err = 0;
	unsigned char *ret;

	frame = get_sigframe(ksig, regs, sizeof(*frame));

	if (!access_ok(frame, sizeof(*frame)))
		return -EFAULT;

	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
		err |= copy_siginfo_to_user(&frame->info, &ksig->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 |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
	err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
	if (err)
		return -EFAULT;

	/* Set up to return from userspace.  */
	ret = (unsigned char *)&frame->retcode;
	if (ksig->ka.sa.sa_flags & SA_RESTORER)
		ret = (unsigned char *)(ksig->ka.sa.sa_restorer);
	else {
		/* sub.l er0,er0; mov.b #__NR_rt_sigreturn,r0l; trapa #0 */
		err |= __put_user(0x1a80f800 + (__NR_rt_sigreturn & 0xff),
				  (unsigned long *)(frame->retcode + 0));
		err |= __put_user(0x5700,
				  (unsigned short *)(frame->retcode + 4));
	}
	err |= __put_user(ret, &frame->pretcode);

	if (err)
		return -EFAULT;

	/* Set up registers for signal handler */
	regs->sp  = (unsigned long)frame;
	regs->pc  = (unsigned long)ksig->ka.sa.sa_handler;
	regs->er0 = ksig->sig;
	regs->er1 = (unsigned long)&(frame->info);
	regs->er2 = (unsigned long)&frame->uc;
	regs->er5 = current->mm->start_data;	/* GOT base */

	return 0;
}