Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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/sched/task_stack.h>
 29#include <linux/mm.h>
 30#include <linux/kernel.h>
 31#include <linux/signal.h>
 32#include <linux/syscalls.h>
 33#include <linux/errno.h>
 34#include <linux/wait.h>
 35#include <linux/ptrace.h>
 36#include <linux/unistd.h>
 37#include <linux/stddef.h>
 38#include <linux/highuid.h>
 39#include <linux/personality.h>
 40#include <linux/tty.h>
 41#include <linux/binfmts.h>
 42#include <linux/tracehook.h>
 43
 44#include <asm/setup.h>
 45#include <linux/uaccess.h>
 46#include <asm/pgtable.h>
 47#include <asm/traps.h>
 48#include <asm/ucontext.h>
 49
 50/*
 51 * Do a signal return; undo the signal stack.
 52 *
 53 * Keep the return code on the stack quadword aligned!
 54 * That makes the cache flush below easier.
 55 */
 56
 57struct rt_sigframe {
 58	long dummy_er0;
 59	long dummy_vector;
 60#if defined(CONFIG_CPU_H8S)
 61	short dummy_exr;
 62#endif
 63	long dummy_pc;
 64	char *pretcode;
 65	struct siginfo *pinfo;
 66	void *puc;
 67	unsigned char retcode[8];
 68	struct siginfo info;
 69	struct ucontext uc;
 70	int sig;
 71} __packed __aligned(2);
 72
 73static inline int
 74restore_sigcontext(struct sigcontext *usc, int *pd0)
 75{
 76	struct pt_regs *regs = current_pt_regs();
 77	int err = 0;
 78	unsigned int ccr;
 79	unsigned int usp;
 80	unsigned int er0;
 81
 82	/* Always make any pending restarted system calls return -EINTR */
 83	current->restart_block.fn = do_no_restart_syscall;
 84
 85	/* restore passed registers */
 86#define COPY(r)  do { err |= get_user(regs->r, &usc->sc_##r); } while (0)
 87	COPY(er1);
 88	COPY(er2);
 89	COPY(er3);
 90	COPY(er5);
 91	COPY(pc);
 92	ccr = regs->ccr & 0x10;
 93	COPY(ccr);
 94#undef COPY
 95	regs->ccr &= 0xef;
 96	regs->ccr |= ccr;
 97	regs->orig_er0 = -1;		/* disable syscall checks */
 98	err |= __get_user(usp, &usc->sc_usp);
 99	regs->sp = usp;
100
101	err |= __get_user(er0, &usc->sc_er0);
102	*pd0 = er0;
103	return err;
104}
105
106asmlinkage int sys_rt_sigreturn(void)
107{
108	unsigned long usp = rdusp();
109	struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
110	sigset_t set;
111	int er0;
112
113	if (!access_ok(frame, sizeof(*frame)))
114		goto badframe;
115	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
116		goto badframe;
117
118	set_current_blocked(&set);
119
120	if (restore_sigcontext(&frame->uc.uc_mcontext, &er0))
121		goto badframe;
122
123	if (restore_altstack(&frame->uc.uc_stack))
124		goto badframe;
125
126	return er0;
127
128badframe:
129	force_sig(SIGSEGV);
130	return 0;
131}
132
133static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
134			     unsigned long mask)
135{
136	int err = 0;
137
138	err |= __put_user(regs->er0, &sc->sc_er0);
139	err |= __put_user(regs->er1, &sc->sc_er1);
140	err |= __put_user(regs->er2, &sc->sc_er2);
141	err |= __put_user(regs->er3, &sc->sc_er3);
142	err |= __put_user(regs->er4, &sc->sc_er4);
143	err |= __put_user(regs->er5, &sc->sc_er5);
144	err |= __put_user(regs->er6, &sc->sc_er6);
145	err |= __put_user(rdusp(),   &sc->sc_usp);
146	err |= __put_user(regs->pc,  &sc->sc_pc);
147	err |= __put_user(regs->ccr, &sc->sc_ccr);
148	err |= __put_user(mask,      &sc->sc_mask);
149
150	return err;
151}
152
153static inline void __user *
154get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size)
155{
156	return (void __user *)((sigsp(rdusp(), ksig) - frame_size) & -8UL);
157}
158
159static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
160			  struct pt_regs *regs)
161{
162	struct rt_sigframe *frame;
163	int err = 0;
164	unsigned char *ret;
165
166	frame = get_sigframe(ksig, regs, sizeof(*frame));
167
168	if (!access_ok(frame, sizeof(*frame)))
169		return -EFAULT;
170
171	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
172		err |= copy_siginfo_to_user(&frame->info, &ksig->info);
173
174	/* Create the ucontext.  */
175	err |= __put_user(0, &frame->uc.uc_flags);
176	err |= __put_user(0, &frame->uc.uc_link);
177	err |= __save_altstack(&frame->uc.uc_stack, rdusp());
178	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
179	err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
180	if (err)
181		return -EFAULT;
182
183	/* Set up to return from userspace.  */
184	ret = (unsigned char *)&frame->retcode;
185	if (ksig->ka.sa.sa_flags & SA_RESTORER)
186		ret = (unsigned char *)(ksig->ka.sa.sa_restorer);
187	else {
188		/* sub.l er0,er0; mov.b #__NR_rt_sigreturn,r0l; trapa #0 */
189		err |= __put_user(0x1a80f800 + (__NR_rt_sigreturn & 0xff),
190				  (unsigned long *)(frame->retcode + 0));
191		err |= __put_user(0x5700,
192				  (unsigned short *)(frame->retcode + 4));
193	}
194	err |= __put_user(ret, &frame->pretcode);
195
196	if (err)
197		return -EFAULT;
198
199	/* Set up registers for signal handler */
200	regs->sp  = (unsigned long)frame;
201	regs->pc  = (unsigned long)ksig->ka.sa.sa_handler;
202	regs->er0 = ksig->sig;
203	regs->er1 = (unsigned long)&(frame->info);
204	regs->er2 = (unsigned long)&frame->uc;
205	regs->er5 = current->mm->start_data;	/* GOT base */
206
207	return 0;
208}
209
210static void
211handle_restart(struct pt_regs *regs, struct k_sigaction *ka)
212{
213	switch (regs->er0) {
214	case -ERESTARTNOHAND:
215		if (!ka)
216			goto do_restart;
217		regs->er0 = -EINTR;
218		break;
219	case -ERESTART_RESTARTBLOCK:
220		if (!ka) {
221			regs->er0 = __NR_restart_syscall;
222			regs->pc -= 2;
223		} else
224			regs->er0 = -EINTR;
225		break;
226	case -ERESTARTSYS:
227		if (!(ka->sa.sa_flags & SA_RESTART)) {
228			regs->er0 = -EINTR;
229			break;
230		}
231		/* fallthrough */
232	case -ERESTARTNOINTR:
233do_restart:
234		regs->er0 = regs->orig_er0;
235		regs->pc -= 2;
236		break;
237	}
238}
239
240/*
241 * OK, we're invoking a handler
242 */
243static void
244handle_signal(struct ksignal *ksig, struct pt_regs *regs)
245{
246	sigset_t *oldset = sigmask_to_save();
247	int ret;
248	/* are we from a system call? */
249	if (regs->orig_er0 >= 0)
250		handle_restart(regs, &ksig->ka);
251
252	ret = setup_rt_frame(ksig, oldset, regs);
253
254	signal_setup_done(ret, ksig, 0);
255}
256
257/*
258 * Note that 'init' is a special process: it doesn't get signals it doesn't
259 * want to handle. Thus you cannot kill init even with a SIGKILL even by
260 * mistake.
261 */
262static void do_signal(struct pt_regs *regs)
263{
264	struct ksignal ksig;
265
266	current->thread.esp0 = (unsigned long) regs;
267
268	if (get_signal(&ksig)) {
269		/* Whee!  Actually deliver the signal.  */
270		handle_signal(&ksig, regs);
271		return;
272	}
273	/* Did we come from a system call? */
274	if (regs->orig_er0 >= 0)
275		handle_restart(regs, NULL);
276
277	/* If there's no signal to deliver, we just restore the saved mask.  */
278	restore_saved_sigmask();
279}
280
281asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
282{
283	if (thread_info_flags & _TIF_SIGPENDING)
284		do_signal(regs);
285
286	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
287		clear_thread_flag(TIF_NOTIFY_RESUME);
288		tracehook_notify_resume(regs);
289	}
290}