blob: 78c8349d151c88c48b15cf6dc5d00657cf8a6c9e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
Martin Michlmayrdda73d02006-02-18 15:21:30 +00007 * Copyright (C) 1994 - 2000, 2006 Ralf Baechle
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9 */
Ralf Baechle02416dc2005-06-15 13:00:12 +000010#include <linux/cache.h>
Ralf Baechle431dc802007-02-13 00:05:11 +000011#include <linux/compat.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include <linux/sched.h>
13#include <linux/mm.h>
14#include <linux/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <linux/suspend.h>
22#include <linux/compiler.h>
Atsushi Nemotofaea6232007-04-16 23:19:44 +090023#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
Ralf Baechlee50c0a82005-05-31 11:49:19 +000025#include <asm/abi.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <asm/asm.h>
Ralf Baechle431dc802007-02-13 00:05:11 +000027#include <asm/compat-signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/bitops.h>
29#include <asm/cacheflush.h>
30#include <asm/sim.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <asm/ucontext.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <asm/fpu.h>
Ralf Baechle02416dc2005-06-15 13:00:12 +000033#include <asm/war.h>
David Howellsb81947c2012-03-28 18:30:02 +010034#include <asm/dsp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Franck Bui-Huu36a1f2c22007-02-05 15:24:22 +010036#include "signal-common.h"
37
Linus Torvalds1da177e2005-04-16 15:20:36 -070038/*
39 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
40 */
Ralf Baechle70342282013-01-22 12:59:30 +010041#define __NR_O32_restart_syscall 4253
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
Linus Torvalds1da177e2005-04-16 15:20:36 -070043/* 32-bit compatibility types */
44
Linus Torvalds1da177e2005-04-16 15:20:36 -070045typedef unsigned int __sighandler32_t;
46typedef void (*vfptr_t)(void);
47
Linus Torvalds1da177e2005-04-16 15:20:36 -070048struct ucontext32 {
Ralf Baechle70342282013-01-22 12:59:30 +010049 u32 uc_flags;
50 s32 uc_link;
Al Viroea536ad2012-12-23 03:13:40 -050051 compat_stack_t uc_stack;
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 struct sigcontext32 uc_mcontext;
Ralf Baechle70342282013-01-22 12:59:30 +010053 compat_sigset_t uc_sigmask; /* mask last for extensibility */
Linus Torvalds1da177e2005-04-16 15:20:36 -070054};
55
Ralf Baechledd02f062007-02-13 00:50:57 +000056struct sigframe32 {
57 u32 sf_ass[4]; /* argument save space for o32 */
David Daneyd814c282010-02-18 16:13:05 -080058 u32 sf_pad[2]; /* Was: signal trampoline */
Ralf Baechledd02f062007-02-13 00:50:57 +000059 struct sigcontext32 sf_sc;
Atsushi Nemoto755f21b2007-02-14 14:41:01 +090060 compat_sigset_t sf_mask;
Ralf Baechledd02f062007-02-13 00:50:57 +000061};
62
Franck Bui-Huuc0b9bae2007-02-05 15:24:21 +010063struct rt_sigframe32 {
64 u32 rs_ass[4]; /* argument save space for o32 */
David Daneyd814c282010-02-18 16:13:05 -080065 u32 rs_pad[2]; /* Was: signal trampoline */
Franck Bui-Huuc0b9bae2007-02-05 15:24:21 +010066 compat_siginfo_t rs_info;
67 struct ucontext32 rs_uc;
68};
69
Franck Bui-Huu9432a9b2007-02-05 15:24:25 +010070static int setup_sigcontext32(struct pt_regs *regs,
71 struct sigcontext32 __user *sc)
72{
73 int err = 0;
74 int i;
75
76 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
Franck Bui-Huu9432a9b2007-02-05 15:24:25 +010077
78 err |= __put_user(0, &sc->sc_regs[0]);
79 for (i = 1; i < 32; i++)
80 err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
81
82 err |= __put_user(regs->hi, &sc->sc_mdhi);
83 err |= __put_user(regs->lo, &sc->sc_mdlo);
84 if (cpu_has_dsp) {
85 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
86 err |= __put_user(mfhi1(), &sc->sc_hi1);
87 err |= __put_user(mflo1(), &sc->sc_lo1);
88 err |= __put_user(mfhi2(), &sc->sc_hi2);
89 err |= __put_user(mflo2(), &sc->sc_lo2);
90 err |= __put_user(mfhi3(), &sc->sc_hi3);
91 err |= __put_user(mflo3(), &sc->sc_lo3);
92 }
93
Paul Burtond02a40a2015-07-27 12:58:18 -070094 /*
95 * Save FPU state to signal context. Signal handler
96 * will "inherit" current FPU state.
97 */
98 err |= protected_save_fp_context(sc);
Franck Bui-Huu9432a9b2007-02-05 15:24:25 +010099
Franck Bui-Huu9432a9b2007-02-05 15:24:25 +0100100 return err;
101}
102
103static int restore_sigcontext32(struct pt_regs *regs,
104 struct sigcontext32 __user *sc)
105{
Franck Bui-Huu9432a9b2007-02-05 15:24:25 +0100106 int err = 0;
107 s32 treg;
108 int i;
109
110 /* Always make any pending restarted system calls return -EINTR */
Andy Lutomirskif56141e2015-02-12 15:01:14 -0800111 current->restart_block.fn = do_no_restart_syscall;
Franck Bui-Huu9432a9b2007-02-05 15:24:25 +0100112
113 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
114 err |= __get_user(regs->hi, &sc->sc_mdhi);
115 err |= __get_user(regs->lo, &sc->sc_mdlo);
116 if (cpu_has_dsp) {
117 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
118 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
119 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
120 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
121 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
122 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
123 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
124 }
125
126 for (i = 1; i < 32; i++)
127 err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
128
Paul Burtond02a40a2015-07-27 12:58:18 -0700129 return err ?: protected_restore_fp_context(sc);
Franck Bui-Huu9432a9b2007-02-05 15:24:25 +0100130}
131
132/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 * Atomically swap in the new signal mask, and wait for a signal.
134 */
135
Al Viro1910f4a2012-12-25 16:25:18 -0500136asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137{
Al Viro1910f4a2012-12-25 16:25:18 -0500138 return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139}
140
Al Viroaa584802012-12-25 18:55:27 -0500141SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *, act,
142 struct compat_sigaction __user *, oact)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143{
144 struct k_sigaction new_ka, old_ka;
145 int ret;
146 int err = 0;
147
148 if (act) {
149 old_sigset_t mask;
Ralf Baechle77c728c2005-03-04 19:36:51 +0000150 s32 handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151
152 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
153 return -EFAULT;
Ralf Baechle77c728c2005-03-04 19:36:51 +0000154 err |= __get_user(handler, &act->sa_handler);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900155 new_ka.sa.sa_handler = (void __user *)(s64)handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
157 err |= __get_user(mask, &act->sa_mask.sig[0]);
158 if (err)
159 return -EFAULT;
160
161 siginitset(&new_ka.sa.sa_mask, mask);
162 }
163
164 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
165
166 if (!ret && oact) {
167 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
Martin Michlmayr62549442006-02-18 20:06:32 +0000168 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
170 err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
Ralf Baechle70342282013-01-22 12:59:30 +0100171 &oact->sa_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
Martin Michlmayr62549442006-02-18 20:06:32 +0000173 err |= __put_user(0, &oact->sa_mask.sig[1]);
174 err |= __put_user(0, &oact->sa_mask.sig[2]);
175 err |= __put_user(0, &oact->sa_mask.sig[3]);
176 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 return -EFAULT;
178 }
179
180 return ret;
181}
182
Al Viroce395962013-10-13 17:23:53 -0400183int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184{
185 int err;
186
187 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
188 return -EFAULT;
189
190 /* If you change siginfo_t structure, please be sure
191 this code is fixed accordingly.
192 It should never copy any pad contained in the structure
193 to avoid security leaks, but must copy the generic
194 3 ints plus the relevant union member.
195 This routine must convert siginfo from 64bit to 32bit as well
196 at the same time. */
197 err = __put_user(from->si_signo, &to->si_signo);
198 err |= __put_user(from->si_errno, &to->si_errno);
199 err |= __put_user((short)from->si_code, &to->si_code);
200 if (from->si_code < 0)
201 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
202 else {
203 switch (from->si_code >> 16) {
Ralf Baechlea9820992005-02-16 21:24:16 +0000204 case __SI_TIMER >> 16:
205 err |= __put_user(from->si_tid, &to->si_tid);
206 err |= __put_user(from->si_overrun, &to->si_overrun);
207 err |= __put_user(from->si_int, &to->si_int);
208 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 case __SI_CHLD >> 16:
210 err |= __put_user(from->si_utime, &to->si_utime);
211 err |= __put_user(from->si_stime, &to->si_stime);
212 err |= __put_user(from->si_status, &to->si_status);
213 default:
214 err |= __put_user(from->si_pid, &to->si_pid);
215 err |= __put_user(from->si_uid, &to->si_uid);
216 break;
217 case __SI_FAULT >> 16:
Atsushi Nemoto5665a0a2006-02-02 01:26:34 +0900218 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 break;
220 case __SI_POLL >> 16:
221 err |= __put_user(from->si_band, &to->si_band);
222 err |= __put_user(from->si_fd, &to->si_fd);
223 break;
224 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
225 case __SI_MESGQ >> 16:
226 err |= __put_user(from->si_pid, &to->si_pid);
227 err |= __put_user(from->si_uid, &to->si_uid);
228 err |= __put_user(from->si_int, &to->si_int);
229 break;
Matt Redfearn5050e912016-03-29 09:35:30 +0100230 case __SI_SYS >> 16:
231 err |= __copy_to_user(&to->si_call_addr, &from->si_call_addr,
232 sizeof(compat_uptr_t));
233 err |= __put_user(from->si_syscall, &to->si_syscall);
234 err |= __put_user(from->si_arch, &to->si_arch);
235 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 }
237 }
238 return err;
239}
240
Thomas Bogendoerfer5d9a76c2008-08-17 16:49:25 +0200241int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
242{
Thomas Bogendoerfer5d9a76c2008-08-17 16:49:25 +0200243 if (copy_from_user(to, from, 3*sizeof(int)) ||
244 copy_from_user(to->_sifields._pad,
245 from->_sifields._pad, SI_PAD_SIZE32))
246 return -EFAULT;
247
248 return 0;
249}
250
Franck Bui-Huuf90080a2007-02-05 15:24:27 +0100251asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252{
Ralf Baechledd02f062007-02-13 00:50:57 +0000253 struct sigframe32 __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 sigset_t blocked;
Atsushi Nemotoc6a2f462007-03-10 01:03:48 +0900255 int sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256
Ralf Baechledd02f062007-02-13 00:50:57 +0000257 frame = (struct sigframe32 __user *) regs.regs[29];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
259 goto badframe;
Ralf Baechle431dc802007-02-13 00:05:11 +0000260 if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 goto badframe;
262
Matt Fleming8598f3c2012-02-14 11:40:52 +0000263 set_current_blocked(&blocked);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
Atsushi Nemotoc6a2f462007-03-10 01:03:48 +0900265 sig = restore_sigcontext32(&regs, &frame->sf_sc);
266 if (sig < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 goto badframe;
Atsushi Nemotoc6a2f462007-03-10 01:03:48 +0900268 else if (sig)
269 force_sig(sig, current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
271 /*
272 * Don't let your children do this ...
273 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 __asm__ __volatile__(
275 "move\t$29, %0\n\t"
276 "j\tsyscall_exit"
277 :/* no outputs */
278 :"r" (&regs));
279 /* Unreached */
280
281badframe:
282 force_sig(SIGSEGV, current);
283}
284
Franck Bui-Huuf90080a2007-02-05 15:24:27 +0100285asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900287 struct rt_sigframe32 __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 sigset_t set;
Atsushi Nemotoc6a2f462007-03-10 01:03:48 +0900289 int sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900291 frame = (struct rt_sigframe32 __user *) regs.regs[29];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
293 goto badframe;
Ralf Baechle431dc802007-02-13 00:05:11 +0000294 if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 goto badframe;
296
Matt Fleming8598f3c2012-02-14 11:40:52 +0000297 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298
Atsushi Nemotoc6a2f462007-03-10 01:03:48 +0900299 sig = restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext);
300 if (sig < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 goto badframe;
Atsushi Nemotoc6a2f462007-03-10 01:03:48 +0900302 else if (sig)
303 force_sig(sig, current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304
Al Viroea536ad2012-12-23 03:13:40 -0500305 if (compat_restore_altstack(&frame->rs_uc.uc_stack))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 goto badframe;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
308 /*
309 * Don't let your children do this ...
310 */
311 __asm__ __volatile__(
312 "move\t$29, %0\n\t"
313 "j\tsyscall_exit"
314 :/* no outputs */
315 :"r" (&regs));
316 /* Unreached */
317
318badframe:
319 force_sig(SIGSEGV, current);
320}
321
Richard Weinberger81d103b2013-10-06 22:25:42 +0200322static int setup_frame_32(void *sig_return, struct ksignal *ksig,
323 struct pt_regs *regs, sigset_t *set)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324{
Ralf Baechledd02f062007-02-13 00:50:57 +0000325 struct sigframe32 __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 int err = 0;
327
Richard Weinberger7c4f5632014-03-05 15:35:41 +0100328 frame = get_sigframe(ksig, regs, sizeof(*frame));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
Richard Weinberger81d103b2013-10-06 22:25:42 +0200330 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 err |= setup_sigcontext32(regs, &frame->sf_sc);
Ralf Baechle431dc802007-02-13 00:05:11 +0000333 err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
334
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 if (err)
Richard Weinberger81d103b2013-10-06 22:25:42 +0200336 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
338 /*
339 * Arguments to signal handler:
340 *
341 * a0 = signal number
342 * a1 = 0 (should be cause)
343 * a2 = pointer to struct sigcontext
344 *
345 * $25 and c0_epc point to the signal handler, $29 points to the
346 * struct sigframe.
347 */
Richard Weinberger81d103b2013-10-06 22:25:42 +0200348 regs->regs[ 4] = ksig->sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 regs->regs[ 5] = 0;
350 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
351 regs->regs[29] = (unsigned long) frame;
David Daneyd814c282010-02-18 16:13:05 -0800352 regs->regs[31] = (unsigned long) sig_return;
Richard Weinberger81d103b2013-10-06 22:25:42 +0200353 regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354
Franck Bui-Huu722bb632007-02-05 15:24:24 +0100355 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 current->comm, current->pid,
Franck Bui-Huu722bb632007-02-05 15:24:24 +0100357 frame, regs->cp0_epc, regs->regs[31]);
358
Ralf Baechle7b3e2fc2006-02-08 12:58:41 +0000359 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360}
361
Richard Weinberger81d103b2013-10-06 22:25:42 +0200362static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
363 struct pt_regs *regs, sigset_t *set)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900365 struct rt_sigframe32 __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367
Richard Weinberger7c4f5632014-03-05 15:35:41 +0100368 frame = get_sigframe(ksig, regs, sizeof(*frame));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
Richard Weinberger81d103b2013-10-06 22:25:42 +0200370 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
Richard Weinberger81d103b2013-10-06 22:25:42 +0200373 err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
Ralf Baechle70342282013-01-22 12:59:30 +0100375 /* Create the ucontext. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 err |= __put_user(0, &frame->rs_uc.uc_flags);
377 err |= __put_user(0, &frame->rs_uc.uc_link);
Al Viroea536ad2012-12-23 03:13:40 -0500378 err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
Ralf Baechle431dc802007-02-13 00:05:11 +0000380 err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
382 if (err)
Richard Weinberger81d103b2013-10-06 22:25:42 +0200383 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
385 /*
386 * Arguments to signal handler:
387 *
388 * a0 = signal number
389 * a1 = 0 (should be cause)
390 * a2 = pointer to ucontext
391 *
392 * $25 and c0_epc point to the signal handler, $29 points to
393 * the struct rt_sigframe32.
394 */
Richard Weinberger81d103b2013-10-06 22:25:42 +0200395 regs->regs[ 4] = ksig->sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 regs->regs[ 5] = (unsigned long) &frame->rs_info;
397 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
398 regs->regs[29] = (unsigned long) frame;
David Daneyd814c282010-02-18 16:13:05 -0800399 regs->regs[31] = (unsigned long) sig_return;
Richard Weinberger81d103b2013-10-06 22:25:42 +0200400 regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
Franck Bui-Huu722bb632007-02-05 15:24:24 +0100402 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 current->comm, current->pid,
Franck Bui-Huu722bb632007-02-05 15:24:24 +0100404 frame, regs->cp0_epc, regs->regs[31]);
405
Ralf Baechle7b3e2fc2006-02-08 12:58:41 +0000406 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407}
408
Ralf Baechle151fd6a2007-02-15 11:40:37 +0000409/*
410 * o32 compatibility on 64-bit kernels, without DSP ASE
411 */
412struct mips_abi mips_abi_32 = {
413 .setup_frame = setup_frame_32,
Ralf Baechle70342282013-01-22 12:59:30 +0100414 .setup_rt_frame = setup_rt_frame_32,
Paul Burton77856102015-07-27 12:58:14 -0700415 .restart = __NR_O32_restart_syscall,
416
417 .off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs),
418 .off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr),
419 .off_sc_used_math = offsetof(struct sigcontext32, sc_used_math),
Alex Smithebb5e782015-10-21 09:54:38 +0100420
421 .vdso = &vdso_image_o32,
Ralf Baechle151fd6a2007-02-15 11:40:37 +0000422};