Commit 3183e06863f49a500fc76427db4d60825a26f81b

Authored by Arnd Bergmann
Committed by Michal Simek
1 parent 0a58458341

microblaze: clean up signal handling

When legacy signal handling is disabled, the
arch/microblaze/kernel/signal.c implementation can
be much simpler, as most of it is handled generically
from kernel/signal.c.

This is also a prerequisite for using the generic
asm/unistd.h, which does not provide __NR_sigreturn,
because this macro is referenced by the current signal.c
implementation.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Michal Simek <monstr@monstr.eu>

Showing 7 changed files with 43 additions and 345 deletions Side-by-side Diff

arch/microblaze/include/asm/signal.h
1   -/*
2   - * Copyright (C) 2006 Atmark Techno, Inc.
3   - * Yasushi SHOJI <yashi@atmark-techno.com>
4   - * Tetsuya OHKAWA <tetsuya@atmark-techno.com>
5   - *
6   - * This file is subject to the terms and conditions of the GNU General Public
7   - * License. See the file "COPYING" in the main directory of this archive
8   - * for more details.
9   - */
10   -
11   -#ifndef _ASM_MICROBLAZE_SIGNAL_H
12   -#define _ASM_MICROBLAZE_SIGNAL_H
13   -
14   -#define SIGHUP 1
15   -#define SIGINT 2
16   -#define SIGQUIT 3
17   -#define SIGILL 4
18   -#define SIGTRAP 5
19   -#define SIGABRT 6
20   -#define SIGIOT 6
21   -#define SIGBUS 7
22   -#define SIGFPE 8
23   -#define SIGKILL 9
24   -#define SIGUSR1 10
25   -#define SIGSEGV 11
26   -#define SIGUSR2 12
27   -#define SIGPIPE 13
28   -#define SIGALRM 14
29   -#define SIGTERM 15
30   -#define SIGSTKFLT 16
31   -#define SIGCHLD 17
32   -#define SIGCONT 18
33   -#define SIGSTOP 19
34   -#define SIGTSTP 20
35   -#define SIGTTIN 21
36   -#define SIGTTOU 22
37   -#define SIGURG 23
38   -#define SIGXCPU 24
39   -#define SIGXFSZ 25
40   -#define SIGVTALRM 26
41   -#define SIGPROF 27
42   -#define SIGWINCH 28
43   -#define SIGIO 29
44   -#define SIGPOLL SIGIO
45   -/*
46   -#define SIGLOST 29
47   -*/
48   -#define SIGPWR 30
49   -#define SIGSYS 31
50   -#define SIGUNUSED 31
51   -
52   -/* These should not be considered constants from userland. */
53   -#define SIGRTMIN 32
54   -#define SIGRTMAX _NSIG
55   -
56   -/*
57   - * SA_FLAGS values:
58   - *
59   - * SA_ONSTACK indicates that a registered stack_t will be used.
60   - * SA_RESTART flag to get restarting signals (which were the default long ago)
61   - * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
62   - * SA_RESETHAND clears the handler when the signal is delivered.
63   - * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
64   - * SA_NODEFER prevents the current signal from being masked in the handler.
65   - *
66   - * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
67   - * Unix names RESETHAND and NODEFER respectively.
68   - */
69   -#define SA_NOCLDSTOP 0x00000001
70   -#define SA_NOCLDWAIT 0x00000002
71   -#define SA_SIGINFO 0x00000004
72   -#define SA_ONSTACK 0x08000000
73   -#define SA_RESTART 0x10000000
74   -#define SA_NODEFER 0x40000000
75   -#define SA_RESETHAND 0x80000000
76   -
77   -#define SA_NOMASK SA_NODEFER
78   -#define SA_ONESHOT SA_RESETHAND
79   -
80   -#define SA_RESTORER 0x04000000
81   -
82   -/*
83   - * sigaltstack controls
84   - */
85   -#define SS_ONSTACK 1
86   -#define SS_DISABLE 2
87   -
88   -#define MINSIGSTKSZ 2048
89   -#define SIGSTKSZ 8192
90   -
91   -# ifndef __ASSEMBLY__
92   -# include <linux/types.h>
93   -# include <asm-generic/signal-defs.h>
94   -
95   -/* Avoid too many header ordering problems. */
96   -struct siginfo;
97   -
98   -# ifdef __KERNEL__
99   -/*
100   - * Most things should be clean enough to redefine this at will, if care
101   - * is taken to make libc match.
102   - */
103   -# define _NSIG 64
104   -# define _NSIG_BPW 32
105   -# define _NSIG_WORDS (_NSIG / _NSIG_BPW)
106   -
107   -typedef unsigned long old_sigset_t; /* at least 32 bits */
108   -
109   -typedef struct {
110   - unsigned long sig[_NSIG_WORDS];
111   -} sigset_t;
112   -
113   -struct old_sigaction {
114   - __sighandler_t sa_handler;
115   - old_sigset_t sa_mask;
116   - unsigned long sa_flags;
117   - void (*sa_restorer)(void);
118   -};
119   -
120   -struct sigaction {
121   - __sighandler_t sa_handler;
122   - unsigned long sa_flags;
123   - void (*sa_restorer)(void);
124   - sigset_t sa_mask; /* mask last for extensibility */
125   -};
126   -
127   -struct k_sigaction {
128   - struct sigaction sa;
129   -};
130   -
131   -# include <asm/sigcontext.h>
132   -# undef __HAVE_ARCH_SIG_BITOPS
133   -
134   -# define ptrace_signal_deliver(regs, cookie) do { } while (0)
135   -
136   -# else /* !__KERNEL__ */
137   -
138   -/* Here we must cater to libcs that poke about in kernel headers. */
139   -
140   -# define NSIG 32
141   -typedef unsigned long sigset_t;
142   -
143   -struct sigaction {
144   - union {
145   - __sighandler_t _sa_handler;
146   - void (*_sa_sigaction)(int, struct siginfo *, void *);
147   - } _u;
148   - sigset_t sa_mask;
149   - unsigned long sa_flags;
150   - void (*sa_restorer)(void);
151   -};
152   -
153   -# define sa_handler _u._sa_handler
154   -# define sa_sigaction _u._sa_sigaction
155   -
156   -# endif /* __KERNEL__ */
157   -
158   -typedef struct sigaltstack {
159   - void *ss_sp;
160   - int ss_flags;
161   - size_t ss_size;
162   -} stack_t;
163   -
164   -# endif /* __ASSEMBLY__ */
165   -#endif /* _ASM_MICROBLAZE_SIGNAL_H */
  1 +#include <asm-generic/signal.h>
