blob: bd36152b780e3cf475ffd230ffaa06ac1f3f41a0 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/arch/parisc/kernel/signal.c: Architecture-specific signal
3 * handling support.
4 *
5 * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
6 * Copyright (C) 2000 Linuxcare, Inc.
7 *
8 * Based on the ia64, i386, and alpha versions.
9 *
10 * Like the IA-64, we are a recent enough port (we are *starting*
11 * with glibc2.2) that we do not need to support the old non-realtime
12 * Linux signals. Therefore we don't. HP/UX signals will go in
13 * arch/parisc/hpux/signal.c when we figure out how to do them.
14 */
15
16#include <linux/sched.h>
17#include <linux/mm.h>
18#include <linux/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <linux/kernel.h>
20#include <linux/signal.h>
21#include <linux/errno.h>
22#include <linux/wait.h>
23#include <linux/ptrace.h>
Kyle McMartinecf02de2009-04-27 00:29:53 -040024#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/unistd.h>
26#include <linux/stddef.h>
27#include <linux/compat.h>
28#include <linux/elf.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <asm/ucontext.h>
30#include <asm/rt_sigframe.h>
31#include <asm/uaccess.h>
32#include <asm/pgalloc.h>
33#include <asm/cacheflush.h>
Sam Ravnborg0013a852005-09-09 20:57:26 +020034#include <asm/asm-offsets.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
36#ifdef CONFIG_COMPAT
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include "signal32.h"
38#endif
39
40#define DEBUG_SIG 0
41#define DEBUG_SIG_LEVEL 2
42
43#if DEBUG_SIG
44#define DBG(LEVEL, ...) \
45 ((DEBUG_SIG_LEVEL >= LEVEL) \
46 ? printk(__VA_ARGS__) : (void) 0)
47#else
48#define DBG(LEVEL, ...)
49#endif
50
51
52#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
53
54/* gcc will complain if a pointer is cast to an integer of different
55 * size. If you really need to do this (and we do for an ELF32 user
56 * application in an ELF64 kernel) then you have to do a cast to an
57 * integer of the same size first. The A() macro accomplishes
58 * this. */
59#define A(__x) ((unsigned long)(__x))
60
Linus Torvalds1da177e2005-04-16 15:20:36 -070061/*
62 * Atomically swap in the new signal mask, and wait for a signal.
63 */
Helge Dellera8f44e32007-01-28 14:58:52 +010064#ifdef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#include "sys32.h"
66#endif
67
Linus Torvalds1da177e2005-04-16 15:20:36 -070068/*
69 * Do a signal return - restore sigcontext.
70 */
71
72/* Trampoline for calling rt_sigreturn() */
73#define INSN_LDI_R25_0 0x34190000 /* ldi 0,%r25 (in_syscall=0) */
74#define INSN_LDI_R25_1 0x34190002 /* ldi 1,%r25 (in_syscall=1) */
75#define INSN_LDI_R20 0x3414015a /* ldi __NR_rt_sigreturn,%r20 */
76#define INSN_BLE_SR2_R0 0xe4008200 /* be,l 0x100(%sr2,%r0),%sr0,%r31 */
77#define INSN_NOP 0x08000240 /* nop */
78/* For debugging */
79#define INSN_DIE_HORRIBLY 0x68000ccc /* stw %r0,0x666(%sr0,%r0) */
80
81static long
82restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
83{
84 long err = 0;
85
86 err |= __copy_from_user(regs->gr, sc->sc_gr, sizeof(regs->gr));
87 err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
88 err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq));
89 err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq));
90 err |= __get_user(regs->sar, &sc->sc_sar);
91 DBG(2,"restore_sigcontext: iaoq is 0x%#lx / 0x%#lx\n",
92 regs->iaoq[0],regs->iaoq[1]);
93 DBG(2,"restore_sigcontext: r28 is %ld\n", regs->gr[28]);
94 return err;
95}
96
97void
98sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
99{
100 struct rt_sigframe __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 sigset_t set;
102 unsigned long usp = (regs->gr[30] & ~(0x01UL));
103 unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
Helge Dellera8f44e32007-01-28 14:58:52 +0100104#ifdef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 compat_sigset_t compat_set;
106 struct compat_rt_sigframe __user * compat_frame;
107
Kyle McMartina3ea84f2006-06-16 19:10:02 +0000108 if (is_compat_task())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
110#endif
111
112
113 /* Unwind the user stack to get the rt_sigframe structure. */
114 frame = (struct rt_sigframe __user *)
115 (usp - sigframe_size);
116 DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
117
Helge Dellera8f44e32007-01-28 14:58:52 +0100118#ifdef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 compat_frame = (struct compat_rt_sigframe __user *)frame;
120
Kyle McMartina3ea84f2006-06-16 19:10:02 +0000121 if (is_compat_task()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 DBG(2,"sys_rt_sigreturn: ELF32 process.\n");
123 if (__copy_from_user(&compat_set, &compat_frame->uc.uc_sigmask, sizeof(compat_set)))
124 goto give_sigsegv;
125 sigset_32to64(&set,&compat_set);
126 } else
127#endif
128 {
129 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
130 goto give_sigsegv;
131 }
132
133 sigdelsetmask(&set, ~_BLOCKABLE);
Matt Flemingade77282012-05-11 10:58:58 +1000134 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135
136 /* Good thing we saved the old gr[30], eh? */
Helge Dellera8f44e32007-01-28 14:58:52 +0100137#ifdef CONFIG_64BIT
Kyle McMartina3ea84f2006-06-16 19:10:02 +0000138 if (is_compat_task()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n",
140 &compat_frame->uc.uc_mcontext);
141// FIXME: Load upper half from register file
142 if (restore_sigcontext32(&compat_frame->uc.uc_mcontext,
143 &compat_frame->regs, regs))
144 goto give_sigsegv;
145 DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n",
146 usp, &compat_frame->uc.uc_stack);
147 if (do_sigaltstack32(&compat_frame->uc.uc_stack, NULL, usp) == -EFAULT)
148 goto give_sigsegv;
149 } else
150#endif
151 {
152 DBG(1,"sys_rt_sigreturn: frame->uc.uc_mcontext 0x%p\n",
153 &frame->uc.uc_mcontext);
154 if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
155 goto give_sigsegv;
156 DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n",
157 usp, &frame->uc.uc_stack);
158 if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT)
159 goto give_sigsegv;
160 }
161
162
163
164 /* If we are on the syscall path IAOQ will not be restored, and
165 * if we are on the interrupt path we must not corrupt gr31.
166 */
167 if (in_syscall)
168 regs->gr[31] = regs->iaoq[0];
169#if DEBUG_SIG
170 DBG(1,"sys_rt_sigreturn: returning to %#lx, DUMPING REGS:\n", regs->iaoq[0]);
171 show_regs(regs);
172#endif
173 return;
174
175give_sigsegv:
176 DBG(1,"sys_rt_sigreturn: Sending SIGSEGV\n");
Kyle McMartin67bace72010-11-29 20:34:38 -0500177 force_sig(SIGSEGV, current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 return;
179}
180
181/*
182 * Set up a signal frame.
183 */
184
185static inline void __user *
186get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
187{
188 /*FIXME: ELF32 vs. ELF64 has different frame_size, but since we
189 don't use the parameter it doesn't matter */
190
191 DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n",
192 (unsigned long)ka, sp, frame_size);
193
Laurent MEYERd09042d2006-06-23 02:05:36 -0700194 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 sp = current->sas_ss_sp; /* Stacks grow up! */
196
197 DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
198 return (void __user *) sp; /* Stacks grow up. Fun. */
199}
200
201static long
202setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_syscall)
203
204{
205 unsigned long flags = 0;
206 long err = 0;
207
208 if (on_sig_stack((unsigned long) sc))
209 flags |= PARISC_SC_FLAG_ONSTACK;
210 if (in_syscall) {
211 flags |= PARISC_SC_FLAG_IN_SYSCALL;
212 /* regs->iaoq is undefined in the syscall return path */
213 err |= __put_user(regs->gr[31], &sc->sc_iaoq[0]);
214 err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]);
215 err |= __put_user(regs->sr[3], &sc->sc_iasq[0]);
216 err |= __put_user(regs->sr[3], &sc->sc_iasq[1]);
217 DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (in syscall)\n",
218 regs->gr[31], regs->gr[31]+4);
219 } else {
220 err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq));
221 err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq));
222 DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (not in syscall)\n",
223 regs->iaoq[0], regs->iaoq[1]);
224 }
225
226 err |= __put_user(flags, &sc->sc_flags);
227 err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr));
228 err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
229 err |= __put_user(regs->sar, &sc->sc_sar);
230 DBG(1,"setup_sigcontext: r28 is %ld\n", regs->gr[28]);
231
232 return err;
233}
234
235static long
236setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
237 sigset_t *set, struct pt_regs *regs, int in_syscall)
238{
239 struct rt_sigframe __user *frame;
240 unsigned long rp, usp;
241 unsigned long haddr, sigframe_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 int err = 0;
Helge Dellera8f44e32007-01-28 14:58:52 +0100243#ifdef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 compat_int_t compat_val;
245 struct compat_rt_sigframe __user * compat_frame;
246 compat_sigset_t compat_set;
247#endif
248
249 usp = (regs->gr[30] & ~(0x01UL));
250 /*FIXME: frame_size parameter is unused, remove it. */
251 frame = get_sigframe(ka, usp, sizeof(*frame));
252
253 DBG(1,"SETUP_RT_FRAME: START\n");
254 DBG(1,"setup_rt_frame: frame %p info %p\n", frame, info);
255
256
Helge Dellera8f44e32007-01-28 14:58:52 +0100257#ifdef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
259 compat_frame = (struct compat_rt_sigframe __user *)frame;
260
Kyle McMartina3ea84f2006-06-16 19:10:02 +0000261 if (is_compat_task()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
Kyle McMartinf671c452006-01-15 14:10:29 -0500263 err |= copy_siginfo_to_user32(&compat_frame->info, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 DBG(1,"SETUP_RT_FRAME: 1\n");
265 compat_val = (compat_int_t)current->sas_ss_sp;
266 err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_sp);
267 DBG(1,"SETUP_RT_FRAME: 2\n");
268 compat_val = (compat_int_t)current->sas_ss_size;
269 err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_size);
270 DBG(1,"SETUP_RT_FRAME: 3\n");
271 compat_val = sas_ss_flags(regs->gr[30]);
272 err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_flags);
273 DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc);
274 DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext);
275 err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext,
276 &compat_frame->regs, regs, in_syscall);
277 sigset_64to32(&compat_set,set);
278 err |= __copy_to_user(&compat_frame->uc.uc_sigmask, &compat_set, sizeof(compat_set));
279 } else
280#endif
281 {
282 DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info);
283 err |= copy_siginfo_to_user(&frame->info, info);
284 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
285 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
286 err |= __put_user(sas_ss_flags(regs->gr[30]),
287 &frame->uc.uc_stack.ss_flags);
288 DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
289 DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
290 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300291 /* FIXME: Should probably be converted as well for the compat case */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
293 }
294
295 if (err)
296 goto give_sigsegv;
297
298 /* Set up to return from userspace. If provided, use a stub
299 already in userspace. The first words of tramp are used to
300 save the previous sigrestartblock trampoline that might be
301 on the stack. We start the sigreturn trampoline at
302 SIGRESTARTBLOCK_TRAMP+X. */
303 err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0,
304 &frame->tramp[SIGRESTARTBLOCK_TRAMP+0]);
305 err |= __put_user(INSN_LDI_R20,
306 &frame->tramp[SIGRESTARTBLOCK_TRAMP+1]);
307 err |= __put_user(INSN_BLE_SR2_R0,
308 &frame->tramp[SIGRESTARTBLOCK_TRAMP+2]);
309 err |= __put_user(INSN_NOP, &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]);
310
311#if DEBUG_SIG
312 /* Assert that we're flushing in the correct space... */
313 {
314 int sid;
315 asm ("mfsp %%sr3,%0" : "=r" (sid));
316 DBG(1,"setup_rt_frame: Flushing 64 bytes at space %#x offset %p\n",
317 sid, frame->tramp);
318 }
319#endif
320
321 flush_user_dcache_range((unsigned long) &frame->tramp[0],
322 (unsigned long) &frame->tramp[TRAMP_SIZE]);
323 flush_user_icache_range((unsigned long) &frame->tramp[0],
324 (unsigned long) &frame->tramp[TRAMP_SIZE]);
325
Paulius Zaleckasefad798b2008-02-03 15:42:53 +0200326 /* TRAMP Words 0-4, Length 5 = SIGRESTARTBLOCK_TRAMP
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 * TRAMP Words 5-9, Length 4 = SIGRETURN_TRAMP
328 * So the SIGRETURN_TRAMP is at the end of SIGRESTARTBLOCK_TRAMP
329 */
330 rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
331
332 if (err)
333 goto give_sigsegv;
334
335 haddr = A(ka->sa.sa_handler);
336 /* The sa_handler may be a pointer to a function descriptor */
Helge Dellera8f44e32007-01-28 14:58:52 +0100337#ifdef CONFIG_64BIT
Kyle McMartina3ea84f2006-06-16 19:10:02 +0000338 if (is_compat_task()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339#endif
340 if (haddr & PA_PLABEL_FDESC) {
341 Elf32_Fdesc fdesc;
342 Elf32_Fdesc __user *ufdesc = (Elf32_Fdesc __user *)A(haddr & ~3);
343
344 err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
345
346 if (err)
347 goto give_sigsegv;
348
349 haddr = fdesc.addr;
350 regs->gr[19] = fdesc.gp;
351 }
Helge Dellera8f44e32007-01-28 14:58:52 +0100352#ifdef CONFIG_64BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 } else {
354 Elf64_Fdesc fdesc;
355 Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3);
356
357 err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
358
359 if (err)
360 goto give_sigsegv;
361
362 haddr = fdesc.addr;
363 regs->gr[19] = fdesc.gp;
364 DBG(1,"setup_rt_frame: 64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
365 haddr, regs->gr[19], in_syscall);
366 }
367#endif
368
369 /* The syscall return path will create IAOQ values from r31.
370 */
371 sigframe_size = PARISC_RT_SIGFRAME_SIZE;
Helge Dellera8f44e32007-01-28 14:58:52 +0100372#ifdef CONFIG_64BIT
Kyle McMartina3ea84f2006-06-16 19:10:02 +0000373 if (is_compat_task())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
375#endif
376 if (in_syscall) {
377 regs->gr[31] = haddr;
Helge Dellera8f44e32007-01-28 14:58:52 +0100378#ifdef CONFIG_64BIT
Kyle McMartindf570b92006-08-27 11:04:26 -0400379 if (!test_thread_flag(TIF_32BIT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 sigframe_size |= 1;
381#endif
382 } else {
383 unsigned long psw = USER_PSW;
Helge Dellera8f44e32007-01-28 14:58:52 +0100384#ifdef CONFIG_64BIT
Kyle McMartindf570b92006-08-27 11:04:26 -0400385 if (!test_thread_flag(TIF_32BIT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 psw |= PSW_W;
387#endif
388
389 /* If we are singlestepping, arrange a trap to be delivered
390 when we return to userspace. Note the semantics -- we
391 should trap before the first insn in the handler is
392 executed. Ref:
393 http://sources.redhat.com/ml/gdb/2004-11/msg00245.html
394 */
395 if (pa_psw(current)->r) {
396 pa_psw(current)->r = 0;
397 psw |= PSW_R;
398 mtctl(-1, 0);
399 }
400
401 regs->gr[0] = psw;
402 regs->iaoq[0] = haddr | 3;
403 regs->iaoq[1] = regs->iaoq[0] + 4;
404 }
405
406 regs->gr[2] = rp; /* userland return pointer */
407 regs->gr[26] = sig; /* signal number */
408
Helge Dellera8f44e32007-01-28 14:58:52 +0100409#ifdef CONFIG_64BIT
Kyle McMartina3ea84f2006-06-16 19:10:02 +0000410 if (is_compat_task()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */
412 regs->gr[24] = A(&compat_frame->uc); /* ucontext pointer */
413 } else
414#endif
415 {
416 regs->gr[25] = A(&frame->info); /* siginfo pointer */
417 regs->gr[24] = A(&frame->uc); /* ucontext pointer */
418 }
419
420 DBG(1,"setup_rt_frame: making sigreturn frame: %#lx + %#lx = %#lx\n",
421 regs->gr[30], sigframe_size,
422 regs->gr[30] + sigframe_size);
423 /* Raise the user stack pointer to make a proper call frame. */
424 regs->gr[30] = (A(frame) + sigframe_size);
425
426
427 DBG(1,"setup_rt_frame: sig deliver (%s,%d) frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
428 current->comm, current->pid, frame, regs->gr[30],
429 regs->iaoq[0], regs->iaoq[1], rp);
430
431 return 1;
432
433give_sigsegv:
434 DBG(1,"setup_rt_frame: sending SIGSEGV\n");
Randolph Chung40c72f22005-10-21 22:49:47 -0400435 force_sigsegv(sig, current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 return 0;
437}
438
439/*
440 * OK, we're invoking a handler.
441 */
442
443static long
444handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
445 sigset_t *oldset, struct pt_regs *regs, int in_syscall)
446{
447 DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
448 sig, ka, info, oldset, regs);
449
450 /* Set up the stack frame */
451 if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
452 return 0;
453
Matt Flemingade77282012-05-11 10:58:58 +1000454 block_sigmask(ka, sig);
Kyle McMartinecf02de2009-04-27 00:29:53 -0400455
Kyle McMartin22a8cdd2010-02-12 10:53:08 -0500456 tracehook_signal_handler(sig, info, ka, regs,
457 test_thread_flag(TIF_SINGLESTEP) ||
458 test_thread_flag(TIF_BLOCKSTEP));
Kyle McMartinecf02de2009-04-27 00:29:53 -0400459
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 return 1;
461}
462
Kyle McMartin2b163b72007-01-15 00:36:26 -0500463static inline void
464syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
465{
466 /* Check the return code */
467 switch (regs->gr[28]) {
468 case -ERESTART_RESTARTBLOCK:
469 current_thread_info()->restart_block.fn =
470 do_no_restart_syscall;
471 case -ERESTARTNOHAND:
472 DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
473 regs->gr[28] = -EINTR;
474 break;
475
476 case -ERESTARTSYS:
477 if (!(ka->sa.sa_flags & SA_RESTART)) {
478 DBG(1,"ERESTARTSYS: putting -EINTR\n");
479 regs->gr[28] = -EINTR;
480 break;
481 }
482 /* fallthrough */
483 case -ERESTARTNOINTR:
484 /* A syscall is just a branch, so all
485 * we have to do is fiddle the return pointer.
486 */
487 regs->gr[31] -= 8; /* delayed branching */
488 /* Preserve original r28. */
489 regs->gr[28] = regs->orig_r28;
490 break;
491 }
492}
493
494static inline void
495insert_restart_trampoline(struct pt_regs *regs)
496{
497 switch(regs->gr[28]) {
498 case -ERESTART_RESTARTBLOCK: {
499 /* Restart the system call - no handlers present */
500 unsigned int *usp = (unsigned int *)regs->gr[30];
501
502 /* Setup a trampoline to restart the syscall
503 * with __NR_restart_syscall
504 *
505 * 0: <return address (orig r31)>
506 * 4: <2nd half for 64-bit>
507 * 8: ldw 0(%sp), %r31
508 * 12: be 0x100(%sr2, %r0)
509 * 16: ldi __NR_restart_syscall, %r20
510 */
511#ifdef CONFIG_64BIT
512 put_user(regs->gr[31] >> 32, &usp[0]);
513 put_user(regs->gr[31] & 0xffffffff, &usp[1]);
514 put_user(0x0fc010df, &usp[2]);
515#else
516 put_user(regs->gr[31], &usp[0]);
517 put_user(0x0fc0109f, &usp[2]);
518#endif
519 put_user(0xe0008200, &usp[3]);
520 put_user(0x34140000, &usp[4]);
521
522 /* Stack is 64-byte aligned, and we only need
523 * to flush 1 cache line.
524 * Flushing one cacheline is cheap.
525 * "sync" on bigger (> 4 way) boxes is not.
526 */
Kyle McMartincf39cc32008-04-15 18:36:38 -0400527 flush_user_dcache_range(regs->gr[30], regs->gr[30] + 4);
528 flush_user_icache_range(regs->gr[30], regs->gr[30] + 4);
Kyle McMartin2b163b72007-01-15 00:36:26 -0500529
530 regs->gr[31] = regs->gr[30] + 8;
531 /* Preserve original r28. */
532 regs->gr[28] = regs->orig_r28;
533
534 return;
535 }
536 case -ERESTARTNOHAND:
537 case -ERESTARTSYS:
538 case -ERESTARTNOINTR: {
539 /* Hooray for delayed branching. We don't
540 * have to restore %r20 (the system call
541 * number) because it gets loaded in the delay
542 * slot of the branch external instruction.
543 */
544 regs->gr[31] -= 8;
545 /* Preserve original r28. */
546 regs->gr[28] = regs->orig_r28;
547
548 return;
549 }
550 default:
551 break;
552 }
553}
554
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555/*
556 * Note that 'init' is a special process: it doesn't get signals it doesn't
557 * want to handle. Thus you cannot kill init even with a SIGKILL even by
558 * mistake.
559 *
560 * We need to be able to restore the syscall arguments (r21-r26) to
561 * restart syscalls. Thus, the syscall path should save them in the
562 * pt_regs structure (it's okay to do so since they are caller-save
563 * registers). As noted below, the syscall number gets restored for
564 * us due to the magic of delayed branching.
565 */
Kyle McMartin4650f0a2007-01-08 16:28:06 -0500566asmlinkage void
567do_signal(struct pt_regs *regs, long in_syscall)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568{
569 siginfo_t info;
570 struct k_sigaction ka;
571 int signr;
Kyle McMartin4650f0a2007-01-08 16:28:06 -0500572 sigset_t *oldset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573
574 DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n",
575 oldset, regs, regs->sr[7], in_syscall);
576
577 /* Everyone else checks to see if they are in kernel mode at
578 this point and exits if that's the case. I'm not sure why
579 we would be called in that case, but for some reason we
580 are. */
581
Kyle McMartin4650f0a2007-01-08 16:28:06 -0500582 if (test_thread_flag(TIF_RESTORE_SIGMASK))
583 oldset = &current->saved_sigmask;
584 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 oldset = &current->blocked;
586
587 DBG(1,"do_signal: oldset %08lx / %08lx\n",
588 oldset->sig[0], oldset->sig[1]);
589
590
591 /* May need to force signal if handle_signal failed to deliver */
592 while (1) {
593
594 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
595 DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
596
597 if (signr <= 0)
598 break;
599
600 /* Restart a system call if necessary. */
Kyle McMartin2b163b72007-01-15 00:36:26 -0500601 if (in_syscall)
602 syscall_restart(regs, &ka);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 /* Whee! Actually deliver the signal. If the
605 delivery failed, we need to continue to iterate in
606 this loop so we can deliver the SIGSEGV... */
Kyle McMartin2b163b72007-01-15 00:36:26 -0500607 if (handle_signal(signr, &info, &ka, oldset,
608 regs, in_syscall)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
610 regs->gr[28]);
Kyle McMartin4650f0a2007-01-08 16:28:06 -0500611 if (test_thread_flag(TIF_RESTORE_SIGMASK))
612 clear_thread_flag(TIF_RESTORE_SIGMASK);
613 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 }
615 }
616 /* end of while(1) looping forever if we can't force a signal */
617
618 /* Did we come from a system call? */
Kyle McMartin2b163b72007-01-15 00:36:26 -0500619 if (in_syscall)
620 insert_restart_trampoline(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
622 DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n",
623 regs->gr[28]);
624
Kyle McMartin4650f0a2007-01-08 16:28:06 -0500625 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
626 clear_thread_flag(TIF_RESTORE_SIGMASK);
627 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
628 }
629
630 return;
631}
632
633void do_notify_resume(struct pt_regs *regs, long in_syscall)
634{
635 if (test_thread_flag(TIF_SIGPENDING) ||
636 test_thread_flag(TIF_RESTORE_SIGMASK))
637 do_signal(regs, in_syscall);
David Howellsd0420c82009-09-02 09:14:16 +0100638
639 if (test_thread_flag(TIF_NOTIFY_RESUME)) {
640 clear_thread_flag(TIF_NOTIFY_RESUME);
641 tracehook_notify_resume(regs);
David Howellsee18d642009-09-02 09:14:21 +0100642 if (current->replacement_session_keyring)
643 key_replace_session_keyring();
David Howellsd0420c82009-09-02 09:14:16 +0100644 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645}