]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blame - arch/x86/ia32/ia32_signal.c
Merge branches 'release', 'ejd', 'sony' and 'wmi' into release
[mirror_ubuntu-kernels.git] / arch / x86 / ia32 / ia32_signal.c
CommitLineData
1da177e4
LT
1/*
2 * linux/arch/x86_64/ia32/ia32_signal.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 *
6 * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
7 * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes
8 * 2000-12-* x86-64 compatibility mode signal handling by Andi Kleen
1da177e4
LT
9 */
10
11#include <linux/sched.h>
12#include <linux/mm.h>
13#include <linux/smp.h>
1da177e4
LT
14#include <linux/kernel.h>
15#include <linux/signal.h>
16#include <linux/errno.h>
17#include <linux/wait.h>
18#include <linux/ptrace.h>
19#include <linux/unistd.h>
20#include <linux/stddef.h>
21#include <linux/personality.h>
22#include <linux/compat.h>
9fbbd4dd 23#include <linux/binfmts.h>
1da177e4
LT
24#include <asm/ucontext.h>
25#include <asm/uaccess.h>
26#include <asm/i387.h>
27#include <asm/ia32.h>
28#include <asm/ptrace.h>
29#include <asm/ia32_unistd.h>
30#include <asm/user32.h>
31#include <asm/sigcontext32.h>
1da177e4 32#include <asm/proto.h>
af65d648 33#include <asm/vdso.h>
1da177e4
LT
34
35#define DEBUG_SIG 0
36
37#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
38
39asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
40void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
41
42int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
43{
44 int err;
99b9cdf7
TG
45
46 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
1da177e4
LT
47 return -EFAULT;
48
49 /* If you change siginfo_t structure, please make sure that
50 this code is fixed accordingly.
51 It should never copy any pad contained in the structure
52 to avoid security leaks, but must copy the generic
53 3 ints plus the relevant union member. */
54 err = __put_user(from->si_signo, &to->si_signo);
55 err |= __put_user(from->si_errno, &to->si_errno);
99b9cdf7 56 err |= __put_user((short)from->si_code, &to->si_code);
1da177e4
LT
57
58 if (from->si_code < 0) {
59 err |= __put_user(from->si_pid, &to->si_pid);
99b9cdf7
TG
60 err |= __put_user(from->si_uid, &to->si_uid);
61 err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
1da177e4 62 } else {
99b9cdf7
TG
63 /*
64 * First 32bits of unions are always present:
65 * si_pid === si_band === si_tid === si_addr(LS half)
66 */
67 err |= __put_user(from->_sifields._pad[0],
68 &to->_sifields._pad[0]);
1da177e4
LT
69 switch (from->si_code >> 16) {
70 case __SI_FAULT >> 16:
71 break;
72 case __SI_CHLD >> 16:
73 err |= __put_user(from->si_utime, &to->si_utime);
74 err |= __put_user(from->si_stime, &to->si_stime);
75 err |= __put_user(from->si_status, &to->si_status);
76 /* FALL THROUGH */
77 default:
78 case __SI_KILL >> 16:
79 err |= __put_user(from->si_uid, &to->si_uid);
80 break;
81 case __SI_POLL >> 16:
99b9cdf7 82 err |= __put_user(from->si_fd, &to->si_fd);
1da177e4
LT
83 break;
84 case __SI_TIMER >> 16:
99b9cdf7 85 err |= __put_user(from->si_overrun, &to->si_overrun);
1da177e4 86 err |= __put_user(ptr_to_compat(from->si_ptr),
99b9cdf7 87 &to->si_ptr);
1da177e4 88 break;
99b9cdf7
TG
89 /* This is not generated by the kernel as of now. */
90 case __SI_RT >> 16:
1da177e4
LT
91 case __SI_MESGQ >> 16:
92 err |= __put_user(from->si_uid, &to->si_uid);
93 err |= __put_user(from->si_int, &to->si_int);
94 break;
95 }
96 }
97 return err;
98}
99
100int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
101{
102 int err;
103 u32 ptr32;
99b9cdf7
TG
104
105 if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
1da177e4
LT
106 return -EFAULT;
107
108 err = __get_user(to->si_signo, &from->si_signo);
109 err |= __get_user(to->si_errno, &from->si_errno);
110 err |= __get_user(to->si_code, &from->si_code);
111
112 err |= __get_user(to->si_pid, &from->si_pid);
113 err |= __get_user(to->si_uid, &from->si_uid);
114 err |= __get_user(ptr32, &from->si_ptr);
115 to->si_ptr = compat_ptr(ptr32);
116
117 return err;
118}
119
99b9cdf7 120asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
1da177e4 121{
1da177e4
LT
122 mask &= _BLOCKABLE;
123 spin_lock_irq(&current->sighand->siglock);
1d001df1 124 current->saved_sigmask = current->blocked;
1da177e4
LT
125 siginitset(&current->blocked, mask);
126 recalc_sigpending();
127 spin_unlock_irq(&current->sighand->siglock);
128
1d001df1
AK
129 current->state = TASK_INTERRUPTIBLE;
130 schedule();
131 set_thread_flag(TIF_RESTORE_SIGMASK);
132 return -ERESTARTNOHAND;
1da177e4
LT
133}
134
99b9cdf7
TG
135asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
136 stack_ia32_t __user *uoss_ptr,
137 struct pt_regs *regs)
1da177e4 138{
99b9cdf7 139 stack_t uss, uoss;
1da177e4 140 int ret;
99b9cdf7
TG
141 mm_segment_t seg;
142
143 if (uss_ptr) {
1da177e4 144 u32 ptr;
99b9cdf7
TG
145
146 memset(&uss, 0, sizeof(stack_t));
147 if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)) ||
1da177e4
LT
148 __get_user(ptr, &uss_ptr->ss_sp) ||
149 __get_user(uss.ss_flags, &uss_ptr->ss_flags) ||
150 __get_user(uss.ss_size, &uss_ptr->ss_size))
151 return -EFAULT;
152 uss.ss_sp = compat_ptr(ptr);
153 }
99b9cdf7
TG
154 seg = get_fs();
155 set_fs(KERNEL_DS);
65ea5b03 156 ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp);
99b9cdf7 157 set_fs(seg);
1da177e4 158 if (ret >= 0 && uoss_ptr) {
99b9cdf7 159 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)) ||
1da177e4
LT
160 __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
161 __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
162 __put_user(uoss.ss_size, &uoss_ptr->ss_size))
163 ret = -EFAULT;
99b9cdf7
TG
164 }
165 return ret;
1da177e4
LT
166}
167
168/*
169 * Do a signal return; undo the signal stack.
170 */
171
172struct sigframe
173{
174 u32 pretcode;
175 int sig;
176 struct sigcontext_ia32 sc;
177 struct _fpstate_ia32 fpstate;
178 unsigned int extramask[_COMPAT_NSIG_WORDS-1];
179 char retcode[8];
180};
181
182struct rt_sigframe
183{
184 u32 pretcode;
185 int sig;
186 u32 pinfo;
187 u32 puc;
188 compat_siginfo_t info;
189 struct ucontext_ia32 uc;
190 struct _fpstate_ia32 fpstate;
191 char retcode[8];
192};
193
742fa54a
PA
194#define COPY(x) { \
195 unsigned int reg; \
196 err |= __get_user(reg, &sc->x); \
65ea5b03 197 regs->x = reg; \
1da177e4
LT
198}
199
200#define RELOAD_SEG(seg,mask) \
99b9cdf7 201 { unsigned int cur; \
1da177e4
LT
202 unsigned short pre; \
203 err |= __get_user(pre, &sc->seg); \
99b9cdf7
TG
204 asm volatile("movl %%" #seg ",%0" : "=r" (cur)); \
205 pre |= mask; \
206 if (pre != cur) loadsegment(seg, pre); }
207
208static int ia32_restore_sigcontext(struct pt_regs *regs,
209 struct sigcontext_ia32 __user *sc,
210 unsigned int *peax)
211{
212 unsigned int tmpflags, gs, oldgs, err = 0;
213 struct _fpstate_ia32 __user *buf;
214 u32 tmp;
215
216 /* Always make any pending restarted system calls return -EINTR */
217 current_thread_info()->restart_block.fn = do_no_restart_syscall;
218
219#if DEBUG_SIG
220 printk(KERN_DEBUG "SIG restore_sigcontext: "
221 "sc=%p err(%x) eip(%x) cs(%x) flg(%x)\n",
65ea5b03 222 sc, sc->err, sc->ip, sc->cs, sc->flags);
99b9cdf7
TG
223#endif
224
225 /*
226 * Reload fs and gs if they have changed in the signal
227 * handler. This does not handle long fs/gs base changes in
228 * the handler, but does not clobber them at least in the
229 * normal case.
230 */
231 err |= __get_user(gs, &sc->gs);
232 gs |= 3;
233 asm("movl %%gs,%0" : "=r" (oldgs));
234 if (gs != oldgs)
235 load_gs_index(gs);
236
237 RELOAD_SEG(fs, 3);
238 RELOAD_SEG(ds, 3);
239 RELOAD_SEG(es, 3);
1da177e4
LT
240
241 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
242 COPY(dx); COPY(cx); COPY(ip);
99b9cdf7
TG
243 /* Don't touch extended registers */
244
245 err |= __get_user(regs->cs, &sc->cs);
246 regs->cs |= 3;
247 err |= __get_user(regs->ss, &sc->ss);
248 regs->ss |= 3;
249
742fa54a 250 err |= __get_user(tmpflags, &sc->flags);
65ea5b03 251 regs->flags = (regs->flags & ~0x40DD5) | (tmpflags & 0x40DD5);
99b9cdf7 252 /* disable syscall checks */
65ea5b03 253 regs->orig_ax = -1;
99b9cdf7
TG
254
255 err |= __get_user(tmp, &sc->fpstate);
256 buf = compat_ptr(tmp);
257 if (buf) {
258 if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
259 goto badframe;
44210111 260 err |= restore_i387_ia32(buf);
99b9cdf7
TG
261 } else {
262 struct task_struct *me = current;
1da177e4 263
99b9cdf7
TG
264 if (used_math()) {
265 clear_fpu(me);
266 clear_used_math();
1da177e4
LT
267 }
268 }
269
742fa54a 270 err |= __get_user(tmp, &sc->ax);
99b9cdf7
TG
271 *peax = tmp;
272
1da177e4
LT
273 return err;
274
275badframe:
276 return 1;
277}
278
279asmlinkage long sys32_sigreturn(struct pt_regs *regs)
280{
65ea5b03 281 struct sigframe __user *frame = (struct sigframe __user *)(regs->sp-8);
1da177e4 282 sigset_t set;
65ea5b03 283 unsigned int ax;
1da177e4
LT
284
285 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
286 goto badframe;
287 if (__get_user(set.sig[0], &frame->sc.oldmask)
288 || (_COMPAT_NSIG_WORDS > 1
99b9cdf7
TG
289 && __copy_from_user((((char *) &set.sig) + 4),
290 &frame->extramask,
1da177e4
LT
291 sizeof(frame->extramask))))
292 goto badframe;
293
294 sigdelsetmask(&set, ~_BLOCKABLE);
295 spin_lock_irq(&current->sighand->siglock);
296 current->blocked = set;
297 recalc_sigpending();
298 spin_unlock_irq(&current->sighand->siglock);
99b9cdf7 299
65ea5b03 300 if (ia32_restore_sigcontext(regs, &frame->sc, &ax))
1da177e4 301 goto badframe;
65ea5b03 302 return ax;
1da177e4
LT
303
304badframe:
305 signal_fault(regs, frame, "32bit sigreturn");
306 return 0;
99b9cdf7 307}
1da177e4
LT
308
309asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
310{
311 struct rt_sigframe __user *frame;
312 sigset_t set;
65ea5b03 313 unsigned int ax;
1da177e4
LT
314 struct pt_regs tregs;
315
65ea5b03 316 frame = (struct rt_sigframe __user *)(regs->sp - 4);
1da177e4
LT
317
318 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
319 goto badframe;
320 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
321 goto badframe;
322
323 sigdelsetmask(&set, ~_BLOCKABLE);
324 spin_lock_irq(&current->sighand->siglock);
325 current->blocked = set;
326 recalc_sigpending();
327 spin_unlock_irq(&current->sighand->siglock);
99b9cdf7 328
65ea5b03 329 if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
1da177e4
LT
330 goto badframe;
331
332 tregs = *regs;
333 if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
334 goto badframe;
335
65ea5b03 336 return ax;
1da177e4
LT
337
338badframe:
99b9cdf7 339 signal_fault(regs, frame, "32bit rt sigreturn");
1da177e4 340 return 0;
99b9cdf7 341}
1da177e4
LT
342
343/*
344 * Set up a signal frame.
345 */
346
99b9cdf7
TG
347static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
348 struct _fpstate_ia32 __user *fpstate,
349 struct pt_regs *regs, unsigned int mask)
1da177e4
LT
350{
351 int tmp, err = 0;
1da177e4
LT
352
353 tmp = 0;
354 __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
355 err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
356 __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp));
357 err |= __put_user(tmp, (unsigned int __user *)&sc->fs);
358 __asm__("movl %%ds,%0" : "=r"(tmp): "0"(tmp));
359 err |= __put_user(tmp, (unsigned int __user *)&sc->ds);
360 __asm__("movl %%es,%0" : "=r"(tmp): "0"(tmp));
361 err |= __put_user(tmp, (unsigned int __user *)&sc->es);
362
742fa54a
PA
363 err |= __put_user((u32)regs->di, &sc->di);
364 err |= __put_user((u32)regs->si, &sc->si);
365 err |= __put_user((u32)regs->bp, &sc->bp);
366 err |= __put_user((u32)regs->sp, &sc->sp);
367 err |= __put_user((u32)regs->bx, &sc->bx);
368 err |= __put_user((u32)regs->dx, &sc->dx);
369 err |= __put_user((u32)regs->cx, &sc->cx);
370 err |= __put_user((u32)regs->ax, &sc->ax);
1da177e4
LT
371 err |= __put_user((u32)regs->cs, &sc->cs);
372 err |= __put_user((u32)regs->ss, &sc->ss);
373 err |= __put_user(current->thread.trap_no, &sc->trapno);
374 err |= __put_user(current->thread.error_code, &sc->err);
742fa54a
PA
375 err |= __put_user((u32)regs->ip, &sc->ip);
376 err |= __put_user((u32)regs->flags, &sc->flags);
377 err |= __put_user((u32)regs->sp, &sc->sp_at_signal);
1da177e4 378
44210111 379 tmp = save_i387_ia32(fpstate);
1da177e4
LT
380 if (tmp < 0)
381 err = -EFAULT;
99b9cdf7 382 else {
1da177e4
LT
383 clear_used_math();
384 stts();
385 err |= __put_user(ptr_to_compat(tmp ? fpstate : NULL),
386 &sc->fpstate);
387 }
388
389 /* non-iBCS2 extensions.. */
390 err |= __put_user(mask, &sc->oldmask);
391 err |= __put_user(current->thread.cr2, &sc->cr2);
392
393 return err;
394}
395
396/*
397 * Determine which stack to use..
398 */
99b9cdf7
TG
399static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
400 size_t frame_size)
1da177e4 401{
65ea5b03 402 unsigned long sp;
1da177e4
LT
403
404 /* Default to using normal stack */
65ea5b03 405 sp = regs->sp;
1da177e4
LT
406
407 /* This is the X/Open sanctioned signal stack switching. */
408 if (ka->sa.sa_flags & SA_ONSTACK) {
65ea5b03
PA
409 if (sas_ss_flags(sp) == 0)
410 sp = current->sas_ss_sp + current->sas_ss_size;
1da177e4
LT
411 }
412
413 /* This is the legacy signal stack switching. */
414 else if ((regs->ss & 0xffff) != __USER_DS &&
415 !(ka->sa.sa_flags & SA_RESTORER) &&
99b9cdf7 416 ka->sa.sa_restorer)
65ea5b03 417 sp = (unsigned long) ka->sa.sa_restorer;
1da177e4 418
65ea5b03 419 sp -= frame_size;
d347f372
MO
420 /* Align the stack pointer according to the i386 ABI,
421 * i.e. so that on function entry ((sp + 4) & 15) == 0. */
65ea5b03
PA
422 sp = ((sp + 4) & -16ul) - 4;
423 return (void __user *) sp;
1da177e4
LT
424}
425
0928d6ef 426int ia32_setup_frame(int sig, struct k_sigaction *ka,
99b9cdf7 427 compat_sigset_t *set, struct pt_regs *regs)
1da177e4
LT
428{
429 struct sigframe __user *frame;
99b9cdf7 430 void __user *restorer;
1da177e4
LT
431 int err = 0;
432
99b9cdf7
TG
433 /* copy_to_user optimizes that into a single 8 byte store */
434 static const struct {
435 u16 poplmovl;
436 u32 val;
437 u16 int80;
438 u16 pad;
439 } __attribute__((packed)) code = {
440 0xb858, /* popl %eax ; movl $...,%eax */
441 __NR_ia32_sigreturn,
442 0x80cd, /* int $0x80 */
443 0,
444 };
445
1da177e4
LT
446 frame = get_sigframe(ka, regs, sizeof(*frame));
447
448 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
449 goto give_sigsegv;
450
dd54a110 451 err |= __put_user(sig, &frame->sig);
1da177e4
LT
452 if (err)
453 goto give_sigsegv;
454
455 err |= ia32_setup_sigcontext(&frame->sc, &frame->fpstate, regs,
456 set->sig[0]);
457 if (err)
458 goto give_sigsegv;
459
460 if (_COMPAT_NSIG_WORDS > 1) {
461 err |= __copy_to_user(frame->extramask, &set->sig[1],
462 sizeof(frame->extramask));
99b9cdf7
TG
463 if (err)
464 goto give_sigsegv;
1da177e4 465 }
1da177e4 466
af65d648 467 if (ka->sa.sa_flags & SA_RESTORER) {
99b9cdf7 468 restorer = ka->sa.sa_restorer;
af65d648
RM
469 } else {
470 /* Return stub is in 32bit vsyscall page */
471 if (current->binfmt->hasvdso)
472 restorer = VDSO32_SYMBOL(current->mm->context.vdso,
473 sigreturn);
474 else
ade1af77 475 restorer = &frame->retcode;
af65d648 476 }
99b9cdf7
TG
477 err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
478
479 /*
480 * These are actually not used anymore, but left because some
481 * gdb versions depend on them as a marker.
482 */
483 err |= __copy_to_user(frame->retcode, &code, 8);
1da177e4
LT
484 if (err)
485 goto give_sigsegv;
486
487 /* Set up registers for signal handler */
65ea5b03
PA
488 regs->sp = (unsigned long) frame;
489 regs->ip = (unsigned long) ka->sa.sa_handler;
1da177e4 490
536e3ee4 491 /* Make -mregparm=3 work */
65ea5b03
PA
492 regs->ax = sig;
493 regs->dx = 0;
494 regs->cx = 0;
536e3ee4 495
99b9cdf7
TG
496 asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
497 asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
1da177e4 498
99b9cdf7
TG
499 regs->cs = __USER32_CS;
500 regs->ss = __USER32_DS;
1da177e4
LT
501
502 set_fs(USER_DS);
e40cd10c 503 regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
ab2e0b46
AK
504 if (test_thread_flag(TIF_SINGLESTEP))
505 ptrace_notify(SIGTRAP);
1da177e4
LT
506
507#if DEBUG_SIG
99b9cdf7 508 printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
65ea5b03 509 current->comm, current->pid, frame, regs->ip, frame->pretcode);
1da177e4
LT
510#endif
511
1d001df1 512 return 0;
1da177e4
LT
513
514give_sigsegv:
515 force_sigsegv(sig, current);
1d001df1 516 return -EFAULT;
1da177e4
LT
517}
518
0928d6ef 519int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
99b9cdf7 520 compat_sigset_t *set, struct pt_regs *regs)
1da177e4
LT
521{
522 struct rt_sigframe __user *frame;
99b9cdf7 523 struct exec_domain *ed = current_thread_info()->exec_domain;
af65d648 524 void __user *restorer;
1da177e4
LT
525 int err = 0;
526
99b9cdf7
TG
527 /* __copy_to_user optimizes that into a single 8 byte store */
528 static const struct {
529 u8 movl;
530 u32 val;
531 u16 int80;
532 u16 pad;
533 u8 pad2;
534 } __attribute__((packed)) code = {
535 0xb8,
536 __NR_ia32_rt_sigreturn,
537 0x80cd,
538 0,
539 };
540
1da177e4
LT
541 frame = get_sigframe(ka, regs, sizeof(*frame));
542
543 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
544 goto give_sigsegv;
545
99b9cdf7
TG
546 err |= __put_user((ed && ed->signal_invmap && sig < 32
547 ? ed->signal_invmap[sig] : sig), &frame->sig);
1da177e4
LT
548 err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo);
549 err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc);
550 err |= copy_siginfo_to_user32(&frame->info, info);
551 if (err)
552 goto give_sigsegv;
553
554 /* Create the ucontext. */
555 err |= __put_user(0, &frame->uc.uc_flags);
556 err |= __put_user(0, &frame->uc.uc_link);
557 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
65ea5b03 558 err |= __put_user(sas_ss_flags(regs->sp),
1da177e4
LT
559 &frame->uc.uc_stack.ss_flags);
560 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
561 err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
99b9cdf7 562 regs, set->sig[0]);
1da177e4
LT
563 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
564 if (err)
565 goto give_sigsegv;
566
99b9cdf7
TG
567 if (ka->sa.sa_flags & SA_RESTORER)
568 restorer = ka->sa.sa_restorer;
af65d648
RM
569 else
570 restorer = VDSO32_SYMBOL(current->mm->context.vdso,
571 rt_sigreturn);
99b9cdf7 572 err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
1da177e4 573
99b9cdf7
TG
574 /*
575 * Not actually used anymore, but left because some gdb
576 * versions need it.
577 */
578 err |= __copy_to_user(frame->retcode, &code, 8);
1da177e4
LT
579 if (err)
580 goto give_sigsegv;
581
582 /* Set up registers for signal handler */
65ea5b03
PA
583 regs->sp = (unsigned long) frame;
584 regs->ip = (unsigned long) ka->sa.sa_handler;
1da177e4 585
a7aacdf9 586 /* Make -mregparm=3 work */
65ea5b03
PA
587 regs->ax = sig;
588 regs->dx = (unsigned long) &frame->info;
589 regs->cx = (unsigned long) &frame->uc;
a7aacdf9 590
8e3de538 591 /* Make -mregparm=3 work */
65ea5b03
PA
592 regs->ax = sig;
593 regs->dx = (unsigned long) &frame->info;
594 regs->cx = (unsigned long) &frame->uc;
8e3de538 595
99b9cdf7
TG
596 asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
597 asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
598
599 regs->cs = __USER32_CS;
600 regs->ss = __USER32_DS;
1da177e4
LT
601
602 set_fs(USER_DS);
e40cd10c 603 regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
ab2e0b46
AK
604 if (test_thread_flag(TIF_SINGLESTEP))
605 ptrace_notify(SIGTRAP);
1da177e4
LT
606
607#if DEBUG_SIG
99b9cdf7 608 printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
65ea5b03 609 current->comm, current->pid, frame, regs->ip, frame->pretcode);
1da177e4
LT
610#endif
611
1d001df1 612 return 0;
1da177e4
LT
613
614give_sigsegv:
615 force_sigsegv(sig, current);
1d001df1 616 return -EFAULT;
1da177e4 617}