arch/openrisc/kernel/signal.c

Source file repositories/reference/linux-study-clean/arch/openrisc/kernel/signal.c

File Facts

System
Linux kernel
Corpus path
arch/openrisc/kernel/signal.c
Extension
.c
Size
9420 bytes
Lines
361
Domain
Architecture Layer
Bucket
arch/openrisc
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct rt_sigframe {
	struct siginfo info;
	struct ucontext uc;
	unsigned char retcode[16];	/* trampoline code */
};

asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs);

asmlinkage int do_work_pending(struct pt_regs *regs, unsigned int thread_flags,
			       int syscall);

#ifdef CONFIG_FPU
static long restore_fp_state(struct sigcontext __user *sc)
{
	long err;

	err = __copy_from_user(&current->thread.fpcsr, &sc->fpcsr, sizeof(unsigned long));
	if (unlikely(err))
		return err;

	/* Restore the FPU state */
	restore_fpu(current);

	return 0;
}

static long save_fp_state(struct sigcontext __user *sc)
{
	long err;

	/* Sync the user FPU state so we can copy to sigcontext */
	save_fpu(current);

	err = __copy_to_user(&sc->fpcsr, &current->thread.fpcsr, sizeof(unsigned long));

	return err;
}
#else
#define save_fp_state(sc) (0)
#define restore_fp_state(sc) (0)
#endif

static int restore_sigcontext(struct pt_regs *regs,
			      struct sigcontext __user *sc)
{
	int err = 0;

	/* Always make any pending restarted system calls return -EINTR */
	current->restart_block.fn = do_no_restart_syscall;

	/*
	 * Restore the regs from &sc->regs.
	 * (sc is already checked since the sigframe was
	 *  checked in sys_sigreturn previously)
	 */
	err |= __copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long));
	err |= __copy_from_user(&regs->pc, &sc->regs.pc, sizeof(unsigned long));
	err |= __copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long));
	err |= restore_fp_state(sc);

	/* make sure the SM-bit is cleared so user-mode cannot fool us */
	regs->sr &= ~SPR_SR_SM;

	regs->orig_gpr11 = -1;	/* Avoid syscall restart checks */

	/* TODO: the other ports use regs->orig_XX to disable syscall checks
	 * after this completes, but we don't use that mechanism. maybe we can
	 * use it now ?
	 */

	return err;
}

asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
{
	struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->sp;
	sigset_t set;

	/*
	 * Since we stacked the signal on a dword boundary,
	 * then frame should be dword aligned here.  If it's
	 * not, then the user is trying to mess with us.
	 */
	if (((unsigned long)frame) & 3)
		goto badframe;

	if (!access_ok(frame, sizeof(*frame)))
		goto badframe;
	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
		goto badframe;

Annotation

Implementation Notes