linux/arch/hexagon/kernel/signal.c
<<
>>
Prefs
   1/*
   2 * Signal support for Hexagon processor
   3 *
   4 * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 and
   8 * only version 2 as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  18 * 02110-1301, USA.
  19 */
  20
  21#include <linux/linkage.h>
  22#include <linux/syscalls.h>
  23#include <linux/tracehook.h>
  24#include <asm/registers.h>
  25#include <asm/thread_info.h>
  26#include <asm/unistd.h>
  27#include <asm/uaccess.h>
  28#include <asm/ucontext.h>
  29#include <asm/cacheflush.h>
  30#include <asm/signal.h>
  31#include <asm/vdso.h>
  32
  33struct rt_sigframe {
  34        unsigned long tramp[2];
  35        struct siginfo info;
  36        struct ucontext uc;
  37};
  38
  39static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
  40                          size_t frame_size)
  41{
  42        unsigned long sp = sigsp(regs->r29, ksig);
  43
  44        return (void __user *)((sp - frame_size) & ~(sizeof(long long) - 1));
  45}
  46
  47static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
  48{
  49        unsigned long tmp;
  50        int err = 0;
  51
  52        err |= copy_to_user(&sc->sc_regs.r0, &regs->r00,
  53                            32*sizeof(unsigned long));
  54
  55        err |= __put_user(regs->sa0, &sc->sc_regs.sa0);
  56        err |= __put_user(regs->lc0, &sc->sc_regs.lc0);
  57        err |= __put_user(regs->sa1, &sc->sc_regs.sa1);
  58        err |= __put_user(regs->lc1, &sc->sc_regs.lc1);
  59        err |= __put_user(regs->m0, &sc->sc_regs.m0);
  60        err |= __put_user(regs->m1, &sc->sc_regs.m1);
  61        err |= __put_user(regs->usr, &sc->sc_regs.usr);
  62        err |= __put_user(regs->preds, &sc->sc_regs.p3_0);
  63        err |= __put_user(regs->gp, &sc->sc_regs.gp);
  64        err |= __put_user(regs->ugp, &sc->sc_regs.ugp);
  65#if CONFIG_HEXAGON_ARCH_VERSION >= 4
  66        err |= __put_user(regs->cs0, &sc->sc_regs.cs0);
  67        err |= __put_user(regs->cs1, &sc->sc_regs.cs1);
  68#endif
  69        tmp = pt_elr(regs); err |= __put_user(tmp, &sc->sc_regs.pc);
  70        tmp = pt_cause(regs); err |= __put_user(tmp, &sc->sc_regs.cause);
  71        tmp = pt_badva(regs); err |= __put_user(tmp, &sc->sc_regs.badva);
  72
  73        return err;
  74}
  75
  76static int restore_sigcontext(struct pt_regs *regs,
  77                              struct sigcontext __user *sc)
  78{
  79        unsigned long tmp;
  80        int err = 0;
  81
  82        err |= copy_from_user(&regs->r00, &sc->sc_regs.r0,
  83                              32 * sizeof(unsigned long));
  84
  85        err |= __get_user(regs->sa0, &sc->sc_regs.sa0);
  86        err |= __get_user(regs->lc0, &sc->sc_regs.lc0);
  87        err |= __get_user(regs->sa1, &sc->sc_regs.sa1);
  88        err |= __get_user(regs->lc1, &sc->sc_regs.lc1);
  89        err |= __get_user(regs->m0, &sc->sc_regs.m0);
  90        err |= __get_user(regs->m1, &sc->sc_regs.m1);
  91        err |= __get_user(regs->usr, &sc->sc_regs.usr);
  92        err |= __get_user(regs->preds, &sc->sc_regs.p3_0);
  93        err |= __get_user(regs->gp, &sc->sc_regs.gp);
  94        err |= __get_user(regs->ugp, &sc->sc_regs.ugp);
  95#if CONFIG_HEXAGON_ARCH_VERSION >= 4
  96        err |= __get_user(regs->cs0, &sc->sc_regs.cs0);
  97        err |= __get_user(regs->cs1, &sc->sc_regs.cs1);
  98#endif
  99        err |= __get_user(tmp, &sc->sc_regs.pc); pt_set_elr(regs, tmp);
 100
 101        return err;
 102}
 103
 104/*
 105 * Setup signal stack frame with siginfo structure
 106 */
 107static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
 108                          struct pt_regs *regs)
 109{
 110        int err = 0;
 111        struct rt_sigframe __user *frame;
 112        struct hexagon_vdso *vdso = current->mm->context.vdso;
 113
 114        frame = get_sigframe(ksig, regs, sizeof(struct rt_sigframe));
 115
 116        if (!access_ok(VERIFY_WRITE, frame, sizeof(struct rt_sigframe)))
 117                return -EFAULT;
 118
 119        if (copy_siginfo_to_user(&frame->info, &ksig->info))
 120                return -EFAULT;
 121
 122        /* The on-stack signal trampoline is no longer executed;
 123         * however, the libgcc signal frame unwinding code checks for
 124         * the presence of these two numeric magic values.
 125         */
 126        err |= __put_user(0x7800d166, &frame->tramp[0]);
 127        err |= __put_user(0x5400c004, &frame->tramp[1]);
 128        err |= setup_sigcontext(regs, &frame->uc.uc_mcontext);
 129        err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 130        err |= __save_altstack(&frame->uc.uc_stack, user_stack_pointer(regs));
 131        if (err)
 132                return -EFAULT;
 133
 134        /* Load r0/r1 pair with signumber/siginfo pointer... */
 135        regs->r0100 = ((unsigned long long)((unsigned long)&frame->info) << 32)
 136                | (unsigned long long)ksig->sig;
 137        regs->r02 = (unsigned long) &frame->uc;
 138        regs->r31 = (unsigned long) vdso->rt_signal_trampoline;
 139        pt_psp(regs) = (unsigned long) frame;
 140        pt_set_elr(regs, (unsigned long)ksig->ka.sa.sa_handler);
 141
 142        return 0;
 143}
 144
 145/*
 146 * Setup invocation of signal handler
 147 */
 148static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 149{
 150        int ret;
 151
 152        /*
 153         * If we're handling a signal that aborted a system call,
 154         * set up the error return value before adding the signal
 155         * frame to the stack.
 156         */
 157
 158        if (regs->syscall_nr >= 0) {
 159                switch (regs->r00) {
 160                case -ERESTART_RESTARTBLOCK:
 161                case -ERESTARTNOHAND:
 162                        regs->r00 = -EINTR;
 163                        break;
 164                case -ERESTARTSYS:
 165                        if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
 166                                regs->r00 = -EINTR;
 167                                break;
 168                        }
 169                        /* Fall through */
 170                case -ERESTARTNOINTR:
 171                        regs->r06 = regs->syscall_nr;
 172                        pt_set_elr(regs, pt_elr(regs) - 4);
 173                        regs->r00 = regs->restart_r0;
 174                        break;
 175                default:
 176                        break;
 177                }
 178        }
 179
 180        /*
 181         * Set up the stack frame; not doing the SA_SIGINFO thing.  We
 182         * only set up the rt_frame flavor.
 183         */
 184        /* If there was an error on setup, no signal was delivered. */
 185        ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
 186
 187        signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
 188}
 189
 190/*
 191 * Called from return-from-event code.
 192 */
 193void do_signal(struct pt_regs *regs)
 194{
 195        struct ksignal ksig;
 196
 197        if (!user_mode(regs))
 198                return;
 199
 200        if (get_signal(&ksig)) {
 201                handle_signal(&ksig, regs);
 202                return;
 203        }
 204
 205        /*
 206         * No (more) signals; if we came from a system call, handle the restart.
 207         */
 208
 209        if (regs->syscall_nr >= 0) {
 210                switch (regs->r00) {
 211                case -ERESTARTNOHAND:
 212                case -ERESTARTSYS:
 213                case -ERESTARTNOINTR:
 214                        regs->r06 = regs->syscall_nr;
 215                        break;
 216                case -ERESTART_RESTARTBLOCK:
 217                        regs->r06 = __NR_restart_syscall;
 218                        break;
 219                default:
 220                        goto no_restart;
 221                }
 222                pt_set_elr(regs, pt_elr(regs) - 4);
 223                regs->r00 = regs->restart_r0;
 224        }
 225
 226no_restart:
 227        /* If there's no signal to deliver, put the saved sigmask back */
 228        restore_saved_sigmask();
 229}
 230
 231/*
 232 * Architecture-specific wrappers for signal-related system calls
 233 */
 234
 235asmlinkage int sys_rt_sigreturn(void)
 236{
 237        struct pt_regs *regs = current_pt_regs();
 238        struct rt_sigframe __user *frame;
 239        sigset_t blocked;
 240
 241        /* Always make any pending restarted system calls return -EINTR */
 242        current->restart_block.fn = do_no_restart_syscall;
 243
 244        frame = (struct rt_sigframe __user *)pt_psp(regs);
 245        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 246                goto badframe;
 247        if (__copy_from_user(&blocked, &frame->uc.uc_sigmask, sizeof(blocked)))
 248                goto badframe;
 249
 250        set_current_blocked(&blocked);
 251
 252        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
 253                goto badframe;
 254
 255        /* Restore the user's stack as well */
 256        pt_psp(regs) = regs->r29;
 257
 258        regs->syscall_nr = -1;
 259
 260        if (restore_altstack(&frame->uc.uc_stack))
 261                goto badframe;
 262
 263        return regs->r00;
 264
 265badframe:
 266        force_sig(SIGSEGV, current);
 267        return 0;
 268}
 269