arch/microblaze/include/asm/syscalls.h
... ... @@ -26,23 +26,16 @@
26 26 unsigned long fd, off_t offset);
27 27  
28 28 /* from signal.c */
29   -asmlinkage int sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs);
30   -
31   -asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize,
  29 +asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize,
32 30 struct pt_regs *regs);
33 31  
34   -asmlinkage int sys_sigaction(int sig, const struct old_sigaction *act,
35   - struct old_sigaction *oact);
36   -
37 32 asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act,
38 33 struct sigaction __user *oact, size_t sigsetsize);
39 34  
40 35 asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
41 36 struct pt_regs *regs);
42 37  
43   -asmlinkage int sys_sigreturn(struct pt_regs *regs);
44   -
45   -asmlinkage int sys_rt_sigreturn(struct pt_regs *regs);
  38 +asmlinkage long sys_rt_sigreturn(struct pt_regs *regs);
46 39  
47 40 #endif /* __KERNEL__ */
48 41 #endif /* __ASM_MICROBLAZE_SYSCALLS_H */
arch/microblaze/include/asm/unistd.h
... ... @@ -408,7 +408,7 @@
408 408 #define __ARCH_WANT_SYS_SIGPENDING
409 409 #define __ARCH_WANT_SYS_SIGPROCMASK
410 410 #define __ARCH_WANT_SYS_RT_SIGACTION
411   -/* #define __ARCH_WANT_SYS_RT_SIGSUSPEND */
  411 +#define __ARCH_WANT_SYS_RT_SIGSUSPEND
