blob: 8504febf8b2293752132a8f1a4ebf7bad7be72e8 [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
7 * Copyright (C) 1994 - 2000 Ralf Baechle
8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9 */
10#include <linux/config.h>
11#include <linux/sched.h>
12#include <linux/mm.h>
13#include <linux/personality.h>
14#include <linux/smp.h>
15#include <linux/smp_lock.h>
16#include <linux/kernel.h>
17#include <linux/signal.h>
18#include <linux/errno.h>
19#include <linux/wait.h>
20#include <linux/ptrace.h>
21#include <linux/unistd.h>
22#include <linux/compiler.h>
23
Ralf Baechlee50c0a82005-05-31 11:49:19 +000024#include <asm/abi.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <asm/asm.h>
26#include <linux/bitops.h>
27#include <asm/cacheflush.h>
28#include <asm/fpu.h>
29#include <asm/sim.h>
30#include <asm/uaccess.h>
31#include <asm/ucontext.h>
32#include <asm/cpu-features.h>
33
34#include "signal-common.h"
35
36#define DEBUG_SIG 0
37
38#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
39
Ralf Baechlee50c0a82005-05-31 11:49:19 +000040int do_signal(sigset_t *oldset, struct pt_regs *regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42/*
43 * Atomically swap in the new signal mask, and wait for a signal.
44 */
45
46#ifdef CONFIG_TRAD_SIGNALS
47save_static_function(sys_sigsuspend);
48__attribute_used__ noinline static int
49_sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
50{
Ralf Baechlefe00f942005-03-01 19:22:29 +000051 sigset_t saveset, newset;
52 sigset_t __user *uset;
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
Ralf Baechlefe00f942005-03-01 19:22:29 +000054 uset = (sigset_t __user *) regs.regs[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -070055 if (copy_from_user(&newset, uset, sizeof(sigset_t)))
56 return -EFAULT;
57 sigdelsetmask(&newset, ~_BLOCKABLE);
58
59 spin_lock_irq(&current->sighand->siglock);
60 saveset = current->blocked;
61 current->blocked = newset;
62 recalc_sigpending();
63 spin_unlock_irq(&current->sighand->siglock);
64
65 regs.regs[2] = EINTR;
66 regs.regs[7] = 1;
67 while (1) {
68 current->state = TASK_INTERRUPTIBLE;
69 schedule();
70 if (do_signal(&saveset, &regs))
71 return -EINTR;
72 }
73}
74#endif
75
76save_static_function(sys_rt_sigsuspend);
77__attribute_used__ noinline static int
78_sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
79{
Ralf Baechlefe00f942005-03-01 19:22:29 +000080 sigset_t saveset, newset;
81 sigset_t __user *unewset;
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 size_t sigsetsize;
83
84 /* XXX Don't preclude handling different sized sigset_t's. */
85 sigsetsize = regs.regs[5];
86 if (sigsetsize != sizeof(sigset_t))
87 return -EINVAL;
88
Ralf Baechlefe00f942005-03-01 19:22:29 +000089 unewset = (sigset_t __user *) regs.regs[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 if (copy_from_user(&newset, unewset, sizeof(newset)))
91 return -EFAULT;
92 sigdelsetmask(&newset, ~_BLOCKABLE);
93
94 spin_lock_irq(&current->sighand->siglock);
95 saveset = current->blocked;
96 current->blocked = newset;
97 recalc_sigpending();
98 spin_unlock_irq(&current->sighand->siglock);
99
100 regs.regs[2] = EINTR;
101 regs.regs[7] = 1;
102 while (1) {
103 current->state = TASK_INTERRUPTIBLE;
104 schedule();
105 if (do_signal(&saveset, &regs))
106 return -EINTR;
107 }
108}
109
110#ifdef CONFIG_TRAD_SIGNALS
111asmlinkage int sys_sigaction(int sig, const struct sigaction *act,
112 struct sigaction *oact)
113{
114 struct k_sigaction new_ka, old_ka;
115 int ret;
116 int err = 0;
117
118 if (act) {
119 old_sigset_t mask;
120
121 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
122 return -EFAULT;
123 err |= __get_user(new_ka.sa.sa_handler, &act->sa_handler);
124 err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
125 err |= __get_user(mask, &act->sa_mask.sig[0]);
126 if (err)
127 return -EFAULT;
128
129 siginitset(&new_ka.sa.sa_mask, mask);
130 }
131
132 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
133
134 if (!ret && oact) {
135 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
136 return -EFAULT;
137 err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
138 err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler);
139 err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
140 err |= __put_user(0, &oact->sa_mask.sig[1]);
141 err |= __put_user(0, &oact->sa_mask.sig[2]);
142 err |= __put_user(0, &oact->sa_mask.sig[3]);
143 if (err)
144 return -EFAULT;
145 }
146
147 return ret;
148}
149#endif
150
151asmlinkage int sys_sigaltstack(nabi_no_regargs struct pt_regs regs)
152{
Ralf Baechlefe00f942005-03-01 19:22:29 +0000153 const stack_t __user *uss = (const stack_t __user *) regs.regs[4];
154 stack_t __user *uoss = (stack_t __user *) regs.regs[5];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 unsigned long usp = regs.regs[29];
156
157 return do_sigaltstack(uss, uoss, usp);
158}
159
160#if PLAT_TRAMPOLINE_STUFF_LINE
161#define __tramp __attribute__((aligned(PLAT_TRAMPOLINE_STUFF_LINE)))
162#else
163#define __tramp
164#endif
165
166#ifdef CONFIG_TRAD_SIGNALS
167struct sigframe {
168 u32 sf_ass[4]; /* argument save space for o32 */
169 u32 sf_code[2] __tramp; /* signal trampoline */
170 struct sigcontext sf_sc __tramp;
171 sigset_t sf_mask;
172};
173#endif
174
175struct rt_sigframe {
176 u32 rs_ass[4]; /* argument save space for o32 */
177 u32 rs_code[2] __tramp; /* signal trampoline */
178 struct siginfo rs_info __tramp;
179 struct ucontext rs_uc;
180};
181
182#ifdef CONFIG_TRAD_SIGNALS
183save_static_function(sys_sigreturn);
184__attribute_used__ noinline static void
185_sys_sigreturn(nabi_no_regargs struct pt_regs regs)
186{
187 struct sigframe *frame;
188 sigset_t blocked;
189
190 frame = (struct sigframe *) regs.regs[29];
191 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
192 goto badframe;
193 if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
194 goto badframe;
195
196 sigdelsetmask(&blocked, ~_BLOCKABLE);
197 spin_lock_irq(&current->sighand->siglock);
198 current->blocked = blocked;
199 recalc_sigpending();
200 spin_unlock_irq(&current->sighand->siglock);
201
202 if (restore_sigcontext(&regs, &frame->sf_sc))
203 goto badframe;
204
205 /*
206 * Don't let your children do this ...
207 */
208 if (current_thread_info()->flags & TIF_SYSCALL_TRACE)
209 do_syscall_trace(&regs, 1);
210 __asm__ __volatile__(
211 "move\t$29, %0\n\t"
212 "j\tsyscall_exit"
213 :/* no outputs */
214 :"r" (&regs));
215 /* Unreached */
216
217badframe:
218 force_sig(SIGSEGV, current);
219}
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000220#endif /* CONFIG_TRAD_SIGNALS */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221
222save_static_function(sys_rt_sigreturn);
223__attribute_used__ noinline static void
224_sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
225{
226 struct rt_sigframe *frame;
227 sigset_t set;
228 stack_t st;
229
230 frame = (struct rt_sigframe *) regs.regs[29];
231 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
232 goto badframe;
233 if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
234 goto badframe;
235
236 sigdelsetmask(&set, ~_BLOCKABLE);
237 spin_lock_irq(&current->sighand->siglock);
238 current->blocked = set;
239 recalc_sigpending();
240 spin_unlock_irq(&current->sighand->siglock);
241
242 if (restore_sigcontext(&regs, &frame->rs_uc.uc_mcontext))
243 goto badframe;
244
245 if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st)))
246 goto badframe;
247 /* It is more difficult to avoid calling this function than to
248 call it and ignore errors. */
249 do_sigaltstack(&st, NULL, regs.regs[29]);
250
251 /*
252 * Don't let your children do this ...
253 */
254 __asm__ __volatile__(
255 "move\t$29, %0\n\t"
256 "j\tsyscall_exit"
257 :/* no outputs */
258 :"r" (&regs));
259 /* Unreached */
260
261badframe:
262 force_sig(SIGSEGV, current);
263}
264
265#ifdef CONFIG_TRAD_SIGNALS
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000266void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 int signr, sigset_t *set)
268{
269 struct sigframe *frame;
270 int err = 0;
271
272 frame = get_sigframe(ka, regs, sizeof(*frame));
273 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
274 goto give_sigsegv;
275
276 /*
277 * Set up the return code ...
278 *
279 * li v0, __NR_sigreturn
280 * syscall
281 */
282 if (PLAT_TRAMPOLINE_STUFF_LINE)
283 __clear_user(frame->sf_code, PLAT_TRAMPOLINE_STUFF_LINE);
284 err |= __put_user(0x24020000 + __NR_sigreturn, frame->sf_code + 0);
285 err |= __put_user(0x0000000c , frame->sf_code + 1);
286 flush_cache_sigtramp((unsigned long) frame->sf_code);
287
288 err |= setup_sigcontext(regs, &frame->sf_sc);
289 err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
290 if (err)
291 goto give_sigsegv;
292
293 /*
294 * Arguments to signal handler:
295 *
296 * a0 = signal number
297 * a1 = 0 (should be cause)
298 * a2 = pointer to struct sigcontext
299 *
300 * $25 and c0_epc point to the signal handler, $29 points to the
301 * struct sigframe.
302 */
303 regs->regs[ 4] = signr;
304 regs->regs[ 5] = 0;
305 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
306 regs->regs[29] = (unsigned long) frame;
307 regs->regs[31] = (unsigned long) frame->sf_code;
308 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
309
310#if DEBUG_SIG
311 printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
312 current->comm, current->pid,
313 frame, regs->cp0_epc, frame->regs[31]);
314#endif
315 return;
316
317give_sigsegv:
318 force_sigsegv(signr, current);
319}
320#endif
321
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000322void setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 int signr, sigset_t *set, siginfo_t *info)
324{
325 struct rt_sigframe *frame;
326 int err = 0;
327
328 frame = get_sigframe(ka, regs, sizeof(*frame));
329 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
330 goto give_sigsegv;
331
332 /*
333 * Set up the return code ...
334 *
335 * li v0, __NR_rt_sigreturn
336 * syscall
337 */
338 if (PLAT_TRAMPOLINE_STUFF_LINE)
339 __clear_user(frame->rs_code, PLAT_TRAMPOLINE_STUFF_LINE);
340 err |= __put_user(0x24020000 + __NR_rt_sigreturn, frame->rs_code + 0);
341 err |= __put_user(0x0000000c , frame->rs_code + 1);
342 flush_cache_sigtramp((unsigned long) frame->rs_code);
343
344 /* Create siginfo. */
345 err |= copy_siginfo_to_user(&frame->rs_info, info);
346
347 /* Create the ucontext. */
348 err |= __put_user(0, &frame->rs_uc.uc_flags);
349 err |= __put_user(0, &frame->rs_uc.uc_link);
350 err |= __put_user((void *)current->sas_ss_sp,
351 &frame->rs_uc.uc_stack.ss_sp);
352 err |= __put_user(sas_ss_flags(regs->regs[29]),
353 &frame->rs_uc.uc_stack.ss_flags);
354 err |= __put_user(current->sas_ss_size,
355 &frame->rs_uc.uc_stack.ss_size);
356 err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
357 err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
358
359 if (err)
360 goto give_sigsegv;
361
362 /*
363 * Arguments to signal handler:
364 *
365 * a0 = signal number
366 * a1 = 0 (should be cause)
367 * a2 = pointer to ucontext
368 *
369 * $25 and c0_epc point to the signal handler, $29 points to
370 * the struct rt_sigframe.
371 */
372 regs->regs[ 4] = signr;
373 regs->regs[ 5] = (unsigned long) &frame->rs_info;
374 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
375 regs->regs[29] = (unsigned long) frame;
376 regs->regs[31] = (unsigned long) frame->rs_code;
377 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
378
379#if DEBUG_SIG
380 printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
381 current->comm, current->pid,
382 frame, regs->cp0_epc, regs->regs[31]);
383#endif
384 return;
385
386give_sigsegv:
387 force_sigsegv(signr, current);
388}
389
390extern void setup_rt_frame_n32(struct k_sigaction * ka,
391 struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info);
392
393static inline void handle_signal(unsigned long sig, siginfo_t *info,
394 struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
395{
396 switch(regs->regs[0]) {
397 case ERESTART_RESTARTBLOCK:
398 case ERESTARTNOHAND:
399 regs->regs[2] = EINTR;
400 break;
401 case ERESTARTSYS:
402 if(!(ka->sa.sa_flags & SA_RESTART)) {
403 regs->regs[2] = EINTR;
404 break;
405 }
406 /* fallthrough */
407 case ERESTARTNOINTR: /* Userland will reload $v0. */
408 regs->regs[7] = regs->regs[26];
409 regs->cp0_epc -= 8;
410 }
411
412 regs->regs[0] = 0; /* Don't deal with this again. */
413
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000414 if (sig_uses_siginfo(ka))
415 current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 else
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000417 current->thread.abi->setup_frame(ka, regs, sig, oldset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
Steven Rostedt69be8f12005-08-29 11:44:09 -0400419 spin_lock_irq(&current->sighand->siglock);
420 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
421 if (!(ka->sa.sa_flags & SA_NODEFER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 sigaddset(&current->blocked,sig);
Steven Rostedt69be8f12005-08-29 11:44:09 -0400423 recalc_sigpending();
424 spin_unlock_irq(&current->sighand->siglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425}
426
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000427int do_signal(sigset_t *oldset, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428{
429 struct k_sigaction ka;
430 siginfo_t info;
431 int signr;
432
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 /*
434 * We want the common case to go fast, which is why we may in certain
435 * cases get here from kernel mode. Just return without doing anything
436 * if so.
437 */
438 if (!user_mode(regs))
439 return 1;
440
Yoichi Yuasad4b3a802005-06-27 14:36:30 -0700441 if (try_to_freeze())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 goto no_signal;
443
444 if (!oldset)
445 oldset = &current->blocked;
446
447 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
448 if (signr > 0) {
449 handle_signal(signr, &info, &ka, oldset, regs);
450 return 1;
451 }
452
453no_signal:
454 /*
455 * Who's code doesn't conform to the restartable syscall convention
456 * dies here!!! The li instruction, a single machine instruction,
457 * must directly be followed by the syscall instruction.
458 */
459 if (regs->regs[0]) {
460 if (regs->regs[2] == ERESTARTNOHAND ||
461 regs->regs[2] == ERESTARTSYS ||
462 regs->regs[2] == ERESTARTNOINTR) {
463 regs->regs[7] = regs->regs[26];
464 regs->cp0_epc -= 8;
465 }
466 if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
467 regs->regs[2] = __NR_restart_syscall;
468 regs->regs[7] = regs->regs[26];
469 regs->cp0_epc -= 4;
470 }
471 }
472 return 0;
473}
474
475/*
476 * notification of userspace execution resumption
477 * - triggered by current->work.notify_resume
478 */
479asmlinkage void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
480 __u32 thread_info_flags)
481{
482 /* deal with pending signal delivery */
483 if (thread_info_flags & _TIF_SIGPENDING) {
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000484 current->thread.abi->do_signal(oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 }
486}