linux/arch/score/kernel/signal.c
<<
>>
Prefs
   1/*
   2 * arch/score/kernel/signal.c
   3 *
   4 * Score Processor version.
   5 *
   6 * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
   7 *  Chen Liqin <liqin.chen@sunplusct.com>
   8 *  Lennox Wu <lennox.wu@sunplusct.com>
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License as published by
  12 * the Free Software Foundation; either version 2 of the License, or
  13 * (at your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU General Public License for more details.
  19 *
  20 * You should have received a copy of the GNU General Public License
  21 * along with this program; if not, see the file COPYING, or write
  22 * to the Free Software Foundation, Inc.,
  23 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  24 */
  25
  26#include <linux/errno.h>
  27#include <linux/signal.h>
  28#include <linux/ptrace.h>
  29#include <linux/unistd.h>
  30#include <linux/uaccess.h>
  31
  32#include <asm/cacheflush.h>
  33#include <asm/syscalls.h>
  34#include <asm/ucontext.h>
  35
  36#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
  37
  38struct rt_sigframe {
  39        u32 rs_ass[4];          /* argument save space */
  40        u32 rs_code[2];         /* signal trampoline */
  41        struct siginfo rs_info;
  42        struct ucontext rs_uc;
  43};
  44
  45static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
  46{
  47        int err = 0;
  48        unsigned long reg;
  49
  50        reg = regs->cp0_epc; err |= __put_user(reg, &sc->sc_pc);
  51        err |= __put_user(regs->cp0_psr, &sc->sc_psr);
  52        err |= __put_user(regs->cp0_condition, &sc->sc_condition);
  53
  54
  55#define save_gp_reg(i) {                                \
  56        reg = regs->regs[i];                            \
  57        err |= __put_user(reg, &sc->sc_regs[i]);        \
  58} while (0)
  59        save_gp_reg(0); save_gp_reg(1); save_gp_reg(2);
  60        save_gp_reg(3); save_gp_reg(4); save_gp_reg(5);
  61        save_gp_reg(6); save_gp_reg(7); save_gp_reg(8);
  62        save_gp_reg(9); save_gp_reg(10); save_gp_reg(11);
  63        save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
  64        save_gp_reg(15); save_gp_reg(16); save_gp_reg(17);
  65        save_gp_reg(18); save_gp_reg(19); save_gp_reg(20);
  66        save_gp_reg(21); save_gp_reg(22); save_gp_reg(23);
  67        save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
  68        save_gp_reg(27); save_gp_reg(28); save_gp_reg(29);
  69#undef save_gp_reg
  70
  71        reg = regs->ceh; err |= __put_user(reg, &sc->sc_mdceh);
  72        reg = regs->cel; err |= __put_user(reg, &sc->sc_mdcel);
  73        err |= __put_user(regs->cp0_ecr, &sc->sc_ecr);
  74        err |= __put_user(regs->cp0_ema, &sc->sc_ema);
  75
  76        return err;
  77}
  78
  79static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
  80{
  81        int err = 0;
  82        u32 reg;
  83
  84        err |= __get_user(regs->cp0_epc, &sc->sc_pc);
  85        err |= __get_user(regs->cp0_condition, &sc->sc_condition);
  86
  87        err |= __get_user(reg, &sc->sc_mdceh);
  88        regs->ceh = (int) reg;
  89        err |= __get_user(reg, &sc->sc_mdcel);
  90        regs->cel = (int) reg;
  91
  92        err |= __get_user(reg, &sc->sc_psr);
  93        regs->cp0_psr = (int) reg;
  94        err |= __get_user(reg, &sc->sc_ecr);
  95        regs->cp0_ecr = (int) reg;
  96        err |= __get_user(reg, &sc->sc_ema);
  97        regs->cp0_ema = (int) reg;
  98
  99#define restore_gp_reg(i) do {                          \
 100        err |= __get_user(reg, &sc->sc_regs[i]);        \
 101        regs->regs[i] = reg;                            \
 102} while (0)
 103        restore_gp_reg(0); restore_gp_reg(1); restore_gp_reg(2);
 104        restore_gp_reg(3); restore_gp_reg(4); restore_gp_reg(5);
 105        restore_gp_reg(6); restore_gp_reg(7); restore_gp_reg(8);
 106        restore_gp_reg(9); restore_gp_reg(10); restore_gp_reg(11);
 107        restore_gp_reg(12); restore_gp_reg(13); restore_gp_reg(14);
 108        restore_gp_reg(15); restore_gp_reg(16); restore_gp_reg(17);
 109        restore_gp_reg(18); restore_gp_reg(19); restore_gp_reg(20);
 110        restore_gp_reg(21); restore_gp_reg(22); restore_gp_reg(23);
 111        restore_gp_reg(24); restore_gp_reg(25); restore_gp_reg(26);
 112        restore_gp_reg(27); restore_gp_reg(28); restore_gp_reg(29);
 113#undef restore_gp_reg
 114
 115        return err;
 116}
 117
 118/*
 119 * Determine which stack to use..
 120 */
 121static void __user *get_sigframe(struct k_sigaction *ka,
 122                        struct pt_regs *regs, size_t frame_size)
 123{
 124        unsigned long sp;
 125
 126        /* Default to using normal stack */
 127        sp = regs->regs[0];
 128        sp -= 32;
 129
 130        /* This is the X/Open sanctioned signal stack switching.  */
 131        if ((ka->sa.sa_flags & SA_ONSTACK) && (!on_sig_stack(sp)))
 132                sp = current->sas_ss_sp + current->sas_ss_size;
 133
 134        return (void __user*)((sp - frame_size) & ~7);
 135}
 136
 137asmlinkage long
 138score_sigaltstack(struct pt_regs *regs)
 139{
 140        const stack_t __user *uss = (const stack_t __user *) regs->regs[4];
 141        stack_t __user *uoss = (stack_t __user *) regs->regs[5];
 142        unsigned long usp = regs->regs[0];
 143
 144        return do_sigaltstack(uss, uoss, usp);
 145}
 146
 147asmlinkage long
 148score_rt_sigreturn(struct pt_regs *regs)
 149{
 150        struct rt_sigframe __user *frame;
 151        sigset_t set;
 152        stack_t st;
 153        int sig;
 154
 155        frame = (struct rt_sigframe __user *) regs->regs[0];
 156        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 157                goto badframe;
 158        if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
 159                goto badframe;
 160
 161        sigdelsetmask(&set, ~_BLOCKABLE);
 162        spin_lock_irq(&current->sighand->siglock);
 163        current->blocked = set;
 164        recalc_sigpending();
 165        spin_unlock_irq(&current->sighand->siglock);
 166
 167        sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext);
 168        if (sig < 0)
 169                goto badframe;
 170        else if (sig)
 171                force_sig(sig, current);
 172
 173        if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st)))
 174                goto badframe;
 175
 176        /* It is more difficult to avoid calling this function than to
 177           call it and ignore errors.  */
 178        do_sigaltstack((stack_t __user *)&st, NULL, regs->regs[0]);
 179
 180        __asm__ __volatile__(
 181                "mv\tr0, %0\n\t"
 182                "la\tr8, syscall_exit\n\t"
 183                "br\tr8\n\t"
 184                : : "r" (regs) : "r8");
 185
 186badframe:
 187        force_sig(SIGSEGV, current);
 188
 189        return 0;
 190}
 191
 192static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
 193                int signr, sigset_t *set, siginfo_t *info)
 194{
 195        struct rt_sigframe __user *frame;
 196        int err = 0;
 197
 198        frame = get_sigframe(ka, regs, sizeof(*frame));
 199        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 200                goto give_sigsegv;
 201
 202        /*
 203         * Set up the return code ...
 204         *
 205         *         li      v0, __NR_rt_sigreturn
 206         *         syscall
 207         */
 208        err |= __put_user(0x87788000 + __NR_rt_sigreturn*2,
 209                        frame->rs_code + 0);
 210        err |= __put_user(0x80008002, frame->rs_code + 1);
 211        flush_cache_sigtramp((unsigned long) frame->rs_code);
 212
 213        err |= copy_siginfo_to_user(&frame->rs_info, info);
 214        err |= __put_user(0, &frame->rs_uc.uc_flags);
 215        err |= __put_user(NULL, &frame->rs_uc.uc_link);
 216        err |= __put_user((void __user *)current->sas_ss_sp,
 217                                &frame->rs_uc.uc_stack.ss_sp);
 218        err |= __put_user(sas_ss_flags(regs->regs[0]),
 219                                &frame->rs_uc.uc_stack.ss_flags);
 220        err |= __put_user(current->sas_ss_size,
 221                                &frame->rs_uc.uc_stack.ss_size);
 222        err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
 223        err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
 224
 225        if (err)
 226                goto give_sigsegv;
 227
 228        regs->regs[0] = (unsigned long) frame;
 229        regs->regs[3] = (unsigned long) frame->rs_code;
 230        regs->regs[4] = signr;
 231        regs->regs[5] = (unsigned long) &frame->rs_info;
 232        regs->regs[6] = (unsigned long) &frame->rs_uc;
 233        regs->regs[29] = (unsigned long) ka->sa.sa_handler;
 234        regs->cp0_epc = (unsigned long) ka->sa.sa_handler;
 235
 236        return 0;
 237
 238give_sigsegv:
 239        if (signr == SIGSEGV)
 240                ka->sa.sa_handler = SIG_DFL;
 241        force_sig(SIGSEGV, current);
 242        return -EFAULT;
 243}
 244
 245static int handle_signal(unsigned long sig, siginfo_t *info,
 246        struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
 247{
 248        int ret;
 249
 250        if (regs->is_syscall) {
 251                switch (regs->regs[4]) {
 252                case ERESTART_RESTARTBLOCK:
 253                case ERESTARTNOHAND:
 254                        regs->regs[4] = EINTR;
 255                        break;
 256                case ERESTARTSYS:
 257                        if (!(ka->sa.sa_flags & SA_RESTART)) {
 258                                regs->regs[4] = EINTR;
 259                                break;
 260                        }
 261                case ERESTARTNOINTR:
 262                        regs->regs[4] = regs->orig_r4;
 263                        regs->regs[7] = regs->orig_r7;
 264                        regs->cp0_epc -= 8;
 265                }
 266
 267                regs->is_syscall = 0;
 268        }
 269
 270        /*
 271         * Set up the stack frame
 272         */
 273        ret = setup_rt_frame(ka, regs, sig, oldset, info);
 274
 275        spin_lock_irq(&current->sighand->siglock);
 276        sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
 277        if (!(ka->sa.sa_flags & SA_NODEFER))
 278                sigaddset(&current->blocked, sig);
 279        recalc_sigpending();
 280        spin_unlock_irq(&current->sighand->siglock);
 281
 282        return ret;
 283}
 284
 285static void do_signal(struct pt_regs *regs)
 286{
 287        struct k_sigaction ka;
 288        sigset_t *oldset;
 289        siginfo_t info;
 290        int signr;
 291
 292        /*
 293         * We want the common case to go fast, which is why we may in certain
 294         * cases get here from kernel mode. Just return without doing anything
 295         * if so.
 296         */
 297        if (!user_mode(regs))
 298                return;
 299
 300        if (test_thread_flag(TIF_RESTORE_SIGMASK))
 301                oldset = &current->saved_sigmask;
 302        else
 303                oldset = &current->blocked;
 304
 305        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 306        if (signr > 0) {
 307                /* Actually deliver the signal.  */
 308                if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
 309                        /*
 310                         * A signal was successfully delivered; the saved
 311                         * sigmask will have been stored in the signal frame,
 312                         * and will be restored by sigreturn, so we can simply
 313                         * clear the TIF_RESTORE_SIGMASK flag.
 314                         */
 315                        if (test_thread_flag(TIF_RESTORE_SIGMASK))
 316                                clear_thread_flag(TIF_RESTORE_SIGMASK);
 317                }
 318
 319                return;
 320        }
 321
 322        if (regs->is_syscall) {
 323                if (regs->regs[4] == ERESTARTNOHAND ||
 324                    regs->regs[4] == ERESTARTSYS ||
 325                    regs->regs[4] == ERESTARTNOINTR) {
 326                        regs->regs[4] = regs->orig_r4;
 327                        regs->regs[7] = regs->orig_r7;
 328                        regs->cp0_epc -= 8;
 329                }
 330
 331                if (regs->regs[4] == ERESTART_RESTARTBLOCK) {
 332                        regs->regs[27] = __NR_restart_syscall;
 333                        regs->regs[4] = regs->orig_r4;
 334                        regs->regs[7] = regs->orig_r7;
 335                        regs->cp0_epc -= 8;
 336                }
 337
 338                regs->is_syscall = 0;   /* Don't deal with this again.  */
 339        }
 340
 341        /*
 342         * If there's no signal to deliver, we just put the saved sigmask
 343         * back
 344         */
 345        if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
 346                clear_thread_flag(TIF_RESTORE_SIGMASK);
 347                sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
 348        }
 349}
 350
 351/*
 352 * notification of userspace execution resumption
 353 * - triggered by the TIF_WORK_MASK flags
 354 */
 355asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
 356                                __u32 thread_info_flags)
 357{
 358        /* deal with pending signal delivery */
 359        if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
 360                do_signal(regs);
 361}
 362