Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma
[deliverable/linux.git] / arch / mips / kernel / signal32.c
CommitLineData
1da177e4
LT
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
dda73d0b 7 * Copyright (C) 1994 - 2000, 2006 Ralf Baechle
1da177e4
LT
8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9 */
02416dcf 10#include <linux/cache.h>
431dc804 11#include <linux/compat.h>
1da177e4
LT
12#include <linux/sched.h>
13#include <linux/mm.h>
14#include <linux/smp.h>
1da177e4
LT
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>
1da177e4
LT
21#include <linux/suspend.h>
22#include <linux/compiler.h>
faea6234 23#include <linux/uaccess.h>
1da177e4 24
e50c0a8f 25#include <asm/abi.h>
1da177e4 26#include <asm/asm.h>
431dc804 27#include <asm/compat-signal.h>
1da177e4
LT
28#include <linux/bitops.h>
29#include <asm/cacheflush.h>
30#include <asm/sim.h>
1da177e4 31#include <asm/ucontext.h>
1da177e4 32#include <asm/fpu.h>
02416dcf 33#include <asm/war.h>
b81947c6 34#include <asm/dsp.h>
1da177e4 35
36a1f2c2
FBH
36#include "signal-common.h"
37
1da177e4
LT
38/*
39 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
40 */
70342287 41#define __NR_O32_restart_syscall 4253
1da177e4 42
1da177e4
LT
43/* 32-bit compatibility types */
44
1da177e4
LT
45typedef unsigned int __sighandler32_t;
46typedef void (*vfptr_t)(void);
47
1da177e4 48struct ucontext32 {
70342287
RB
49 u32 uc_flags;
50 s32 uc_link;
ea536ad4 51 compat_stack_t uc_stack;
1da177e4 52 struct sigcontext32 uc_mcontext;
70342287 53 compat_sigset_t uc_sigmask; /* mask last for extensibility */
1da177e4
LT
54};
55
dd02f06a
RB
56struct sigframe32 {
57 u32 sf_ass[4]; /* argument save space for o32 */
d814c28c 58 u32 sf_pad[2]; /* Was: signal trampoline */
dd02f06a 59 struct sigcontext32 sf_sc;
755f21bb 60 compat_sigset_t sf_mask;
dd02f06a
RB
61};
62
c0b9bae9
FBH
63struct rt_sigframe32 {
64 u32 rs_ass[4]; /* argument save space for o32 */
d814c28c 65 u32 rs_pad[2]; /* Was: signal trampoline */
c0b9bae9
FBH
66 compat_siginfo_t rs_info;
67 struct ucontext32 rs_uc;
68};
69
9432a9ba
FBH
70static 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);
9432a9ba
FBH
77
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
d02a40af
PB
94 /*
95 * Save FPU state to signal context. Signal handler
96 * will "inherit" current FPU state.
97 */
98 err |= protected_save_fp_context(sc);
9432a9ba 99
9432a9ba
FBH
100 return err;
101}
102
103static int restore_sigcontext32(struct pt_regs *regs,
104 struct sigcontext32 __user *sc)
105{
9432a9ba
FBH
106 int err = 0;
107 s32 treg;
108 int i;
109
110 /* Always make any pending restarted system calls return -EINTR */
f56141e3 111 current->restart_block.fn = do_no_restart_syscall;
9432a9ba
FBH
112
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
d02a40af 129 return err ?: protected_restore_fp_context(sc);
9432a9ba
FBH
130}
131
1da177e4
LT
132/*
133 * Atomically swap in the new signal mask, and wait for a signal.
134 */
135
1910f4ab 136asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset)
1da177e4 137{
1910f4ab 138 return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t));
1da177e4
LT
139}
140
aa584802
AV
141SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *, act,
142 struct compat_sigaction __user *, oact)
1da177e4
LT
143{
144 struct k_sigaction new_ka, old_ka;
145 int ret;
146 int err = 0;
147
148 if (act) {
149 old_sigset_t mask;
77c728c2 150 s32 handler;
1da177e4
LT
151
152 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
153 return -EFAULT;
77c728c2 154 err |= __get_user(handler, &act->sa_handler);
9bbf28a3 155 new_ka.sa.sa_handler = (void __user *)(s64)handler;
1da177e4
LT
156 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)))
6254944f 168 return -EFAULT;
1da177e4
LT
169 err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
170 err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
70342287 171 &oact->sa_handler);
1da177e4 172 err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
6254944f
MM
173 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)
1da177e4
LT
177 return -EFAULT;
178 }
179
180 return ret;
181}
182
ce395960 183int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
1da177e4
LT
184{
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) {
a982099c
RB
204 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;
1da177e4
LT
209 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:
5665a0ac 218 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
1da177e4
LT
219 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;
5050e91f
MR
230 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;
1da177e4
LT
236 }
237 }
238 return err;
239}
240
5d9a76cd
TB
241int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
242{
5d9a76cd
TB
243 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
f90080a0 251asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
1da177e4 252{
dd02f06a 253 struct sigframe32 __user *frame;
1da177e4 254 sigset_t blocked;
c6a2f467 255 int sig;
1da177e4 256
dd02f06a 257 frame = (struct sigframe32 __user *) regs.regs[29];
1da177e4
LT
258 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
259 goto badframe;
431dc804 260 if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
1da177e4
LT
261 goto badframe;
262
8598f3cd 263 set_current_blocked(&blocked);
1da177e4 264
c6a2f467
AN
265 sig = restore_sigcontext32(&regs, &frame->sf_sc);
266 if (sig < 0)
1da177e4 267 goto badframe;
c6a2f467
AN
268 else if (sig)
269 force_sig(sig, current);
1da177e4
LT
270
271 /*
272 * Don't let your children do this ...
273 */
1da177e4
LT
274 __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
f90080a0 285asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
1da177e4 286{
9bbf28a3 287 struct rt_sigframe32 __user *frame;
1da177e4 288 sigset_t set;
c6a2f467 289 int sig;
1da177e4 290
9bbf28a3 291 frame = (struct rt_sigframe32 __user *) regs.regs[29];
1da177e4
LT
292 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
293 goto badframe;
431dc804 294 if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
1da177e4
LT
295 goto badframe;
296
8598f3cd 297 set_current_blocked(&set);
1da177e4 298
c6a2f467
AN
299 sig = restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext);
300 if (sig < 0)
1da177e4 301 goto badframe;
c6a2f467
AN
302 else if (sig)
303 force_sig(sig, current);
1da177e4 304
ea536ad4 305 if (compat_restore_altstack(&frame->rs_uc.uc_stack))
1da177e4 306 goto badframe;
1da177e4
LT
307
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
81d103bf
RW
322static int setup_frame_32(void *sig_return, struct ksignal *ksig,
323 struct pt_regs *regs, sigset_t *set)
1da177e4 324{
dd02f06a 325 struct sigframe32 __user *frame;
1da177e4
LT
326 int err = 0;
327
7c4f5635 328 frame = get_sigframe(ksig, regs, sizeof(*frame));
1da177e4 329 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
81d103bf 330 return -EFAULT;
1da177e4 331
1da177e4 332 err |= setup_sigcontext32(regs, &frame->sf_sc);
431dc804
RB
333 err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
334
1da177e4 335 if (err)
81d103bf 336 return -EFAULT;
1da177e4
LT
337
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 */
81d103bf 348 regs->regs[ 4] = ksig->sig;
1da177e4
LT
349 regs->regs[ 5] = 0;
350 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
351 regs->regs[29] = (unsigned long) frame;
d814c28c 352 regs->regs[31] = (unsigned long) sig_return;
81d103bf 353 regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
1da177e4 354
722bb63d 355 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
1da177e4 356 current->comm, current->pid,
722bb63d
FBH
357 frame, regs->cp0_epc, regs->regs[31]);
358
7b3e2fc8 359 return 0;
1da177e4
LT
360}
361
81d103bf
RW
362static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
363 struct pt_regs *regs, sigset_t *set)
1da177e4 364{
9bbf28a3 365 struct rt_sigframe32 __user *frame;
1da177e4 366 int err = 0;
1da177e4 367
7c4f5635 368 frame = get_sigframe(ksig, regs, sizeof(*frame));
1da177e4 369 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
81d103bf 370 return -EFAULT;
1da177e4 371
1da177e4 372 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
81d103bf 373 err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info);
1da177e4 374
70342287 375 /* Create the ucontext. */
1da177e4
LT
376 err |= __put_user(0, &frame->rs_uc.uc_flags);
377 err |= __put_user(0, &frame->rs_uc.uc_link);
ea536ad4 378 err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]);
1da177e4 379 err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
431dc804 380 err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
1da177e4
LT
381
382 if (err)
81d103bf 383 return -EFAULT;
1da177e4
LT
384
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 */
81d103bf 395 regs->regs[ 4] = ksig->sig;
1da177e4
LT
396 regs->regs[ 5] = (unsigned long) &frame->rs_info;
397 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
398 regs->regs[29] = (unsigned long) frame;
d814c28c 399 regs->regs[31] = (unsigned long) sig_return;
81d103bf 400 regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
1da177e4 401
722bb63d 402 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
1da177e4 403 current->comm, current->pid,
722bb63d
FBH
404 frame, regs->cp0_epc, regs->regs[31]);
405
7b3e2fc8 406 return 0;
1da177e4
LT
407}
408
151fd6ac
RB
409/*
410 * o32 compatibility on 64-bit kernels, without DSP ASE
411 */
412struct mips_abi mips_abi_32 = {
413 .setup_frame = setup_frame_32,
70342287 414 .setup_rt_frame = setup_rt_frame_32,
77856100
PB
415 .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),
ebb5e78c
AS
420
421 .vdso = &vdso_image_o32,
151fd6ac 422};
This page took 0.732962 seconds and 5 git commands to generate.