11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 31da177e4SLinus Torvalds * License. See the file "COPYING" in the main directory of this archive 41da177e4SLinus Torvalds * for more details. 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds 7dda73d0bSMartin Michlmayr * Copyright (C) 1994 - 2000, 2006 Ralf Baechle 81da177e4SLinus Torvalds * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 91da177e4SLinus Torvalds */ 1002416dcfSRalf Baechle #include <linux/cache.h> 11431dc804SRalf Baechle #include <linux/compat.h> 121da177e4SLinus Torvalds #include <linux/sched.h> 131da177e4SLinus Torvalds #include <linux/mm.h> 141da177e4SLinus Torvalds #include <linux/smp.h> 151da177e4SLinus Torvalds #include <linux/kernel.h> 161da177e4SLinus Torvalds #include <linux/signal.h> 171da177e4SLinus Torvalds #include <linux/syscalls.h> 181da177e4SLinus Torvalds #include <linux/errno.h> 191da177e4SLinus Torvalds #include <linux/wait.h> 201da177e4SLinus Torvalds #include <linux/ptrace.h> 211da177e4SLinus Torvalds #include <linux/suspend.h> 221da177e4SLinus Torvalds #include <linux/compiler.h> 23faea6234SAtsushi Nemoto #include <linux/uaccess.h> 241da177e4SLinus Torvalds 25e50c0a8fSRalf Baechle #include <asm/abi.h> 261da177e4SLinus Torvalds #include <asm/asm.h> 27431dc804SRalf Baechle #include <asm/compat-signal.h> 281da177e4SLinus Torvalds #include <linux/bitops.h> 291da177e4SLinus Torvalds #include <asm/cacheflush.h> 301da177e4SLinus Torvalds #include <asm/sim.h> 311da177e4SLinus Torvalds #include <asm/ucontext.h> 321da177e4SLinus Torvalds #include <asm/fpu.h> 3302416dcfSRalf Baechle #include <asm/war.h> 34b81947c6SDavid Howells #include <asm/dsp.h> 351da177e4SLinus Torvalds 3636a1f2c2SFranck Bui-Huu #include "signal-common.h" 3736a1f2c2SFranck Bui-Huu 381da177e4SLinus Torvalds /* 391da177e4SLinus Torvalds * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... 401da177e4SLinus Torvalds */ 411da177e4SLinus Torvalds #define __NR_O32_restart_syscall 4253 421da177e4SLinus Torvalds 431da177e4SLinus Torvalds /* 32-bit compatibility types */ 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds typedef unsigned int __sighandler32_t; 461da177e4SLinus Torvalds typedef void (*vfptr_t)(void); 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds struct ucontext32 { 491da177e4SLinus Torvalds u32 uc_flags; 501da177e4SLinus Torvalds s32 uc_link; 51ea536ad4SAl Viro compat_stack_t uc_stack; 521da177e4SLinus Torvalds struct sigcontext32 uc_mcontext; 5301ee6037SRalf Baechle compat_sigset_t uc_sigmask; /* mask last for extensibility */ 541da177e4SLinus Torvalds }; 551da177e4SLinus Torvalds 56dd02f06aSRalf Baechle struct sigframe32 { 57dd02f06aSRalf Baechle u32 sf_ass[4]; /* argument save space for o32 */ 58d814c28cSDavid Daney u32 sf_pad[2]; /* Was: signal trampoline */ 59dd02f06aSRalf Baechle struct sigcontext32 sf_sc; 60755f21bbSAtsushi Nemoto compat_sigset_t sf_mask; 61dd02f06aSRalf Baechle }; 62dd02f06aSRalf Baechle 63c0b9bae9SFranck Bui-Huu struct rt_sigframe32 { 64c0b9bae9SFranck Bui-Huu u32 rs_ass[4]; /* argument save space for o32 */ 65d814c28cSDavid Daney u32 rs_pad[2]; /* Was: signal trampoline */ 66c0b9bae9SFranck Bui-Huu compat_siginfo_t rs_info; 67c0b9bae9SFranck Bui-Huu struct ucontext32 rs_uc; 68c0b9bae9SFranck Bui-Huu }; 69c0b9bae9SFranck Bui-Huu 709432a9baSFranck Bui-Huu static int setup_sigcontext32(struct pt_regs *regs, 719432a9baSFranck Bui-Huu struct sigcontext32 __user *sc) 729432a9baSFranck Bui-Huu { 739432a9baSFranck Bui-Huu int err = 0; 749432a9baSFranck Bui-Huu int i; 759432a9baSFranck Bui-Huu 769432a9baSFranck Bui-Huu err |= __put_user(regs->cp0_epc, &sc->sc_pc); 779432a9baSFranck Bui-Huu 789432a9baSFranck Bui-Huu err |= __put_user(0, &sc->sc_regs[0]); 799432a9baSFranck Bui-Huu for (i = 1; i < 32; i++) 809432a9baSFranck Bui-Huu err |= __put_user(regs->regs[i], &sc->sc_regs[i]); 819432a9baSFranck Bui-Huu 829432a9baSFranck Bui-Huu err |= __put_user(regs->hi, &sc->sc_mdhi); 839432a9baSFranck Bui-Huu err |= __put_user(regs->lo, &sc->sc_mdlo); 849432a9baSFranck Bui-Huu if (cpu_has_dsp) { 859432a9baSFranck Bui-Huu err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); 869432a9baSFranck Bui-Huu err |= __put_user(mfhi1(), &sc->sc_hi1); 879432a9baSFranck Bui-Huu err |= __put_user(mflo1(), &sc->sc_lo1); 889432a9baSFranck Bui-Huu err |= __put_user(mfhi2(), &sc->sc_hi2); 899432a9baSFranck Bui-Huu err |= __put_user(mflo2(), &sc->sc_lo2); 909432a9baSFranck Bui-Huu err |= __put_user(mfhi3(), &sc->sc_hi3); 919432a9baSFranck Bui-Huu err |= __put_user(mflo3(), &sc->sc_lo3); 929432a9baSFranck Bui-Huu } 939432a9baSFranck Bui-Huu 949432a9baSFranck Bui-Huu /* 959432a9baSFranck Bui-Huu * Save FPU state to signal context. Signal handler 969432a9baSFranck Bui-Huu * will "inherit" current FPU state. 979432a9baSFranck Bui-Huu */ 98d02a40afSPaul Burton err |= protected_save_fp_context(sc); 99d02a40afSPaul Burton 1009432a9baSFranck Bui-Huu return err; 1019432a9baSFranck Bui-Huu } 1029432a9baSFranck Bui-Huu 1039432a9baSFranck Bui-Huu static int restore_sigcontext32(struct pt_regs *regs, 1049432a9baSFranck Bui-Huu struct sigcontext32 __user *sc) 1059432a9baSFranck Bui-Huu { 1069432a9baSFranck Bui-Huu int err = 0; 1079432a9baSFranck Bui-Huu s32 treg; 1089432a9baSFranck Bui-Huu int i; 1099432a9baSFranck Bui-Huu 1109432a9baSFranck Bui-Huu /* Always make any pending restarted system calls return -EINTR */ 111f56141e3SAndy Lutomirski current->restart_block.fn = do_no_restart_syscall; 1129432a9baSFranck Bui-Huu 1139432a9baSFranck Bui-Huu err |= __get_user(regs->cp0_epc, &sc->sc_pc); 1149432a9baSFranck Bui-Huu err |= __get_user(regs->hi, &sc->sc_mdhi); 1159432a9baSFranck Bui-Huu err |= __get_user(regs->lo, &sc->sc_mdlo); 1169432a9baSFranck Bui-Huu if (cpu_has_dsp) { 1179432a9baSFranck Bui-Huu err |= __get_user(treg, &sc->sc_hi1); mthi1(treg); 1189432a9baSFranck Bui-Huu err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg); 1199432a9baSFranck Bui-Huu err |= __get_user(treg, &sc->sc_hi2); mthi2(treg); 1209432a9baSFranck Bui-Huu err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg); 1219432a9baSFranck Bui-Huu err |= __get_user(treg, &sc->sc_hi3); mthi3(treg); 1229432a9baSFranck Bui-Huu err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg); 1239432a9baSFranck Bui-Huu err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK); 1249432a9baSFranck Bui-Huu } 1259432a9baSFranck Bui-Huu 1269432a9baSFranck Bui-Huu for (i = 1; i < 32; i++) 1279432a9baSFranck Bui-Huu err |= __get_user(regs->regs[i], &sc->sc_regs[i]); 1289432a9baSFranck Bui-Huu 129d02a40afSPaul Burton return err ?: protected_restore_fp_context(sc); 1309432a9baSFranck Bui-Huu } 1319432a9baSFranck Bui-Huu 1329432a9baSFranck Bui-Huu /* 1331da177e4SLinus Torvalds * Atomically swap in the new signal mask, and wait for a signal. 1341da177e4SLinus Torvalds */ 1351da177e4SLinus Torvalds 1361910f4abSAl Viro asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset) 1371da177e4SLinus Torvalds { 1381910f4abSAl Viro return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t)); 1391da177e4SLinus Torvalds } 1401da177e4SLinus Torvalds 141aa584802SAl Viro SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *, act, 142aa584802SAl Viro struct compat_sigaction __user *, oact) 1431da177e4SLinus Torvalds { 1441da177e4SLinus Torvalds struct k_sigaction new_ka, old_ka; 1451da177e4SLinus Torvalds int ret; 1461da177e4SLinus Torvalds int err = 0; 1471da177e4SLinus Torvalds 1481da177e4SLinus Torvalds if (act) { 1491da177e4SLinus Torvalds old_sigset_t mask; 15077c728c2SRalf Baechle s32 handler; 1511da177e4SLinus Torvalds 1521da177e4SLinus Torvalds if (!access_ok(VERIFY_READ, act, sizeof(*act))) 1531da177e4SLinus Torvalds return -EFAULT; 15477c728c2SRalf Baechle err |= __get_user(handler, &act->sa_handler); 1559bbf28a3SAtsushi Nemoto new_ka.sa.sa_handler = (void __user *)(s64)handler; 1561da177e4SLinus Torvalds err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); 1571da177e4SLinus Torvalds err |= __get_user(mask, &act->sa_mask.sig[0]); 1581da177e4SLinus Torvalds if (err) 1591da177e4SLinus Torvalds return -EFAULT; 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds siginitset(&new_ka.sa.sa_mask, mask); 1621da177e4SLinus Torvalds } 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds if (!ret && oact) { 1671da177e4SLinus Torvalds if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact))) 1681da177e4SLinus Torvalds return -EFAULT; 1691da177e4SLinus Torvalds err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); 1701da177e4SLinus Torvalds err |= __put_user((u32)(u64)old_ka.sa.sa_handler, 1711da177e4SLinus Torvalds &oact->sa_handler); 1721da177e4SLinus Torvalds err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig); 1731da177e4SLinus Torvalds err |= __put_user(0, &oact->sa_mask.sig[1]); 1741da177e4SLinus Torvalds err |= __put_user(0, &oact->sa_mask.sig[2]); 1751da177e4SLinus Torvalds err |= __put_user(0, &oact->sa_mask.sig[3]); 1761da177e4SLinus Torvalds if (err) 1771da177e4SLinus Torvalds return -EFAULT; 1781da177e4SLinus Torvalds } 1791da177e4SLinus Torvalds 1801da177e4SLinus Torvalds return ret; 1811da177e4SLinus Torvalds } 1821da177e4SLinus Torvalds 183ce395960SAl Viro int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) 1841da177e4SLinus Torvalds { 1851da177e4SLinus Torvalds int err; 1861da177e4SLinus Torvalds 1871da177e4SLinus Torvalds if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t))) 1881da177e4SLinus Torvalds return -EFAULT; 1891da177e4SLinus Torvalds 1901da177e4SLinus Torvalds /* If you change siginfo_t structure, please be sure 1911da177e4SLinus Torvalds this code is fixed accordingly. 1921da177e4SLinus Torvalds It should never copy any pad contained in the structure 1931da177e4SLinus Torvalds to avoid security leaks, but must copy the generic 1941da177e4SLinus Torvalds 3 ints plus the relevant union member. 1951da177e4SLinus Torvalds This routine must convert siginfo from 64bit to 32bit as well 1961da177e4SLinus Torvalds at the same time. */ 1971da177e4SLinus Torvalds err = __put_user(from->si_signo, &to->si_signo); 1981da177e4SLinus Torvalds err |= __put_user(from->si_errno, &to->si_errno); 1991da177e4SLinus Torvalds err |= __put_user((short)from->si_code, &to->si_code); 2001da177e4SLinus Torvalds if (from->si_code < 0) 2011da177e4SLinus Torvalds err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); 2021da177e4SLinus Torvalds else { 2031da177e4SLinus Torvalds switch (from->si_code >> 16) { 204a982099cSRalf Baechle case __SI_TIMER >> 16: 205a982099cSRalf Baechle err |= __put_user(from->si_tid, &to->si_tid); 206a982099cSRalf Baechle err |= __put_user(from->si_overrun, &to->si_overrun); 207a982099cSRalf Baechle err |= __put_user(from->si_int, &to->si_int); 208a982099cSRalf Baechle break; 2091da177e4SLinus Torvalds case __SI_CHLD >> 16: 2101da177e4SLinus Torvalds err |= __put_user(from->si_utime, &to->si_utime); 2111da177e4SLinus Torvalds err |= __put_user(from->si_stime, &to->si_stime); 2121da177e4SLinus Torvalds err |= __put_user(from->si_status, &to->si_status); 2131da177e4SLinus Torvalds default: 2141da177e4SLinus Torvalds err |= __put_user(from->si_pid, &to->si_pid); 2151da177e4SLinus Torvalds err |= __put_user(from->si_uid, &to->si_uid); 2161da177e4SLinus Torvalds break; 2171da177e4SLinus Torvalds case __SI_FAULT >> 16: 2185665a0acSAtsushi Nemoto err |= __put_user((unsigned long)from->si_addr, &to->si_addr); 2191da177e4SLinus Torvalds break; 2201da177e4SLinus Torvalds case __SI_POLL >> 16: 2211da177e4SLinus Torvalds err |= __put_user(from->si_band, &to->si_band); 2221da177e4SLinus Torvalds err |= __put_user(from->si_fd, &to->si_fd); 2231da177e4SLinus Torvalds break; 2241da177e4SLinus Torvalds case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ 2251da177e4SLinus Torvalds case __SI_MESGQ >> 16: 2261da177e4SLinus Torvalds err |= __put_user(from->si_pid, &to->si_pid); 2271da177e4SLinus Torvalds err |= __put_user(from->si_uid, &to->si_uid); 2281da177e4SLinus Torvalds err |= __put_user(from->si_int, &to->si_int); 2291da177e4SLinus Torvalds break; 230*5050e91fSMatt Redfearn case __SI_SYS >> 16: 231*5050e91fSMatt Redfearn err |= __copy_to_user(&to->si_call_addr, &from->si_call_addr, 232*5050e91fSMatt Redfearn sizeof(compat_uptr_t)); 233*5050e91fSMatt Redfearn err |= __put_user(from->si_syscall, &to->si_syscall); 234*5050e91fSMatt Redfearn err |= __put_user(from->si_arch, &to->si_arch); 235*5050e91fSMatt Redfearn break; 2361da177e4SLinus Torvalds } 2371da177e4SLinus Torvalds } 2381da177e4SLinus Torvalds return err; 2391da177e4SLinus Torvalds } 2401da177e4SLinus Torvalds 2415d9a76cdSThomas Bogendoerfer int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) 2425d9a76cdSThomas Bogendoerfer { 2435d9a76cdSThomas Bogendoerfer if (copy_from_user(to, from, 3*sizeof(int)) || 2445d9a76cdSThomas Bogendoerfer copy_from_user(to->_sifields._pad, 2455d9a76cdSThomas Bogendoerfer from->_sifields._pad, SI_PAD_SIZE32)) 2465d9a76cdSThomas Bogendoerfer return -EFAULT; 2475d9a76cdSThomas Bogendoerfer 2485d9a76cdSThomas Bogendoerfer return 0; 2495d9a76cdSThomas Bogendoerfer } 2505d9a76cdSThomas Bogendoerfer 251f90080a0SFranck Bui-Huu asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs) 2521da177e4SLinus Torvalds { 253dd02f06aSRalf Baechle struct sigframe32 __user *frame; 2541da177e4SLinus Torvalds sigset_t blocked; 255c6a2f467SAtsushi Nemoto int sig; 2561da177e4SLinus Torvalds 257dd02f06aSRalf Baechle frame = (struct sigframe32 __user *) regs.regs[29]; 2581da177e4SLinus Torvalds if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 2591da177e4SLinus Torvalds goto badframe; 260431dc804SRalf Baechle if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask)) 2611da177e4SLinus Torvalds goto badframe; 2621da177e4SLinus Torvalds 2638598f3cdSMatt Fleming set_current_blocked(&blocked); 2641da177e4SLinus Torvalds 265c6a2f467SAtsushi Nemoto sig = restore_sigcontext32(®s, &frame->sf_sc); 266c6a2f467SAtsushi Nemoto if (sig < 0) 2671da177e4SLinus Torvalds goto badframe; 268c6a2f467SAtsushi Nemoto else if (sig) 269c6a2f467SAtsushi Nemoto force_sig(sig, current); 2701da177e4SLinus Torvalds 2711da177e4SLinus Torvalds /* 2721da177e4SLinus Torvalds * Don't let your children do this ... 2731da177e4SLinus Torvalds */ 2741da177e4SLinus Torvalds __asm__ __volatile__( 2751da177e4SLinus Torvalds "move\t$29, %0\n\t" 2761da177e4SLinus Torvalds "j\tsyscall_exit" 2771da177e4SLinus Torvalds :/* no outputs */ 2781da177e4SLinus Torvalds :"r" (®s)); 2791da177e4SLinus Torvalds /* Unreached */ 2801da177e4SLinus Torvalds 2811da177e4SLinus Torvalds badframe: 2821da177e4SLinus Torvalds force_sig(SIGSEGV, current); 2831da177e4SLinus Torvalds } 2841da177e4SLinus Torvalds 285f90080a0SFranck Bui-Huu asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) 2861da177e4SLinus Torvalds { 2879bbf28a3SAtsushi Nemoto struct rt_sigframe32 __user *frame; 2881da177e4SLinus Torvalds sigset_t set; 289c6a2f467SAtsushi Nemoto int sig; 2901da177e4SLinus Torvalds 2919bbf28a3SAtsushi Nemoto frame = (struct rt_sigframe32 __user *) regs.regs[29]; 2921da177e4SLinus Torvalds if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 2931da177e4SLinus Torvalds goto badframe; 294431dc804SRalf Baechle if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask)) 2951da177e4SLinus Torvalds goto badframe; 2961da177e4SLinus Torvalds 2978598f3cdSMatt Fleming set_current_blocked(&set); 2981da177e4SLinus Torvalds 299c6a2f467SAtsushi Nemoto sig = restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext); 300c6a2f467SAtsushi Nemoto if (sig < 0) 3011da177e4SLinus Torvalds goto badframe; 302c6a2f467SAtsushi Nemoto else if (sig) 303c6a2f467SAtsushi Nemoto force_sig(sig, current); 3041da177e4SLinus Torvalds 305ea536ad4SAl Viro if (compat_restore_altstack(&frame->rs_uc.uc_stack)) 3061da177e4SLinus Torvalds goto badframe; 3071da177e4SLinus Torvalds 3081da177e4SLinus Torvalds /* 3091da177e4SLinus Torvalds * Don't let your children do this ... 3101da177e4SLinus Torvalds */ 3111da177e4SLinus Torvalds __asm__ __volatile__( 3121da177e4SLinus Torvalds "move\t$29, %0\n\t" 3131da177e4SLinus Torvalds "j\tsyscall_exit" 3141da177e4SLinus Torvalds :/* no outputs */ 3151da177e4SLinus Torvalds :"r" (®s)); 3161da177e4SLinus Torvalds /* Unreached */ 3171da177e4SLinus Torvalds 3181da177e4SLinus Torvalds badframe: 3191da177e4SLinus Torvalds force_sig(SIGSEGV, current); 3201da177e4SLinus Torvalds } 3211da177e4SLinus Torvalds 32281d103bfSRichard Weinberger static int setup_frame_32(void *sig_return, struct ksignal *ksig, 32381d103bfSRichard Weinberger struct pt_regs *regs, sigset_t *set) 3241da177e4SLinus Torvalds { 325dd02f06aSRalf Baechle struct sigframe32 __user *frame; 3261da177e4SLinus Torvalds int err = 0; 3271da177e4SLinus Torvalds 3287c4f5635SRichard Weinberger frame = get_sigframe(ksig, regs, sizeof(*frame)); 3291da177e4SLinus Torvalds if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 33081d103bfSRichard Weinberger return -EFAULT; 3311da177e4SLinus Torvalds 3321da177e4SLinus Torvalds err |= setup_sigcontext32(regs, &frame->sf_sc); 333431dc804SRalf Baechle err |= __copy_conv_sigset_to_user(&frame->sf_mask, set); 334431dc804SRalf Baechle 3351da177e4SLinus Torvalds if (err) 33681d103bfSRichard Weinberger return -EFAULT; 3371da177e4SLinus Torvalds 3381da177e4SLinus Torvalds /* 3391da177e4SLinus Torvalds * Arguments to signal handler: 3401da177e4SLinus Torvalds * 3411da177e4SLinus Torvalds * a0 = signal number 3421da177e4SLinus Torvalds * a1 = 0 (should be cause) 3431da177e4SLinus Torvalds * a2 = pointer to struct sigcontext 3441da177e4SLinus Torvalds * 3451da177e4SLinus Torvalds * $25 and c0_epc point to the signal handler, $29 points to the 3461da177e4SLinus Torvalds * struct sigframe. 3471da177e4SLinus Torvalds */ 34881d103bfSRichard Weinberger regs->regs[ 4] = ksig->sig; 3491da177e4SLinus Torvalds regs->regs[ 5] = 0; 3501da177e4SLinus Torvalds regs->regs[ 6] = (unsigned long) &frame->sf_sc; 3511da177e4SLinus Torvalds regs->regs[29] = (unsigned long) frame; 352d814c28cSDavid Daney regs->regs[31] = (unsigned long) sig_return; 35381d103bfSRichard Weinberger regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler; 3541da177e4SLinus Torvalds 355722bb63dSFranck Bui-Huu DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", 3561da177e4SLinus Torvalds current->comm, current->pid, 357722bb63dSFranck Bui-Huu frame, regs->cp0_epc, regs->regs[31]); 358722bb63dSFranck Bui-Huu 3597b3e2fc8SRalf Baechle return 0; 3601da177e4SLinus Torvalds } 3611da177e4SLinus Torvalds 36281d103bfSRichard Weinberger static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig, 36381d103bfSRichard Weinberger struct pt_regs *regs, sigset_t *set) 3641da177e4SLinus Torvalds { 3659bbf28a3SAtsushi Nemoto struct rt_sigframe32 __user *frame; 3661da177e4SLinus Torvalds int err = 0; 3671da177e4SLinus Torvalds 3687c4f5635SRichard Weinberger frame = get_sigframe(ksig, regs, sizeof(*frame)); 3691da177e4SLinus Torvalds if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 37081d103bfSRichard Weinberger return -EFAULT; 3711da177e4SLinus Torvalds 3721da177e4SLinus Torvalds /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */ 37381d103bfSRichard Weinberger err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info); 3741da177e4SLinus Torvalds 3751da177e4SLinus Torvalds /* Create the ucontext. */ 3761da177e4SLinus Torvalds err |= __put_user(0, &frame->rs_uc.uc_flags); 3771da177e4SLinus Torvalds err |= __put_user(0, &frame->rs_uc.uc_link); 378ea536ad4SAl Viro err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]); 3791da177e4SLinus Torvalds err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext); 380431dc804SRalf Baechle err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set); 3811da177e4SLinus Torvalds 3821da177e4SLinus Torvalds if (err) 38381d103bfSRichard Weinberger return -EFAULT; 3841da177e4SLinus Torvalds 3851da177e4SLinus Torvalds /* 3861da177e4SLinus Torvalds * Arguments to signal handler: 3871da177e4SLinus Torvalds * 3881da177e4SLinus Torvalds * a0 = signal number 3891da177e4SLinus Torvalds * a1 = 0 (should be cause) 3901da177e4SLinus Torvalds * a2 = pointer to ucontext 3911da177e4SLinus Torvalds * 3921da177e4SLinus Torvalds * $25 and c0_epc point to the signal handler, $29 points to 3931da177e4SLinus Torvalds * the struct rt_sigframe32. 3941da177e4SLinus Torvalds */ 39581d103bfSRichard Weinberger regs->regs[ 4] = ksig->sig; 3961da177e4SLinus Torvalds regs->regs[ 5] = (unsigned long) &frame->rs_info; 3971da177e4SLinus Torvalds regs->regs[ 6] = (unsigned long) &frame->rs_uc; 3981da177e4SLinus Torvalds regs->regs[29] = (unsigned long) frame; 399d814c28cSDavid Daney regs->regs[31] = (unsigned long) sig_return; 40081d103bfSRichard Weinberger regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler; 4011da177e4SLinus Torvalds 402722bb63dSFranck Bui-Huu DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", 4031da177e4SLinus Torvalds current->comm, current->pid, 404722bb63dSFranck Bui-Huu frame, regs->cp0_epc, regs->regs[31]); 405722bb63dSFranck Bui-Huu 4067b3e2fc8SRalf Baechle return 0; 4071da177e4SLinus Torvalds } 4081da177e4SLinus Torvalds 4091da177e4SLinus Torvalds /* 410151fd6acSRalf Baechle * o32 compatibility on 64-bit kernels, without DSP ASE 4111da177e4SLinus Torvalds */ 412151fd6acSRalf Baechle struct mips_abi mips_abi_32 = { 413151fd6acSRalf Baechle .setup_frame = setup_frame_32, 414151fd6acSRalf Baechle .setup_rt_frame = setup_rt_frame_32, 41577856100SPaul Burton .restart = __NR_O32_restart_syscall, 41677856100SPaul Burton 41777856100SPaul Burton .off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs), 41877856100SPaul Burton .off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr), 41977856100SPaul Burton .off_sc_used_math = offsetof(struct sigcontext32, sc_used_math), 420ebb5e78cSAlex Smith 421ebb5e78cSAlex Smith .vdso = &vdso_image_o32, 422151fd6acSRalf Baechle }; 423