• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/h8300/kernel/
1/*
2 *  linux/arch/h8300/kernel/signal.c
3 *
4 *  Copyright (C) 1991, 1992  Linus Torvalds
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/*
12 * uClinux H8/300 support by Yoshinori Sato <ysato@users.sourceforge.jp>
13 *                and David McCullough <davidm@snapgear.com>
14 *
15 * Based on
16 * Linux/m68k by Hamish Macdonald
17 */
18
19/*
20 * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
21 * Atari :-) Current limitation: Only one sigstack can be active at one time.
22 * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
23 * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
24 * signal handlers!
25 */
26
27#include <linux/sched.h>
28#include <linux/mm.h>
29#include <linux/kernel.h>
30#include <linux/signal.h>
31#include <linux/syscalls.h>
32#include <linux/errno.h>
33#include <linux/wait.h>
34#include <linux/ptrace.h>
35#include <linux/unistd.h>
36#include <linux/stddef.h>
37#include <linux/highuid.h>
38#include <linux/personality.h>
39#include <linux/tty.h>
40#include <linux/binfmts.h>
41#include <linux/freezer.h>
42#include <linux/tracehook.h>
43
44#include <asm/setup.h>
45#include <asm/uaccess.h>
46#include <asm/pgtable.h>
47#include <asm/traps.h>
48#include <asm/ucontext.h>
49
50#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
51
52asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
53
54/*
55 * Atomically swap in the new signal mask, and wait for a signal.
56 */
57asmlinkage int do_sigsuspend(struct pt_regs *regs)
58{
59	old_sigset_t mask = regs->er3;
60	sigset_t saveset;
61
62	mask &= _BLOCKABLE;
63	spin_lock_irq(&current->sighand->siglock);
64	saveset = current->blocked;
65	siginitset(&current->blocked, mask);
66	recalc_sigpending();
67	spin_unlock_irq(&current->sighand->siglock);
68
69	regs->er0 = -EINTR;
70	while (1) {
71		current->state = TASK_INTERRUPTIBLE;
72		schedule();
73		if (do_signal(regs, &saveset))
74			return -EINTR;
75	}
76}
77
78asmlinkage int
79do_rt_sigsuspend(struct pt_regs *regs)
80{
81	sigset_t *unewset = (sigset_t *)regs->er1;
82	size_t sigsetsize = (size_t)regs->er2;
83	sigset_t saveset, newset;
84
85	if (sigsetsize != sizeof(sigset_t))
86		return -EINVAL;
87
88	if (copy_from_user(&newset, unewset, sizeof(newset)))
89		return -EFAULT;
90	sigdelsetmask(&newset, ~_BLOCKABLE);
91
92	spin_lock_irq(&current->sighand->siglock);
93	saveset = current->blocked;
94	current->blocked = newset;
95	recalc_sigpending();
96	spin_unlock_irq(&current->sighand->siglock);
97
98	regs->er0 = -EINTR;
99	while (1) {
100		current->state = TASK_INTERRUPTIBLE;
101		schedule();
102		if (do_signal(regs, &saveset))
103			return -EINTR;
104	}
105}
106
107asmlinkage int
108sys_sigaction(int sig, const struct old_sigaction *act,
109	      struct old_sigaction *oact)
110{
111	struct k_sigaction new_ka, old_ka;
112	int ret;
113
114	if (act) {
115		old_sigset_t mask;
116		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
117		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
118		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
119			return -EFAULT;
120		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
121		__get_user(mask, &act->sa_mask);
122		siginitset(&new_ka.sa.sa_mask, mask);
123	}
124
125	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
126
127	if (!ret && oact) {
128		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
129		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
130		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
131			return -EFAULT;
132		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
133		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
134	}
135
136	return ret;
137}
138
139asmlinkage int
140sys_sigaltstack(const stack_t *uss, stack_t *uoss)
141{
142	return do_sigaltstack(uss, uoss, rdusp());
143}
144
145
146/*
147 * Do a signal return; undo the signal stack.
148 *
149 * Keep the return code on the stack quadword aligned!
150 * That makes the cache flush below easier.
151 */
152
153struct sigframe
154{
155	long dummy_er0;
156	long dummy_vector;
157#if defined(CONFIG_CPU_H8S)
158	short dummy_exr;
159#endif
160	long dummy_pc;
161	char *pretcode;
162	unsigned char retcode[8];
163	unsigned long extramask[_NSIG_WORDS-1];
164	struct sigcontext sc;
165	int sig;
166} __attribute__((aligned(2),packed));
167
168struct rt_sigframe
169{
170	long dummy_er0;
171	long dummy_vector;
172#if defined(CONFIG_CPU_H8S)
173	short dummy_exr;
174#endif
175	long dummy_pc;
176	char *pretcode;
177	struct siginfo *pinfo;
178	void *puc;
179	unsigned char retcode[8];
180	struct siginfo info;
181	struct ucontext uc;
182	int sig;
183} __attribute__((aligned(2),packed));
184
185static inline int
186restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc,
187		   int *pd0)
188{
189	int err = 0;
190	unsigned int ccr;
191	unsigned int usp;
192	unsigned int er0;
193
194	/* Always make any pending restarted system calls return -EINTR */
195	current_thread_info()->restart_block.fn = do_no_restart_syscall;
196
197#define COPY(r) err |= __get_user(regs->r, &usc->sc_##r)    /* restore passed registers */
198	COPY(er1);
199	COPY(er2);
200	COPY(er3);
201	COPY(er5);
202	COPY(pc);
203	ccr = regs->ccr & 0x10;
204	COPY(ccr);
205#undef COPY
206	regs->ccr &= 0xef;
207	regs->ccr |= ccr;
208	regs->orig_er0 = -1;		/* disable syscall checks */
209	err |= __get_user(usp, &usc->sc_usp);
210	wrusp(usp);
211
212	err |= __get_user(er0, &usc->sc_er0);
213	*pd0 = er0;
214	return err;
215}
216
217asmlinkage int do_sigreturn(unsigned long __unused,...)
218{
219	struct pt_regs *regs = (struct pt_regs *) (&__unused - 1);
220	unsigned long usp = rdusp();
221	struct sigframe *frame = (struct sigframe *)(usp - 4);
222	sigset_t set;
223	int er0;
224
225	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
226		goto badframe;
227	if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
228	    (_NSIG_WORDS > 1 &&
229	     __copy_from_user(&set.sig[1], &frame->extramask,
230			      sizeof(frame->extramask))))
231		goto badframe;
232
233	sigdelsetmask(&set, ~_BLOCKABLE);
234	spin_lock_irq(&current->sighand->siglock);
235	current->blocked = set;
236	recalc_sigpending();
237	spin_unlock_irq(&current->sighand->siglock);
238
239	if (restore_sigcontext(regs, &frame->sc, &er0))
240		goto badframe;
241	return er0;
242
243badframe:
244	force_sig(SIGSEGV, current);
245	return 0;
246}
247
248asmlinkage int do_rt_sigreturn(unsigned long __unused,...)
249{
250	struct pt_regs *regs = (struct pt_regs *) &__unused;
251	unsigned long usp = rdusp();
252	struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
253	sigset_t set;
254	int er0;
255
256	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
257		goto badframe;
258	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
259		goto badframe;
260
261	sigdelsetmask(&set, ~_BLOCKABLE);
262	spin_unlock_irq(&current->sighand->siglock);
263	current->blocked = set;
264	recalc_sigpending();
265	spin_lock_irq(&current->sighand->siglock);
266
267	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0))
268		goto badframe;
269
270	if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT)
271		goto badframe;
272
273	return er0;
274
275badframe:
276	force_sig(SIGSEGV, current);
277	return 0;
278}
279
280static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
281			     unsigned long mask)
282{
283	int err = 0;
284
285	err |= __put_user(regs->er0, &sc->sc_er0);
286	err |= __put_user(regs->er1, &sc->sc_er1);
287	err |= __put_user(regs->er2, &sc->sc_er2);
288	err |= __put_user(regs->er3, &sc->sc_er3);
289	err |= __put_user(regs->er4, &sc->sc_er4);
290	err |= __put_user(regs->er5, &sc->sc_er5);
291	err |= __put_user(regs->er6, &sc->sc_er6);
292	err |= __put_user(rdusp(),   &sc->sc_usp);
293	err |= __put_user(regs->pc,  &sc->sc_pc);
294	err |= __put_user(regs->ccr, &sc->sc_ccr);
295	err |= __put_user(mask,      &sc->sc_mask);
296
297	return err;
298}
299
300static inline void *
301get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
302{
303	unsigned long usp;
304
305	/* Default to using normal stack.  */
306	usp = rdusp();
307
308	/* This is the X/Open sanctioned signal stack switching.  */
309	if (ka->sa.sa_flags & SA_ONSTACK) {
310		if (!sas_ss_flags(usp))
311			usp = current->sas_ss_sp + current->sas_ss_size;
312	}
313	return (void *)((usp - frame_size) & -8UL);
314}
315
316static void setup_frame (int sig, struct k_sigaction *ka,
317			 sigset_t *set, struct pt_regs *regs)
318{
319	struct sigframe *frame;
320	int err = 0;
321	int usig;
322	unsigned char *ret;
323
324	frame = get_sigframe(ka, regs, sizeof(*frame));
325
326	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
327		goto give_sigsegv;
328
329	usig = current_thread_info()->exec_domain
330		&& current_thread_info()->exec_domain->signal_invmap
331		&& sig < 32
332		? current_thread_info()->exec_domain->signal_invmap[sig]
333		: sig;
334
335	err |= __put_user(usig, &frame->sig);
336	if (err)
337		goto give_sigsegv;
338
339	err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
340	if (err)
341		goto give_sigsegv;
342
343	if (_NSIG_WORDS > 1) {
344		err |= copy_to_user(frame->extramask, &set->sig[1],
345				    sizeof(frame->extramask));
346		if (err)
347			goto give_sigsegv;
348	}
349
350	ret = frame->retcode;
351	if (ka->sa.sa_flags & SA_RESTORER)
352		ret = (unsigned char *)(ka->sa.sa_restorer);
353	else {
354		/* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */
355		err |= __put_user(0x1a80f800 + (__NR_sigreturn & 0xff),
356				  (unsigned long *)(frame->retcode + 0));
357		err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4));
358	}
359
360	/* Set up to return from userspace.  */
361	err |= __put_user(ret, &frame->pretcode);
362
363	if (err)
364		goto give_sigsegv;
365
366	/* Set up registers for signal handler */
367	wrusp ((unsigned long) frame);
368	regs->pc = (unsigned long) ka->sa.sa_handler;
369	regs->er0 = (current_thread_info()->exec_domain
370			   && current_thread_info()->exec_domain->signal_invmap
371			   && sig < 32
372			   ? current_thread_info()->exec_domain->signal_invmap[sig]
373		          : sig);
374	regs->er1 = (unsigned long)&(frame->sc);
375	regs->er5 = current->mm->start_data;	/* GOT base */
376
377	return;
378
379give_sigsegv:
380	force_sigsegv(sig, current);
381}
382
383static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
384			    sigset_t *set, struct pt_regs *regs)
385{
386	struct rt_sigframe *frame;
387	int err = 0;
388	int usig;
389	unsigned char *ret;
390
391	frame = get_sigframe(ka, regs, sizeof(*frame));
392
393	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
394		goto give_sigsegv;
395
396	usig = current_thread_info()->exec_domain
397		&& current_thread_info()->exec_domain->signal_invmap
398		&& sig < 32
399		? current_thread_info()->exec_domain->signal_invmap[sig]
400		: sig;
401
402	err |= __put_user(usig, &frame->sig);
403	if (err)
404		goto give_sigsegv;
405
406	err |= __put_user(&frame->info, &frame->pinfo);
407	err |= __put_user(&frame->uc, &frame->puc);
408	err |= copy_siginfo_to_user(&frame->info, info);
409	if (err)
410		goto give_sigsegv;
411
412	/* Create the ucontext.  */
413	err |= __put_user(0, &frame->uc.uc_flags);
414	err |= __put_user(0, &frame->uc.uc_link);
415	err |= __put_user((void *)current->sas_ss_sp,
416			  &frame->uc.uc_stack.ss_sp);
417	err |= __put_user(sas_ss_flags(rdusp()),
418			  &frame->uc.uc_stack.ss_flags);
419	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
420	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
421	err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
422	if (err)
423		goto give_sigsegv;
424
425	/* Set up to return from userspace.  */
426	ret = frame->retcode;
427	if (ka->sa.sa_flags & SA_RESTORER)
428		ret = (unsigned char *)(ka->sa.sa_restorer);
429	else {
430		/* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */
431		err |= __put_user(0x1a80f800 + (__NR_sigreturn & 0xff),
432				  (unsigned long *)(frame->retcode + 0));
433		err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4));
434	}
435	err |= __put_user(ret, &frame->pretcode);
436
437	if (err)
438		goto give_sigsegv;
439
440	/* Set up registers for signal handler */
441	wrusp ((unsigned long) frame);
442	regs->pc  = (unsigned long) ka->sa.sa_handler;
443	regs->er0 = (current_thread_info()->exec_domain
444		     && current_thread_info()->exec_domain->signal_invmap
445		     && sig < 32
446		     ? current_thread_info()->exec_domain->signal_invmap[sig]
447		     : sig);
448	regs->er1 = (unsigned long)&(frame->info);
449	regs->er2 = (unsigned long)&frame->uc;
450	regs->er5 = current->mm->start_data;	/* GOT base */
451
452	return;
453
454give_sigsegv:
455	force_sigsegv(sig, current);
456}
457
458/*
459 * OK, we're invoking a handler
460 */
461static void
462handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
463	      sigset_t *oldset,	struct pt_regs * regs)
464{
465	/* are we from a system call? */
466	if (regs->orig_er0 >= 0) {
467		switch (regs->er0) {
468		        case -ERESTART_RESTARTBLOCK:
469			case -ERESTARTNOHAND:
470				regs->er0 = -EINTR;
471				break;
472
473			case -ERESTARTSYS:
474				if (!(ka->sa.sa_flags & SA_RESTART)) {
475					regs->er0 = -EINTR;
476					break;
477				}
478			/* fallthrough */
479			case -ERESTARTNOINTR:
480				regs->er0 = regs->orig_er0;
481				regs->pc -= 2;
482		}
483	}
484
485	/* set up the stack frame */
486	if (ka->sa.sa_flags & SA_SIGINFO)
487		setup_rt_frame(sig, ka, info, oldset, regs);
488	else
489		setup_frame(sig, ka, oldset, regs);
490
491	spin_lock_irq(&current->sighand->siglock);
492	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
493	if (!(ka->sa.sa_flags & SA_NODEFER))
494		sigaddset(&current->blocked,sig);
495	recalc_sigpending();
496	spin_unlock_irq(&current->sighand->siglock);
497}
498
499/*
500 * Note that 'init' is a special process: it doesn't get signals it doesn't
501 * want to handle. Thus you cannot kill init even with a SIGKILL even by
502 * mistake.
503 */
504asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
505{
506	siginfo_t info;
507	int signr;
508	struct k_sigaction ka;
509
510	/*
511	 * We want the common case to go fast, which
512	 * is why we may in certain cases get here from
513	 * kernel mode. Just return without doing anything
514	 * if so.
515	 */
516	if ((regs->ccr & 0x10))
517		return 1;
518
519	if (try_to_freeze())
520		goto no_signal;
521
522	current->thread.esp0 = (unsigned long) regs;
523
524	if (!oldset)
525		oldset = &current->blocked;
526
527	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
528	if (signr > 0) {
529		/* Whee!  Actually deliver the signal.  */
530		handle_signal(signr, &info, &ka, oldset, regs);
531		return 1;
532	}
533 no_signal:
534	/* Did we come from a system call? */
535	if (regs->orig_er0 >= 0) {
536		/* Restart the system call - no handlers present */
537		if (regs->er0 == -ERESTARTNOHAND ||
538		    regs->er0 == -ERESTARTSYS ||
539		    regs->er0 == -ERESTARTNOINTR) {
540			regs->er0 = regs->orig_er0;
541			regs->pc -= 2;
542		}
543		if (regs->er0 == -ERESTART_RESTARTBLOCK){
544			regs->er0 = __NR_restart_syscall;
545			regs->pc -= 2;
546		}
547	}
548	return 0;
549}
550
551asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
552{
553	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
554		do_signal(regs, NULL);
555
556	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
557		clear_thread_flag(TIF_NOTIFY_RESUME);
558		tracehook_notify_resume(regs);
559		if (current->replacement_session_keyring)
560			key_replace_session_keyring();
561	}
562}
563