linux/arch/xtensa/kernel/signal.c
<<
>>
Prefs
   1/*
   2 * arch/xtensa/kernel/signal.c
   3 *
   4 * Default platform functions.
   5 *
   6 * This file is subject to the terms and conditions of the GNU General Public
   7 * License.  See the file "COPYING" in the main directory of this archive
   8 * for more details.
   9 *
  10 * Copyright (C) 2005, 2006 Tensilica Inc.
  11 * Copyright (C) 1991, 1992  Linus Torvalds
  12 * 1997-11-28  Modified for POSIX.1b signals by Richard Henderson
  13 *
  14 * Chris Zankel <chris@zankel.net>
  15 * Joe Taylor <joe@tensilica.com>
  16 */
  17
  18#include <linux/signal.h>
  19#include <linux/errno.h>
  20#include <linux/ptrace.h>
  21#include <linux/personality.h>
  22#include <linux/freezer.h>
  23
  24#include <asm/ucontext.h>
  25#include <asm/uaccess.h>
  26#include <asm/cacheflush.h>
  27#include <asm/coprocessor.h>
  28#include <asm/unistd.h>
  29
  30#define DEBUG_SIG  0
  31
  32#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
  33
  34asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
  35
  36extern struct task_struct *coproc_owners[];
  37
  38struct rt_sigframe
  39{
  40        struct siginfo info;
  41        struct ucontext uc;
  42        struct {
  43                xtregs_opt_t opt;
  44                xtregs_user_t user;
  45#if XTENSA_HAVE_COPROCESSORS
  46                xtregs_coprocessor_t cp;
  47#endif
  48        } xtregs;
  49        unsigned char retcode[6];
  50        unsigned int window[4];
  51};
  52
  53/* 
  54 * Flush register windows stored in pt_regs to stack.
  55 * Returns 1 for errors.
  56 */
  57
  58int
  59flush_window_regs_user(struct pt_regs *regs)
  60{
  61        const unsigned long ws = regs->windowstart;
  62        const unsigned long wb = regs->windowbase;
  63        unsigned long sp = 0;
  64        unsigned long wm;
  65        int err = 1;
  66        int base;
  67
  68        /* Return if no other frames. */
  69
  70        if (regs->wmask == 1)
  71                return 0;
  72
  73        /* Rotate windowmask and skip empty frames. */
  74
  75        wm = (ws >> wb) | (ws << (XCHAL_NUM_AREGS / 4 - wb));
  76        base = (XCHAL_NUM_AREGS / 4) - (regs->wmask >> 4);
  77                
  78        /* For call8 or call12 frames, we need the previous stack pointer. */
  79
  80        if ((regs->wmask & 2) == 0)
  81                if (__get_user(sp, (int*)(regs->areg[base * 4 + 1] - 12)))
  82                        goto errout;
  83
  84        /* Spill frames to stack. */
  85
  86        while (base < XCHAL_NUM_AREGS / 4) {
  87
  88                int m = (wm >> base);
  89                int inc = 0;
  90
  91                /* Save registers a4..a7 (call8) or a4...a11 (call12) */
  92
  93                if (m & 2) {                    /* call4 */
  94                        inc = 1;
  95
  96                } else if (m & 4) {             /* call8 */
  97                        if (copy_to_user((void*)(sp - 32),
  98                                           &regs->areg[(base + 1) * 4], 16))
  99                                goto errout;
 100                        inc = 2;
 101
 102                } else if (m & 8) {     /* call12 */
 103                        if (copy_to_user((void*)(sp - 48),
 104                                           &regs->areg[(base + 1) * 4], 32))
 105                                goto errout;
 106                        inc = 3;
 107                }
 108
 109                /* Save current frame a0..a3 under next SP */
 110
 111                sp = regs->areg[((base + inc) * 4 + 1) % XCHAL_NUM_AREGS];
 112                if (copy_to_user((void*)(sp - 16), &regs->areg[base * 4], 16))
 113                        goto errout;
 114
 115                /* Get current stack pointer for next loop iteration. */
 116
 117                sp = regs->areg[base * 4 + 1];
 118                base += inc;
 119        }
 120
 121        regs->wmask = 1;
 122        regs->windowstart = 1 << wb;
 123
 124        return 0;
 125
 126errout:
 127        return err;
 128}
 129
 130/*
 131 * Note: We don't copy double exception 'regs', we have to finish double exc. 
 132 * first before we return to signal handler! This dbl.exc.handler might cause 
 133 * another double exception, but I think we are fine as the situation is the 
 134 * same as if we had returned to the signal handerl and got an interrupt 
 135 * immediately...
 136 */
 137
 138static int
 139setup_sigcontext(struct rt_sigframe __user *frame, struct pt_regs *regs)
 140{
 141        struct sigcontext __user *sc = &frame->uc.uc_mcontext;
 142        struct thread_info *ti = current_thread_info();
 143        int err = 0;
 144
 145#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
 146        COPY(pc);
 147        COPY(ps);
 148        COPY(lbeg);
 149        COPY(lend);
 150        COPY(lcount);
 151        COPY(sar);
 152#undef COPY
 153
 154        err |= flush_window_regs_user(regs);
 155        err |= __copy_to_user (sc->sc_a, regs->areg, 16 * 4);
 156        err |= __put_user(0, &sc->sc_xtregs);
 157
 158        if (err)
 159                return err;
 160
 161#if XTENSA_HAVE_COPROCESSORS
 162        coprocessor_flush_all(ti);
 163        coprocessor_release_all(ti);
 164        err |= __copy_to_user(&frame->xtregs.cp, &ti->xtregs_cp,
 165                              sizeof (frame->xtregs.cp));
 166#endif
 167        err |= __copy_to_user(&frame->xtregs.opt, &regs->xtregs_opt,
 168                              sizeof (xtregs_opt_t));
 169        err |= __copy_to_user(&frame->xtregs.user, &ti->xtregs_user,
 170                              sizeof (xtregs_user_t));
 171
 172        err |= __put_user(err ? NULL : &frame->xtregs, &sc->sc_xtregs);
 173
 174        return err;
 175}
 176
 177static int
 178restore_sigcontext(struct pt_regs *regs, struct rt_sigframe __user *frame)
 179{
 180        struct sigcontext __user *sc = &frame->uc.uc_mcontext;
 181        struct thread_info *ti = current_thread_info();
 182        unsigned int err = 0;
 183        unsigned long ps;
 184
 185#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
 186        COPY(pc);
 187        COPY(lbeg);
 188        COPY(lend);
 189        COPY(lcount);
 190        COPY(sar);
 191#undef COPY
 192
 193        /* All registers were flushed to stack. Start with a prestine frame. */
 194
 195        regs->wmask = 1;
 196        regs->windowbase = 0;
 197        regs->windowstart = 1;
 198
 199        regs->syscall = -1;             /* disable syscall checks */
 200
 201        /* For PS, restore only PS.CALLINC.
 202         * Assume that all other bits are either the same as for the signal
 203         * handler, or the user mode value doesn't matter (e.g. PS.OWB).
 204         */
 205        err |= __get_user(ps, &sc->sc_ps);
 206        regs->ps = (regs->ps & ~PS_CALLINC_MASK) | (ps & PS_CALLINC_MASK);
 207
 208        /* Additional corruption checks */
 209
 210        if ((regs->lcount > 0)
 211            && ((regs->lbeg > TASK_SIZE) || (regs->lend > TASK_SIZE)) )
 212                err = 1;
 213
 214        err |= __copy_from_user(regs->areg, sc->sc_a, 16 * 4);
 215
 216        if (err)
 217                return err;
 218
 219        /* The signal handler may have used coprocessors in which
 220         * case they are still enabled.  We disable them to force a
 221         * reloading of the original task's CP state by the lazy
 222         * context-switching mechanisms of CP exception handling.
 223         * Also, we essentially discard any coprocessor state that the
 224         * signal handler created. */
 225
 226#if XTENSA_HAVE_COPROCESSORS
 227        coprocessor_release_all(ti);
 228        err |= __copy_from_user(&ti->xtregs_cp, &frame->xtregs.cp,
 229                                sizeof (frame->xtregs.cp));
 230#endif
 231        err |= __copy_from_user(&ti->xtregs_user, &frame->xtregs.user,
 232                                sizeof (xtregs_user_t));
 233        err |= __copy_from_user(&regs->xtregs_opt, &frame->xtregs.opt,
 234                                sizeof (xtregs_opt_t));
 235
 236        return err;
 237}
 238
 239
 240/*
 241 * Do a signal return; undo the signal stack.
 242 */
 243
 244asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3,
 245                                    long a4, long a5, struct pt_regs *regs)
 246{
 247        struct rt_sigframe __user *frame;
 248        sigset_t set;
 249        int ret;
 250
 251        if (regs->depc > 64)
 252                panic("rt_sigreturn in double exception!\n");
 253
 254        frame = (struct rt_sigframe __user *) regs->areg[1];
 255
 256        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 257                goto badframe;
 258
 259        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
 260                goto badframe;
 261
 262        sigdelsetmask(&set, ~_BLOCKABLE);
 263        spin_lock_irq(&current->sighand->siglock);
 264        current->blocked = set;
 265        recalc_sigpending();
 266        spin_unlock_irq(&current->sighand->siglock);
 267
 268        if (restore_sigcontext(regs, frame))
 269                goto badframe;
 270
 271        ret = regs->areg[2];
 272
 273        if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->areg[1]) == -EFAULT)
 274                goto badframe;
 275
 276        return ret;
 277
 278badframe:
 279        force_sig(SIGSEGV, current);
 280        return 0;
 281}
 282
 283
 284
 285/*
 286 * Set up a signal frame.
 287 */
 288
 289static int
 290gen_return_code(unsigned char *codemem)
 291{
 292        int err = 0;
 293
 294        /*
 295         * The 12-bit immediate is really split up within the 24-bit MOVI
 296         * instruction.  As long as the above system call numbers fit within
 297         * 8-bits, the following code works fine. See the Xtensa ISA for
 298         * details.
 299         */
 300
 301#if __NR_rt_sigreturn > 255
 302# error Generating the MOVI instruction below breaks!
 303#endif
 304
 305#ifdef __XTENSA_EB__   /* Big Endian version */
 306        /* Generate instruction:  MOVI a2, __NR_rt_sigreturn */
 307        err |= __put_user(0x22, &codemem[0]);
 308        err |= __put_user(0x0a, &codemem[1]);
 309        err |= __put_user(__NR_rt_sigreturn, &codemem[2]);
 310        /* Generate instruction:  SYSCALL */
 311        err |= __put_user(0x00, &codemem[3]);
 312        err |= __put_user(0x05, &codemem[4]);
 313        err |= __put_user(0x00, &codemem[5]);
 314
 315#elif defined __XTENSA_EL__   /* Little Endian version */
 316        /* Generate instruction:  MOVI a2, __NR_rt_sigreturn */
 317        err |= __put_user(0x22, &codemem[0]);
 318        err |= __put_user(0xa0, &codemem[1]);
 319        err |= __put_user(__NR_rt_sigreturn, &codemem[2]);
 320        /* Generate instruction:  SYSCALL */
 321        err |= __put_user(0x00, &codemem[3]);
 322        err |= __put_user(0x50, &codemem[4]);
 323        err |= __put_user(0x00, &codemem[5]);
 324#else
 325# error Must use compiler for Xtensa processors.
 326#endif
 327
 328        /* Flush generated code out of the data cache */
 329
 330        if (err == 0) {
 331                __invalidate_icache_range((unsigned long)codemem, 6UL);
 332                __flush_invalidate_dcache_range((unsigned long)codemem, 6UL);
 333        }
 334
 335        return err;
 336}
 337
 338
 339static void setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 340                        sigset_t *set, struct pt_regs *regs)
 341{
 342        struct rt_sigframe *frame;
 343        int err = 0;
 344        int signal;
 345        unsigned long sp, ra;
 346
 347        sp = regs->areg[1];
 348
 349        if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) {
 350                sp = current->sas_ss_sp + current->sas_ss_size;
 351        }
 352
 353        frame = (void *)((sp - sizeof(*frame)) & -16ul);
 354
 355        if (regs->depc > 64)
 356                panic ("Double exception sys_sigreturn\n");
 357
 358        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) {
 359                goto give_sigsegv;
 360        }
 361
 362        signal = current_thread_info()->exec_domain
 363                && current_thread_info()->exec_domain->signal_invmap
 364                && sig < 32
 365                ? current_thread_info()->exec_domain->signal_invmap[sig]
 366                : sig;
 367
 368        if (ka->sa.sa_flags & SA_SIGINFO) {
 369                err |= copy_siginfo_to_user(&frame->info, info);
 370        }
 371
 372        /* Create the user context.  */
 373
 374        err |= __put_user(0, &frame->uc.uc_flags);
 375        err |= __put_user(0, &frame->uc.uc_link);
 376        err |= __put_user((void *)current->sas_ss_sp,
 377                          &frame->uc.uc_stack.ss_sp);
 378        err |= __put_user(sas_ss_flags(regs->areg[1]),
 379                          &frame->uc.uc_stack.ss_flags);
 380        err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
 381        err |= setup_sigcontext(frame, regs);
 382        err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 383
 384        if (ka->sa.sa_flags & SA_RESTORER) {
 385                ra = (unsigned long)ka->sa.sa_restorer;
 386        } else {
 387
 388                /* Create sys_rt_sigreturn syscall in stack frame */
 389
 390                err |= gen_return_code(frame->retcode);
 391
 392                if (err) {
 393                        goto give_sigsegv;
 394                }
 395                ra = (unsigned long) frame->retcode;
 396        }
 397
 398        /* 
 399         * Create signal handler execution context.
 400         * Return context not modified until this point.
 401         */
 402
 403        /* Set up registers for signal handler */
 404        start_thread(regs, (unsigned long) ka->sa.sa_handler, 
 405                     (unsigned long) frame);
 406
 407        /* Set up a stack frame for a call4
 408         * Note: PS.CALLINC is set to one by start_thread
 409         */
 410        regs->areg[4] = (((unsigned long) ra) & 0x3fffffff) | 0x40000000;
 411        regs->areg[6] = (unsigned long) signal;
 412        regs->areg[7] = (unsigned long) &frame->info;
 413        regs->areg[8] = (unsigned long) &frame->uc;
 414
 415        /* Set access mode to USER_DS.  Nomenclature is outdated, but
 416         * functionality is used in uaccess.h
 417         */
 418        set_fs(USER_DS);
 419
 420#if DEBUG_SIG
 421        printk("SIG rt deliver (%s:%d): signal=%d sp=%p pc=%08x\n",
 422                current->comm, current->pid, signal, frame, regs->pc);
 423#endif
 424
 425        return;
 426
 427give_sigsegv:
 428        if (sig == SIGSEGV)
 429                ka->sa.sa_handler = SIG_DFL;
 430        force_sig(SIGSEGV, current);
 431}
 432
 433/*
 434 * Atomically swap in the new signal mask, and wait for a signal.
 435 */
 436
 437asmlinkage long xtensa_rt_sigsuspend(sigset_t __user *unewset, 
 438                                     size_t sigsetsize,
 439                                     long a2, long a3, long a4, long a5, 
 440                                     struct pt_regs *regs)
 441{
 442        sigset_t saveset, newset;
 443
 444        /* XXX: Don't preclude handling different sized sigset_t's.  */
 445        if (sigsetsize != sizeof(sigset_t))
 446                return -EINVAL;
 447
 448        if (copy_from_user(&newset, unewset, sizeof(newset)))
 449                return -EFAULT;
 450
 451        sigdelsetmask(&newset, ~_BLOCKABLE);
 452        spin_lock_irq(&current->sighand->siglock);
 453        saveset = current->blocked;
 454        current->blocked = newset;
 455        recalc_sigpending();
 456        spin_unlock_irq(&current->sighand->siglock);
 457
 458        regs->areg[2] = -EINTR;
 459        while (1) {
 460                current->state = TASK_INTERRUPTIBLE;
 461                schedule();
 462                if (do_signal(regs, &saveset))
 463                        return -EINTR;
 464        }
 465}
 466
 467asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, 
 468                                   stack_t __user *uoss,
 469                                   long a2, long a3, long a4, long a5,
 470                                   struct pt_regs *regs)
 471{
 472        return do_sigaltstack(uss, uoss, regs->areg[1]);
 473}
 474
 475
 476
 477/*
 478 * Note that 'init' is a special process: it doesn't get signals it doesn't
 479 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 480 * mistake.
 481 *
 482 * Note that we go through the signals twice: once to check the signals that
 483 * the kernel can handle, and then we build all the user-level signal handling
 484 * stack-frames in one go after that.
 485 */
 486int do_signal(struct pt_regs *regs, sigset_t *oldset)
 487{
 488        siginfo_t info;
 489        int signr;
 490        struct k_sigaction ka;
 491
 492        if (!user_mode(regs))
 493                return 0;
 494
 495        if (try_to_freeze())
 496                goto no_signal;
 497
 498        if (!oldset)
 499                oldset = &current->blocked;
 500
 501        task_pt_regs(current)->icountlevel = 0;
 502
 503        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 504
 505        if (signr > 0) {
 506
 507                /* Are we from a system call? */
 508
 509                if ((signed)regs->syscall >= 0) {
 510
 511                        /* If so, check system call restarting.. */
 512
 513                        switch (regs->areg[2]) {
 514                                case -ERESTARTNOHAND:
 515                                case -ERESTART_RESTARTBLOCK:
 516                                        regs->areg[2] = -EINTR;
 517                                        break;
 518
 519                                case -ERESTARTSYS:
 520                                        if (!(ka.sa.sa_flags & SA_RESTART)) {
 521                                                regs->areg[2] = -EINTR;
 522                                                break;
 523                                        }
 524                                        /* fallthrough */
 525                                case -ERESTARTNOINTR:
 526                                        regs->areg[2] = regs->syscall;
 527                                        regs->pc -= 3;
 528                                        break;
 529
 530                                default:
 531                                        /* nothing to do */
 532                                        if (regs->areg[2] != 0)
 533                                        break;
 534                        }
 535                }
 536
 537                /* Whee!  Actually deliver the signal.  */
 538                /* Set up the stack frame */
 539                setup_frame(signr, &ka, &info, oldset, regs);
 540
 541                if (ka.sa.sa_flags & SA_ONESHOT)
 542                        ka.sa.sa_handler = SIG_DFL;
 543
 544                spin_lock_irq(&current->sighand->siglock);
 545                sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
 546                if (!(ka.sa.sa_flags & SA_NODEFER))
 547                        sigaddset(&current->blocked, signr);
 548                recalc_sigpending();
 549                spin_unlock_irq(&current->sighand->siglock);
 550                if (current->ptrace & PT_SINGLESTEP)
 551                        task_pt_regs(current)->icountlevel = 1;
 552
 553                return 1;
 554        }
 555
 556no_signal:
 557        /* Did we come from a system call? */
 558        if ((signed) regs->syscall >= 0) {
 559                /* Restart the system call - no handlers present */
 560                switch (regs->areg[2]) {
 561                case -ERESTARTNOHAND:
 562                case -ERESTARTSYS:
 563                case -ERESTARTNOINTR:
 564                        regs->areg[2] = regs->syscall;
 565                        regs->pc -= 3;
 566                        break;
 567                case -ERESTART_RESTARTBLOCK:
 568                        regs->areg[2] = __NR_restart_syscall;
 569                        regs->pc -= 3;
 570                        break;
 571                }
 572        }
 573        if (current->ptrace & PT_SINGLESTEP)
 574                task_pt_regs(current)->icountlevel = 1;
 575        return 0;
 576}
 577
 578