cregit-Linux how code gets into the kernel

Release 4.11 arch/c6x/kernel/signal.c

Directory: arch/c6x/kernel
/*
 *  Port on Texas Instruments TMS320C6x architecture
 *
 *  Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated
 *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
 *
 *  Updated for 2.6.34: Mark Salter <msalter@redhat.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 */

#include <linux/kernel.h>
#include <linux/uaccess.h>
#include <linux/syscalls.h>
#include <linux/tracehook.h>

#include <asm/ucontext.h>
#include <asm/cacheflush.h>


/*
 * Do a signal return, undo the signal stack.
 */


#define RETCODE_SIZE (9 << 2)	
/* 9 instructions = 36 bytes */


struct rt_sigframe {
	
struct siginfo __user *pinfo;
	
void __user *puc;
	
struct siginfo info;
	
struct ucontext uc;
	
unsigned long retcode[RETCODE_SIZE >> 2];
};


static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) { int err = 0; /* The access_ok check was done by caller, so use __get_user here */ #define COPY(x) (err |= __get_user(regs->x, &sc->sc_##x)) COPY(sp); COPY(a4); COPY(b4); COPY(a6); COPY(b6); COPY(a8); COPY(b8); COPY(a0); COPY(a1); COPY(a2); COPY(a3); COPY(a5); COPY(a7); COPY(a9); COPY(b0); COPY(b1); COPY(b2); COPY(b3); COPY(b5); COPY(b7); COPY(b9); COPY(a16); COPY(a17); COPY(a18); COPY(a19); COPY(a20); COPY(a21); COPY(a22); COPY(a23); COPY(a24); COPY(a25); COPY(a26); COPY(a27); COPY(a28); COPY(a29); COPY(a30); COPY(a31); COPY(b16); COPY(b17); COPY(b18); COPY(b19); COPY(b20); COPY(b21); COPY(b22); COPY(b23); COPY(b24); COPY(b25); COPY(b26); COPY(b27); COPY(b28); COPY(b29); COPY(b30); COPY(b31); COPY(csr); COPY(pc); #undef COPY return err; }

Contributors

PersonTokensPropCommitsCommitProp
Aurelien Jacquiot311100.00%1100.00%
Total311100.00%1100.00%


asmlinkage int do_rt_sigreturn(struct pt_regs *regs) { struct rt_sigframe __user *frame; sigset_t set; /* Always make any pending restarted system calls return -EINTR */ current->restart_block.fn = do_no_restart_syscall; /* * Since we stacked the signal on a dword boundary, * 'sp' should be dword aligned here. If it's * not, then the user is trying to mess with us. */ if (regs->sp & 7) goto badframe; frame = (struct rt_sigframe __user *) ((unsigned long) regs->sp + 8); if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) goto badframe; return regs->a4; badframe: force_sig(SIGSEGV, current); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Aurelien Jacquiot13393.01%125.00%
Al Viro85.59%125.00%
Andrew Lutomirski10.70%125.00%
Matt Fleming10.70%125.00%
Total143100.00%4100.00%


static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask) { int err = 0; err |= __put_user(mask, &sc->sc_mask); /* The access_ok check was done by caller, so use __put_user here */ #define COPY(x) (err |= __put_user(regs->x, &sc->sc_##x)) COPY(sp); COPY(a4); COPY(b4); COPY(a6); COPY(b6); COPY(a8); COPY(b8); COPY(a0); COPY(a1); COPY(a2); COPY(a3); COPY(a5); COPY(a7); COPY(a9); COPY(b0); COPY(b1); COPY(b2); COPY(b3); COPY(b5); COPY(b7); COPY(b9); COPY(a16); COPY(a17); COPY(a18); COPY(a19); COPY(a20); COPY(a21); COPY(a22); COPY(a23); COPY(a24); COPY(a25); COPY(a26); COPY(a27); COPY(a28); COPY(a29); COPY(a30); COPY(a31); COPY(b16); COPY(b17); COPY(b18); COPY(b19); COPY(b20); COPY(b21); COPY(b22); COPY(b23); COPY(b24); COPY(b25); COPY(b26); COPY(b27); COPY(b28); COPY(b29); COPY(b30); COPY(b31); COPY(csr); COPY(pc); #undef COPY return err; }

Contributors

PersonTokensPropCommitsCommitProp
Aurelien Jacquiot327100.00%1100.00%
Total327100.00%1100.00%


static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize) { unsigned long sp = sigsp(regs->sp, ksig); /* * No matter what happens, 'sp' must be dword * aligned. Otherwise, nasty things will happen */ return (void __user *)((sp - framesize) & ~7); }

Contributors

PersonTokensPropCommitsCommitProp
Aurelien Jacquiot4787.04%150.00%
Richard Weinberger712.96%150.00%
Total54100.00%2100.00%


