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