diff options
author | Arnd Bergmann <arnd@arndb.de> | 2009-06-18 13:55:29 -0400 |
---|---|---|
committer | Michal Simek <monstr@monstr.eu> | 2009-07-06 04:26:57 -0400 |
commit | 3183e06863f49a500fc76427db4d60825a26f81b (patch) | |
tree | 749cfd09f4469a2ad08321ad10afbad4d92dfcdb | |
parent | 0a58458341fd571e521be542ff746a4a8995980c (diff) |
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>
-rw-r--r-- | arch/microblaze/include/asm/signal.h | 166 | ||||
-rw-r--r-- | arch/microblaze/include/asm/syscalls.h | 11 | ||||
-rw-r--r-- | arch/microblaze/include/asm/unistd.h | 2 | ||||
-rw-r--r-- | arch/microblaze/kernel/entry-nommu.S | 8 | ||||
-rw-r--r-- | arch/microblaze/kernel/entry.S | 23 | ||||
-rw-r--r-- | arch/microblaze/kernel/signal.c | 172 | ||||
-rw-r--r-- | arch/microblaze/kernel/syscall_table.S | 6 |
7 files changed, 43 insertions, 345 deletions
diff --git a/arch/microblaze/include/asm/signal.h b/arch/microblaze/include/asm/signal.h index 46bc2267d949..7b1573ce19de 100644 --- a/arch/microblaze/include/asm/signal.h +++ b/arch/microblaze/include/asm/signal.h | |||
@@ -1,165 +1 @@ | |||
1 | /* | #include <asm-generic/signal.h> | |
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 */ | ||
diff --git a/arch/microblaze/include/asm/syscalls.h b/arch/microblaze/include/asm/syscalls.h index ddea9eb31f8d..ea23843e2c26 100644 --- a/arch/microblaze/include/asm/syscalls.h +++ b/arch/microblaze/include/asm/syscalls.h | |||
@@ -26,23 +26,16 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, | |||
26 | unsigned long fd, off_t offset); | 26 | unsigned long fd, off_t offset); |
27 | 27 | ||
28 | /* from signal.c */ | 28 | /* from signal.c */ |
29 | asmlinkage int sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs); | 29 | asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, |
30 | |||
31 | asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, | ||
32 | struct pt_regs *regs); | 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 | asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, | 32 | asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, |
38 | struct sigaction __user *oact, size_t sigsetsize); | 33 | struct sigaction __user *oact, size_t sigsetsize); |
39 | 34 | ||
40 | asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 35 | asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, |
41 | struct pt_regs *regs); | 36 | struct pt_regs *regs); |
42 | 37 | ||
43 | asmlinkage int sys_sigreturn(struct pt_regs *regs); | 38 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs); |
44 | |||
45 | asmlinkage int sys_rt_sigreturn(struct pt_regs *regs); | ||
46 | 39 | ||
47 | #endif /* __KERNEL__ */ | 40 | #endif /* __KERNEL__ */ |
48 | #endif /* __ASM_MICROBLAZE_SYSCALLS_H */ | 41 | #endif /* __ASM_MICROBLAZE_SYSCALLS_H */ |
diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index b5e2f5fa5c53..6c660c144653 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h | |||
@@ -408,7 +408,7 @@ | |||
408 | #define __ARCH_WANT_SYS_SIGPENDING | 408 | #define __ARCH_WANT_SYS_SIGPENDING |
409 | #define __ARCH_WANT_SYS_SIGPROCMASK | 409 | #define __ARCH_WANT_SYS_SIGPROCMASK |
410 | #define __ARCH_WANT_SYS_RT_SIGACTION | 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 | * "Conditional" syscalls | 414 | * "Conditional" syscalls |
diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 1fce6b803f54..2eaf3946cb42 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S | |||
@@ -563,18 +563,10 @@ sys_execve_wrapper: | |||
563 | brid sys_execve | 563 | brid sys_execve |
564 | addk r8, r1, r0 | 564 | addk r8, r1, r0 |
565 | 565 | ||
566 | sys_sigreturn_wrapper: | ||
567 | brid sys_sigreturn | ||
568 | addk r5, r1, r0 | ||
569 | |||
570 | sys_rt_sigreturn_wrapper: | 566 | sys_rt_sigreturn_wrapper: |
571 | brid sys_rt_sigreturn | 567 | brid sys_rt_sigreturn |
572 | addk r5, r1, r0 | 568 | addk r5, r1, r0 |
573 | 569 | ||
574 | sys_sigsuspend_wrapper: | ||
575 | brid sys_rt_sigsuspend | ||
576 | addk r6, r1, r0 | ||
577 | |||
578 | sys_rt_sigsuspend_wrapper: | 570 | sys_rt_sigsuspend_wrapper: |
579 | brid sys_rt_sigsuspend | 571 | brid sys_rt_sigsuspend |
580 | addk r7, r1, r0 | 572 | addk r7, r1, r0 |
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 91a0e7b185dd..ea7107652d8d 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S | |||
@@ -449,17 +449,6 @@ C_ENTRY(sys_execve_wrapper): | |||
449 | brid sys_execve; /* Do real work (tail-call).*/ | 449 | brid sys_execve; /* Do real work (tail-call).*/ |
450 | nop; | 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 | C_ENTRY(sys_rt_sigsuspend_wrapper): | 452 | C_ENTRY(sys_rt_sigsuspend_wrapper): |
464 | swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ | 453 | swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ |
465 | swi r4, r1, PTO+PT_R4; | 454 | swi r4, r1, PTO+PT_R4; |
@@ -471,18 +460,6 @@ C_ENTRY(sys_rt_sigsuspend_wrapper): | |||
471 | bri ret_from_trap /* fall through will not work here due to align */ | 460 | bri ret_from_trap /* fall through will not work here due to align */ |
472 | nop; | 461 | nop; |
473 | 462 | ||
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 | nop; | ||
481 | lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ | ||
482 | lwi r4, r1, PTO+PT_R4; | ||
483 | bri ret_from_trap /* fall through will not work here due to align */ | ||
484 | nop; | ||
485 | |||
486 | C_ENTRY(sys_rt_sigreturn_wrapper): | 463 | C_ENTRY(sys_rt_sigreturn_wrapper): |
487 | swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ | 464 | swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ |
488 | swi r4, r1, PTO+PT_R4; | 465 | swi r4, r1, PTO+PT_R4; |
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 4c0e6521b114..2e5862c3002a 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c | |||
@@ -45,89 +45,6 @@ | |||
45 | 45 | ||
46 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall); | 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 | |||
56 | mask &= _BLOCKABLE; | ||
57 | spin_lock_irq(¤t->sighand->siglock); | ||
58 | saveset = current->blocked; | ||
59 | siginitset(¤t->blocked, mask); | ||
60 | recalc_sigpending(); | ||
61 | spin_unlock_irq(¤t->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 | 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(¤t->sighand->siglock); | ||
86 | saveset = current->blocked; | ||
87 | current->blocked = newset; | ||
88 | recalc_sigpending(); | ||
89 | spin_unlock_irq(¤t->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 | 48 | ||
132 | asmlinkage int | 49 | asmlinkage int |
133 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 50 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, |
@@ -139,7 +56,6 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | |||
139 | /* | 56 | /* |
140 | * Do a signal return; undo the signal stack. | 57 | * Do a signal return; undo the signal stack. |
141 | */ | 58 | */ |
142 | |||
143 | struct sigframe { | 59 | struct sigframe { |
144 | struct sigcontext sc; | 60 | struct sigcontext sc; |
145 | unsigned long extramask[_NSIG_WORDS-1]; | 61 | unsigned long extramask[_NSIG_WORDS-1]; |
@@ -176,40 +92,7 @@ static int restore_sigcontext(struct pt_regs *regs, | |||
176 | return err; | 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 | { | ||
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(¤t->sighand->siglock); | ||
199 | current->blocked = set; | ||
200 | recalc_sigpending(); | ||
201 | spin_unlock_irq(¤t->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 | { | 96 | { |
214 | struct rt_sigframe __user *frame = | 97 | struct rt_sigframe __user *frame = |
215 | (struct rt_sigframe __user *)(regs->r1 + STATE_SAVE_ARG_SPACE); | 98 | (struct rt_sigframe __user *)(regs->r1 + STATE_SAVE_ARG_SPACE); |
@@ -324,21 +207,17 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
324 | /* Set up to return from userspace. If provided, use a stub | 207 | /* Set up to return from userspace. If provided, use a stub |
325 | already in userspace. */ | 208 | already in userspace. */ |
326 | /* minus 8 is offset to cater for "rtsd r15,8" */ | 209 | /* minus 8 is offset to cater for "rtsd r15,8" */ |
327 | if (ka->sa.sa_flags & SA_RESTORER) { | 210 | /* addi r12, r0, __NR_sigreturn */ |
328 | regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8; | 211 | err |= __put_user(0x31800000 | __NR_rt_sigreturn , |
329 | } else { | 212 | frame->tramp + 0); |
330 | /* addi r12, r0, __NR_sigreturn */ | 213 | /* brki r14, 0x8 */ |
331 | err |= __put_user(0x31800000 | __NR_rt_sigreturn , | 214 | err |= __put_user(0xb9cc0008, frame->tramp + 1); |
332 | frame->tramp + 0); | 215 | |
333 | /* brki r14, 0x8 */ | 216 | /* Return from sighandler will jump to the tramp. |
334 | err |= __put_user(0xb9cc0008, frame->tramp + 1); | 217 | Negative 8 offset because return is rtsd r15, 8 */ |
335 | 218 | regs->r15 = ((unsigned long)frame->tramp)-8; | |
336 | /* Return from sighandler will jump to the tramp. | 219 | |
337 | Negative 8 offset because return is rtsd r15, 8 */ | 220 | __invalidate_cache_sigtramp((unsigned long)frame->tramp); |
338 | regs->r15 = ((unsigned long)frame->tramp)-8; | ||
339 | |||
340 | __invalidate_cache_sigtramp((unsigned long)frame->tramp); | ||
341 | } | ||
342 | 221 | ||
343 | if (err) | 222 | if (err) |
344 | goto give_sigsegv; | 223 | goto give_sigsegv; |
@@ -405,7 +284,7 @@ do_restart: | |||
405 | * OK, we're invoking a handler | 284 | * OK, we're invoking a handler |
406 | */ | 285 | */ |
407 | 286 | ||
408 | static void | 287 | static int |
409 | handle_signal(unsigned long sig, struct k_sigaction *ka, | 288 | handle_signal(unsigned long sig, struct k_sigaction *ka, |
410 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) | 289 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) |
411 | { | 290 | { |
@@ -426,6 +305,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
426 | recalc_sigpending(); | 305 | recalc_sigpending(); |
427 | spin_unlock_irq(¤t->sighand->siglock); | 306 | spin_unlock_irq(¤t->sighand->siglock); |
428 | } | 307 | } |
308 | return 1; | ||
429 | } | 309 | } |
430 | 310 | ||
431 | /* | 311 | /* |
@@ -456,7 +336,9 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall) | |||
456 | if (kernel_mode(regs)) | 336 | if (kernel_mode(regs)) |
457 | return 1; | 337 | return 1; |
458 | 338 | ||
459 | if (!oldset) | 339 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) |
340 | oldset = ¤t->saved_sigmask; | ||
341 | else | ||
460 | oldset = ¤t->blocked; | 342 | oldset = ¤t->blocked; |
461 | 343 | ||
462 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 344 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
@@ -464,13 +346,31 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall) | |||
464 | /* Whee! Actually deliver the signal. */ | 346 | /* Whee! Actually deliver the signal. */ |
465 | if (in_syscall) | 347 | if (in_syscall) |
466 | handle_restart(regs, &ka, 1); | 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 | return 1; | 359 | return 1; |
469 | } | 360 | } |
470 | 361 | ||
471 | if (in_syscall) | 362 | if (in_syscall) |
472 | handle_restart(regs, NULL, 0); | 363 | handle_restart(regs, NULL, 0); |
473 | 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, ¤t->saved_sigmask, NULL); | ||
372 | } | ||
373 | |||
474 | /* Did we come from a system call? */ | 374 | /* Did we come from a system call? */ |
475 | return 0; | 375 | return 0; |
476 | } | 376 | } |
diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index 376d1789f7c0..ef0e8932af33 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S | |||
@@ -71,12 +71,12 @@ ENTRY(sys_call_table) | |||
71 | .long sys_getppid | 71 | .long sys_getppid |
72 | .long sys_getpgrp /* 65 */ | 72 | .long sys_getpgrp /* 65 */ |
73 | .long sys_setsid | 73 | .long sys_setsid |
74 | .long sys_sigaction | 74 | .long sys_ni_syscall /* sys_sigaction */ |
75 | .long sys_sgetmask | 75 | .long sys_sgetmask |
76 | .long sys_ssetmask | 76 | .long sys_ssetmask |
77 | .long sys_setreuid /* 70 */ | 77 | .long sys_setreuid /* 70 */ |
78 | .long sys_setregid | 78 | .long sys_setregid |
79 | .long sys_sigsuspend_wrapper | 79 | .long sys_ni_syscall /* sys_sigsuspend_wrapper */ |
80 | .long sys_sigpending | 80 | .long sys_sigpending |
81 | .long sys_sethostname | 81 | .long sys_sethostname |
82 | .long sys_setrlimit /* 75 */ | 82 | .long sys_setrlimit /* 75 */ |
@@ -123,7 +123,7 @@ ENTRY(sys_call_table) | |||
123 | .long sys_sysinfo | 123 | .long sys_sysinfo |
124 | .long sys_ipc | 124 | .long sys_ipc |
125 | .long sys_fsync | 125 | .long sys_fsync |
126 | .long sys_sigreturn_wrapper | 126 | .long sys_ni_syscall /* sys_sigreturn_wrapper */ |
127 | .long sys_clone_wrapper /* 120 */ | 127 | .long sys_clone_wrapper /* 120 */ |
128 | .long sys_setdomainname | 128 | .long sys_setdomainname |
129 | .long sys_newuname | 129 | .long sys_newuname |