diff options
Diffstat (limited to 'arch/cris/arch-v10/kernel/signal.c')
-rw-r--r-- | arch/cris/arch-v10/kernel/signal.c | 580 |
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 | |||
44 | int 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 | */ | ||
51 | int | ||
52 | sys_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(¤t->sighand->siglock); | ||
59 | saveset = current->blocked; | ||
60 | siginitset(¤t->blocked, mask); | ||
61 | recalc_sigpending(); | ||
62 | spin_unlock_irq(¤t->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 | */ | ||
83 | int | ||
84 | sys_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(¤t->sighand->siglock); | ||
98 | saveset = current->blocked; | ||
99 | current->blocked = newset; | ||
100 | recalc_sigpending(); | ||
101 | spin_unlock_irq(¤t->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 | |||
119 | int | ||
120 | sys_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 | |||
151 | int | ||
152 | sys_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 | |||
162 | struct sigframe { | ||
163 | struct sigcontext sc; | ||
164 | unsigned long extramask[_NSIG_WORDS-1]; | ||
165 | unsigned char retcode[8]; /* trampoline code */ | ||
166 | }; | ||
167 | |||
168 | struct 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 | |||
177 | static int | ||
178 | restore_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 | |||
214 | badframe: | ||
215 | return 1; | ||
216 | } | ||
217 | |||
218 | /* Define dummy arguments to be able to reach the regs argument. */ | ||
219 | |||
220 | asmlinkage 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(¤t->sighand->siglock); | ||
244 | current->blocked = set; | ||
245 | recalc_sigpending(); | ||
246 | spin_unlock_irq(¤t->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 | |||
255 | badframe: | ||
256 | force_sig(SIGSEGV, current); | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | /* Define dummy arguments to be able to reach the regs argument. */ | ||
261 | |||
262 | asmlinkage 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(¤t->sighand->siglock); | ||
283 | current->blocked = set; | ||
284 | recalc_sigpending(); | ||
285 | spin_unlock_irq(¤t->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 | |||
295 | badframe: | ||
296 | force_sig(SIGSEGV, current); | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | /* | ||
301 | * Set up a signal frame. | ||
302 | */ | ||
303 | |||
304 | static int | ||
305 | setup_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 | |||
330 | static inline void __user * | ||
331 | get_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 | |||
356 | static 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 | |||
407 | give_sigsegv: | ||
408 | force_sigsegv(sig, current); | ||
409 | } | ||
410 | |||
411 | static 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 | |||
471 | give_sigsegv: | ||
472 | force_sigsegv(sig, current); | ||
473 | } | ||
474 | |||
475 | /* | ||
476 | * OK, we're invoking a handler | ||
477 | */ | ||
478 | |||
479 | extern inline void | ||
480 | handle_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(¤t->sighand->siglock); | ||
522 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | ||
523 | sigaddset(¤t->blocked,sig); | ||
524 | recalc_sigpending(); | ||
525 | spin_unlock_irq(¤t->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 | |||
541 | int 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 = ¤t->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 | } | ||