1/* MN10300 Signal handling
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#include <linux/sched.h>
13#include <linux/mm.h>
14#include <linux/smp.h>
15#include <linux/kernel.h>
16#include <linux/signal.h>
17#include <linux/errno.h>
18#include <linux/wait.h>
19#include <linux/ptrace.h>
20#include <linux/unistd.h>
21#include <linux/stddef.h>
22#include <linux/tty.h>
23#include <linux/personality.h>
24#include <linux/suspend.h>
25#include <linux/tracehook.h>
26#include <asm/cacheflush.h>
27#include <asm/ucontext.h>
28#include <asm/uaccess.h>
29#include <asm/fpu.h>
30#include "sigframe.h"
31
32#define DEBUG_SIG 0
33
34/*
35 * do a signal return; undo the signal stack.
36 */
37static int restore_sigcontext(struct pt_regs *regs,
38			      struct sigcontext __user *sc, long *_d0)
39{
40	unsigned int err = 0;
41
42	/* Always make any pending restarted system calls return -EINTR */
43	current->restart_block.fn = do_no_restart_syscall;
44
45	if (is_using_fpu(current))
46		fpu_kill_state(current);
47
48#define COPY(x) err |= __get_user(regs->x, &sc->x)
49	COPY(d1); COPY(d2); COPY(d3);
50	COPY(a0); COPY(a1); COPY(a2); COPY(a3);
51	COPY(e0); COPY(e1); COPY(e2); COPY(e3);
52	COPY(e4); COPY(e5); COPY(e6); COPY(e7);
53	COPY(lar); COPY(lir);
54	COPY(mdr); COPY(mdrq);
55	COPY(mcvf); COPY(mcrl); COPY(mcrh);
56	COPY(sp); COPY(pc);
57#undef COPY
58
59	{
60		unsigned int tmpflags;
61#ifndef CONFIG_MN10300_USING_JTAG
62#define USER_EPSW (EPSW_FLAG_Z | EPSW_FLAG_N | EPSW_FLAG_C | EPSW_FLAG_V | \
63		   EPSW_T | EPSW_nAR)
64#else
65#define USER_EPSW (EPSW_FLAG_Z | EPSW_FLAG_N | EPSW_FLAG_C | EPSW_FLAG_V | \
66		   EPSW_nAR)
67#endif
68		err |= __get_user(tmpflags, &sc->epsw);
69		regs->epsw = (regs->epsw & ~USER_EPSW) |
70		  (tmpflags & USER_EPSW);
71		regs->orig_d0 = -1;		/* disable syscall checks */
72	}
73
74	{
75		struct fpucontext *buf;
76		err |= __get_user(buf, &sc->fpucontext);
77		if (buf) {
78			if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
79				goto badframe;
80			err |= fpu_restore_sigcontext(buf);
81		}
82	}
83
84	err |= __get_user(*_d0, &sc->d0);
85	return err;
86
87badframe:
88	return 1;
89}
90
91/*
92 * standard signal return syscall
93 */
94asmlinkage long sys_sigreturn(void)
95{
96	struct sigframe __user *frame;
97	sigset_t set;
98	long d0;
99
100	frame = (struct sigframe __user *) current_frame()->sp;
101	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
102		goto badframe;
103	if (__get_user(set.sig[0], &frame->sc.oldmask))
104		goto badframe;
105
106	if (_NSIG_WORDS > 1 &&
107	    __copy_from_user(&set.sig[1], &frame->extramask,
108			     sizeof(frame->extramask)))
109		goto badframe;
110
111	set_current_blocked(&set);
112
113	if (restore_sigcontext(current_frame(), &frame->sc, &d0))
114		goto badframe;
115
116	return d0;
117
118badframe:
119	force_sig(SIGSEGV, current);
120	return 0;
121}
122
123/*
124 * realtime signal return syscall
125 */
126asmlinkage long sys_rt_sigreturn(void)
127{
128	struct rt_sigframe __user *frame;
129	sigset_t set;
130	long d0;
131
132	frame = (struct rt_sigframe __user *) current_frame()->sp;
133	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
134		goto badframe;
135	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
136		goto badframe;
137
138	set_current_blocked(&set);
139
140	if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0))
141		goto badframe;
142
143	if (restore_altstack(&frame->uc.uc_stack))
144		goto badframe;
145
146	return d0;
147
148badframe:
149	force_sig(SIGSEGV, current);
150	return 0;
151}
152
153/*
154 * store the userspace context into a signal frame
155 */
156static int setup_sigcontext(struct sigcontext __user *sc,
157			    struct fpucontext *fpuctx,
158			    struct pt_regs *regs,
159			    unsigned long mask)
160{
161	int tmp, err = 0;
162
163#define COPY(x) err |= __put_user(regs->x, &sc->x)
164	COPY(d0); COPY(d1); COPY(d2); COPY(d3);
165	COPY(a0); COPY(a1); COPY(a2); COPY(a3);
166	COPY(e0); COPY(e1); COPY(e2); COPY(e3);
167	COPY(e4); COPY(e5); COPY(e6); COPY(e7);
168	COPY(lar); COPY(lir);
169	COPY(mdr); COPY(mdrq);
170	COPY(mcvf); COPY(mcrl); COPY(mcrh);
171	COPY(sp); COPY(epsw); COPY(pc);
172#undef COPY
173
174	tmp = fpu_setup_sigcontext(fpuctx);
175	if (tmp < 0)
176		err = 1;
177	else
178		err |= __put_user(tmp ? fpuctx : NULL, &sc->fpucontext);
179
180	/* non-iBCS2 extensions.. */
181	err |= __put_user(mask, &sc->oldmask);
182
183	return err;
184}
185
186/*
187 * determine which stack to use..
188 */
189static inline void __user *get_sigframe(struct ksignal *ksig,
190					struct pt_regs *regs,
191					size_t frame_size)
192{
193	unsigned long sp = sigsp(regs->sp, ksig);
194
195	return (void __user *) ((sp - frame_size) & ~7UL);
196}
197
198/*
199 * set up a normal signal frame
200 */
201static int setup_frame(struct ksignal *ksig, sigset_t *set,
202		       struct pt_regs *regs)
203{
204	struct sigframe __user *frame;
205	int sig = ksig->sig;
206
207	frame = get_sigframe(ksig, regs, sizeof(*frame));
208
209	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
210		return -EFAULT;
211
212	if (__put_user(sig, &frame->sig) < 0 ||
213	    __put_user(&frame->sc, &frame->psc) < 0)
214		return -EFAULT;
215
216	if (setup_sigcontext(&frame->sc, &frame->fpuctx, regs, set->sig[0]))
217		return -EFAULT;
218
219	if (_NSIG_WORDS > 1) {
220		if (__copy_to_user(frame->extramask, &set->sig[1],
221				   sizeof(frame->extramask)))
222			return -EFAULT;
223	}
224
225	/* set up to return from userspace.  If provided, use a stub already in
226	 * userspace */
227	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
228		if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode))
229			return -EFAULT;
230	} else {
231		if (__put_user((void (*)(void))frame->retcode,
232			       &frame->pretcode))
233			return -EFAULT;
234		/* this is mov $,d0; syscall 0 */
235		if (__put_user(0x2c, (char *)(frame->retcode + 0)) ||
236		    __put_user(__NR_sigreturn, (char *)(frame->retcode + 1)) ||
237		    __put_user(0x00, (char *)(frame->retcode + 2)) ||
238		    __put_user(0xf0, (char *)(frame->retcode + 3)) ||
239		    __put_user(0xe0, (char *)(frame->retcode + 4)))
240			return -EFAULT;
241		flush_icache_range((unsigned long) frame->retcode,
242				   (unsigned long) frame->retcode + 5);
243	}
244
245	/* set up registers for signal handler */
246	regs->sp = (unsigned long) frame;
247	regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
248	regs->d0 = sig;
249	regs->d1 = (unsigned long) &frame->sc;
250
251#if DEBUG_SIG
252	printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
253	       sig, current->comm, current->pid, frame, regs->pc,
254	       frame->pretcode);
255#endif
256
257	return 0;
258}
259
260/*
261 * set up a realtime signal frame
262 */
263static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
264			  struct pt_regs *regs)
265{
266	struct rt_sigframe __user *frame;
267	int sig = ksig->sig;
268
269	frame = get_sigframe(ksig, regs, sizeof(*frame));
270
271	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
272		return -EFAULT;
273
274	if (__put_user(sig, &frame->sig) ||
275	    __put_user(&frame->info, &frame->pinfo) ||
276	    __put_user(&frame->uc, &frame->puc) ||
277	    copy_siginfo_to_user(&frame->info, &ksig->info))
278		return -EFAULT;
279
280	/* create the ucontext.  */
281	if (__put_user(0, &frame->uc.uc_flags) ||
282	    __put_user(0, &frame->uc.uc_link) ||
283	    __save_altstack(&frame->uc.uc_stack, regs->sp) ||
284	    setup_sigcontext(&frame->uc.uc_mcontext,
285			     &frame->fpuctx, regs, set->sig[0]) ||
286	    __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
287		return -EFAULT;
288
289	/* set up to return from userspace.  If provided, use a stub already in
290	 * userspace */
291	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
292		if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode))
293			return -EFAULT;
294
295	} else {
296		if (__put_user((void(*)(void))frame->retcode,
297			       &frame->pretcode) ||
298		    /* This is mov $,d0; syscall 0 */
299		    __put_user(0x2c, (char *)(frame->retcode + 0)) ||
300		    __put_user(__NR_rt_sigreturn,
301			       (char *)(frame->retcode + 1)) ||
302		    __put_user(0x00, (char *)(frame->retcode + 2)) ||
303		    __put_user(0xf0, (char *)(frame->retcode + 3)) ||
304		    __put_user(0xe0, (char *)(frame->retcode + 4)))
305			return -EFAULT;
306
307		flush_icache_range((u_long) frame->retcode,
308				   (u_long) frame->retcode + 5);
309	}
310
311	/* Set up registers for signal handler */
312	regs->sp = (unsigned long) frame;
313	regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
314	regs->d0 = sig;
315	regs->d1 = (long) &frame->info;
316
317#if DEBUG_SIG
318	printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
319	       sig, current->comm, current->pid, frame, regs->pc,
320	       frame->pretcode);
321#endif
322
323	return 0;
324}
325
326static inline void stepback(struct pt_regs *regs)
327{
328	regs->pc -= 2;
329	regs->orig_d0 = -1;
330}
331
332/*
333 * handle the actual delivery of a signal to userspace
334 */
335static int handle_signal(struct ksignal *ksig, struct pt_regs *regs)
336{
337	sigset_t *oldset = sigmask_to_save();
338	int ret;
339
340	/* Are we from a system call? */
341	if (regs->orig_d0 >= 0) {
342		/* If so, check system call restarting.. */
343		switch (regs->d0) {
344		case -ERESTART_RESTARTBLOCK:
345		case -ERESTARTNOHAND:
346			regs->d0 = -EINTR;
347			break;
348
349		case -ERESTARTSYS:
350			if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
351				regs->d0 = -EINTR;
352				break;
353			}
354
355			/* fallthrough */
356		case -ERESTARTNOINTR:
357			regs->d0 = regs->orig_d0;
358			stepback(regs);
359		}
360	}
361
362	/* Set up the stack frame */
363	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
364		ret = setup_rt_frame(ksig, oldset, regs);
365	else
366		ret = setup_frame(ksig, oldset, regs);
367
368	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
369	return 0;
370}
371
372/*
373 * handle a potential signal
374 */
375static void do_signal(struct pt_regs *regs)
376{
377	struct ksignal ksig;
378
379	if (get_signal(&ksig)) {
380		handle_signal(&ksig, regs);
381		return;
382	}
383
384	/* did we come from a system call? */
385	if (regs->orig_d0 >= 0) {
386		/* restart the system call - no handlers present */
387		switch (regs->d0) {
388		case -ERESTARTNOHAND:
389		case -ERESTARTSYS:
390		case -ERESTARTNOINTR:
391			regs->d0 = regs->orig_d0;
392			stepback(regs);
393			break;
394
395		case -ERESTART_RESTARTBLOCK:
396			regs->d0 = __NR_restart_syscall;
397			stepback(regs);
398			break;
399		}
400	}
401
402	/* if there's no signal to deliver, we just put the saved sigmask
403	 * back */
404	restore_saved_sigmask();
405}
406
407/*
408 * notification of userspace execution resumption
409 * - triggered by current->work.notify_resume
410 */
411asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
412{
413	/* Pending single-step? */
414	if (thread_info_flags & _TIF_SINGLESTEP) {
415#ifndef CONFIG_MN10300_USING_JTAG
416		regs->epsw |= EPSW_T;
417		clear_thread_flag(TIF_SINGLESTEP);
418#else
419		BUG(); /* no h/w single-step if using JTAG unit */
420#endif
421	}
422
423	/* deal with pending signal delivery */
424	if (thread_info_flags & _TIF_SIGPENDING)
425		do_signal(regs);
426
427	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
428		clear_thread_flag(TIF_NOTIFY_RESUME);
429		tracehook_notify_resume(current_frame());
430	}
431}
432