aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris/arch-v10/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/cris/arch-v10/kernel/signal.c')
-rw-r--r--arch/cris/arch-v10/kernel/signal.c580
1 files changed, 580 insertions, 0 deletions
diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c
new file mode 100644
index 000000000000..85e0032e664f
--- /dev/null
+++ b/arch/cris/arch-v10/kernel/signal.c
@@ -0,0 +1,580 @@
1/*
2 * linux/arch/cris/kernel/signal.c
3 *
4 * Based on arch/i386/kernel/signal.c by
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson *
7 *
8 * Ideas also taken from arch/arm.
9 *
10 * Copyright (C) 2000, 2001 Axis Communications AB
11 *
12 * Authors: Bjorn Wesen (bjornw@axis.com)
13 *
14 */
15
16#include <linux/sched.h>
17#include <linux/mm.h>
18#include <linux/smp.h>
19#include <linux/smp_lock.h>
20#include <linux/kernel.h>
21#include <linux/signal.h>
22#include <linux/errno.h>
23#include <linux/wait.h>
24#include <linux/ptrace.h>
25#include <linux/unistd.h>
26#include <linux/stddef.h>
27
28#include <asm/processor.h>
29#include <asm/ucontext.h>
30#include <asm/uaccess.h>
31
32#define DEBUG_SIG 0
33
34#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
35
36/* a syscall in Linux/CRIS is a break 13 instruction which is 2 bytes */
37/* manipulate regs so that upon return, it will be re-executed */
38
39/* We rely on that pc points to the instruction after "break 13", so the
40 * library must never do strange things like putting it in a delay slot.
41 */
42#define RESTART_CRIS_SYS(regs) regs->r10 = regs->orig_r10; regs->irp -= 2;
43
44int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs);
45
46/*
47 * Atomically swap in the new signal mask, and wait for a signal. Define
48 * dummy arguments to be able to reach the regs argument. (Note that this
49 * arrangement relies on old_sigset_t occupying one register.)
50 */
51int
52sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof,
53 long srp, struct pt_regs *regs)
54{
55 sigset_t saveset;
56
57 mask &= _BLOCKABLE;
58 spin_lock_irq(&current->sighand->siglock);
59 saveset = current->blocked;
60 siginitset(&current->blocked, mask);
61 recalc_sigpending();
62 spin_unlock_irq(&current->sighand->siglock);
63
64 regs->r10 = -EINTR;
65 while (1) {
66 current->state = TASK_INTERRUPTIBLE;
67 schedule();
68 if (do_signal(0, &saveset, regs))
69 /* We will get here twice: once to call the signal
70 handler, then again to return from the
71 sigsuspend system call. When calling the
72 signal handler, R10 holds the signal number as
73 set through do_signal. The sigsuspend call
74 will return with the restored value set above;
75 always -EINTR. */
76 return regs->r10;
77 }
78}
79
80/* Define dummy arguments to be able to reach the regs argument. (Note that
81 * this arrangement relies on size_t occupying one register.)
82 */
83int
84sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, long r12, long r13,
85 long mof, long srp, struct pt_regs *regs)
86{
87 sigset_t saveset, newset;
88
89 /* XXX: Don't preclude handling different sized sigset_t's. */
90 if (sigsetsize != sizeof(sigset_t))
91 return -EINVAL;
92
93 if (copy_from_user(&newset, unewset, sizeof(newset)))
94 return -EFAULT;
95 sigdelsetmask(&newset, ~_BLOCKABLE);
96
97 spin_lock_irq(&current->sighand->siglock);
98 saveset = current->blocked;
99 current->blocked = newset;
100 recalc_sigpending();
101 spin_unlock_irq(&current->sighand->siglock);
102
103 regs->r10 = -EINTR;
104 while (1) {
105 current->state = TASK_INTERRUPTIBLE;
106 schedule();
107 if (do_signal(0, &saveset, regs))
108 /* We will get here twice: once to call the signal
109 handler, then again to return from the
110 sigsuspend system call. When calling the
111 signal handler, R10 holds the signal number as
112 set through do_signal. The sigsuspend call
113 will return with the restored value set above;
114 always -EINTR. */
115 return regs->r10;
116 }
117}
118
119int
120sys_sigaction(int sig, const struct old_sigaction __user *act,
121 struct old_sigaction *oact)
122{
123 struct k_sigaction new_ka, old_ka;
124 int ret;
125
126 if (act) {
127 old_sigset_t mask;
128 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
129 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
130 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
131 return -EFAULT;
132 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
133 __get_user(mask, &act->sa_mask);
134 siginitset(&new_ka.sa.sa_mask, mask);
135 }
136
137 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
138
139 if (!ret && oact) {
140 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
141 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
142 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
143 return -EFAULT;
144 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
145 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
146 }
147
148 return ret;
149}
150
151int
152sys_sigaltstack(const stack_t *uss, stack_t __user *uoss)
153{
154 return do_sigaltstack(uss, uoss, rdusp());
155}
156
157
158/*
159 * Do a signal return; undo the signal stack.
160 */
161
162struct sigframe {
163 struct sigcontext sc;
164 unsigned long extramask[_NSIG_WORDS-1];
165 unsigned char retcode[8]; /* trampoline code */
166};
167
168struct rt_sigframe {
169 struct siginfo *pinfo;
170 void *puc;
171 struct siginfo info;
172 struct ucontext uc;
173 unsigned char retcode[8]; /* trampoline code */
174};
175
176
177static int
178restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
179{
180 unsigned int err = 0;
181 unsigned long old_usp;
182
183 /* Always make any pending restarted system calls return -EINTR */
184 current_thread_info()->restart_block.fn = do_no_restart_syscall;
185
186 /* restore the regs from &sc->regs (same as sc, since regs is first)
187 * (sc is already checked for VERIFY_READ since the sigframe was
188 * checked in sys_sigreturn previously)
189 */
190
191 if (__copy_from_user(regs, sc, sizeof(struct pt_regs)))
192 goto badframe;
193
194 /* make sure the U-flag is set so user-mode cannot fool us */
195
196 regs->dccr |= 1 << 8;
197
198 /* restore the old USP as it was before we stacked the sc etc.
199 * (we cannot just pop the sigcontext since we aligned the sp and
200 * stuff after pushing it)
201 */
202
203 err |= __get_user(old_usp, &sc->usp);
204
205 wrusp(old_usp);
206
207 /* TODO: the other ports use regs->orig_XX to disable syscall checks
208 * after this completes, but we don't use that mechanism. maybe we can
209 * use it now ?
210 */
211
212 return err;
213
214badframe:
215 return 1;
216}
217
218/* Define dummy arguments to be able to reach the regs argument. */
219
220asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
221 long srp, struct pt_regs *regs)
222{
223 struct sigframe __user *frame = (struct sigframe *)rdusp();
224 sigset_t set;
225
226 /*
227 * Since we stacked the signal on a dword boundary,
228 * then frame should be dword aligned here. If it's
229 * not, then the user is trying to mess with us.
230 */
231 if (((long)frame) & 3)
232 goto badframe;
233
234 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
235 goto badframe;
236 if (__get_user(set.sig[0], &frame->sc.oldmask)
237 || (_NSIG_WORDS > 1
238 && __copy_from_user(&set.sig[1], frame->extramask,
239 sizeof(frame->extramask))))
240 goto badframe;
241
242 sigdelsetmask(&set, ~_BLOCKABLE);
243 spin_lock_irq(&current->sighand->siglock);
244 current->blocked = set;
245 recalc_sigpending();
246 spin_unlock_irq(&current->sighand->siglock);
247
248 if (restore_sigcontext(regs, &frame->sc))
249 goto badframe;
250
251 /* TODO: SIGTRAP when single-stepping as in arm ? */
252
253 return regs->r10;
254
255badframe:
256 force_sig(SIGSEGV, current);
257 return 0;
258}
259
260/* Define dummy arguments to be able to reach the regs argument. */
261
262asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
263 long mof, long srp, struct pt_regs *regs)
264{
265 struct rt_sigframe __user *frame = (struct rt_sigframe *)rdusp();
266 sigset_t set;
267
268 /*
269 * Since we stacked the signal on a dword boundary,
270 * then frame should be dword aligned here. If it's
271 * not, then the user is trying to mess with us.
272 */
273 if (((long)frame) & 3)
274 goto badframe;
275
276 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
277 goto badframe;
278 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
279 goto badframe;
280
281 sigdelsetmask(&set, ~_BLOCKABLE);
282 spin_lock_irq(&current->sighand->siglock);
283 current->blocked = set;
284 recalc_sigpending();
285 spin_unlock_irq(&current->sighand->siglock);
286
287 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
288 goto badframe;
289
290 if (do_sigaltstack(&frame->uc.uc_stack, NULL, rdusp()) == -EFAULT)
291 goto badframe;
292
293 return regs->r10;
294
295badframe:
296 force_sig(SIGSEGV, current);
297 return 0;
298}
299
300/*
301 * Set up a signal frame.
302 */
303
304static int
305setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask)
306{
307 int err = 0;
308 unsigned long usp = rdusp();
309
310 /* copy the regs. they are first in sc so we can use sc directly */
311
312 err |= __copy_to_user(sc, regs, sizeof(struct pt_regs));
313
314 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
315 the signal handler. The frametype will be restored to its previous
316 value in restore_sigcontext. */
317 regs->frametype = CRIS_FRAME_NORMAL;
318
319 /* then some other stuff */
320
321 err |= __put_user(mask, &sc->oldmask);
322
323 err |= __put_user(usp, &sc->usp);
324
325 return err;
326}
327
328/* figure out where we want to put the new signal frame - usually on the stack */
329
330static inline void __user *
331get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
332{
333 unsigned long sp = rdusp();
334
335 /* This is the X/Open sanctioned signal stack switching. */
336 if (ka->sa.sa_flags & SA_ONSTACK) {
337 if (! on_sig_stack(sp))
338 sp = current->sas_ss_sp + current->sas_ss_size;
339 }
340
341 /* make sure the frame is dword-aligned */
342
343 sp &= ~3;
344
345 return (void __user*)(sp - frame_size);
346}
347
348/* grab and setup a signal frame.
349 *
350 * basically we stack a lot of state info, and arrange for the
351 * user-mode program to return to the kernel using either a
352 * trampoline which performs the syscall sigreturn, or a provided
353 * user-mode trampoline.
354 */
355
356static void setup_frame(int sig, struct k_sigaction *ka,
357 sigset_t *set, struct pt_regs * regs)
358{
359 struct sigframe __user *frame;
360 unsigned long return_ip;
361 int err = 0;
362
363 frame = get_sigframe(ka, regs, sizeof(*frame));
364
365 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
366 goto give_sigsegv;
367
368 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
369 if (err)
370 goto give_sigsegv;
371
372 if (_NSIG_WORDS > 1) {
373 err |= __copy_to_user(frame->extramask, &set->sig[1],
374 sizeof(frame->extramask));
375 }
376 if (err)
377 goto give_sigsegv;
378
379 /* Set up to return from userspace. If provided, use a stub
380 already in userspace. */
381 if (ka->sa.sa_flags & SA_RESTORER) {
382 return_ip = (unsigned long)ka->sa.sa_restorer;
383 } else {
384 /* trampoline - the desired return ip is the retcode itself */
385 return_ip = (unsigned long)&frame->retcode;
386 /* This is movu.w __NR_sigreturn, r9; break 13; */
387 err |= __put_user(0x9c5f, (short __user*)(frame->retcode+0));
388 err |= __put_user(__NR_sigreturn, (short __user*)(frame->retcode+2));
389 err |= __put_user(0xe93d, (short __user*)(frame->retcode+4));
390 }
391
392 if (err)
393 goto give_sigsegv;
394
395 /* Set up registers for signal handler */
396
397 regs->irp = (unsigned long) ka->sa.sa_handler; /* what we enter NOW */
398 regs->srp = return_ip; /* what we enter LATER */
399 regs->r10 = sig; /* first argument is signo */
400
401 /* actually move the usp to reflect the stacked frame */
402
403 wrusp((unsigned long)frame);
404
405 return;
406
407give_sigsegv:
408 force_sigsegv(sig, current);
409}
410
411static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
412 sigset_t *set, struct pt_regs * regs)
413{
414 struct rt_sigframe __user *frame;
415 unsigned long return_ip;
416 int err = 0;
417
418 frame = get_sigframe(ka, regs, sizeof(*frame));
419
420 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
421 goto give_sigsegv;
422
423 err |= __put_user(&frame->info, &frame->pinfo);
424 err |= __put_user(&frame->uc, &frame->puc);
425 err |= copy_siginfo_to_user(&frame->info, info);
426 if (err)
427 goto give_sigsegv;
428
429 /* Clear all the bits of the ucontext we don't use. */
430 err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
431
432 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
433
434 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
435
436 if (err)
437 goto give_sigsegv;
438
439 /* Set up to return from userspace. If provided, use a stub
440 already in userspace. */
441 if (ka->sa.sa_flags & SA_RESTORER) {
442 return_ip = (unsigned long)ka->sa.sa_restorer;
443 } else {
444 /* trampoline - the desired return ip is the retcode itself */
445 return_ip = (unsigned long)&frame->retcode;
446 /* This is movu.w __NR_rt_sigreturn, r9; break 13; */
447 err |= __put_user(0x9c5f, (short __user*)(frame->retcode+0));
448 err |= __put_user(__NR_rt_sigreturn, (short __user*)(frame->retcode+2));
449 err |= __put_user(0xe93d, (short __user*)(frame->retcode+4));
450 }
451
452 if (err)
453 goto give_sigsegv;
454
455 /* TODO what is the current->exec_domain stuff and invmap ? */
456
457 /* Set up registers for signal handler */
458
459 regs->irp = (unsigned long) ka->sa.sa_handler; /* what we enter NOW */
460 regs->srp = return_ip; /* what we enter LATER */
461 regs->r10 = sig; /* first argument is signo */
462 regs->r11 = (unsigned long) &frame->info; /* second argument is (siginfo_t *) */
463 regs->r12 = 0; /* third argument is unused */
464
465 /* actually move the usp to reflect the stacked frame */
466
467 wrusp((unsigned long)frame);
468
469 return;
470
471give_sigsegv:
472 force_sigsegv(sig, current);
473}
474
475/*
476 * OK, we're invoking a handler
477 */
478
479extern inline void
480handle_signal(int canrestart, unsigned long sig,
481 siginfo_t *info, struct k_sigaction *ka,
482 sigset_t *oldset, struct pt_regs * regs)
483{
484 /* Are we from a system call? */
485 if (canrestart) {
486 /* If so, check system call restarting.. */
487 switch (regs->r10) {
488 case -ERESTART_RESTARTBLOCK:
489 case -ERESTARTNOHAND:
490 /* ERESTARTNOHAND means that the syscall should only be
491 restarted if there was no handler for the signal, and since
492 we only get here if there is a handler, we don't restart */
493 regs->r10 = -EINTR;
494 break;
495
496 case -ERESTARTSYS:
497 /* ERESTARTSYS means to restart the syscall if there is no
498 handler or the handler was registered with SA_RESTART */
499 if (!(ka->sa.sa_flags & SA_RESTART)) {
500 regs->r10 = -EINTR;
501 break;
502 }
503 /* fallthrough */
504 case -ERESTARTNOINTR:
505 /* ERESTARTNOINTR means that the syscall should be called again
506 after the signal handler returns. */
507 RESTART_CRIS_SYS(regs);
508 }
509 }
510
511 /* Set up the stack frame */
512 if (ka->sa.sa_flags & SA_SIGINFO)
513 setup_rt_frame(sig, ka, info, oldset, regs);
514 else
515 setup_frame(sig, ka, oldset, regs);
516
517 if (ka->sa.sa_flags & SA_ONESHOT)
518 ka->sa.sa_handler = SIG_DFL;
519
520 if (!(ka->sa.sa_flags & SA_NODEFER)) {
521 spin_lock_irq(&current->sighand->siglock);
522 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
523 sigaddset(&current->blocked,sig);
524 recalc_sigpending();
525 spin_unlock_irq(&current->sighand->siglock);
526 }
527}
528
529/*
530 * Note that 'init' is a special process: it doesn't get signals it doesn't
531 * want to handle. Thus you cannot kill init even with a SIGKILL even by
532 * mistake.
533 *
534 * Also note that the regs structure given here as an argument, is the latest
535 * pushed pt_regs. It may or may not be the same as the first pushed registers
536 * when the initial usermode->kernelmode transition took place. Therefore
537 * we can use user_mode(regs) to see if we came directly from kernel or user
538 * mode below.
539 */
540
541int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs)
542{
543 siginfo_t info;
544 int signr;
545 struct k_sigaction ka;
546
547 /*
548 * We want the common case to go fast, which
549 * is why we may in certain cases get here from
550 * kernel mode. Just return without doing anything
551 * if so.
552 */
553 if (!user_mode(regs))
554 return 1;
555
556 if (!oldset)
557 oldset = &current->blocked;
558
559 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
560 if (signr > 0) {
561 /* Whee! Actually deliver the signal. */
562 handle_signal(canrestart, signr, &info, &ka, oldset, regs);
563 return 1;
564 }
565
566 /* Did we come from a system call? */
567 if (canrestart) {
568 /* Restart the system call - no handlers present */
569 if (regs->r10 == -ERESTARTNOHAND ||
570 regs->r10 == -ERESTARTSYS ||
571 regs->r10 == -ERESTARTNOINTR) {
572 RESTART_CRIS_SYS(regs);
573 }
574 if (regs->r10 == -ERESTART_RESTARTBLOCK){
575 regs->r10 = __NR_restart_syscall;
576 regs->irp -= 2;
577 }
578 }
579 return 0;
580}