linux/arch/mips/kernel/signal32.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 1991, 1992  Linus Torvalds
   7 * Copyright (C) 1994 - 2000, 2006  Ralf Baechle
   8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
   9 */
  10#include <linux/cache.h>
  11#include <linux/compat.h>
  12#include <linux/sched.h>
  13#include <linux/mm.h>
  14#include <linux/smp.h>
  15#include <linux/kernel.h>
  16#include <linux/signal.h>
  17#include <linux/syscalls.h>
  18#include <linux/errno.h>
  19#include <linux/wait.h>
  20#include <linux/ptrace.h>
  21#include <linux/suspend.h>
  22#include <linux/compiler.h>
  23#include <linux/uaccess.h>
  24
  25#include <asm/abi.h>
  26#include <asm/asm.h>
  27#include <asm/compat-signal.h>
  28#include <linux/bitops.h>
  29#include <asm/cacheflush.h>
  30#include <asm/sim.h>
  31#include <asm/ucontext.h>
  32#include <asm/system.h>
  33#include <asm/fpu.h>
  34#include <asm/war.h>
  35
  36#include "signal-common.h"
  37
  38/*
  39 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
  40 */
  41#define __NR_O32_sigreturn              4119
  42#define __NR_O32_rt_sigreturn           4193
  43#define __NR_O32_restart_syscall        4253
  44
  45/* 32-bit compatibility types */
  46
  47typedef unsigned int __sighandler32_t;
  48typedef void (*vfptr_t)(void);
  49
  50struct sigaction32 {
  51        unsigned int            sa_flags;
  52        __sighandler32_t        sa_handler;
  53        compat_sigset_t         sa_mask;
  54};
  55
  56/* IRIX compatible stack_t  */
  57typedef struct sigaltstack32 {
  58        s32 ss_sp;
  59        compat_size_t ss_size;
  60        int ss_flags;
  61} stack32_t;
  62
  63struct ucontext32 {
  64        u32                 uc_flags;
  65        s32                 uc_link;
  66        stack32_t           uc_stack;
  67        struct sigcontext32 uc_mcontext;
  68        compat_sigset_t     uc_sigmask;   /* mask last for extensibility */
  69};
  70
  71/*
  72 * Horribly complicated - with the bloody RM9000 workarounds enabled
  73 * the signal trampolines is moving to the end of the structure so we can
  74 * increase the alignment without breaking software compatibility.
  75 */
  76#if ICACHE_REFILLS_WORKAROUND_WAR == 0
  77
  78struct sigframe32 {
  79        u32 sf_ass[4];          /* argument save space for o32 */
  80        u32 sf_code[2];         /* signal trampoline */
  81        struct sigcontext32 sf_sc;
  82        compat_sigset_t sf_mask;
  83};
  84
  85struct rt_sigframe32 {
  86        u32 rs_ass[4];                  /* argument save space for o32 */
  87        u32 rs_code[2];                 /* signal trampoline */
  88        compat_siginfo_t rs_info;
  89        struct ucontext32 rs_uc;
  90};
  91
  92#else  /* ICACHE_REFILLS_WORKAROUND_WAR */
  93
  94struct sigframe32 {
  95        u32 sf_ass[4];                  /* argument save space for o32 */
  96        u32 sf_pad[2];
  97        struct sigcontext32 sf_sc;      /* hw context */
  98        compat_sigset_t sf_mask;
  99        u32 sf_code[8] ____cacheline_aligned;   /* signal trampoline */
 100};
 101
 102struct rt_sigframe32 {
 103        u32 rs_ass[4];                  /* argument save space for o32 */
 104        u32 rs_pad[2];
 105        compat_siginfo_t rs_info;
 106        struct ucontext32 rs_uc;
 107        u32 rs_code[8] __attribute__((aligned(32)));    /* signal trampoline */
 108};
 109
 110#endif  /* !ICACHE_REFILLS_WORKAROUND_WAR */
 111
 112/*
 113 * sigcontext handlers
 114 */
 115static int protected_save_fp_context32(struct sigcontext32 __user *sc)
 116{
 117        int err;
 118        while (1) {
 119                lock_fpu_owner();
 120                own_fpu_inatomic(1);
 121                err = save_fp_context32(sc); /* this might fail */
 122                unlock_fpu_owner();
 123                if (likely(!err))
 124                        break;
 125                /* touch the sigcontext and try again */
 126                err = __put_user(0, &sc->sc_fpregs[0]) |
 127                        __put_user(0, &sc->sc_fpregs[31]) |
 128                        __put_user(0, &sc->sc_fpc_csr);
 129                if (err)
 130                        break;  /* really bad sigcontext */
 131        }
 132        return err;
 133}
 134
 135static int protected_restore_fp_context32(struct sigcontext32 __user *sc)
 136{
 137        int err, tmp;
 138        while (1) {
 139                lock_fpu_owner();
 140                own_fpu_inatomic(0);
 141                err = restore_fp_context32(sc); /* this might fail */
 142                unlock_fpu_owner();
 143                if (likely(!err))
 144                        break;
 145                /* touch the sigcontext and try again */
 146                err = __get_user(tmp, &sc->sc_fpregs[0]) |
 147                        __get_user(tmp, &sc->sc_fpregs[31]) |
 148                        __get_user(tmp, &sc->sc_fpc_csr);
 149                if (err)
 150                        break;  /* really bad sigcontext */
 151        }
 152        return err;
 153}
 154
 155static int setup_sigcontext32(struct pt_regs *regs,
 156                              struct sigcontext32 __user *sc)
 157{
 158        int err = 0;
 159        int i;
 160        u32 used_math;
 161
 162        err |= __put_user(regs->cp0_epc, &sc->sc_pc);
 163
 164        err |= __put_user(0, &sc->sc_regs[0]);
 165        for (i = 1; i < 32; i++)
 166                err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
 167
 168        err |= __put_user(regs->hi, &sc->sc_mdhi);
 169        err |= __put_user(regs->lo, &sc->sc_mdlo);
 170        if (cpu_has_dsp) {
 171                err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
 172                err |= __put_user(mfhi1(), &sc->sc_hi1);
 173                err |= __put_user(mflo1(), &sc->sc_lo1);
 174                err |= __put_user(mfhi2(), &sc->sc_hi2);
 175                err |= __put_user(mflo2(), &sc->sc_lo2);
 176                err |= __put_user(mfhi3(), &sc->sc_hi3);
 177                err |= __put_user(mflo3(), &sc->sc_lo3);
 178        }
 179
 180        used_math = !!used_math();
 181        err |= __put_user(used_math, &sc->sc_used_math);
 182
 183        if (used_math) {
 184                /*
 185                 * Save FPU state to signal context.  Signal handler
 186                 * will "inherit" current FPU state.
 187                 */
 188                err |= protected_save_fp_context32(sc);
 189        }
 190        return err;
 191}
 192
 193static int
 194check_and_restore_fp_context32(struct sigcontext32 __user *sc)
 195{
 196        int err, sig;
 197
 198        err = sig = fpcsr_pending(&sc->sc_fpc_csr);
 199        if (err > 0)
 200                err = 0;
 201        err |= protected_restore_fp_context32(sc);
 202        return err ?: sig;
 203}
 204
 205static int restore_sigcontext32(struct pt_regs *regs,
 206                                struct sigcontext32 __user *sc)
 207{
 208        u32 used_math;
 209        int err = 0;
 210        s32 treg;
 211        int i;
 212
 213        /* Always make any pending restarted system calls return -EINTR */
 214        current_thread_info()->restart_block.fn = do_no_restart_syscall;
 215
 216        err |= __get_user(regs->cp0_epc, &sc->sc_pc);
 217        err |= __get_user(regs->hi, &sc->sc_mdhi);
 218        err |= __get_user(regs->lo, &sc->sc_mdlo);
 219        if (cpu_has_dsp) {
 220                err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
 221                err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
 222                err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
 223                err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
 224                err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
 225                err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
 226                err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
 227        }
 228
 229        for (i = 1; i < 32; i++)
 230                err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
 231
 232        err |= __get_user(used_math, &sc->sc_used_math);
 233        conditional_used_math(used_math);
 234
 235        if (used_math) {
 236                /* restore fpu context if we have used it before */
 237                if (!err)
 238                        err = check_and_restore_fp_context32(sc);
 239        } else {
 240                /* signal handler may have used FPU.  Give it up. */
 241                lose_fpu(0);
 242        }
 243
 244        return err;
 245}
 246
 247/*
 248 *
 249 */
 250extern void __put_sigset_unknown_nsig(void);
 251extern void __get_sigset_unknown_nsig(void);
 252
 253static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf)
 254{
 255        int err = 0;
 256
 257        if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
 258                return -EFAULT;
 259
 260        switch (_NSIG_WORDS) {
 261        default:
 262                __put_sigset_unknown_nsig();
 263        case 2:
 264                err |= __put_user(kbuf->sig[1] >> 32, &ubuf->sig[3]);
 265                err |= __put_user(kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
 266        case 1:
 267                err |= __put_user(kbuf->sig[0] >> 32, &ubuf->sig[1]);
 268                err |= __put_user(kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
 269        }
 270
 271        return err;
 272}
 273
 274static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t __user *ubuf)
 275{
 276        int err = 0;
 277        unsigned long sig[4];
 278
 279        if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
 280                return -EFAULT;
 281
 282        switch (_NSIG_WORDS) {
 283        default:
 284                __get_sigset_unknown_nsig();
 285        case 2:
 286                err |= __get_user(sig[3], &ubuf->sig[3]);
 287                err |= __get_user(sig[2], &ubuf->sig[2]);
 288                kbuf->sig[1] = sig[2] | (sig[3] << 32);
 289        case 1:
 290                err |= __get_user(sig[1], &ubuf->sig[1]);
 291                err |= __get_user(sig[0], &ubuf->sig[0]);
 292                kbuf->sig[0] = sig[0] | (sig[1] << 32);
 293        }
 294
 295        return err;
 296}
 297
 298/*
 299 * Atomically swap in the new signal mask, and wait for a signal.
 300 */
 301
 302asmlinkage int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
 303{
 304        compat_sigset_t __user *uset;
 305        sigset_t newset;
 306
 307        uset = (compat_sigset_t __user *) regs.regs[4];
 308        if (get_sigset(&newset, uset))
 309                return -EFAULT;
 310        sigdelsetmask(&newset, ~_BLOCKABLE);
 311
 312        spin_lock_irq(&current->sighand->siglock);
 313        current->saved_sigmask = current->blocked;
 314        current->blocked = newset;
 315        recalc_sigpending();
 316        spin_unlock_irq(&current->sighand->siglock);
 317
 318        current->state = TASK_INTERRUPTIBLE;
 319        schedule();
 320        set_thread_flag(TIF_RESTORE_SIGMASK);
 321        return -ERESTARTNOHAND;
 322}
 323
 324asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
 325{
 326        compat_sigset_t __user *uset;
 327        sigset_t newset;
 328        size_t sigsetsize;
 329
 330        /* XXX Don't preclude handling different sized sigset_t's.  */
 331        sigsetsize = regs.regs[5];
 332        if (sigsetsize != sizeof(compat_sigset_t))
 333                return -EINVAL;
 334
 335        uset = (compat_sigset_t __user *) regs.regs[4];
 336        if (get_sigset(&newset, uset))
 337                return -EFAULT;
 338        sigdelsetmask(&newset, ~_BLOCKABLE);
 339
 340        spin_lock_irq(&current->sighand->siglock);
 341        current->saved_sigmask = current->blocked;
 342        current->blocked = newset;
 343        recalc_sigpending();
 344        spin_unlock_irq(&current->sighand->siglock);
 345
 346        current->state = TASK_INTERRUPTIBLE;
 347        schedule();
 348        set_thread_flag(TIF_RESTORE_SIGMASK);
 349        return -ERESTARTNOHAND;
 350}
 351
 352asmlinkage int sys32_sigaction(int sig, const struct sigaction32 __user *act,
 353                               struct sigaction32 __user *oact)
 354{
 355        struct k_sigaction new_ka, old_ka;
 356        int ret;
 357        int err = 0;
 358
 359        if (act) {
 360                old_sigset_t mask;
 361                s32 handler;
 362
 363                if (!access_ok(VERIFY_READ, act, sizeof(*act)))
 364                        return -EFAULT;
 365                err |= __get_user(handler, &act->sa_handler);
 366                new_ka.sa.sa_handler = (void __user *)(s64)handler;
 367                err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 368                err |= __get_user(mask, &act->sa_mask.sig[0]);
 369                if (err)
 370                        return -EFAULT;
 371
 372                siginitset(&new_ka.sa.sa_mask, mask);
 373        }
 374
 375        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 376
 377        if (!ret && oact) {
 378                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
 379                        return -EFAULT;
 380                err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 381                err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
 382                                  &oact->sa_handler);
 383                err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
 384                err |= __put_user(0, &oact->sa_mask.sig[1]);
 385                err |= __put_user(0, &oact->sa_mask.sig[2]);
 386                err |= __put_user(0, &oact->sa_mask.sig[3]);
 387                if (err)
 388                        return -EFAULT;
 389        }
 390
 391        return ret;
 392}
 393
 394asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
 395{
 396        const stack32_t __user *uss = (const stack32_t __user *) regs.regs[4];
 397        stack32_t __user *uoss = (stack32_t __user *) regs.regs[5];
 398        unsigned long usp = regs.regs[29];
 399        stack_t kss, koss;
 400        int ret, err = 0;
 401        mm_segment_t old_fs = get_fs();
 402        s32 sp;
 403
 404        if (uss) {
 405                if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
 406                        return -EFAULT;
 407                err |= __get_user(sp, &uss->ss_sp);
 408                kss.ss_sp = (void __user *) (long) sp;
 409                err |= __get_user(kss.ss_size, &uss->ss_size);
 410                err |= __get_user(kss.ss_flags, &uss->ss_flags);
 411                if (err)
 412                        return -EFAULT;
 413        }
 414
 415        set_fs(KERNEL_DS);
 416        ret = do_sigaltstack(uss ? (stack_t __user *)&kss : NULL,
 417                             uoss ? (stack_t __user *)&koss : NULL, usp);
 418        set_fs(old_fs);
 419
 420        if (!ret && uoss) {
 421                if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
 422                        return -EFAULT;
 423                sp = (int) (unsigned long) koss.ss_sp;
 424                err |= __put_user(sp, &uoss->ss_sp);
 425                err |= __put_user(koss.ss_size, &uoss->ss_size);
 426                err |= __put_user(koss.ss_flags, &uoss->ss_flags);
 427                if (err)
 428                        return -EFAULT;
 429        }
 430        return ret;
 431}
 432
 433int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 434{
 435        int err;
 436
 437        if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
 438                return -EFAULT;
 439
 440        /* If you change siginfo_t structure, please be sure
 441           this code is fixed accordingly.
 442           It should never copy any pad contained in the structure
 443           to avoid security leaks, but must copy the generic
 444           3 ints plus the relevant union member.
 445           This routine must convert siginfo from 64bit to 32bit as well
 446           at the same time.  */
 447        err = __put_user(from->si_signo, &to->si_signo);
 448        err |= __put_user(from->si_errno, &to->si_errno);
 449        err |= __put_user((short)from->si_code, &to->si_code);
 450        if (from->si_code < 0)
 451                err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
 452        else {
 453                switch (from->si_code >> 16) {
 454                case __SI_TIMER >> 16:
 455                        err |= __put_user(from->si_tid, &to->si_tid);
 456                        err |= __put_user(from->si_overrun, &to->si_overrun);
 457                        err |= __put_user(from->si_int, &to->si_int);
 458                        break;
 459                case __SI_CHLD >> 16:
 460                        err |= __put_user(from->si_utime, &to->si_utime);
 461                        err |= __put_user(from->si_stime, &to->si_stime);
 462                        err |= __put_user(from->si_status, &to->si_status);
 463                default:
 464                        err |= __put_user(from->si_pid, &to->si_pid);
 465                        err |= __put_user(from->si_uid, &to->si_uid);
 466                        break;
 467                case __SI_FAULT >> 16:
 468                        err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
 469                        break;
 470                case __SI_POLL >> 16:
 471                        err |= __put_user(from->si_band, &to->si_band);
 472                        err |= __put_user(from->si_fd, &to->si_fd);
 473                        break;
 474                case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
 475                case __SI_MESGQ >> 16:
 476                        err |= __put_user(from->si_pid, &to->si_pid);
 477                        err |= __put_user(from->si_uid, &to->si_uid);
 478                        err |= __put_user(from->si_int, &to->si_int);
 479                        break;
 480                }
 481        }
 482        return err;
 483}
 484
 485asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
 486{
 487        struct sigframe32 __user *frame;
 488        sigset_t blocked;
 489        int sig;
 490
 491        frame = (struct sigframe32 __user *) regs.regs[29];
 492        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 493                goto badframe;
 494        if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
 495                goto badframe;
 496
 497        sigdelsetmask(&blocked, ~_BLOCKABLE);
 498        spin_lock_irq(&current->sighand->siglock);
 499        current->blocked = blocked;
 500        recalc_sigpending();
 501        spin_unlock_irq(&current->sighand->siglock);
 502
 503        sig = restore_sigcontext32(&regs, &frame->sf_sc);
 504        if (sig < 0)
 505                goto badframe;
 506        else if (sig)
 507                force_sig(sig, current);
 508
 509        /*
 510         * Don't let your children do this ...
 511         */
 512        __asm__ __volatile__(
 513                "move\t$29, %0\n\t"
 514                "j\tsyscall_exit"
 515                :/* no outputs */
 516                :"r" (&regs));
 517        /* Unreached */
 518
 519badframe:
 520        force_sig(SIGSEGV, current);
 521}
 522
 523asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
 524{
 525        struct rt_sigframe32 __user *frame;
 526        mm_segment_t old_fs;
 527        sigset_t set;
 528        stack_t st;
 529        s32 sp;
 530        int sig;
 531
 532        frame = (struct rt_sigframe32 __user *) regs.regs[29];
 533        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 534                goto badframe;
 535        if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
 536                goto badframe;
 537
 538        sigdelsetmask(&set, ~_BLOCKABLE);
 539        spin_lock_irq(&current->sighand->siglock);
 540        current->blocked = set;
 541        recalc_sigpending();
 542        spin_unlock_irq(&current->sighand->siglock);
 543
 544        sig = restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext);
 545        if (sig < 0)
 546                goto badframe;
 547        else if (sig)
 548                force_sig(sig, current);
 549
 550        /* The ucontext contains a stack32_t, so we must convert!  */
 551        if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
 552                goto badframe;
 553        st.ss_sp = (void __user *)(long) sp;
 554        if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
 555                goto badframe;
 556        if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
 557                goto badframe;
 558
 559        /* It is more difficult to avoid calling this function than to
 560           call it and ignore errors.  */
 561        old_fs = get_fs();
 562        set_fs(KERNEL_DS);
 563        do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
 564        set_fs(old_fs);
 565
 566        /*
 567         * Don't let your children do this ...
 568         */
 569        __asm__ __volatile__(
 570                "move\t$29, %0\n\t"
 571                "j\tsyscall_exit"
 572                :/* no outputs */
 573                :"r" (&regs));
 574        /* Unreached */
 575
 576badframe:
 577        force_sig(SIGSEGV, current);
 578}
 579
 580static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
 581        int signr, sigset_t *set)
 582{
 583        struct sigframe32 __user *frame;
 584        int err = 0;
 585
 586        frame = get_sigframe(ka, regs, sizeof(*frame));
 587        if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
 588                goto give_sigsegv;
 589
 590        err |= install_sigtramp(frame->sf_code, __NR_O32_sigreturn);
 591
 592        err |= setup_sigcontext32(regs, &frame->sf_sc);
 593        err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
 594
 595        if (err)
 596                goto give_sigsegv;
 597
 598        /*
 599         * Arguments to signal handler:
 600         *
 601         *   a0 = signal number
 602         *   a1 = 0 (should be cause)
 603         *   a2 = pointer to struct sigcontext
 604         *
 605         * $25 and c0_epc point to the signal handler, $29 points to the
 606         * struct sigframe.
 607         */
 608        regs->regs[ 4] = signr;
 609        regs->regs[ 5] = 0;
 610        regs->regs[ 6] = (unsigned long) &frame->sf_sc;
 611        regs->regs[29] = (unsigned long) frame;
 612        regs->regs[31] = (unsigned long) frame->sf_code;
 613        regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
 614
 615        DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
 616               current->comm, current->pid,
 617               frame, regs->cp0_epc, regs->regs[31]);
 618
 619        return 0;
 620
 621give_sigsegv:
 622        force_sigsegv(signr, current);
 623        return -EFAULT;
 624}
 625
 626static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
 627        int signr, sigset_t *set, siginfo_t *info)
 628{
 629        struct rt_sigframe32 __user *frame;
 630        int err = 0;
 631        s32 sp;
 632
 633        frame = get_sigframe(ka, regs, sizeof(*frame));
 634        if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
 635                goto give_sigsegv;
 636
 637        err |= install_sigtramp(frame->rs_code, __NR_O32_rt_sigreturn);
 638
 639        /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
 640        err |= copy_siginfo_to_user32(&frame->rs_info, info);
 641
 642        /* Create the ucontext.  */
 643        err |= __put_user(0, &frame->rs_uc.uc_flags);
 644        err |= __put_user(0, &frame->rs_uc.uc_link);
 645        sp = (int) (long) current->sas_ss_sp;
 646        err |= __put_user(sp,
 647                          &frame->rs_uc.uc_stack.ss_sp);
 648        err |= __put_user(sas_ss_flags(regs->regs[29]),
 649                          &frame->rs_uc.uc_stack.ss_flags);
 650        err |= __put_user(current->sas_ss_size,
 651                          &frame->rs_uc.uc_stack.ss_size);
 652        err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
 653        err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
 654
 655        if (err)
 656                goto give_sigsegv;
 657
 658        /*
 659         * Arguments to signal handler:
 660         *
 661         *   a0 = signal number
 662         *   a1 = 0 (should be cause)
 663         *   a2 = pointer to ucontext
 664         *
 665         * $25 and c0_epc point to the signal handler, $29 points to
 666         * the struct rt_sigframe32.
 667         */
 668        regs->regs[ 4] = signr;
 669        regs->regs[ 5] = (unsigned long) &frame->rs_info;
 670        regs->regs[ 6] = (unsigned long) &frame->rs_uc;
 671        regs->regs[29] = (unsigned long) frame;
 672        regs->regs[31] = (unsigned long) frame->rs_code;
 673        regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
 674
 675        DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
 676               current->comm, current->pid,
 677               frame, regs->cp0_epc, regs->regs[31]);
 678
 679        return 0;
 680
 681give_sigsegv:
 682        force_sigsegv(signr, current);
 683        return -EFAULT;
 684}
 685
 686/*
 687 * o32 compatibility on 64-bit kernels, without DSP ASE
 688 */
 689struct mips_abi mips_abi_32 = {
 690        .setup_frame    = setup_frame_32,
 691        .setup_rt_frame = setup_rt_frame_32,
 692        .restart        = __NR_O32_restart_syscall
 693};
 694
 695asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
 696                                  struct sigaction32 __user *oact,
 697                                  unsigned int sigsetsize)
 698{
 699        struct k_sigaction new_sa, old_sa;
 700        int ret = -EINVAL;
 701
 702        /* XXX: Don't preclude handling different sized sigset_t's.  */
 703        if (sigsetsize != sizeof(sigset_t))
 704                goto out;
 705
 706        if (act) {
 707                s32 handler;
 708                int err = 0;
 709
 710                if (!access_ok(VERIFY_READ, act, sizeof(*act)))
 711                        return -EFAULT;
 712                err |= __get_user(handler, &act->sa_handler);
 713                new_sa.sa.sa_handler = (void __user *)(s64)handler;
 714                err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
 715                err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
 716                if (err)
 717                        return -EFAULT;
 718        }
 719
 720        ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
 721
 722        if (!ret && oact) {
 723                int err = 0;
 724
 725                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
 726                        return -EFAULT;
 727
 728                err |= __put_user((u32)(u64)old_sa.sa.sa_handler,
 729                                   &oact->sa_handler);
 730                err |= __put_user(old_sa.sa.sa_flags, &oact->sa_flags);
 731                err |= put_sigset(&old_sa.sa.sa_mask, &oact->sa_mask);
 732                if (err)
 733                        return -EFAULT;
 734        }
 735out:
 736        return ret;
 737}
 738
 739asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
 740        compat_sigset_t __user *oset, unsigned int sigsetsize)
 741{
 742        sigset_t old_set, new_set;
 743        int ret;
 744        mm_segment_t old_fs = get_fs();
 745
 746        if (set && get_sigset(&new_set, set))
 747                return -EFAULT;
 748
 749        set_fs(KERNEL_DS);
 750        ret = sys_rt_sigprocmask(how, set ? (sigset_t __user *)&new_set : NULL,
 751                                 oset ? (sigset_t __user *)&old_set : NULL,
 752                                 sigsetsize);
 753        set_fs(old_fs);
 754
 755        if (!ret && oset && put_sigset(&old_set, oset))
 756                return -EFAULT;
 757
 758        return ret;
 759}
 760
 761asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *uset,
 762        unsigned int sigsetsize)
 763{
 764        int ret;
 765        sigset_t set;
 766        mm_segment_t old_fs = get_fs();
 767
 768        set_fs(KERNEL_DS);
 769        ret = sys_rt_sigpending((sigset_t __user *)&set, sigsetsize);
 770        set_fs(old_fs);
 771
 772        if (!ret && put_sigset(&set, uset))
 773                return -EFAULT;
 774
 775        return ret;
 776}
 777
 778asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
 779{
 780        siginfo_t info;
 781        int ret;
 782        mm_segment_t old_fs = get_fs();
 783
 784        if (copy_from_user(&info, uinfo, 3*sizeof(int)) ||
 785            copy_from_user(info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
 786                return -EFAULT;
 787        set_fs(KERNEL_DS);
 788        ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
 789        set_fs(old_fs);
 790        return ret;
 791}
 792
 793asmlinkage long
 794sys32_waitid(int which, compat_pid_t pid,
 795             compat_siginfo_t __user *uinfo, int options,
 796             struct compat_rusage __user *uru)
 797{
 798        siginfo_t info;
 799        struct rusage ru;
 800        long ret;
 801        mm_segment_t old_fs = get_fs();
 802
 803        info.si_signo = 0;
 804        set_fs(KERNEL_DS);
 805        ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
 806                         uru ? (struct rusage __user *) &ru : NULL);
 807        set_fs(old_fs);
 808
 809        if (ret < 0 || info.si_signo == 0)
 810                return ret;
 811
 812        if (uru && (ret = put_compat_rusage(&ru, uru)))
 813                return ret;
 814
 815        BUG_ON(info.si_code & __SI_MASK);
 816        info.si_code |= __SI_CHLD;
 817        return copy_siginfo_to_user32(uinfo, &info);
 818}
 819