blob: 91f8d0826db1084b0abb8c7206431406c9108f23 [file] [log] [blame]
David S. Miller5526b7e2008-04-27 02:26:36 -07001/* arch/sparc64/kernel/signal32.c
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 *
3 * Copyright (C) 1991, 1992 Linus Torvalds
4 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
5 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
6 * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
7 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
8 */
9
10#include <linux/sched.h>
11#include <linux/kernel.h>
12#include <linux/signal.h>
13#include <linux/errno.h>
14#include <linux/wait.h>
15#include <linux/ptrace.h>
16#include <linux/unistd.h>
17#include <linux/mm.h>
18#include <linux/tty.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <linux/binfmts.h>
20#include <linux/compat.h>
21#include <linux/bitops.h>
22
23#include <asm/uaccess.h>
24#include <asm/ptrace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <asm/pgtable.h>
26#include <asm/psrcompat.h>
27#include <asm/fpumacro.h>
28#include <asm/visasm.h>
David S. Miller14cc6ab2006-10-02 14:17:57 -070029#include <asm/compat_signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030
31#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
32
Linus Torvalds1da177e2005-04-16 15:20:36 -070033/* This magic should be in g_upper[0] for all upper parts
34 * to be valid.
35 */
36#define SIGINFO_EXTRA_V8PLUS_MAGIC 0x130e269
37typedef struct {
38 unsigned int g_upper[8];
39 unsigned int o_upper[8];
40 unsigned int asi;
41} siginfo_extra_v8plus_t;
42
David S. Miller5526b7e2008-04-27 02:26:36 -070043struct signal_frame32 {
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 struct sparc_stackf32 ss;
45 __siginfo32_t info;
46 /* __siginfo_fpu32_t * */ u32 fpu_save;
47 unsigned int insns[2];
48 unsigned int extramask[_COMPAT_NSIG_WORDS - 1];
49 unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */
50 /* Only valid if (info.si_regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */
51 siginfo_extra_v8plus_t v8plus;
52 __siginfo_fpu_t fpu_state;
53};
54
55typedef struct compat_siginfo{
56 int si_signo;
57 int si_errno;
58 int si_code;
59
60 union {
61 int _pad[SI_PAD_SIZE32];
62
63 /* kill() */
64 struct {
65 compat_pid_t _pid; /* sender's pid */
66 unsigned int _uid; /* sender's uid */
67 } _kill;
68
69 /* POSIX.1b timers */
70 struct {
Stephen Rothwell0d77e5a2005-06-23 00:10:14 -070071 compat_timer_t _tid; /* timer id */
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 int _overrun; /* overrun count */
73 compat_sigval_t _sigval; /* same as below */
74 int _sys_private; /* not to be passed to user */
75 } _timer;
76
77 /* POSIX.1b signals */
78 struct {
79 compat_pid_t _pid; /* sender's pid */
80 unsigned int _uid; /* sender's uid */
81 compat_sigval_t _sigval;
82 } _rt;
83
84 /* SIGCHLD */
85 struct {
86 compat_pid_t _pid; /* which child */
87 unsigned int _uid; /* sender's uid */
88 int _status; /* exit code */
89 compat_clock_t _utime;
90 compat_clock_t _stime;
91 } _sigchld;
92
93 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
94 struct {
95 u32 _addr; /* faulting insn/memory ref. */
96 int _trapno;
97 } _sigfault;
98
99 /* SIGPOLL */
100 struct {
101 int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
102 int _fd;
103 } _sigpoll;
104 } _sifields;
105}compat_siginfo_t;
106
107struct rt_signal_frame32 {
108 struct sparc_stackf32 ss;
109 compat_siginfo_t info;
110 struct pt_regs32 regs;
111 compat_sigset_t mask;
112 /* __siginfo_fpu32_t * */ u32 fpu_save;
113 unsigned int insns[2];
114 stack_t32 stack;
115 unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */
116 /* Only valid if (regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */
117 siginfo_extra_v8plus_t v8plus;
118 __siginfo_fpu_t fpu_state;
119};
120
121/* Align macros */
David S. Miller5526b7e2008-04-27 02:26:36 -0700122#define SF_ALIGNEDSZ (((sizeof(struct signal_frame32) + 7) & (~7)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 7) & (~7)))
124
125int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
126{
127 int err;
128
129 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
130 return -EFAULT;
131
132 /* If you change siginfo_t structure, please be sure
133 this code is fixed accordingly.
134 It should never copy any pad contained in the structure
135 to avoid security leaks, but must copy the generic
136 3 ints plus the relevant union member.
137 This routine must convert siginfo from 64bit to 32bit as well
138 at the same time. */
139 err = __put_user(from->si_signo, &to->si_signo);
140 err |= __put_user(from->si_errno, &to->si_errno);
141 err |= __put_user((short)from->si_code, &to->si_code);
142 if (from->si_code < 0)
143 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
144 else {
145 switch (from->si_code >> 16) {
146 case __SI_TIMER >> 16:
147 err |= __put_user(from->si_tid, &to->si_tid);
148 err |= __put_user(from->si_overrun, &to->si_overrun);
149 err |= __put_user(from->si_int, &to->si_int);
150 break;
151 case __SI_CHLD >> 16:
152 err |= __put_user(from->si_utime, &to->si_utime);
153 err |= __put_user(from->si_stime, &to->si_stime);
154 err |= __put_user(from->si_status, &to->si_status);
155 default:
156 err |= __put_user(from->si_pid, &to->si_pid);
157 err |= __put_user(from->si_uid, &to->si_uid);
158 break;
159 case __SI_FAULT >> 16:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 err |= __put_user(from->si_trapno, &to->si_trapno);
161 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
162 break;
Jurij Smakov9c7d3b32005-04-17 18:03:12 -0700163 case __SI_POLL >> 16:
164 err |= __put_user(from->si_band, &to->si_band);
165 err |= __put_user(from->si_fd, &to->si_fd);
166 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
168 case __SI_MESGQ >> 16:
169 err |= __put_user(from->si_pid, &to->si_pid);
170 err |= __put_user(from->si_uid, &to->si_uid);
171 err |= __put_user(from->si_int, &to->si_int);
172 break;
173 }
174 }
175 return err;
176}
177
178/* CAUTION: This is just a very minimalist implementation for the
179 * sake of compat_sys_rt_sigqueueinfo()
180 */
181int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
182{
183 if (!access_ok(VERIFY_WRITE, from, sizeof(compat_siginfo_t)))
184 return -EFAULT;
185
186 if (copy_from_user(to, from, 3*sizeof(int)) ||
187 copy_from_user(to->_sifields._pad, from->_sifields._pad,
188 SI_PAD_SIZE))
189 return -EFAULT;
190
191 return 0;
192}
193
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
195{
196 unsigned long *fpregs = current_thread_info()->fpregs;
197 unsigned long fprs;
198 int err;
199
200 err = __get_user(fprs, &fpu->si_fprs);
201 fprs_write(0);
202 regs->tstate &= ~TSTATE_PEF;
203 if (fprs & FPRS_DL)
204 err |= copy_from_user(fpregs, &fpu->si_float_regs[0], (sizeof(unsigned int) * 32));
205 if (fprs & FPRS_DU)
206 err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], (sizeof(unsigned int) * 32));
207 err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
208 err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr);
209 current_thread_info()->fpsaved[0] |= fprs;
210 return err;
211}
212
David S. Miller5526b7e2008-04-27 02:26:36 -0700213void do_sigreturn32(struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214{
David S. Miller5526b7e2008-04-27 02:26:36 -0700215 struct signal_frame32 __user *sf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 unsigned int psr;
217 unsigned pc, npc, fpu_save;
218 sigset_t set;
219 unsigned seta[_COMPAT_NSIG_WORDS];
220 int err, i;
221
David S. Miller5526b7e2008-04-27 02:26:36 -0700222 /* Always make any pending restarted system calls return -EINTR */
223 current_thread_info()->restart_block.fn = do_no_restart_syscall;
224
225 synchronize_user_stack();
226
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
David S. Miller5526b7e2008-04-27 02:26:36 -0700228 sf = (struct signal_frame32 __user *) regs->u_regs[UREG_FP];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229
230 /* 1. Make sure we are not getting garbage from the user */
231 if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
232 (((unsigned long) sf) & 3))
233 goto segv;
234
235 get_user(pc, &sf->info.si_regs.pc);
236 __get_user(npc, &sf->info.si_regs.npc);
237
238 if ((pc | npc) & 3)
239 goto segv;
240
241 if (test_thread_flag(TIF_32BIT)) {
242 pc &= 0xffffffff;
243 npc &= 0xffffffff;
244 }
245 regs->tpc = pc;
246 regs->tnpc = npc;
247
248 /* 2. Restore the state */
249 err = __get_user(regs->y, &sf->info.si_regs.y);
250 err |= __get_user(psr, &sf->info.si_regs.psr);
251
252 for (i = UREG_G1; i <= UREG_I7; i++)
253 err |= __get_user(regs->u_regs[i], &sf->info.si_regs.u_regs[i]);
254 if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) {
255 err |= __get_user(i, &sf->v8plus.g_upper[0]);
256 if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) {
257 unsigned long asi;
258
259 for (i = UREG_G1; i <= UREG_I7; i++)
260 err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
261 err |= __get_user(asi, &sf->v8plus.asi);
262 regs->tstate &= ~TSTATE_ASI;
263 regs->tstate |= ((asi & 0xffUL) << 24UL);
264 }
265 }
266
267 /* User can only change condition codes in %tstate. */
268 regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);
269 regs->tstate |= psr_to_tstate_icc(psr);
270
271 err |= __get_user(fpu_save, &sf->fpu_save);
272 if (fpu_save)
273 err |= restore_fpu_state32(regs, &sf->fpu_state);
274 err |= __get_user(seta[0], &sf->info.si_mask);
275 err |= copy_from_user(seta+1, &sf->extramask,
276 (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int));
277 if (err)
278 goto segv;
279 switch (_NSIG_WORDS) {
280 case 4: set.sig[3] = seta[6] + (((long)seta[7]) << 32);
281 case 3: set.sig[2] = seta[4] + (((long)seta[5]) << 32);
282 case 2: set.sig[1] = seta[2] + (((long)seta[3]) << 32);
283 case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32);
284 }
285 sigdelsetmask(&set, ~_BLOCKABLE);
286 spin_lock_irq(&current->sighand->siglock);
287 current->blocked = set;
288 recalc_sigpending();
289 spin_unlock_irq(&current->sighand->siglock);
290 return;
291
292segv:
293 force_sig(SIGSEGV, current);
294}
295
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
297{
298 struct rt_signal_frame32 __user *sf;
299 unsigned int psr, pc, npc, fpu_save, u_ss_sp;
300 mm_segment_t old_fs;
301 sigset_t set;
302 compat_sigset_t seta;
303 stack_t st;
304 int err, i;
305
306 /* Always make any pending restarted system calls return -EINTR */
307 current_thread_info()->restart_block.fn = do_no_restart_syscall;
308
309 synchronize_user_stack();
310 regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
311 sf = (struct rt_signal_frame32 __user *) regs->u_regs[UREG_FP];
312
313 /* 1. Make sure we are not getting garbage from the user */
314 if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
315 (((unsigned long) sf) & 3))
316 goto segv;
317
318 get_user(pc, &sf->regs.pc);
319 __get_user(npc, &sf->regs.npc);
320
321 if ((pc | npc) & 3)
322 goto segv;
323
324 if (test_thread_flag(TIF_32BIT)) {
325 pc &= 0xffffffff;
326 npc &= 0xffffffff;
327 }
328 regs->tpc = pc;
329 regs->tnpc = npc;
330
331 /* 2. Restore the state */
332 err = __get_user(regs->y, &sf->regs.y);
333 err |= __get_user(psr, &sf->regs.psr);
334
335 for (i = UREG_G1; i <= UREG_I7; i++)
336 err |= __get_user(regs->u_regs[i], &sf->regs.u_regs[i]);
337 if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) {
338 err |= __get_user(i, &sf->v8plus.g_upper[0]);
339 if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) {
340 unsigned long asi;
341
342 for (i = UREG_G1; i <= UREG_I7; i++)
343 err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
344 err |= __get_user(asi, &sf->v8plus.asi);
345 regs->tstate &= ~TSTATE_ASI;
346 regs->tstate |= ((asi & 0xffUL) << 24UL);
347 }
348 }
349
350 /* User can only change condition codes in %tstate. */
351 regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);
352 regs->tstate |= psr_to_tstate_icc(psr);
353
354 err |= __get_user(fpu_save, &sf->fpu_save);
355 if (fpu_save)
356 err |= restore_fpu_state32(regs, &sf->fpu_state);
357 err |= copy_from_user(&seta, &sf->mask, sizeof(compat_sigset_t));
358 err |= __get_user(u_ss_sp, &sf->stack.ss_sp);
359 st.ss_sp = compat_ptr(u_ss_sp);
360 err |= __get_user(st.ss_flags, &sf->stack.ss_flags);
361 err |= __get_user(st.ss_size, &sf->stack.ss_size);
362 if (err)
363 goto segv;
364
365 /* It is more difficult to avoid calling this function than to
366 call it and ignore errors. */
367 old_fs = get_fs();
368 set_fs(KERNEL_DS);
369 do_sigaltstack((stack_t __user *) &st, NULL, (unsigned long)sf);
370 set_fs(old_fs);
371
372 switch (_NSIG_WORDS) {
373 case 4: set.sig[3] = seta.sig[6] + (((long)seta.sig[7]) << 32);
374 case 3: set.sig[2] = seta.sig[4] + (((long)seta.sig[5]) << 32);
375 case 2: set.sig[1] = seta.sig[2] + (((long)seta.sig[3]) << 32);
376 case 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32);
377 }
378 sigdelsetmask(&set, ~_BLOCKABLE);
379 spin_lock_irq(&current->sighand->siglock);
380 current->blocked = set;
381 recalc_sigpending();
382 spin_unlock_irq(&current->sighand->siglock);
383 return;
384segv:
385 force_sig(SIGSEGV, current);
386}
387
388/* Checks if the fp is valid */
389static int invalid_frame_pointer(void __user *fp, int fplen)
390{
391 if ((((unsigned long) fp) & 7) || ((unsigned long)fp) > 0x100000000ULL - fplen)
392 return 1;
393 return 0;
394}
395
396static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize)
397{
398 unsigned long sp;
399
400 regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
401 sp = regs->u_regs[UREG_FP];
402
403 /* This is the X/Open sanctioned signal stack switching. */
404 if (sa->sa_flags & SA_ONSTACK) {
405 if (!on_sig_stack(sp) && !((current->sas_ss_sp + current->sas_ss_size) & 7))
406 sp = current->sas_ss_sp + current->sas_ss_size;
407 }
408 return (void __user *)(sp - framesize);
409}
410
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
412{
413 unsigned long *fpregs = current_thread_info()->fpregs;
414 unsigned long fprs;
415 int err = 0;
416
417 fprs = current_thread_info()->fpsaved[0];
418 if (fprs & FPRS_DL)
419 err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
420 (sizeof(unsigned int) * 32));
421 if (fprs & FPRS_DU)
422 err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
423 (sizeof(unsigned int) * 32));
424 err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
425 err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr);
426 err |= __put_user(fprs, &fpu->si_fprs);
427
428 return err;
429}
430
David S. Miller5526b7e2008-04-27 02:26:36 -0700431static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
432 int signo, sigset_t *oldset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433{
David S. Miller5526b7e2008-04-27 02:26:36 -0700434 struct signal_frame32 __user *sf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 int sigframe_size;
436 u32 psr;
437 int i, err;
438 unsigned int seta[_COMPAT_NSIG_WORDS];
439
440 /* 1. Make sure everything is clean */
441 synchronize_user_stack();
442 save_and_clear_fpu();
443
David S. Miller5526b7e2008-04-27 02:26:36 -0700444 sigframe_size = SF_ALIGNEDSZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 if (!(current_thread_info()->fpsaved[0] & FPRS_FEF))
446 sigframe_size -= sizeof(__siginfo_fpu_t);
447
David S. Miller5526b7e2008-04-27 02:26:36 -0700448 sf = (struct signal_frame32 __user *)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 get_sigframe(&ka->sa, regs, sigframe_size);
450
451 if (invalid_frame_pointer(sf, sigframe_size))
452 goto sigill;
453
454 if (get_thread_wsaved() != 0)
455 goto sigill;
456
457 /* 2. Save the current process state */
458 if (test_thread_flag(TIF_32BIT)) {
459 regs->tpc &= 0xffffffff;
460 regs->tnpc &= 0xffffffff;
461 }
462 err = put_user(regs->tpc, &sf->info.si_regs.pc);
463 err |= __put_user(regs->tnpc, &sf->info.si_regs.npc);
464 err |= __put_user(regs->y, &sf->info.si_regs.y);
465 psr = tstate_to_psr(regs->tstate);
466 if (current_thread_info()->fpsaved[0] & FPRS_FEF)
467 psr |= PSR_EF;
468 err |= __put_user(psr, &sf->info.si_regs.psr);
469 for (i = 0; i < 16; i++)
470 err |= __put_user(regs->u_regs[i], &sf->info.si_regs.u_regs[i]);
471 err |= __put_user(sizeof(siginfo_extra_v8plus_t), &sf->extra_size);
472 err |= __put_user(SIGINFO_EXTRA_V8PLUS_MAGIC, &sf->v8plus.g_upper[0]);
473 for (i = 1; i < 16; i++)
474 err |= __put_user(((u32 *)regs->u_regs)[2*i],
475 &sf->v8plus.g_upper[i]);
476 err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL,
477 &sf->v8plus.asi);
478
479 if (psr & PSR_EF) {
480 err |= save_fpu_state32(regs, &sf->fpu_state);
481 err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save);
482 } else {
483 err |= __put_user(0, &sf->fpu_save);
484 }
485
486 switch (_NSIG_WORDS) {
487 case 4: seta[7] = (oldset->sig[3] >> 32);
488 seta[6] = oldset->sig[3];
489 case 3: seta[5] = (oldset->sig[2] >> 32);
490 seta[4] = oldset->sig[2];
491 case 2: seta[3] = (oldset->sig[1] >> 32);
492 seta[2] = oldset->sig[1];
493 case 1: seta[1] = (oldset->sig[0] >> 32);
494 seta[0] = oldset->sig[0];
495 }
496 err |= __put_user(seta[0], &sf->info.si_mask);
497 err |= __copy_to_user(sf->extramask, seta + 1,
498 (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int));
499
500 err |= copy_in_user((u32 __user *)sf,
501 (u32 __user *)(regs->u_regs[UREG_FP]),
502 sizeof(struct reg_window32));
503
504 if (err)
505 goto sigsegv;
506
507 /* 3. signal handler back-trampoline and parameters */
508 regs->u_regs[UREG_FP] = (unsigned long) sf;
509 regs->u_regs[UREG_I0] = signo;
510 regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
511 regs->u_regs[UREG_I2] = (unsigned long) &sf->info;
512
513 /* 4. signal handler */
514 regs->tpc = (unsigned long) ka->sa.sa_handler;
515 regs->tnpc = (regs->tpc + 4);
516 if (test_thread_flag(TIF_32BIT)) {
517 regs->tpc &= 0xffffffff;
518 regs->tnpc &= 0xffffffff;
519 }
520
521 /* 5. return to kernel instructions */
522 if (ka->ka_restorer) {
523 regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
524 } else {
525 /* Flush instruction space. */
526 unsigned long address = ((unsigned long)&(sf->insns[0]));
527 pgd_t *pgdp = pgd_offset(current->mm, address);
528 pud_t *pudp = pud_offset(pgdp, address);
529 pmd_t *pmdp = pmd_offset(pudp, address);
530 pte_t *ptep;
Hugh Dickinsb8ae4862005-11-07 14:08:46 -0800531 pte_t pte;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532
533 regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
534
535 err = __put_user(0x821020d8, &sf->insns[0]); /*mov __NR_sigreturn, %g1*/
536 err |= __put_user(0x91d02010, &sf->insns[1]); /*t 0x10*/
537 if (err)
538 goto sigsegv;
539
540 preempt_disable();
541 ptep = pte_offset_map(pmdp, address);
Hugh Dickinsb8ae4862005-11-07 14:08:46 -0800542 pte = *ptep;
543 if (pte_present(pte)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 unsigned long page = (unsigned long)
Hugh Dickinsb8ae4862005-11-07 14:08:46 -0800545 page_address(pte_page(pte));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546
David S. Miller4f071182005-08-29 12:46:22 -0700547 wmb();
548 __asm__ __volatile__("flush %0 + %1"
549 : /* no outputs */
550 : "r" (page),
551 "r" (address & (PAGE_SIZE - 1))
552 : "memory");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 }
554 pte_unmap(ptep);
555 preempt_enable();
556 }
557 return;
558
559sigill:
560 do_exit(SIGILL);
561sigsegv:
562 force_sigsegv(signo, current);
563}
564
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
566 unsigned long signr, sigset_t *oldset,
567 siginfo_t *info)
568{
569 struct rt_signal_frame32 __user *sf;
570 int sigframe_size;
571 u32 psr;
572 int i, err;
573 compat_sigset_t seta;
574
575 /* 1. Make sure everything is clean */
576 synchronize_user_stack();
577 save_and_clear_fpu();
578
579 sigframe_size = RT_ALIGNEDSZ;
580 if (!(current_thread_info()->fpsaved[0] & FPRS_FEF))
581 sigframe_size -= sizeof(__siginfo_fpu_t);
582
583 sf = (struct rt_signal_frame32 __user *)
584 get_sigframe(&ka->sa, regs, sigframe_size);
585
586 if (invalid_frame_pointer(sf, sigframe_size))
587 goto sigill;
588
589 if (get_thread_wsaved() != 0)
590 goto sigill;
591
592 /* 2. Save the current process state */
593 if (test_thread_flag(TIF_32BIT)) {
594 regs->tpc &= 0xffffffff;
595 regs->tnpc &= 0xffffffff;
596 }
597 err = put_user(regs->tpc, &sf->regs.pc);
598 err |= __put_user(regs->tnpc, &sf->regs.npc);
599 err |= __put_user(regs->y, &sf->regs.y);
600 psr = tstate_to_psr(regs->tstate);
601 if (current_thread_info()->fpsaved[0] & FPRS_FEF)
602 psr |= PSR_EF;
603 err |= __put_user(psr, &sf->regs.psr);
604 for (i = 0; i < 16; i++)
605 err |= __put_user(regs->u_regs[i], &sf->regs.u_regs[i]);
606 err |= __put_user(sizeof(siginfo_extra_v8plus_t), &sf->extra_size);
607 err |= __put_user(SIGINFO_EXTRA_V8PLUS_MAGIC, &sf->v8plus.g_upper[0]);
608 for (i = 1; i < 16; i++)
609 err |= __put_user(((u32 *)regs->u_regs)[2*i],
610 &sf->v8plus.g_upper[i]);
611 err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL,
612 &sf->v8plus.asi);
613
614 if (psr & PSR_EF) {
615 err |= save_fpu_state32(regs, &sf->fpu_state);
616 err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save);
617 } else {
618 err |= __put_user(0, &sf->fpu_save);
619 }
620
621 /* Update the siginfo structure. */
622 err |= copy_siginfo_to_user32(&sf->info, info);
623
624 /* Setup sigaltstack */
625 err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
626 err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
627 err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);
628
629 switch (_NSIG_WORDS) {
630 case 4: seta.sig[7] = (oldset->sig[3] >> 32);
631 seta.sig[6] = oldset->sig[3];
632 case 3: seta.sig[5] = (oldset->sig[2] >> 32);
633 seta.sig[4] = oldset->sig[2];
634 case 2: seta.sig[3] = (oldset->sig[1] >> 32);
635 seta.sig[2] = oldset->sig[1];
636 case 1: seta.sig[1] = (oldset->sig[0] >> 32);
637 seta.sig[0] = oldset->sig[0];
638 }
639 err |= __copy_to_user(&sf->mask, &seta, sizeof(compat_sigset_t));
640
641 err |= copy_in_user((u32 __user *)sf,
642 (u32 __user *)(regs->u_regs[UREG_FP]),
643 sizeof(struct reg_window32));
644 if (err)
645 goto sigsegv;
646
647 /* 3. signal handler back-trampoline and parameters */
648 regs->u_regs[UREG_FP] = (unsigned long) sf;
649 regs->u_regs[UREG_I0] = signr;
650 regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
651 regs->u_regs[UREG_I2] = (unsigned long) &sf->regs;
652
653 /* 4. signal handler */
654 regs->tpc = (unsigned long) ka->sa.sa_handler;
655 regs->tnpc = (regs->tpc + 4);
656 if (test_thread_flag(TIF_32BIT)) {
657 regs->tpc &= 0xffffffff;
658 regs->tnpc &= 0xffffffff;
659 }
660
661 /* 5. return to kernel instructions */
662 if (ka->ka_restorer)
663 regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
664 else {
665 /* Flush instruction space. */
666 unsigned long address = ((unsigned long)&(sf->insns[0]));
667 pgd_t *pgdp = pgd_offset(current->mm, address);
668 pud_t *pudp = pud_offset(pgdp, address);
669 pmd_t *pmdp = pmd_offset(pudp, address);
670 pte_t *ptep;
671
672 regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
673
674 /* mov __NR_rt_sigreturn, %g1 */
675 err |= __put_user(0x82102065, &sf->insns[0]);
676
677 /* t 0x10 */
678 err |= __put_user(0x91d02010, &sf->insns[1]);
679 if (err)
680 goto sigsegv;
681
682 preempt_disable();
683 ptep = pte_offset_map(pmdp, address);
684 if (pte_present(*ptep)) {
685 unsigned long page = (unsigned long)
686 page_address(pte_page(*ptep));
687
David S. Miller4f071182005-08-29 12:46:22 -0700688 wmb();
689 __asm__ __volatile__("flush %0 + %1"
690 : /* no outputs */
691 : "r" (page),
692 "r" (address & (PAGE_SIZE - 1))
693 : "memory");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 }
695 pte_unmap(ptep);
696 preempt_enable();
697 }
698 return;
699
700sigill:
701 do_exit(SIGILL);
702sigsegv:
703 force_sigsegv(signr, current);
704}
705
706static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
707 siginfo_t *info,
David S. Millerec98c6b2008-04-20 02:14:23 -0700708 sigset_t *oldset, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709{
David S. Millerec98c6b2008-04-20 02:14:23 -0700710 if (ka->sa.sa_flags & SA_SIGINFO)
711 setup_rt_frame32(ka, regs, signr, oldset, info);
David S. Millerec98c6b2008-04-20 02:14:23 -0700712 else
David S. Miller5526b7e2008-04-27 02:26:36 -0700713 setup_frame32(ka, regs, signr, oldset);
714
Steven Rostedt69be8f12005-08-29 11:44:09 -0400715 spin_lock_irq(&current->sighand->siglock);
716 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
717 if (!(ka->sa.sa_flags & SA_NOMASK))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 sigaddset(&current->blocked,signr);
Steven Rostedt69be8f12005-08-29 11:44:09 -0400719 recalc_sigpending();
720 spin_unlock_irq(&current->sighand->siglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721}
722
723static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs,
724 struct sigaction *sa)
725{
726 switch (regs->u_regs[UREG_I0]) {
727 case ERESTART_RESTARTBLOCK:
728 case ERESTARTNOHAND:
729 no_system_call_restart:
730 regs->u_regs[UREG_I0] = EINTR;
731 regs->tstate |= TSTATE_ICARRY;
732 break;
733 case ERESTARTSYS:
734 if (!(sa->sa_flags & SA_RESTART))
735 goto no_system_call_restart;
736 /* fallthrough */
737 case ERESTARTNOINTR:
738 regs->u_regs[UREG_I0] = orig_i0;
739 regs->tpc -= 4;
740 regs->tnpc -= 4;
741 }
742}
743
744/* Note that 'init' is a special process: it doesn't get signals it doesn't
745 * want to handle. Thus you cannot kill init even with a SIGKILL even by
746 * mistake.
747 */
David S. Miller2d7d5f02006-01-19 02:42:49 -0800748void do_signal32(sigset_t *oldset, struct pt_regs * regs,
David S. Miller238468b2008-04-24 03:01:48 -0700749 struct signal_deliver_cookie *cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 struct k_sigaction ka;
David S. Miller238468b2008-04-24 03:01:48 -0700752 siginfo_t info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 int signr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
David S. Miller238468b2008-04-24 03:01:48 -0700755 signr = get_signal_to_deliver(&info, &ka, regs, cookie);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 if (signr > 0) {
David S. Miller238468b2008-04-24 03:01:48 -0700757 if (cookie->restart_syscall)
758 syscall_restart32(cookie->orig_i0, regs, &ka.sa);
David S. Millerec98c6b2008-04-20 02:14:23 -0700759 handle_signal32(signr, &ka, &info, oldset, regs);
David S. Miller2d7d5f02006-01-19 02:42:49 -0800760
761 /* a signal was successfully delivered; the saved
762 * sigmask will have been stored in the signal frame,
763 * and will be restored by sigreturn, so we can simply
764 * clear the TIF_RESTORE_SIGMASK flag.
765 */
766 if (test_thread_flag(TIF_RESTORE_SIGMASK))
767 clear_thread_flag(TIF_RESTORE_SIGMASK);
768 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 }
David S. Miller238468b2008-04-24 03:01:48 -0700770 if (cookie->restart_syscall &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
772 regs->u_regs[UREG_I0] == ERESTARTSYS ||
773 regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
774 /* replay the system call when we are done */
David S. Miller238468b2008-04-24 03:01:48 -0700775 regs->u_regs[UREG_I0] = cookie->orig_i0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 regs->tpc -= 4;
777 regs->tnpc -= 4;
778 }
David S. Miller238468b2008-04-24 03:01:48 -0700779 if (cookie->restart_syscall &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
781 regs->u_regs[UREG_G1] = __NR_restart_syscall;
782 regs->tpc -= 4;
783 regs->tnpc -= 4;
784 }
David S. Miller2d7d5f02006-01-19 02:42:49 -0800785
786 /* if there's no signal to deliver, we just put the saved sigmask
787 * back
788 */
789 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
790 clear_thread_flag(TIF_RESTORE_SIGMASK);
791 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
792 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793}
794
795struct sigstack32 {
796 u32 the_stack;
797 int cur_status;
798};
799
800asmlinkage int do_sys32_sigstack(u32 u_ssptr, u32 u_ossptr, unsigned long sp)
801{
802 struct sigstack32 __user *ssptr =
803 (struct sigstack32 __user *)((unsigned long)(u_ssptr));
804 struct sigstack32 __user *ossptr =
805 (struct sigstack32 __user *)((unsigned long)(u_ossptr));
806 int ret = -EFAULT;
807
808 /* First see if old state is wanted. */
809 if (ossptr) {
810 if (put_user(current->sas_ss_sp + current->sas_ss_size,
811 &ossptr->the_stack) ||
812 __put_user(on_sig_stack(sp), &ossptr->cur_status))
813 goto out;
814 }
815
816 /* Now see if we want to update the new state. */
817 if (ssptr) {
818 u32 ss_sp;
819
820 if (get_user(ss_sp, &ssptr->the_stack))
821 goto out;
822
823 /* If the current stack was set with sigaltstack, don't
824 * swap stacks while we are on it.
825 */
826 ret = -EPERM;
827 if (current->sas_ss_sp && on_sig_stack(sp))
828 goto out;
829
830 /* Since we don't know the extent of the stack, and we don't
831 * track onstack-ness, but rather calculate it, we must
832 * presume a size. Ho hum this interface is lossy.
833 */
834 current->sas_ss_sp = (unsigned long)ss_sp - SIGSTKSZ;
835 current->sas_ss_size = SIGSTKSZ;
836 }
837
838 ret = 0;
839out:
840 return ret;
841}
842
843asmlinkage long do_sys32_sigaltstack(u32 ussa, u32 uossa, unsigned long sp)
844{
845 stack_t uss, uoss;
846 u32 u_ss_sp = 0;
847 int ret;
848 mm_segment_t old_fs;
849 stack_t32 __user *uss32 = compat_ptr(ussa);
850 stack_t32 __user *uoss32 = compat_ptr(uossa);
851
852 if (ussa && (get_user(u_ss_sp, &uss32->ss_sp) ||
853 __get_user(uss.ss_flags, &uss32->ss_flags) ||
854 __get_user(uss.ss_size, &uss32->ss_size)))
855 return -EFAULT;
856 uss.ss_sp = compat_ptr(u_ss_sp);
857 old_fs = get_fs();
858 set_fs(KERNEL_DS);
859 ret = do_sigaltstack(ussa ? (stack_t __user *) &uss : NULL,
860 uossa ? (stack_t __user *) &uoss : NULL, sp);
861 set_fs(old_fs);
862 if (!ret && uossa && (put_user(ptr_to_compat(uoss.ss_sp), &uoss32->ss_sp) ||
863 __put_user(uoss.ss_flags, &uoss32->ss_flags) ||
864 __put_user(uoss.ss_size, &uoss32->ss_size)))
865 return -EFAULT;
866 return ret;
867}