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