diff options
Diffstat (limited to 'arch/score/kernel/signal.c')
-rw-r--r-- | arch/score/kernel/signal.c | 308 |
1 files changed, 0 insertions, 308 deletions
diff --git a/arch/score/kernel/signal.c b/arch/score/kernel/signal.c deleted file mode 100644 index e381c8c4ff65..000000000000 --- a/arch/score/kernel/signal.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * arch/score/kernel/signal.c - * - * Score Processor version. - * - * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. - * Chen Liqin <liqin.chen@sunplusct.com> - * Lennox Wu <lennox.wu@sunplusct.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <linux/errno.h> -#include <linux/signal.h> -#include <linux/ptrace.h> -#include <linux/unistd.h> -#include <linux/uaccess.h> -#include <linux/tracehook.h> - -#include <asm/cacheflush.h> -#include <asm/syscalls.h> -#include <asm/ucontext.h> - -struct rt_sigframe { - u32 rs_ass[4]; /* argument save space */ - u32 rs_code[2]; /* signal trampoline */ - struct siginfo rs_info; - struct ucontext rs_uc; -}; - -static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) -{ - int err = 0; - unsigned long reg; - - reg = regs->cp0_epc; err |= __put_user(reg, &sc->sc_pc); - err |= __put_user(regs->cp0_psr, &sc->sc_psr); - err |= __put_user(regs->cp0_condition, &sc->sc_condition); - - -#define save_gp_reg(i) { \ - reg = regs->regs[i]; \ - err |= __put_user(reg, &sc->sc_regs[i]); \ -} while (0) - save_gp_reg(0); save_gp_reg(1); save_gp_reg(2); - save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); - save_gp_reg(6); save_gp_reg(7); save_gp_reg(8); - save_gp_reg(9); save_gp_reg(10); save_gp_reg(11); - save_gp_reg(12); save_gp_reg(13); save_gp_reg(14); - save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); - save_gp_reg(18); save_gp_reg(19); save_gp_reg(20); - save_gp_reg(21); save_gp_reg(22); save_gp_reg(23); - save_gp_reg(24); save_gp_reg(25); save_gp_reg(26); - save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); -#undef save_gp_reg - - reg = regs->ceh; err |= __put_user(reg, &sc->sc_mdceh); - reg = regs->cel; err |= __put_user(reg, &sc->sc_mdcel); - err |= __put_user(regs->cp0_ecr, &sc->sc_ecr); - err |= __put_user(regs->cp0_ema, &sc->sc_ema); - - return err; -} - -static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) -{ - int err = 0; - u32 reg; - - err |= __get_user(regs->cp0_epc, &sc->sc_pc); - err |= __get_user(regs->cp0_condition, &sc->sc_condition); - - err |= __get_user(reg, &sc->sc_mdceh); - regs->ceh = (int) reg; - err |= __get_user(reg, &sc->sc_mdcel); - regs->cel = (int) reg; - - err |= __get_user(reg, &sc->sc_psr); - regs->cp0_psr = (int) reg; - err |= __get_user(reg, &sc->sc_ecr); - regs->cp0_ecr = (int) reg; - err |= __get_user(reg, &sc->sc_ema); - regs->cp0_ema = (int) reg; - -#define restore_gp_reg(i) do { \ - err |= __get_user(reg, &sc->sc_regs[i]); \ - regs->regs[i] = reg; \ -} while (0) - restore_gp_reg(0); restore_gp_reg(1); restore_gp_reg(2); - restore_gp_reg(3); restore_gp_reg(4); restore_gp_reg(5); - restore_gp_reg(6); restore_gp_reg(7); restore_gp_reg(8); - restore_gp_reg(9); restore_gp_reg(10); restore_gp_reg(11); - restore_gp_reg(12); restore_gp_reg(13); restore_gp_reg(14); - restore_gp_reg(15); restore_gp_reg(16); restore_gp_reg(17); - restore_gp_reg(18); restore_gp_reg(19); restore_gp_reg(20); - restore_gp_reg(21); restore_gp_reg(22); restore_gp_reg(23); - restore_gp_reg(24); restore_gp_reg(25); restore_gp_reg(26); - restore_gp_reg(27); restore_gp_reg(28); restore_gp_reg(29); -#undef restore_gp_reg - - return err; -} - -/* - * Determine which stack to use.. - */ -static void __user *get_sigframe(struct k_sigaction *ka, - struct pt_regs *regs, size_t frame_size) -{ - unsigned long sp; - - /* Default to using normal stack */ - sp = regs->regs[0]; - sp -= 32; - - /* This is the X/Open sanctioned signal stack switching. */ - if ((ka->sa.sa_flags & SA_ONSTACK) && (!on_sig_stack(sp))) - sp = current->sas_ss_sp + current->sas_ss_size; - - return (void __user*)((sp - frame_size) & ~7); -} - -asmlinkage long -score_rt_sigreturn(struct pt_regs *regs) -{ - struct rt_sigframe __user *frame; - sigset_t set; - int sig; - - /* Always make any pending restarted system calls return -EINTR */ - current->restart_block.fn = do_no_restart_syscall; - - frame = (struct rt_sigframe __user *) regs->regs[0]; - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) - goto badframe; - - set_current_blocked(&set); - - sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext); - if (sig < 0) - goto badframe; - else if (sig) - force_sig(sig, current); - - if (restore_altstack(&frame->rs_uc.uc_stack)) - goto badframe; - regs->is_syscall = 0; - - __asm__ __volatile__( - "mv\tr0, %0\n\t" - "la\tr8, syscall_exit\n\t" - "br\tr8\n\t" - : : "r" (regs) : "r8"); - -badframe: - force_sig(SIGSEGV, current); - - return 0; -} - -static int setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs, - sigset_t *set) -{ - struct rt_sigframe __user *frame; - int err = 0; - - frame = get_sigframe(&ksig->ka, regs, sizeof(*frame)); - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - return -EFAULT; - - /* - * Set up the return code ... - * - * li v0, __NR_rt_sigreturn - * syscall - */ - err |= __put_user(0x87788000 + __NR_rt_sigreturn*2, - frame->rs_code + 0); - err |= __put_user(0x80008002, frame->rs_code + 1); - flush_cache_sigtramp((unsigned long) frame->rs_code); - - err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info); - err |= __put_user(0, &frame->rs_uc.uc_flags); - err |= __put_user(NULL, &frame->rs_uc.uc_link); - err |= __save_altstack(&frame->rs_uc.uc_stack, regs->regs[0]); - err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext); - err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set)); - - if (err) - return -EFAULT; - - regs->regs[0] = (unsigned long) frame; - regs->regs[3] = (unsigned long) frame->rs_code; - regs->regs[4] = ksig->sig; - regs->regs[5] = (unsigned long) &frame->rs_info; - regs->regs[6] = (unsigned long) &frame->rs_uc; - regs->regs[29] = (unsigned long) ksig->ka.sa.sa_handler; - regs->cp0_epc = (unsigned long) ksig->ka.sa.sa_handler; - - return 0; -} - -static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) -{ - int ret; - - if (regs->is_syscall) { - switch (regs->regs[4]) { - case ERESTART_RESTARTBLOCK: - case ERESTARTNOHAND: - regs->regs[4] = EINTR; - break; - case ERESTARTSYS: - if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { - regs->regs[4] = EINTR; - break; - } - case ERESTARTNOINTR: - regs->regs[4] = regs->orig_r4; - regs->regs[7] = regs->orig_r7; - regs->cp0_epc -= 8; - } - - regs->is_syscall = 0; - } - - /* - * Set up the stack frame - */ - ret = setup_rt_frame(ksig, regs, sigmask_to_save()); - - signal_setup_done(ret, ksig, 0); -} - -static void do_signal(struct pt_regs *regs) -{ - struct ksignal ksig; - - /* - * We want the common case to go fast, which is why we may in certain - * cases get here from kernel mode. Just return without doing anything - * if so. - */ - if (!user_mode(regs)) - return; - - if (get_signal(&ksig)) { - /* Actually deliver the signal. */ - handle_signal(&ksig, regs); - return; - } - - if (regs->is_syscall) { - if (regs->regs[4] == ERESTARTNOHAND || - regs->regs[4] == ERESTARTSYS || - regs->regs[4] == ERESTARTNOINTR) { - regs->regs[4] = regs->orig_r4; - regs->regs[7] = regs->orig_r7; - regs->cp0_epc -= 8; - } - - if (regs->regs[4] == ERESTART_RESTARTBLOCK) { - regs->regs[27] = __NR_restart_syscall; - regs->regs[4] = regs->orig_r4; - regs->regs[7] = regs->orig_r7; - regs->cp0_epc -= 8; - } - - regs->is_syscall = 0; /* Don't deal with this again. */ - } - - /* - * If there's no signal to deliver, we just put the saved sigmask - * back - */ - restore_saved_sigmask(); -} - -/* - * notification of userspace execution resumption - * - triggered by the TIF_WORK_MASK flags - */ -asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, - __u32 thread_info_flags) -{ - /* deal with pending signal delivery */ - if (thread_info_flags & _TIF_SIGPENDING) - do_signal(regs); - if (thread_info_flags & _TIF_NOTIFY_RESUME) { - clear_thread_flag(TIF_NOTIFY_RESUME); - tracehook_notify_resume(regs); - } -} |