blob: 6ea19c25f90d46ce209c646382443c5a8ae0e46e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 */
10
11#include <linux/sched.h>
12#include <linux/mm.h>
13#include <linux/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#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>
Andi Kleen9fbbd4d2007-02-13 13:26:26 +010023#include <linux/binfmts.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#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>
32#include <asm/fpu32.h>
33#include <asm/proto.h>
34#include <asm/vsyscall32.h>
35
36#define DEBUG_SIG 0
37
38#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
39
40asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
41void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
42
43int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
44{
45 int err;
46 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
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);
56 err |= __put_user((short)from->si_code, &to->si_code);
57
58 if (from->si_code < 0) {
59 err |= __put_user(from->si_pid, &to->si_pid);
60 err |= __put_user(from->si_uid, &to->si_uid);
61 err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
62 } else {
63 /* First 32bits of unions are always present:
64 * si_pid === si_band === si_tid === si_addr(LS half) */
65 err |= __put_user(from->_sifields._pad[0], &to->_sifields._pad[0]);
66 switch (from->si_code >> 16) {
67 case __SI_FAULT >> 16:
68 break;
69 case __SI_CHLD >> 16:
70 err |= __put_user(from->si_utime, &to->si_utime);
71 err |= __put_user(from->si_stime, &to->si_stime);
72 err |= __put_user(from->si_status, &to->si_status);
73 /* FALL THROUGH */
74 default:
75 case __SI_KILL >> 16:
76 err |= __put_user(from->si_uid, &to->si_uid);
77 break;
78 case __SI_POLL >> 16:
79 err |= __put_user(from->si_fd, &to->si_fd);
80 break;
81 case __SI_TIMER >> 16:
82 err |= __put_user(from->si_overrun, &to->si_overrun);
83 err |= __put_user(ptr_to_compat(from->si_ptr),
84 &to->si_ptr);
85 break;
86 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
87 case __SI_MESGQ >> 16:
88 err |= __put_user(from->si_uid, &to->si_uid);
89 err |= __put_user(from->si_int, &to->si_int);
90 break;
91 }
92 }
93 return err;
94}
95
96int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
97{
98 int err;
99 u32 ptr32;
100 if (!access_ok (VERIFY_READ, from, sizeof(compat_siginfo_t)))
101 return -EFAULT;
102
103 err = __get_user(to->si_signo, &from->si_signo);
104 err |= __get_user(to->si_errno, &from->si_errno);
105 err |= __get_user(to->si_code, &from->si_code);
106
107 err |= __get_user(to->si_pid, &from->si_pid);
108 err |= __get_user(to->si_uid, &from->si_uid);
109 err |= __get_user(ptr32, &from->si_ptr);
110 to->si_ptr = compat_ptr(ptr32);
111
112 return err;
113}
114
115asmlinkage long
Andi Kleen1d001df2006-09-26 10:52:26 +0200116sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 mask &= _BLOCKABLE;
119 spin_lock_irq(&current->sighand->siglock);
Andi Kleen1d001df2006-09-26 10:52:26 +0200120 current->saved_sigmask = current->blocked;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 siginitset(&current->blocked, mask);
122 recalc_sigpending();
123 spin_unlock_irq(&current->sighand->siglock);
124
Andi Kleen1d001df2006-09-26 10:52:26 +0200125 current->state = TASK_INTERRUPTIBLE;
126 schedule();
127 set_thread_flag(TIF_RESTORE_SIGMASK);
128 return -ERESTARTNOHAND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129}
130
131asmlinkage long
132sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
133 stack_ia32_t __user *uoss_ptr,
134 struct pt_regs *regs)
135{
136 stack_t uss,uoss;
137 int ret;
138 mm_segment_t seg;
139 if (uss_ptr) {
140 u32 ptr;
141 memset(&uss,0,sizeof(stack_t));
142 if (!access_ok(VERIFY_READ,uss_ptr,sizeof(stack_ia32_t)) ||
143 __get_user(ptr, &uss_ptr->ss_sp) ||
144 __get_user(uss.ss_flags, &uss_ptr->ss_flags) ||
145 __get_user(uss.ss_size, &uss_ptr->ss_size))
146 return -EFAULT;
147 uss.ss_sp = compat_ptr(ptr);
148 }
149 seg = get_fs();
150 set_fs(KERNEL_DS);
151 ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->rsp);
152 set_fs(seg);
153 if (ret >= 0 && uoss_ptr) {
154 if (!access_ok(VERIFY_WRITE,uoss_ptr,sizeof(stack_ia32_t)) ||
155 __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
156 __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
157 __put_user(uoss.ss_size, &uoss_ptr->ss_size))
158 ret = -EFAULT;
159 }
160 return ret;
161}
162
163/*
164 * Do a signal return; undo the signal stack.
165 */
166
167struct sigframe
168{
169 u32 pretcode;
170 int sig;
171 struct sigcontext_ia32 sc;
172 struct _fpstate_ia32 fpstate;
173 unsigned int extramask[_COMPAT_NSIG_WORDS-1];
174 char retcode[8];
175};
176
177struct rt_sigframe
178{
179 u32 pretcode;
180 int sig;
181 u32 pinfo;
182 u32 puc;
183 compat_siginfo_t info;
184 struct ucontext_ia32 uc;
185 struct _fpstate_ia32 fpstate;
186 char retcode[8];
187};
188
189static int
190ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 __user *sc, unsigned int *peax)
191{
192 unsigned int err = 0;
193
194 /* Always make any pending restarted system calls return -EINTR */
195 current_thread_info()->restart_block.fn = do_no_restart_syscall;
196
197#if DEBUG_SIG
198 printk("SIG restore_sigcontext: sc=%p err(%x) eip(%x) cs(%x) flg(%x)\n",
199 sc, sc->err, sc->eip, sc->cs, sc->eflags);
200#endif
201#define COPY(x) { \
202 unsigned int reg; \
203 err |= __get_user(reg, &sc->e ##x); \
204 regs->r ## x = reg; \
205}
206
207#define RELOAD_SEG(seg,mask) \
208 { unsigned int cur; \
209 unsigned short pre; \
210 err |= __get_user(pre, &sc->seg); \
211 asm volatile("movl %%" #seg ",%0" : "=r" (cur)); \
212 pre |= mask; \
213 if (pre != cur) loadsegment(seg,pre); }
214
215 /* Reload fs and gs if they have changed in the signal handler.
216 This does not handle long fs/gs base changes in the handler, but
217 does not clobber them at least in the normal case. */
218
219 {
220 unsigned gs, oldgs;
221 err |= __get_user(gs, &sc->gs);
222 gs |= 3;
223 asm("movl %%gs,%0" : "=r" (oldgs));
224 if (gs != oldgs)
225 load_gs_index(gs);
226 }
227 RELOAD_SEG(fs,3);
228 RELOAD_SEG(ds,3);
229 RELOAD_SEG(es,3);
230
231 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
232 COPY(dx); COPY(cx); COPY(ip);
233 /* Don't touch extended registers */
234
235 err |= __get_user(regs->cs, &sc->cs);
236 regs->cs |= 3;
237 err |= __get_user(regs->ss, &sc->ss);
238 regs->ss |= 3;
239
240 {
241 unsigned int tmpflags;
242 err |= __get_user(tmpflags, &sc->eflags);
243 regs->eflags = (regs->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
244 regs->orig_rax = -1; /* disable syscall checks */
245 }
246
247 {
248 u32 tmp;
249 struct _fpstate_ia32 __user * buf;
250 err |= __get_user(tmp, &sc->fpstate);
251 buf = compat_ptr(tmp);
252 if (buf) {
253 if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
254 goto badframe;
255 err |= restore_i387_ia32(current, buf, 0);
256 } else {
257 struct task_struct *me = current;
258 if (used_math()) {
259 clear_fpu(me);
260 clear_used_math();
261 }
262 }
263 }
264
265 {
266 u32 tmp;
267 err |= __get_user(tmp, &sc->eax);
268 *peax = tmp;
269 }
270 return err;
271
272badframe:
273 return 1;
274}
275
276asmlinkage long sys32_sigreturn(struct pt_regs *regs)
277{
278 struct sigframe __user *frame = (struct sigframe __user *)(regs->rsp-8);
279 sigset_t set;
280 unsigned int eax;
281
282 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
283 goto badframe;
284 if (__get_user(set.sig[0], &frame->sc.oldmask)
285 || (_COMPAT_NSIG_WORDS > 1
286 && __copy_from_user((((char *) &set.sig) + 4), &frame->extramask,
287 sizeof(frame->extramask))))
288 goto badframe;
289
290 sigdelsetmask(&set, ~_BLOCKABLE);
291 spin_lock_irq(&current->sighand->siglock);
292 current->blocked = set;
293 recalc_sigpending();
294 spin_unlock_irq(&current->sighand->siglock);
295
296 if (ia32_restore_sigcontext(regs, &frame->sc, &eax))
297 goto badframe;
298 return eax;
299
300badframe:
301 signal_fault(regs, frame, "32bit sigreturn");
302 return 0;
303}
304
305asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
306{
307 struct rt_sigframe __user *frame;
308 sigset_t set;
309 unsigned int eax;
310 struct pt_regs tregs;
311
312 frame = (struct rt_sigframe __user *)(regs->rsp - 4);
313
314 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
315 goto badframe;
316 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
317 goto badframe;
318
319 sigdelsetmask(&set, ~_BLOCKABLE);
320 spin_lock_irq(&current->sighand->siglock);
321 current->blocked = set;
322 recalc_sigpending();
323 spin_unlock_irq(&current->sighand->siglock);
324
325 if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax))
326 goto badframe;
327
328 tregs = *regs;
329 if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
330 goto badframe;
331
332 return eax;
333
334badframe:
335 signal_fault(regs,frame,"32bit rt sigreturn");
336 return 0;
337}
338
339/*
340 * Set up a signal frame.
341 */
342
343static int
344ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __user *fpstate,
345 struct pt_regs *regs, unsigned int mask)
346{
347 int tmp, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348
349 tmp = 0;
350 __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
351 err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
352 __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp));
353 err |= __put_user(tmp, (unsigned int __user *)&sc->fs);
354 __asm__("movl %%ds,%0" : "=r"(tmp): "0"(tmp));
355 err |= __put_user(tmp, (unsigned int __user *)&sc->ds);
356 __asm__("movl %%es,%0" : "=r"(tmp): "0"(tmp));
357 err |= __put_user(tmp, (unsigned int __user *)&sc->es);
358
359 err |= __put_user((u32)regs->rdi, &sc->edi);
360 err |= __put_user((u32)regs->rsi, &sc->esi);
361 err |= __put_user((u32)regs->rbp, &sc->ebp);
362 err |= __put_user((u32)regs->rsp, &sc->esp);
363 err |= __put_user((u32)regs->rbx, &sc->ebx);
364 err |= __put_user((u32)regs->rdx, &sc->edx);
365 err |= __put_user((u32)regs->rcx, &sc->ecx);
366 err |= __put_user((u32)regs->rax, &sc->eax);
367 err |= __put_user((u32)regs->cs, &sc->cs);
368 err |= __put_user((u32)regs->ss, &sc->ss);
369 err |= __put_user(current->thread.trap_no, &sc->trapno);
370 err |= __put_user(current->thread.error_code, &sc->err);
371 err |= __put_user((u32)regs->rip, &sc->eip);
Peter Beutner4724e3e2006-01-11 22:43:18 +0100372 err |= __put_user((u32)regs->eflags, &sc->eflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 err |= __put_user((u32)regs->rsp, &sc->esp_at_signal);
374
375 tmp = save_i387_ia32(current, fpstate, regs, 0);
376 if (tmp < 0)
377 err = -EFAULT;
378 else {
379 clear_used_math();
380 stts();
381 err |= __put_user(ptr_to_compat(tmp ? fpstate : NULL),
382 &sc->fpstate);
383 }
384
385 /* non-iBCS2 extensions.. */
386 err |= __put_user(mask, &sc->oldmask);
387 err |= __put_user(current->thread.cr2, &sc->cr2);
388
389 return err;
390}
391
392/*
393 * Determine which stack to use..
394 */
395static void __user *
396get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
397{
398 unsigned long rsp;
399
400 /* Default to using normal stack */
401 rsp = regs->rsp;
402
403 /* This is the X/Open sanctioned signal stack switching. */
404 if (ka->sa.sa_flags & SA_ONSTACK) {
405 if (sas_ss_flags(rsp) == 0)
406 rsp = current->sas_ss_sp + current->sas_ss_size;
407 }
408
409 /* This is the legacy signal stack switching. */
410 else if ((regs->ss & 0xffff) != __USER_DS &&
411 !(ka->sa.sa_flags & SA_RESTORER) &&
412 ka->sa.sa_restorer) {
413 rsp = (unsigned long) ka->sa.sa_restorer;
414 }
415
Markus F.X.J. Oberhumerd347f372005-10-09 18:54:23 +0200416 rsp -= frame_size;
417 /* Align the stack pointer according to the i386 ABI,
418 * i.e. so that on function entry ((sp + 4) & 15) == 0. */
419 rsp = ((rsp + 4) & -16ul) - 4;
420 return (void __user *) rsp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421}
422
Roland McGrath0928d6e2005-06-23 00:08:37 -0700423int ia32_setup_frame(int sig, struct k_sigaction *ka,
424 compat_sigset_t *set, struct pt_regs * regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425{
426 struct sigframe __user *frame;
427 int err = 0;
428
429 frame = get_sigframe(ka, regs, sizeof(*frame));
430
431 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
432 goto give_sigsegv;
433
Andi Kleendd54a112006-09-26 10:52:41 +0200434 err |= __put_user(sig, &frame->sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 if (err)
436 goto give_sigsegv;
437
438 err |= ia32_setup_sigcontext(&frame->sc, &frame->fpstate, regs,
439 set->sig[0]);
440 if (err)
441 goto give_sigsegv;
442
443 if (_COMPAT_NSIG_WORDS > 1) {
444 err |= __copy_to_user(frame->extramask, &set->sig[1],
445 sizeof(frame->extramask));
446 }
447 if (err)
448 goto give_sigsegv;
449
450 /* Return stub is in 32bit vsyscall page */
451 {
Andi Kleen9fbbd4d2007-02-13 13:26:26 +0100452 void __user *restorer;
453 if (current->binfmt->hasvdso)
454 restorer = VSYSCALL32_SIGRETURN;
455 else
456 restorer = (void *)&frame->retcode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 if (ka->sa.sa_flags & SA_RESTORER)
458 restorer = ka->sa.sa_restorer;
459 err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
460 }
461 /* These are actually not used anymore, but left because some
462 gdb versions depend on them as a marker. */
463 {
464 /* copy_to_user optimizes that into a single 8 byte store */
465 static const struct {
466 u16 poplmovl;
467 u32 val;
468 u16 int80;
469 u16 pad;
470 } __attribute__((packed)) code = {
471 0xb858, /* popl %eax ; movl $...,%eax */
472 __NR_ia32_sigreturn,
473 0x80cd, /* int $0x80 */
474 0,
475 };
476 err |= __copy_to_user(frame->retcode, &code, 8);
477 }
478 if (err)
479 goto give_sigsegv;
480
481 /* Set up registers for signal handler */
482 regs->rsp = (unsigned long) frame;
483 regs->rip = (unsigned long) ka->sa.sa_handler;
484
Andi Kleen536e3ee2006-09-26 10:52:41 +0200485 /* Make -mregparm=3 work */
486 regs->rax = sig;
487 regs->rdx = 0;
488 regs->rcx = 0;
489
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
491 asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
492
493 regs->cs = __USER32_CS;
494 regs->ss = __USER32_DS;
495
496 set_fs(USER_DS);
Andi Kleenab2e0b42006-09-26 10:52:41 +0200497 regs->eflags &= ~TF_MASK;
498 if (test_thread_flag(TIF_SINGLESTEP))
499 ptrace_notify(SIGTRAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500
501#if DEBUG_SIG
Evgeniy Polyakov8469add2007-02-13 13:26:25 +0100502 printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 current->comm, current->pid, frame, regs->rip, frame->pretcode);
504#endif
505
Andi Kleen1d001df2006-09-26 10:52:26 +0200506 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
508give_sigsegv:
509 force_sigsegv(sig, current);
Andi Kleen1d001df2006-09-26 10:52:26 +0200510 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511}
512
Roland McGrath0928d6e2005-06-23 00:08:37 -0700513int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
514 compat_sigset_t *set, struct pt_regs * regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515{
516 struct rt_sigframe __user *frame;
517 int err = 0;
518
519 frame = get_sigframe(ka, regs, sizeof(*frame));
520
521 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
522 goto give_sigsegv;
523
524 {
525 struct exec_domain *ed = current_thread_info()->exec_domain;
526 err |= __put_user((ed
527 && ed->signal_invmap
528 && sig < 32
529 ? ed->signal_invmap[sig]
530 : sig),
531 &frame->sig);
532 }
533 err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo);
534 err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc);
535 err |= copy_siginfo_to_user32(&frame->info, info);
536 if (err)
537 goto give_sigsegv;
538
539 /* Create the ucontext. */
540 err |= __put_user(0, &frame->uc.uc_flags);
541 err |= __put_user(0, &frame->uc.uc_link);
542 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
543 err |= __put_user(sas_ss_flags(regs->rsp),
544 &frame->uc.uc_stack.ss_flags);
545 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
546 err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
547 regs, set->sig[0]);
548 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
549 if (err)
550 goto give_sigsegv;
551
552
553 {
554 void __user *restorer = VSYSCALL32_RTSIGRETURN;
555 if (ka->sa.sa_flags & SA_RESTORER)
556 restorer = ka->sa.sa_restorer;
557 err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
558 }
559
560 /* This is movl $,%eax ; int $0x80 */
561 /* Not actually used anymore, but left because some gdb versions
562 need it. */
563 {
564 /* __copy_to_user optimizes that into a single 8 byte store */
565 static const struct {
566 u8 movl;
567 u32 val;
568 u16 int80;
569 u16 pad;
570 u8 pad2;
571 } __attribute__((packed)) code = {
572 0xb8,
573 __NR_ia32_rt_sigreturn,
574 0x80cd,
575 0,
576 };
577 err |= __copy_to_user(frame->retcode, &code, 8);
578 }
579 if (err)
580 goto give_sigsegv;
581
582 /* Set up registers for signal handler */
583 regs->rsp = (unsigned long) frame;
584 regs->rip = (unsigned long) ka->sa.sa_handler;
585
Albert Cahalana7aacdf2006-10-29 22:26:17 -0500586 /* Make -mregparm=3 work */
587 regs->rax = sig;
588 regs->rdx = (unsigned long) &frame->info;
589 regs->rcx = (unsigned long) &frame->uc;
590
Albert Cahalan8e3de532006-12-07 02:14:06 +0100591 /* Make -mregparm=3 work */
592 regs->rax = sig;
593 regs->rdx = (unsigned long) &frame->info;
594 regs->rcx = (unsigned long) &frame->uc;
595
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 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;
601
602 set_fs(USER_DS);
Andi Kleen1d001df2006-09-26 10:52:26 +0200603 regs->eflags &= ~TF_MASK;
Andi Kleenab2e0b42006-09-26 10:52:41 +0200604 if (test_thread_flag(TIF_SINGLESTEP))
605 ptrace_notify(SIGTRAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606
607#if DEBUG_SIG
Evgeniy Polyakov8469add2007-02-13 13:26:25 +0100608 printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 current->comm, current->pid, frame, regs->rip, frame->pretcode);
610#endif
611
Andi Kleen1d001df2006-09-26 10:52:26 +0200612 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
614give_sigsegv:
615 force_sigsegv(sig, current);
Andi Kleen1d001df2006-09-26 10:52:26 +0200616 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617}