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