412 412  
413 413 /*
414 414 * "Conditional" syscalls
arch/microblaze/kernel/entry-nommu.S
... ... @@ -563,17 +563,9 @@
563 563 brid sys_execve
564 564 addk r8, r1, r0
565 565  
566   -sys_sigreturn_wrapper:
567   - brid sys_sigreturn
568   - addk r5, r1, r0
569   -
570 566 sys_rt_sigreturn_wrapper:
571 567 brid sys_rt_sigreturn
572 568 addk r5, r1, r0
573   -
574   -sys_sigsuspend_wrapper:
575   - brid sys_rt_sigsuspend
576   - addk r6, r1, r0
577 569  
578 570 sys_rt_sigsuspend_wrapper:
579 571 brid sys_rt_sigsuspend
arch/microblaze/kernel/entry.S
... ... @@ -449,34 +449,11 @@
449 449 brid sys_execve; /* Do real work (tail-call).*/
450 450 nop;
451 451  
452   -C_ENTRY(sys_sigsuspend_wrapper):
453   - swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
454   - swi r4, r1, PTO+PT_R4;
455   - la r6, r1, PTO; /* add user context as 2nd arg */
456   - bralid r15, sys_sigsuspend; /* Do real work.*/
457   - nop;
458   - lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
459   - lwi r4, r1, PTO+PT_R4;
460   - bri ret_from_trap /* fall through will not work here due to align */
461   - nop;
462   -
463 452 C_ENTRY(sys_rt_sigsuspend_wrapper):
464 453 swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
465 454 swi r4, r1, PTO+PT_R4;
466 455 la r7, r1, PTO; /* add user context as 3rd arg */
467 456 brlid r15, sys_rt_sigsuspend; /* Do real work.*/
468   - nop;
469   - lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
470   - lwi r4, r1, PTO+PT_R4;
471   - bri ret_from_trap /* fall through will not work here due to align */
472   - nop;
473   -
474   -
475   -C_ENTRY(sys_sigreturn_wrapper):
476   - swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
477   - swi r4, r1, PTO+PT_R4;
478   - la r5, r1, PTO; /* add user context as 1st arg */
479   - brlid r15, sys_sigreturn; /* Do real work.*/
480 457 nop;
481 458 lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
482 459 lwi r4, r1, PTO+PT_R4;
arch/microblaze/kernel/signal.c
... ... @@ -45,91 +45,8 @@
45 45  
46 46 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall);
47 47  
48   -/*
49   - * Atomically swap in the new signal mask, and wait for a signal.
50   - */
51   -asmlinkage int
52   -sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs)
53   -{
54   - sigset_t saveset;
55 48  
56   - mask &= _BLOCKABLE;
57   - spin_lock_irq(&current->sighand->siglock);
58   - saveset = current->blocked;
59   - siginitset(&current->blocked, mask);
60   - recalc_sigpending();
61   - spin_unlock_irq(&current->sighand->siglock);
62   -
63   - regs->r3 = -EINTR;
64   - while (1) {
65   - current->state = TASK_INTERRUPTIBLE;
66   - schedule();
67   - if (do_signal(regs, &saveset, 1))
68   - return -EINTR;
69   - }
70   -}
71   -
72 49 asmlinkage int
73   -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize,
74   - struct pt_regs *regs)
75   -{
76   - sigset_t saveset, newset;
77   -
78   - /* XXX: Don't preclude handling different sized sigset_t's. */
79   - if (sigsetsize != sizeof(sigset_t))
80   - return -EINVAL;
81   -
82   - if (copy_from_user(&newset, unewset, sizeof(newset)))
83   - return -EFAULT;
84   - sigdelsetmask(&newset, ~_BLOCKABLE);
85   - spin_lock_irq(&current->sighand->siglock);
86   - saveset = current->blocked;
87   - current->blocked = newset;
88   - recalc_sigpending();
89   - spin_unlock_irq(&current->sighand->siglock);
90   -
91   - regs->r3 = -EINTR;
92   - while (1) {
93   - current->state = TASK_INTERRUPTIBLE;
94   - schedule();
95   - if (do_signal(regs, &saveset, 1))
96   - return -EINTR;
97   - }
98   -}
99   -
100   -asmlinkage int
101   -sys_sigaction(int sig, const struct old_sigaction *act,
102   - struct old_sigaction *oact)
103   -{
104   - struct k_sigaction new_ka, old_ka;
105   - int ret;
106   -
107   - if (act) {
108   - old_sigset_t mask;
109   - if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
110   - __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
111   - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
112   - return -EFAULT;
113   - __get_user(new_ka.sa.sa_flags, &act->sa_flags);
114   - __get_user(mask, &act->sa_mask);
115   - siginitset(&new_ka.sa.sa_mask, mask);
116   - }
117   -
118   - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
119   -
120   - if (!ret && oact) {
121   - if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
122   - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
123   - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
124   - return -EFAULT;
125   - __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
126   - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
127   - }
128   -
129   - return ret;
130   -}
131   -
132   -asmlinkage int
133 50 sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
134 51 struct pt_regs *regs)
135 52 {
... ... @@ -139,7 +56,6 @@
139 56 /*
140 57 * Do a signal return; undo the signal stack.
141 58 */
142   -
143 59 struct sigframe {
144 60 struct sigcontext sc;
145 61 unsigned long extramask[_NSIG_WORDS-1];
146 62  
... ... @@ -176,41 +92,8 @@
176 92 return err;
177 93 }
178 94  
179   -asmlinkage int sys_sigreturn(struct pt_regs *regs)
  95 +asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
180 96 {
181   - struct sigframe *frame =
182   - (struct sigframe *)(regs->r1 + STATE_SAVE_ARG_SPACE);
183   -
184   - sigset_t set;
185   - int rval;
186   -
187   - if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
188   - goto badframe;
189   -
190   - if (__get_user(set.sig[0], &frame->sc.oldmask)
191   - || (_NSIG_WORDS > 1
192   - && __copy_from_user(&set.sig[1], &frame->extramask,
193   - sizeof(frame->extramask))))
194   - goto badframe;
195   -
196   - sigdelsetmask(&set, ~_BLOCKABLE);
197   -
198   - spin_lock_irq(&current->sighand->siglock);
199   - current->blocked = set;
200   - recalc_sigpending();
201   - spin_unlock_irq(&current->sighand->siglock);
202   -
203   - if (restore_sigcontext(regs, &frame->sc, &rval))
204   - goto badframe;
205   - return rval;
206   -
207   -badframe:
208   - force_sig(SIGSEGV, current);
209   - return 0;
210   -}
211   -
212   -asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
213   -{
214 97 struct rt_sigframe __user *frame =
215 98 (struct rt_sigframe __user *)(regs->r1 + STATE_SAVE_ARG_SPACE);
216 99  
217 100  
218 101  
... ... @@ -324,21 +207,17 @@
324 207 /* Set up to return from userspace. If provided, use a stub
325 208 already in userspace. */
326 209 /* minus 8 is offset to cater for "rtsd r15,8" */
327   - if (ka->sa.sa_flags & SA_RESTORER) {
328   - regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8;
329   - } else {
330   - /* addi r12, r0, __NR_sigreturn */
331   - err |= __put_user(0x31800000 | __NR_rt_sigreturn ,
332   - frame->tramp + 0);
333   - /* brki r14, 0x8 */
334   - err |= __put_user(0xb9cc0008, frame->tramp + 1);
  210 + /* addi r12, r0, __NR_sigreturn */
  211 + err |= __put_user(0x31800000 | __NR_rt_sigreturn ,
  212 + frame->tramp + 0);
  213 + /* brki r14, 0x8 */
  214 + err |= __put_user(0xb9cc0008, frame->tramp + 1);
335 215  
336   - /* Return from sighandler will jump to the tramp.
337   - Negative 8 offset because return is rtsd r15, 8 */
338   - regs->r15 = ((unsigned long)frame->tramp)-8;
  216 + /* Return from sighandler will jump to the tramp.
  217 + Negative 8 offset because return is rtsd r15, 8 */
  218 + regs->r15 = ((unsigned long)frame->tramp)-8;
339 219  
340   - __invalidate_cache_sigtramp((unsigned long)frame->tramp);
341   - }
  220 + __invalidate_cache_sigtramp((unsigned long)frame->tramp);
342 221  
343 222 if (err)
344 223 goto give_sigsegv;
... ... @@ -405,7 +284,7 @@
405 284 * OK, we're invoking a handler
406 285 */
407 286  
408   -static void
  287 +static int
409 288 handle_signal(unsigned long sig, struct k_sigaction *ka,
410 289 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
411 290 {
... ... @@ -426,6 +305,7 @@
426 305 recalc_sigpending();
427 306 spin_unlock_irq(&current->sighand->siglock);
428 307 }
  308 + return 1;
429 309 }
430 310  
431 311 /*
... ... @@ -456,7 +336,9 @@
456 336 if (kernel_mode(regs))
457 337 return 1;
458 338  
459   - if (!oldset)
  339 + if (current_thread_info()->status & TS_RESTORE_SIGMASK)
  340 + oldset = &current->saved_sigmask;
  341 + else
460 342 oldset = &current->blocked;
461 343  
462 344 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
463 345  
... ... @@ -464,12 +346,30 @@
464 346 /* Whee! Actually deliver the signal. */
465 347 if (in_syscall)
466 348 handle_restart(regs, &ka, 1);
467   - handle_signal(signr, &ka, &info, oldset, regs);
  349 + if (handle_signal(signr, &ka, &info, oldset, regs)) {
  350 + /*
  351 + * A signal was successfully delivered; the saved
  352 + * sigmask will have been stored in the signal frame,
  353 + * and will be restored by sigreturn, so we can simply
  354 + * clear the TS_RESTORE_SIGMASK flag.
  355 + */
  356 + current_thread_info()->status &=
  357 + ~TS_RESTORE_SIGMASK;
  358 + }
468 359 return 1;
469 360 }
470 361  
471 362 if (in_syscall)
472 363 handle_restart(regs, NULL, 0);
  364 +
  365 + /*
  366 + * If there's no signal to deliver, we just put the saved sigmask
  367 + * back.
  368 + */
  369 + if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
  370 + current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
  371 + sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
  372 + }
473 373  
474 374 /* Did we come from a system call? */
475 375 return 0;
arch/microblaze/kernel/syscall_table.S
... ... @@ -71,12 +71,12 @@
71 71 .long sys_getppid
72 72 .long sys_getpgrp /* 65 */
73 73 .long sys_setsid
74   - .long sys_sigaction
  74 + .long sys_ni_syscall /* sys_sigaction */
75 75 .long sys_sgetmask
76 76 .long sys_ssetmask
77 77 .long sys_setreuid /* 70 */
78 78 .long sys_setregid
79   - .long sys_sigsuspend_wrapper
  79 + .long sys_ni_syscall /* sys_sigsuspend_wrapper */
80 80 .long sys_sigpending
81 81 .long sys_sethostname
82 82 .long sys_setrlimit /* 75 */
... ... @@ -123,7 +123,7 @@
123 123 .long sys_sysinfo
124 124 .long sys_ipc
125 125 .long sys_fsync
126   - .long sys_sigreturn_wrapper
  126 + .long sys_ni_syscall /* sys_sigreturn_wrapper */
127 127 .long sys_clone_wrapper /* 120 */
128 128 .long sys_setdomainname
129 129 .long sys_newuname