static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; unsigned long __user *retcode; int err = 0; frame = get_sigframe(ksig, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, &ksig->info); /* Clear all the bits of the ucontext we don't use. */ err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); /* Set up to return from userspace */ retcode = (unsigned long __user *) &frame->retcode; /* The access_ok check was done above, so use __put_user here */ #define COPY(x) (err |= __put_user(x, retcode++)) COPY(0x0000002AUL | (__NR_rt_sigreturn << 7)); /* MVK __NR_rt_sigreturn,B0 */ COPY(0x10000000UL); /* SWE */ COPY(0x00006000UL); /* NOP 4 */ COPY(0x00006000UL); /* NOP 4 */ COPY(0x00006000UL); /* NOP 4 */ COPY(0x00006000UL); /* NOP 4 */ COPY(0x00006000UL); /* NOP 4 */ COPY(0x00006000UL); /* NOP 4 */ COPY(0x00006000UL); /* NOP 4 */ #undef COPY if (err) return -EFAULT; flush_icache_range((unsigned long) &frame->retcode, (unsigned long) &frame->retcode + RETCODE_SIZE); retcode = (unsigned long __user *) &frame->retcode; /* Change user context to branch to signal handler */ regs->sp = (unsigned long) frame - 8; regs->b3 = (unsigned long) retcode; regs->pc = (unsigned long) ksig->ka.sa.sa_handler; /* Give the signal number to the handler */ regs->a4 = ksig->sig; /* * For realtime signals we must also set the second and third * arguments for the signal handler. * -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06 */ regs->b4 = (unsigned long)&frame->info; regs->a6 = (unsigned long)&frame->uc; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Aurelien Jacquiot36494.79%150.00%
Richard Weinberger205.21%150.00%
Total384100.00%2100.00%


static inline void handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) { switch (regs->a4) { case -ERESTARTNOHAND: if (!has_handler) goto do_restart; regs->a4 = -EINTR; break; case -ERESTARTSYS: if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) { regs->a4 = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: do_restart: regs->a4 = regs->orig_a4; regs->pc -= 4; break; } }

Contributors

PersonTokensPropCommitsCommitProp
Aurelien Jacquiot99100.00%1100.00%
Total99100.00%1100.00%

/* * handle the actual delivery of a signal to userspace */
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs, int syscall) { int ret; /* Are we from a system call? */ if (syscall) { /* If so, check system call restarting.. */ switch (regs->a4) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: regs->a4 = -EINTR; break; case -ERESTARTSYS: if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { regs->a4 = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: regs->a4 = regs->orig_a4; regs->pc -= 4; } } /* Set up the stack frame */ ret = setup_rt_frame(ksig, sigmask_to_save(), regs); signal_setup_done(ret, ksig, 0); }

Contributors

PersonTokensPropCommitsCommitProp
Aurelien Jacquiot10080.65%125.00%
Richard Weinberger1512.10%125.00%
Al Viro97.26%250.00%
Total124100.00%4100.00%

/* * handle a potential signal */
static void do_signal(struct pt_regs *regs, int syscall) { struct ksignal ksig; /* we want the common case to go fast, which is why we may in certain * cases get here from kernel mode */ if (!user_mode(regs)) return; if (get_signal(&ksig)) { handle_signal(&ksig, regs, syscall); return; } /* did we come from a system call? */ if (syscall) { /* restart the system call - no handlers present */ switch (regs->a4) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: regs->a4 = regs->orig_a4; regs->pc -= 4; break; case -ERESTART_RESTARTBLOCK: regs->a4 = regs->orig_a4; regs->b0 = __NR_restart_syscall; regs->pc -= 4; break; } } /* if there's no signal to deliver, we just put the saved sigmask * back */ restore_saved_sigmask(); }

Contributors

PersonTokensPropCommitsCommitProp
Aurelien Jacquiot11292.56%133.33%
Richard Weinberger75.79%133.33%
Al Viro21.65%133.33%
Total121100.00%3100.00%

/* * notification of userspace execution resumption * - triggered by current->work.notify_resume */
asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags, int syscall) { /* deal with pending signal delivery */ if (thread_info_flags & (1 << TIF_SIGPENDING)) do_signal(regs, syscall); if (thread_info_flags & (1 << TIF_NOTIFY_RESUME)) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); } }

Contributors

PersonTokensPropCommitsCommitProp
Aurelien Jacquiot57100.00%1100.00%
Total57100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Aurelien Jacquiot161195.84%111.11%
Richard Weinberger492.91%222.22%
Al Viro191.13%444.44%
Andrew Lutomirski10.06%111.11%
Matt Fleming10.06%111.11%
Total1681100.00%9100.00%
Directory: arch/c6x/kernel
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.