blob: 6de049fbe62dced08c1deddb4330077d3d4158ae [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Heiko Carstensa53c8fa2012-07-20 11:15:04 +02002 * Copyright IBM Corp. 2000, 2006
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
4 * Gerhard Tonn (ton@de.ibm.com)
5 *
6 * Copyright (C) 1991, 1992 Linus Torvalds
7 *
8 * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
9 */
10
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <linux/compat.h>
12#include <linux/sched.h>
13#include <linux/mm.h>
14#include <linux/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#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/binfmts.h>
25#include <asm/ucontext.h>
26#include <asm/uaccess.h>
27#include <asm/lowcore.h>
David Howellsa0616cd2012-03-28 18:30:02 +010028#include <asm/switch_to.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include "compat_linux.h"
30#include "compat_ptrace.h"
Heiko Carstensa8061702008-04-17 07:46:26 +020031#include "entry.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070032
Linus Torvalds1da177e2005-04-16 15:20:36 -070033typedef struct
34{
35 __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
36 struct sigcontext32 sc;
37 _sigregs32 sregs;
38 int signo;
Heiko Carstensea2a4d32009-10-06 10:34:13 +020039 __u32 gprs_high[NUM_GPRS];
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 __u8 retcode[S390_SYSCALL_SIZE];
41} sigframe32;
42
43typedef struct
44{
45 __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
46 __u8 retcode[S390_SYSCALL_SIZE];
47 compat_siginfo_t info;
48 struct ucontext32 uc;
Heiko Carstensea2a4d32009-10-06 10:34:13 +020049 __u32 gprs_high[NUM_GPRS];
Linus Torvalds1da177e2005-04-16 15:20:36 -070050} rt_sigframe32;
51
Linus Torvalds1da177e2005-04-16 15:20:36 -070052int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
53{
54 int err;
55
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 /* If you change siginfo_t structure, please be sure
57 this code is fixed accordingly.
58 It should never copy any pad contained in the structure
59 to avoid security leaks, but must copy the generic
60 3 ints plus the relevant union member.
61 This routine must convert siginfo from 64bit to 32bit as well
62 at the same time. */
63 err = __put_user(from->si_signo, &to->si_signo);
64 err |= __put_user(from->si_errno, &to->si_errno);
65 err |= __put_user((short)from->si_code, &to->si_code);
66 if (from->si_code < 0)
67 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
68 else {
69 switch (from->si_code >> 16) {
70 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
71 case __SI_MESGQ >> 16:
72 err |= __put_user(from->si_int, &to->si_int);
73 /* fallthrough */
74 case __SI_KILL >> 16:
75 err |= __put_user(from->si_pid, &to->si_pid);
76 err |= __put_user(from->si_uid, &to->si_uid);
77 break;
78 case __SI_CHLD >> 16:
79 err |= __put_user(from->si_pid, &to->si_pid);
80 err |= __put_user(from->si_uid, &to->si_uid);
81 err |= __put_user(from->si_utime, &to->si_utime);
82 err |= __put_user(from->si_stime, &to->si_stime);
83 err |= __put_user(from->si_status, &to->si_status);
84 break;
85 case __SI_FAULT >> 16:
86 err |= __put_user((unsigned long) from->si_addr,
87 &to->si_addr);
88 break;
89 case __SI_POLL >> 16:
90 err |= __put_user(from->si_band, &to->si_band);
91 err |= __put_user(from->si_fd, &to->si_fd);
92 break;
93 case __SI_TIMER >> 16:
94 err |= __put_user(from->si_tid, &to->si_tid);
95 err |= __put_user(from->si_overrun, &to->si_overrun);
96 err |= __put_user(from->si_int, &to->si_int);
97 break;
98 default:
99 break;
100 }
101 }
102 return err;
103}
104
105int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
106{
107 int err;
108 u32 tmp;
109
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 err = __get_user(to->si_signo, &from->si_signo);
111 err |= __get_user(to->si_errno, &from->si_errno);
112 err |= __get_user(to->si_code, &from->si_code);
113
114 if (to->si_code < 0)
115 err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
116 else {
117 switch (to->si_code >> 16) {
118 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
119 case __SI_MESGQ >> 16:
120 err |= __get_user(to->si_int, &from->si_int);
121 /* fallthrough */
122 case __SI_KILL >> 16:
123 err |= __get_user(to->si_pid, &from->si_pid);
124 err |= __get_user(to->si_uid, &from->si_uid);
125 break;
126 case __SI_CHLD >> 16:
127 err |= __get_user(to->si_pid, &from->si_pid);
128 err |= __get_user(to->si_uid, &from->si_uid);
129 err |= __get_user(to->si_utime, &from->si_utime);
130 err |= __get_user(to->si_stime, &from->si_stime);
131 err |= __get_user(to->si_status, &from->si_status);
132 break;
133 case __SI_FAULT >> 16:
134 err |= __get_user(tmp, &from->si_addr);
Martin Schwidefsky3c52e492011-10-30 15:17:15 +0100135 to->si_addr = (void __force __user *)
136 (u64) (tmp & PSW32_ADDR_INSN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 break;
138 case __SI_POLL >> 16:
139 err |= __get_user(to->si_band, &from->si_band);
140 err |= __get_user(to->si_fd, &from->si_fd);
141 break;
142 case __SI_TIMER >> 16:
143 err |= __get_user(to->si_tid, &from->si_tid);
144 err |= __get_user(to->si_overrun, &from->si_overrun);
145 err |= __get_user(to->si_int, &from->si_int);
146 break;
147 default:
148 break;
149 }
150 }
151 return err;
152}
153
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
155{
156 _s390_regs_common32 regs32;
157 int err, i;
158
Martin Schwidefskyb50511e2011-10-30 15:16:50 +0100159 regs32.psw.mask = psw32_user_bits |
160 ((__u32)(regs->psw.mask >> 32) & PSW32_MASK_USER);
Martin Schwidefskyd4e81b32011-10-30 15:16:51 +0100161 regs32.psw.addr = (__u32) regs->psw.addr |
162 (__u32)(regs->psw.mask & PSW_MASK_BA);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 for (i = 0; i < NUM_GPRS; i++)
164 regs32.gprs[i] = (__u32) regs->gprs[i];
165 save_access_regs(current->thread.acrs);
166 memcpy(regs32.acrs, current->thread.acrs, sizeof(regs32.acrs));
167 err = __copy_to_user(&sregs->regs, &regs32, sizeof(regs32));
168 if (err)
169 return err;
170 save_fp_regs(&current->thread.fp_regs);
171 /* s390_fp_regs and _s390_fp_regs32 are the same ! */
172 return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
173 sizeof(_s390_fp_regs32));
174}
175
176static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
177{
178 _s390_regs_common32 regs32;
179 int err, i;
180
181 /* Alwys make any pending restarted system call return -EINTR */
182 current_thread_info()->restart_block.fn = do_no_restart_syscall;
183
184 err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
185 if (err)
186 return err;
Martin Schwidefskyb50511e2011-10-30 15:16:50 +0100187 regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
Martin Schwidefskyd4e81b32011-10-30 15:16:51 +0100188 (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
189 (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
Martin Schwidefskyfa968ee2012-11-07 10:44:08 +0100190 /* Check for invalid user address space control. */
191 if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
192 regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
193 (regs->psw.mask & ~PSW_MASK_ASC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
195 for (i = 0; i < NUM_GPRS; i++)
196 regs->gprs[i] = (__u64) regs32.gprs[i];
197 memcpy(current->thread.acrs, regs32.acrs, sizeof(current->thread.acrs));
198 restore_access_regs(current->thread.acrs);
199
200 err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
201 sizeof(_s390_fp_regs32));
202 current->thread.fp_regs.fpc &= FPC_VALID_MASK;
203 if (err)
204 return err;
205
206 restore_fp_regs(&current->thread.fp_regs);
Martin Schwidefskyb6ef5bb2011-10-30 15:16:49 +0100207 clear_thread_flag(TIF_SYSCALL); /* No longer in a system call */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 return 0;
209}
210
Heiko Carstensea2a4d32009-10-06 10:34:13 +0200211static int save_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
212{
213 __u32 gprs_high[NUM_GPRS];
214 int i;
215
216 for (i = 0; i < NUM_GPRS; i++)
217 gprs_high[i] = regs->gprs[i] >> 32;
218
219 return __copy_to_user(uregs, &gprs_high, sizeof(gprs_high));
220}
221
222static int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
223{
224 __u32 gprs_high[NUM_GPRS];
225 int err, i;
226
227 err = __copy_from_user(&gprs_high, uregs, sizeof(gprs_high));
228 if (err)
229 return err;
230 for (i = 0; i < NUM_GPRS; i++)
231 *(__u32 *)&regs->gprs[i] = gprs_high[i];
232 return 0;
233}
234
Martin Schwidefsky03ff9a22007-04-27 16:01:40 +0200235asmlinkage long sys32_sigreturn(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236{
Martin Schwidefsky03ff9a22007-04-27 16:01:40 +0200237 struct pt_regs *regs = task_pt_regs(current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15];
239 sigset_t set;
240
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
242 goto badframe;
Heiko Carstens391c62f2011-08-03 16:44:26 +0200243 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 if (restore_sigregs32(regs, &frame->sregs))
245 goto badframe;
Heiko Carstensea2a4d32009-10-06 10:34:13 +0200246 if (restore_sigregs_gprs_high(regs, frame->gprs_high))
247 goto badframe;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 return regs->gprs[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249badframe:
250 force_sig(SIGSEGV, current);
251 return 0;
252}
253
Martin Schwidefsky03ff9a22007-04-27 16:01:40 +0200254asmlinkage long sys32_rt_sigreturn(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255{
Martin Schwidefsky03ff9a22007-04-27 16:01:40 +0200256 struct pt_regs *regs = task_pt_regs(current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15];
258 sigset_t set;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
261 goto badframe;
Heiko Carstens391c62f2011-08-03 16:44:26 +0200262 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
264 goto badframe;
Heiko Carstensea2a4d32009-10-06 10:34:13 +0200265 if (restore_sigregs_gprs_high(regs, frame->gprs_high))
266 goto badframe;
Al Viroe2141252012-12-23 03:36:41 -0500267 if (compat_restore_altstack(&frame->uc.uc_stack))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 goto badframe;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 return regs->gprs[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270badframe:
Martin Schwidefsky03ff9a22007-04-27 16:01:40 +0200271 force_sig(SIGSEGV, current);
272 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273}
274
275/*
276 * Set up a signal frame.
277 */
278
279
280/*
281 * Determine which stack to use..
282 */
283static inline void __user *
284get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
285{
286 unsigned long sp;
287
288 /* Default to using normal stack */
289 sp = (unsigned long) A(regs->gprs[15]);
290
Heiko Carstensde553432008-04-17 07:45:57 +0200291 /* Overflow on alternate signal stack gives SIGSEGV. */
292 if (on_sig_stack(sp) && !on_sig_stack((sp - frame_size) & -8UL))
293 return (void __user *) -1UL;
294
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 /* This is the X/Open sanctioned signal stack switching. */
296 if (ka->sa.sa_flags & SA_ONSTACK) {
Laurent Meyer28f22372006-04-27 18:40:07 -0700297 if (! sas_ss_flags(sp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 sp = current->sas_ss_sp + current->sas_ss_size;
299 }
300
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 return (void __user *)((sp - frame_size) & -8ul);
302}
303
304static inline int map_signal(int sig)
305{
306 if (current_thread_info()->exec_domain
307 && current_thread_info()->exec_domain->signal_invmap
308 && sig < 32)
309 return current_thread_info()->exec_domain->signal_invmap[sig];
310 else
311 return sig;
312}
313
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800314static int setup_frame32(int sig, struct k_sigaction *ka,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 sigset_t *set, struct pt_regs * regs)
316{
317 sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318
Heiko Carstensde553432008-04-17 07:45:57 +0200319 if (frame == (void __user *) -1UL)
320 goto give_sigsegv;
321
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
323 goto give_sigsegv;
324
325 if (save_sigregs32(regs, &frame->sregs))
326 goto give_sigsegv;
Heiko Carstensea2a4d32009-10-06 10:34:13 +0200327 if (save_sigregs_gprs_high(regs, frame->gprs_high))
328 goto give_sigsegv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
330 goto give_sigsegv;
331
332 /* Set up to return from userspace. If provided, use a stub
333 already in userspace. */
334 if (ka->sa.sa_flags & SA_RESTORER) {
Martin Schwidefskyd4e81b32011-10-30 15:16:51 +0100335 regs->gprs[14] = (__u64) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 } else {
Martin Schwidefskyd4e81b32011-10-30 15:16:51 +0100337 regs->gprs[14] = (__u64) frame->retcode | PSW32_ADDR_AMODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
Martin Schwidefsky3c52e492011-10-30 15:17:15 +0100339 (u16 __force __user *)(frame->retcode)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 goto give_sigsegv;
341 }
342
343 /* Set up backchain. */
344 if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
345 goto give_sigsegv;
346
347 /* Set up registers for signal handler */
Martin Schwidefsky3c52e492011-10-30 15:17:15 +0100348 regs->gprs[15] = (__force __u64) frame;
Martin Schwidefskyfa968ee2012-11-07 10:44:08 +0100349 /* Force 31 bit amode and default user address space control. */
350 regs->psw.mask = PSW_MASK_BA |
351 (psw_user_bits & PSW_MASK_ASC) |
352 (regs->psw.mask & ~PSW_MASK_ASC);
Martin Schwidefsky3c52e492011-10-30 15:17:15 +0100353 regs->psw.addr = (__force __u64) ka->sa.sa_handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354
355 regs->gprs[2] = map_signal(sig);
Martin Schwidefsky3c52e492011-10-30 15:17:15 +0100356 regs->gprs[3] = (__force __u64) &frame->sc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
358 /* We forgot to include these in the sigcontext.
359 To avoid breaking binary compatibility, they are passed as args. */
Martin Schwidefskyaa33c8c2011-12-27 11:27:18 +0100360 if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
361 sig == SIGTRAP || sig == SIGFPE) {
362 /* set extra registers only for synchronous signals */
363 regs->gprs[4] = regs->int_code & 127;
364 regs->gprs[5] = regs->int_parm_long;
365 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
367 /* Place signal number on stack to allow backtrace from handler. */
Martin Schwidefsky3c52e492011-10-30 15:17:15 +0100368 if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 goto give_sigsegv;
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800370 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371
372give_sigsegv:
373 force_sigsegv(sig, current);
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800374 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375}
376
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800377static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 sigset_t *set, struct pt_regs * regs)
379{
380 int err = 0;
381 rt_sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
Heiko Carstensde553432008-04-17 07:45:57 +0200383 if (frame == (void __user *) -1UL)
384 goto give_sigsegv;
385
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 if (copy_siginfo_to_user32(&frame->info, info))
387 goto give_sigsegv;
388
389 /* Create the ucontext. */
Heiko Carstensea2a4d32009-10-06 10:34:13 +0200390 err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 err |= __put_user(0, &frame->uc.uc_link);
Al Viroe2141252012-12-23 03:36:41 -0500392 err |= __compat_save_altstack(&frame->uc.uc_stack, regs->gprs[15]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
Heiko Carstensea2a4d32009-10-06 10:34:13 +0200394 err |= save_sigregs_gprs_high(regs, frame->gprs_high);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
396 if (err)
397 goto give_sigsegv;
398
399 /* Set up to return from userspace. If provided, use a stub
400 already in userspace. */
401 if (ka->sa.sa_flags & SA_RESTORER) {
Martin Schwidefsky207a0542011-12-27 11:27:30 +0100402 regs->gprs[14] = (__u64) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 } else {
Martin Schwidefsky207a0542011-12-27 11:27:30 +0100404 regs->gprs[14] = (__u64) frame->retcode | PSW32_ADDR_AMODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
Martin Schwidefsky3c52e492011-10-30 15:17:15 +0100406 (u16 __force __user *)(frame->retcode));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 }
408
409 /* Set up backchain. */
Martin Schwidefsky3c52e492011-10-30 15:17:15 +0100410 if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 goto give_sigsegv;
412
413 /* Set up registers for signal handler */
Martin Schwidefsky3c52e492011-10-30 15:17:15 +0100414 regs->gprs[15] = (__force __u64) frame;
Martin Schwidefskyfa968ee2012-11-07 10:44:08 +0100415 /* Force 31 bit amode and default user address space control. */
416 regs->psw.mask = PSW_MASK_BA |
417 (psw_user_bits & PSW_MASK_ASC) |
418 (regs->psw.mask & ~PSW_MASK_ASC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 regs->psw.addr = (__u64) ka->sa.sa_handler;
420
421 regs->gprs[2] = map_signal(sig);
Martin Schwidefsky3c52e492011-10-30 15:17:15 +0100422 regs->gprs[3] = (__force __u64) &frame->info;
423 regs->gprs[4] = (__force __u64) &frame->uc;
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800424 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
426give_sigsegv:
427 force_sigsegv(sig, current);
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800428 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429}
430
431/*
432 * OK, we're invoking a handler
433 */
434
Al Viroa610d6e2012-05-21 23:42:15 -0400435void handle_signal32(unsigned long sig, struct k_sigaction *ka,
Heiko Carstens391c62f2011-08-03 16:44:26 +0200436 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437{
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800438 int ret;
439
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 /* Set up the stack frame */
441 if (ka->sa.sa_flags & SA_SIGINFO)
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800442 ret = setup_rt_frame32(sig, ka, info, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 else
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800444 ret = setup_frame32(sig, ka, oldset, regs);
Heiko Carstens391c62f2011-08-03 16:44:26 +0200445 if (ret)
Al Viroa610d6e2012-05-21 23:42:15 -0400446 return;
Al Viroefee9842012-04-28 02:04:15 -0400447 signal_delivered(sig, info, ka, regs,
Al Viroa610d6e2012-05-21 23:42:15 -0400448 test_thread_flag(TIF_SINGLE_STEP));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449}
450