2 * arch/ubicom32/kernel/signal.c
3 * Ubicom32 architecture signal handling implementation.
5 * (C) Copyright 2009, Ubicom, Inc.
6 * Copyright (C) 1991, 1992 Linus Torvalds
7 * Linux/m68k support by Hamish Macdonald
8 * 68060 fixes by Jesper Skov
9 * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab
10 * mathemu support by Roman Zippel
11 * ++roman (07/09/96): implemented signal stacks
13 * This file is part of the Ubicom32 Linux Kernel Port.
15 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16 * it and/or modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation, either version 2 of the
18 * License, or (at your option) any later version.
20 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
22 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
23 * the GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with the Ubicom32 Linux Kernel Port. If not,
27 * see <http://www.gnu.org/licenses/>.
29 * Ubicom32 implementation derived from (with many thanks):
34 * mathemu support by Roman Zippel
35 * (Note: fpstate in the signal context is completely ignored for the emulator
36 * and the internal floating point format is put on stack)
38 * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
39 * Atari :-) Current limitation: Only one sigstack can be active at one time.
40 * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
41 * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
45 #include <linux/module.h>
46 #include <linux/sched.h>
48 #include <linux/kernel.h>
49 #include <linux/signal.h>
50 #include <linux/syscalls.h>
51 #include <linux/errno.h>
52 #include <linux/wait.h>
53 #include <linux/ptrace.h>
54 #include <linux/unistd.h>
55 #include <linux/stddef.h>
56 #include <linux/highuid.h>
57 #include <linux/tty.h>
58 #include <linux/personality.h>
59 #include <linux/binfmts.h>
61 #include <asm/setup.h>
62 #include <asm/uaccess.h>
63 #include <asm/pgtable.h>
64 #include <asm/traps.h>
65 #include <asm/ucontext.h>
67 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
70 * asm signal return handlers.
72 void ret_from_user_signal(void);
73 void ret_from_user_rt_signal(void);
74 asmlinkage
int do_signal(sigset_t
*oldset
, struct pt_regs
*regs
);
77 * Common signal suspend implementation
79 static int signal_suspend(sigset_t
*saveset
, struct pt_regs
*regs
)
83 current
->state
= TASK_INTERRUPTIBLE
;
85 if (!do_signal(saveset
, regs
)) {
89 * If the current frame type is a signal trampoline we are
90 * actually going to call the signal handler so we return the
91 * desired d0 as the return value.
93 if (regs
->frame_type
== UBICOM32_FRAME_TYPE_SIGTRAMP
) {
99 * Should never get here
106 * Atomically swap in the new signal mask, and wait for a signal.
108 asmlinkage
int do_sigsuspend(struct pt_regs
*regs
)
110 old_sigset_t mask
= regs
->dn
[0];
114 spin_lock_irq(¤t
->sighand
->siglock
);
115 saveset
= current
->blocked
;
116 siginitset(¤t
->blocked
, mask
);
118 spin_unlock_irq(¤t
->sighand
->siglock
);
121 * Call common handler
123 return signal_suspend(&saveset
, regs
);
127 do_rt_sigsuspend(struct pt_regs
*regs
)
129 sigset_t
*unewset
= (sigset_t
*)regs
->dn
[0];
130 size_t sigsetsize
= (size_t)regs
->dn
[1];
131 sigset_t saveset
, newset
;
133 /* XXX: Don't preclude handling different sized sigset_t's. */
134 if (sigsetsize
!= sizeof(sigset_t
))
137 if (copy_from_user(&newset
, unewset
, sizeof(newset
)))
139 sigdelsetmask(&newset
, ~_BLOCKABLE
);
141 spin_lock_irq(¤t
->sighand
->siglock
);
142 saveset
= current
->blocked
;
143 current
->blocked
= newset
;
145 spin_unlock_irq(¤t
->sighand
->siglock
);
148 * Call common handler
150 return signal_suspend(&saveset
, regs
);
154 sys_sigaction(int sig
, const struct old_sigaction
*act
,
155 struct old_sigaction
*oact
)
157 struct k_sigaction new_ka
, old_ka
;
162 if (!access_ok(VERIFY_READ
, act
, sizeof(*act
)) ||
163 __get_user(new_ka
.sa
.sa_handler
, &act
->sa_handler
) ||
164 __get_user(new_ka
.sa
.sa_restorer
, &act
->sa_restorer
))
166 __get_user(new_ka
.sa
.sa_flags
, &act
->sa_flags
);
167 __get_user(mask
, &act
->sa_mask
);
168 siginitset(&new_ka
.sa
.sa_mask
, mask
);
171 ret
= do_sigaction(sig
, act
? &new_ka
: NULL
, oact
? &old_ka
: NULL
);
174 if (!access_ok(VERIFY_WRITE
, oact
, sizeof(*oact
)) ||
175 __put_user(old_ka
.sa
.sa_handler
, &oact
->sa_handler
) ||
176 __put_user(old_ka
.sa
.sa_restorer
, &oact
->sa_restorer
))
178 __put_user(old_ka
.sa
.sa_flags
, &oact
->sa_flags
);
179 __put_user(old_ka
.sa
.sa_mask
.sig
[0], &oact
->sa_mask
);
186 do_sys_sigaltstack(struct pt_regs
*regs
)
188 const stack_t
*uss
= (stack_t
*) regs
->dn
[0];
189 stack_t
*uoss
= (stack_t
*)regs
->dn
[1];
190 return do_sigaltstack(uss
, uoss
, regs
->an
[7]);
194 * fdpic_func_descriptor describes sa_handler when the application is FDPIC
196 struct fdpic_func_descriptor
{
202 * rt_sigframe is stored on the user stack immediately before (above)
203 * the signal handlers stack.
207 unsigned long syscall_number
; /* This holds __NR_rt_sigreturn. */
208 unsigned long restore_all_regs
; /* This field gets set to 1 if the frame
209 * type is TRAP or INTERRUPT. */
217 * Do a signal return; undo the signal stack.
219 asmlinkage
int do_sigreturn(unsigned long __unused
)
225 asmlinkage
int do_rt_sigreturn(struct pt_regs
*regs
)
227 unsigned long usp
= regs
->an
[7];
228 struct rt_sigframe
*frame
= (struct rt_sigframe
*)(usp
);
231 if (!access_ok(VERIFY_READ
, frame
, sizeof(*frame
)))
233 if (__copy_from_user(&set
, &frame
->uc
.uc_sigmask
, sizeof(set
)))
236 sigdelsetmask(&set
, ~_BLOCKABLE
);
237 spin_lock_irq(¤t
->sighand
->siglock
);
238 current
->blocked
= set
;
240 spin_unlock_irq(¤t
->sighand
->siglock
);
242 if (copy_from_user(regs
, &frame
->uc
.uc_mcontext
, sizeof(struct pt_regs
)))
247 force_sig(SIGSEGV
, current
);
252 get_sigframe(struct k_sigaction
*ka
, struct pt_regs
*regs
, size_t frame_size
)
256 /* Default to using normal stack. */
259 /* This is the X/Open sanctioned signal stack switching. */
260 if (ka
->sa
.sa_flags
& SA_ONSTACK
) {
261 if (!sas_ss_flags(usp
))
262 usp
= current
->sas_ss_sp
+ current
->sas_ss_size
;
264 return (void *)((usp
- frame_size
) & ~0x3);
268 * signal_trampoline: Defined in ubicom32_syscall.S
270 asmlinkage
void signal_trampoline(void)__attribute__((naked
));
272 static void setup_rt_frame (int sig
, struct k_sigaction
*ka
, siginfo_t
*info
,
273 sigset_t
*set
, struct pt_regs
*regs
)
275 struct rt_sigframe
*frame
;
278 frame
= (struct rt_sigframe
*) get_sigframe(ka
, regs
, sizeof(*frame
));
281 * The 'err |=' have been may criticized as bad code style, but I
282 * strongly suspect that we want this code to be fast. So for
283 * now it stays as is.
285 err
|= __put_user( ( (current_thread_info()->exec_domain
)
286 && (current_thread_info()->exec_domain
->signal_invmap
)
288 ? current_thread_info()->exec_domain
->signal_invmap
[sig
]
290 err
|= __put_user(info
, &frame
->info
);
292 /* Create the ucontext. */
293 err
|= __put_user(0, &frame
->uc
.uc_flags
);
294 err
|= __put_user(0, &frame
->uc
.uc_link
);
295 err
|= __put_user((void *)current
->sas_ss_sp
,
296 &frame
->uc
.uc_stack
.ss_sp
);
297 err
|= __put_user(sas_ss_flags(regs
->an
[7]),
298 &frame
->uc
.uc_stack
.ss_flags
);
299 err
|= __put_user(current
->sas_ss_size
, &frame
->uc
.uc_stack
.ss_size
);
300 err
|= __put_user(__NR_rt_sigreturn
, &frame
->syscall_number
);
301 if ((regs
->frame_type
== UBICOM32_FRAME_TYPE_TRAP
) ||
302 (regs
->frame_type
== UBICOM32_FRAME_TYPE_INTERRUPT
)) {
303 err
|= __put_user(1, &frame
->restore_all_regs
);
305 err
|= __put_user(0, &frame
->restore_all_regs
);
307 err
|= copy_to_user (&frame
->uc
.uc_mcontext
.sc_regs
, regs
, sizeof(struct pt_regs
));
308 err
|= copy_to_user (&frame
->uc
.uc_sigmask
, set
, sizeof(*set
));
314 * Set up registers for signal handler NOTE: Do not modify dn[14], it
315 * contains the userspace tls pointer, so it important that it carries
316 * over to the signal handler.
318 regs
->an
[7] = (unsigned long)frame
;
319 regs
->pc
= (unsigned long) signal_trampoline
;
320 regs
->an
[5] = (unsigned long) signal_trampoline
;
322 regs
->dn
[1] = (unsigned long) frame
->info
;
323 regs
->dn
[2] = (unsigned int) &frame
->uc
;
326 * If this is FDPIC then the signal handler is actually a function
329 if (current
->personality
& FDPIC_FUNCPTRS
) {
330 struct fdpic_func_descriptor __user
*funcptr
=
331 (struct fdpic_func_descriptor
*) ka
->sa
.sa_handler
;
332 err
|= __get_user(regs
->dn
[3], &funcptr
->text
);
333 err
|= __get_user(regs
->an
[0], &funcptr
->GOT
);
338 * The funcdesc must be in a3 as this is required for the lazy
339 * resolver in ld.so, if the application is not FDPIC a3 is not
342 regs
->an
[3] = (unsigned long) funcptr
;
345 regs
->dn
[3] = (unsigned long)ka
->sa
.sa_handler
;
349 regs
->frame_type
= UBICOM32_FRAME_TYPE_SIGTRAMP
;
354 /* user space exception */
355 force_sigsegv(sig
, current
);
359 handle_restart(struct pt_regs
*regs
, struct k_sigaction
*ka
, int has_handler
)
361 switch (regs
->dn
[0]) {
362 case -ERESTARTNOHAND
:
365 regs
->dn
[0] = -EINTR
;
369 if (has_handler
&& !(ka
->sa
.sa_flags
& SA_RESTART
)) {
370 regs
->dn
[0] = -EINTR
;
374 case -ERESTARTNOINTR
:
376 regs
->dn
[0] = regs
->original_dn_0
;
384 * OK, we're invoking a handler
387 handle_signal(int sig
, struct k_sigaction
*ka
, siginfo_t
*info
,
388 sigset_t
*oldset
, struct pt_regs
*regs
)
390 /* are we from a system call? */
391 if (regs
->frame_type
== -1)
392 /* If so, check system call restarting.. */
393 handle_restart(regs
, ka
, 1);
395 /* set up the stack frame */
396 setup_rt_frame(sig
, ka
, info
, oldset
, regs
);
398 if (ka
->sa
.sa_flags
& SA_ONESHOT
)
399 ka
->sa
.sa_handler
= SIG_DFL
;
401 spin_lock_irq(¤t
->sighand
->siglock
);
402 sigorsets(¤t
->blocked
,¤t
->blocked
,&ka
->sa
.sa_mask
);
403 if (!(ka
->sa
.sa_flags
& SA_NODEFER
))
404 sigaddset(¤t
->blocked
,sig
);
406 spin_unlock_irq(¤t
->sighand
->siglock
);
410 * Note that 'init' is a special process: it doesn't get signals it doesn't
411 * want to handle. Thus you cannot kill init even with a SIGKILL even by
414 asmlinkage
int do_signal(sigset_t
*oldset
, struct pt_regs
*regs
)
416 struct k_sigaction ka
;
421 * We want the common case to go fast, which
422 * is why we may in certain cases get here from
423 * kernel mode. Just return without doing anything
426 if (!user_mode(regs
))
430 oldset
= ¤t
->blocked
;
432 signr
= get_signal_to_deliver(&info
, &ka
, regs
, NULL
);
434 /* Whee! Actually deliver the signal. */
435 handle_signal(signr
, &ka
, &info
, oldset
, regs
);
439 /* Did we come from a system call? */
440 if (regs
->frame_type
== -1) {
441 /* Restart the system call - no handlers present */
442 handle_restart(regs
, NULL
, 0);
450 * Return handler for signal clean-up.
452 * NOTE: Ubicom32 does not use this syscall. Instead we rely
453 * on do_rt_sigreturn().
455 asmlinkage
long sys_sigreturn(void)