cleanup
[linux-2.4.21-pre4.git] / arch / ia64 / ia32 / ia32_signal.c
1 /*
2  * IA32 Architecture-specific signal handling support.
3  *
4  * Copyright (C) 1999, 2001 Hewlett-Packard Co
5  *      David Mosberger-Tang <davidm@hpl.hp.com>
6  * Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
7  * Copyright (C) 2000 VA Linux Co
8  * Copyright (C) 2000 Don Dugger <n0ano@valinux.com>
9  *
10  * Derived from i386 and Alpha versions.
11  */
12
13 #include <linux/errno.h>
14 #include <linux/kernel.h>
15 #include <linux/mm.h>
16 #include <linux/personality.h>
17 #include <linux/ptrace.h>
18 #include <linux/sched.h>
19 #include <linux/signal.h>
20 #include <linux/smp.h>
21 #include <linux/smp_lock.h>
22 #include <linux/stddef.h>
23 #include <linux/unistd.h>
24 #include <linux/wait.h>
25
26 #include <asm/uaccess.h>
27 #include <asm/rse.h>
28 #include <asm/sigcontext.h>
29 #include <asm/segment.h>
30 #include <asm/ia32.h>
31
32 #include "../kernel/sigframe.h"
33
34 #define A(__x)          ((unsigned long)(__x))
35
36 #define DEBUG_SIG       0
37 #define _BLOCKABLE      (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
38
39 #define __IA32_NR_sigreturn            119
40 #define __IA32_NR_rt_sigreturn         173
41
42 register double f16 asm ("f16"); register double f17 asm ("f17");
43 register double f18 asm ("f18"); register double f19 asm ("f19");
44 register double f20 asm ("f20"); register double f21 asm ("f21");
45 register double f22 asm ("f22"); register double f23 asm ("f23");
46
47 register double f24 asm ("f24"); register double f25 asm ("f25");
48 register double f26 asm ("f26"); register double f27 asm ("f27");
49 register double f28 asm ("f28"); register double f29 asm ("f29");
50 register double f30 asm ("f30"); register double f31 asm ("f31");
51
52 struct sigframe_ia32
53 {
54        int pretcode;
55        int sig;
56        struct sigcontext_ia32 sc;
57        struct _fpstate_ia32 fpstate;
58        unsigned int extramask[_IA32_NSIG_WORDS-1];
59        char retcode[8];
60 };
61
62 struct rt_sigframe_ia32
63 {
64        int pretcode;
65        int sig;
66        int pinfo;
67        int puc;
68        siginfo_t32 info;
69        struct ucontext_ia32 uc;
70        struct _fpstate_ia32 fpstate;
71        char retcode[8];
72 };
73
74 int
75 copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from)
76 {
77         unsigned long tmp;
78         int err;
79
80         if (!access_ok(VERIFY_READ, from, sizeof(siginfo_t32)))
81                 return -EFAULT;
82
83         err = __get_user(to->si_signo, &from->si_signo);
84         err |= __get_user(to->si_errno, &from->si_errno);
85         err |= __get_user(to->si_code, &from->si_code);
86
87         if (from->si_code < 0)
88                 err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
89         else {
90                 switch (from->si_code >> 16) {
91                       case __SI_CHLD >> 16:
92                         err |= __get_user(to->si_utime, &from->si_utime);
93                         err |= __get_user(to->si_stime, &from->si_stime);
94                         err |= __get_user(to->si_status, &from->si_status);
95                       default:
96                         err |= __get_user(to->si_pid, &from->si_pid);
97                         err |= __get_user(to->si_uid, &from->si_uid);
98                         break;
99                       case __SI_FAULT >> 16:
100                         err |= __get_user(tmp, &from->si_addr);
101                         to->si_addr = (void *) tmp;
102                         break;
103                       case __SI_POLL >> 16:
104                         err |= __get_user(to->si_band, &from->si_band);
105                         err |= __get_user(to->si_fd, &from->si_fd);
106                         break;
107                         /* case __SI_RT: This is not generated by the kernel as of now.  */
108                 }
109         }
110         return err;
111 }
112
113 int
114 copy_siginfo_to_user32 (siginfo_t32 *to, siginfo_t *from)
115 {
116         int err;
117
118         if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t32)))
119                 return -EFAULT;
120
121         /* If you change siginfo_t structure, please be sure
122            this code is fixed accordingly.
123            It should never copy any pad contained in the structure
124            to avoid security leaks, but must copy the generic
125            3 ints plus the relevant union member.
126            This routine must convert siginfo from 64bit to 32bit as well
127            at the same time.  */
128         err = __put_user(from->si_signo, &to->si_signo);
129         err |= __put_user(from->si_errno, &to->si_errno);
130         err |= __put_user((short)from->si_code, &to->si_code);
131         if (from->si_code < 0)
132                 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
133         else {
134                 switch (from->si_code >> 16) {
135                 case __SI_CHLD >> 16:
136                         err |= __put_user(from->si_utime, &to->si_utime);
137                         err |= __put_user(from->si_stime, &to->si_stime);
138                         err |= __put_user(from->si_status, &to->si_status);
139                 default:
140                         err |= __put_user(from->si_pid, &to->si_pid);
141                         err |= __put_user(from->si_uid, &to->si_uid);
142                         break;
143                 case __SI_FAULT >> 16:
144                         err |= __put_user((long)from->si_addr, &to->si_addr);
145                         break;
146                 case __SI_POLL >> 16:
147                         err |= __put_user(from->si_band, &to->si_band);
148                         err |= __put_user(from->si_fd, &to->si_fd);
149                         break;
150                 /* case __SI_RT: This is not generated by the kernel as of now.  */
151                 }
152         }
153         return err;
154 }
155
156
157 /*
158  *  SAVE and RESTORE of ia32 fpstate info, from ia64 current state
159  *  Used in exception handler to pass the fpstate to the user, and restore
160  *  the fpstate while returning from the exception handler.
161  *
162  *    fpstate info and their mapping to IA64 regs:
163  *    fpstate    REG(BITS)      Attribute    Comments
164  *    cw         ar.fcr(0:12)                with bits 7 and 6 not used
165  *    sw         ar.fsr(0:15)
166  *    tag        ar.fsr(16:31)               with odd numbered bits not used
167  *                                           (read returns 0, writes ignored)
168  *    ipoff      ar.fir(0:31)
169  *    cssel      ar.fir(32:47)
170  *    dataoff    ar.fdr(0:31)
171  *    datasel    ar.fdr(32:47)
172  *
173  *    _st[(0+TOS)%8]   f8
174  *    _st[(1+TOS)%8]   f9                    (f8, f9 from ptregs)
175  *      : :            :                     (f10..f15 from live reg)
176  *      : :            :
177  *    _st[(7+TOS)%8]   f15                   TOS=sw.top(bits11:13)
178  *
179  *    status     Same as sw     RO
180  *    magic      0                           as X86_FXSR_MAGIC in ia32
181  *    mxcsr      Bits(7:15)=ar.fcr(39:47)
182  *               Bits(0:5) =ar.fsr(32:37)    with bit 6 reserved
183  *    _xmm[0..7] f16..f31                    (live registers)
184  *                                           with _xmm[0]
185  *                                             Bit(64:127)=f17(0:63)
186  *                                             Bit(0:63)=f16(0:63)
187  *    All other fields unused...
188  */
189
190 #define __ldfe(regnum, x)                                               \
191 ({                                                                      \
192         register double __f__ asm ("f"#regnum);                         \
193         __asm__ __volatile__ ("ldfe %0=[%1] ;;" :"=f"(__f__): "r"(x));  \
194 })
195
196 #define __ldf8(regnum, x)                                               \
197 ({                                                                      \
198         register double __f__ asm ("f"#regnum);                         \
199         __asm__ __volatile__ ("ldf8 %0=[%1] ;;" :"=f"(__f__): "r"(x));  \
200 })
201
202 #define __stfe(x, regnum)                                                       \
203 ({                                                                              \
204         register double __f__ asm ("f"#regnum);                                 \
205         __asm__ __volatile__ ("stfe [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \
206 })
207
208 #define __stf8(x, regnum)                                                       \
209 ({                                                                              \
210         register double __f__ asm ("f"#regnum);                                 \
211         __asm__ __volatile__ ("stf8 [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \
212 })
213
214 static int
215 save_ia32_fpstate_live (struct _fpstate_ia32 *save)
216 {
217         struct task_struct *tsk = current;
218         struct pt_regs *ptp;
219         struct _fpreg_ia32 *fpregp;
220         char buf[32];
221         unsigned long fsr, fcr, fir, fdr;
222         unsigned long new_fsr;
223         unsigned long num128[2];
224         unsigned long mxcsr=0;
225         int fp_tos, fr8_st_map;
226
227         if (!access_ok(VERIFY_WRITE, save, sizeof(*save)))
228                 return -EFAULT;
229
230         /* Readin fsr, fcr, fir, fdr and copy onto fpstate */
231         asm volatile ( "mov %0=ar.fsr;" : "=r"(fsr));
232         asm volatile ( "mov %0=ar.fcr;" : "=r"(fcr));
233         asm volatile ( "mov %0=ar.fir;" : "=r"(fir));
234         asm volatile ( "mov %0=ar.fdr;" : "=r"(fdr));
235         /*
236          * We need to clear the exception state before calling the signal handler. Clear
237          * the bits 15, bits 0-7 in fp status word. Similar to the functionality of fnclex
238          * instruction.
239          */
240         new_fsr = fsr & ~0x80ff;
241         asm volatile ( "mov ar.fsr=%0;" :: "r"(new_fsr));
242
243         __put_user(fcr & 0xffff, &save->cw);
244         __put_user(fsr & 0xffff, &save->sw);
245         __put_user((fsr>>16) & 0xffff, &save->tag);
246         __put_user(fir, &save->ipoff);
247         __put_user((fir>>32) & 0xffff, &save->cssel);
248         __put_user(fdr, &save->dataoff);
249         __put_user((fdr>>32) & 0xffff, &save->datasel);
250         __put_user(fsr & 0xffff, &save->status);
251
252         mxcsr = ((fcr>>32) & 0xff80) | ((fsr>>32) & 0x3f);
253         __put_user(mxcsr & 0xffff, &save->mxcsr);
254         __put_user( 0, &save->magic); //#define X86_FXSR_MAGIC   0x0000
255
256         /*
257          * save f8 and f9  from pt_regs
258          * save f10..f15 from live register set
259          */
260         /*
261          *  Find the location where f8 has to go in fp reg stack.  This depends on
262          *  TOP(11:13) field of sw. Other f reg continue sequentially from where f8 maps
263          *  to.
264          */
265         fp_tos = (fsr>>11)&0x7;
266         fr8_st_map = (8-fp_tos)&0x7;
267         ptp = ia64_task_regs(tsk);
268         fpregp = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15);
269         ia64f2ia32f(fpregp, &ptp->f8);
270         copy_to_user(&save->_st[(0+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));
271         ia64f2ia32f(fpregp, &ptp->f9);
272         copy_to_user(&save->_st[(1+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));
273
274         __stfe(fpregp, 10);
275         copy_to_user(&save->_st[(2+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));
276         __stfe(fpregp, 11);
277         copy_to_user(&save->_st[(3+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));
278         __stfe(fpregp, 12);
279         copy_to_user(&save->_st[(4+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));
280         __stfe(fpregp, 13);
281         copy_to_user(&save->_st[(5+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));
282         __stfe(fpregp, 14);
283         copy_to_user(&save->_st[(6+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));
284         __stfe(fpregp, 15);
285         copy_to_user(&save->_st[(7+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));
286
287         __stf8(&num128[0], 16);
288         __stf8(&num128[1], 17);
289         copy_to_user(&save->_xmm[0], num128, sizeof(struct _xmmreg_ia32));
290
291         __stf8(&num128[0], 18);
292         __stf8(&num128[1], 19);
293         copy_to_user(&save->_xmm[1], num128, sizeof(struct _xmmreg_ia32));
294
295         __stf8(&num128[0], 20);
296         __stf8(&num128[1], 21);
297         copy_to_user(&save->_xmm[2], num128, sizeof(struct _xmmreg_ia32));
298
299         __stf8(&num128[0], 22);
300         __stf8(&num128[1], 23);
301         copy_to_user(&save->_xmm[3], num128, sizeof(struct _xmmreg_ia32));
302
303         __stf8(&num128[0], 24);
304         __stf8(&num128[1], 25);
305         copy_to_user(&save->_xmm[4], num128, sizeof(struct _xmmreg_ia32));
306
307         __stf8(&num128[0], 26);
308         __stf8(&num128[1], 27);
309         copy_to_user(&save->_xmm[5], num128, sizeof(struct _xmmreg_ia32));
310
311         __stf8(&num128[0], 28);
312         __stf8(&num128[1], 29);
313         copy_to_user(&save->_xmm[6], num128, sizeof(struct _xmmreg_ia32));
314
315         __stf8(&num128[0], 30);
316         __stf8(&num128[1], 31);
317         copy_to_user(&save->_xmm[7], num128, sizeof(struct _xmmreg_ia32));
318         return 0;
319 }
320
321 static int
322 restore_ia32_fpstate_live (struct _fpstate_ia32 *save)
323 {
324         struct task_struct *tsk = current;
325         struct pt_regs *ptp;
326         unsigned int lo, hi;
327         unsigned long num128[2];
328         unsigned long num64, mxcsr;
329         struct _fpreg_ia32 *fpregp;
330         char buf[32];
331         unsigned long fsr, fcr, fir, fdr;
332         int fp_tos, fr8_st_map;
333
334         if (!access_ok(VERIFY_READ, save, sizeof(*save)))
335                 return(-EFAULT);
336
337         /*
338          * Updating fsr, fcr, fir, fdr.
339          * Just a bit more complicated than save.
340          * - Need to make sure that we dont write any value other than the
341          *   specific fpstate info
342          * - Need to make sure that the untouched part of frs, fdr, fir, fcr
343          *   should remain same while writing.
344          * So, we do a read, change specific fields and write.
345          */
346         asm volatile ( "mov %0=ar.fsr;" : "=r"(fsr));
347         asm volatile ( "mov %0=ar.fcr;" : "=r"(fcr));
348         asm volatile ( "mov %0=ar.fir;" : "=r"(fir));
349         asm volatile ( "mov %0=ar.fdr;" : "=r"(fdr));
350
351         __get_user(mxcsr, (unsigned int *)&save->mxcsr);
352         /* setting bits 0..5 8..12 with cw and 39..47 from mxcsr */
353         __get_user(lo, (unsigned int *)&save->cw);
354         num64 = mxcsr & 0xff10;
355         num64 = (num64 << 32) | (lo & 0x1f3f);
356         fcr = (fcr & (~0xff1000001f3f)) | num64;
357
358         /* setting bits 0..31 with sw and tag and 32..37 from mxcsr */
359         __get_user(lo, (unsigned int *)&save->sw);
360         /* set bits 15,7 (fsw.b, fsw.es) to reflect the current error status */
361         if ( !(lo & 0x7f) )
362                 lo &= (~0x8080);
363         __get_user(hi, (unsigned int *)&save->tag);
364         num64 = mxcsr & 0x3f;
365         num64 = (num64 << 16) | (hi & 0xffff);
366         num64 = (num64 << 16) | (lo & 0xffff);
367         fsr = (fsr & (~0x3fffffffff)) | num64;
368
369         /* setting bits 0..47 with cssel and ipoff */
370         __get_user(lo, (unsigned int *)&save->ipoff);
371         __get_user(hi, (unsigned int *)&save->cssel);
372         num64 = hi & 0xffff;
373         num64 = (num64 << 32) | lo;
374         fir = (fir & (~0xffffffffffff)) | num64;
375
376         /* setting bits 0..47 with datasel and dataoff */
377         __get_user(lo, (unsigned int *)&save->dataoff);
378         __get_user(hi, (unsigned int *)&save->datasel);
379         num64 = hi & 0xffff;
380         num64 = (num64 << 32) | lo;
381         fdr = (fdr & (~0xffffffffffff)) | num64;
382
383         asm volatile ( "mov ar.fsr=%0;" :: "r"(fsr));
384         asm volatile ( "mov ar.fcr=%0;" :: "r"(fcr));
385         asm volatile ( "mov ar.fir=%0;" :: "r"(fir));
386         asm volatile ( "mov ar.fdr=%0;" :: "r"(fdr));
387
388         /*
389          * restore f8, f9 onto pt_regs
390          * restore f10..f15 onto live registers
391          */
392         /*
393          *  Find the location where f8 has to go in fp reg stack.  This depends on
394          *  TOP(11:13) field of sw. Other f reg continue sequentially from where f8 maps
395          *  to.
396          */
397         fp_tos = (fsr>>11)&0x7;
398         fr8_st_map = (8-fp_tos)&0x7;
399         fpregp = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15);
400
401         ptp = ia64_task_regs(tsk);
402         copy_from_user(fpregp, &save->_st[(0+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32));
403         ia32f2ia64f(&ptp->f8, fpregp);
404         copy_from_user(fpregp, &save->_st[(1+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32));
405         ia32f2ia64f(&ptp->f9, fpregp);
406
407         copy_from_user(fpregp, &save->_st[(2+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32));
408         __ldfe(10, fpregp);
409         copy_from_user(fpregp, &save->_st[(3+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32));
410         __ldfe(11, fpregp);
411         copy_from_user(fpregp, &save->_st[(4+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32));
412         __ldfe(12, fpregp);
413         copy_from_user(fpregp, &save->_st[(5+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32));
414         __ldfe(13, fpregp);
415         copy_from_user(fpregp, &save->_st[(6+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32));
416         __ldfe(14, fpregp);
417         copy_from_user(fpregp, &save->_st[(7+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32));
418         __ldfe(15, fpregp);
419
420         copy_from_user(num128, &save->_xmm[0], sizeof(struct _xmmreg_ia32));
421         __ldf8(16, &num128[0]);
422         __ldf8(17, &num128[1]);
423
424         copy_from_user(num128, &save->_xmm[1], sizeof(struct _xmmreg_ia32));
425         __ldf8(18, &num128[0]);
426         __ldf8(19, &num128[1]);
427
428         copy_from_user(num128, &save->_xmm[2], sizeof(struct _xmmreg_ia32));
429         __ldf8(20, &num128[0]);
430         __ldf8(21, &num128[1]);
431
432         copy_from_user(num128, &save->_xmm[3], sizeof(struct _xmmreg_ia32));
433         __ldf8(22, &num128[0]);
434         __ldf8(23, &num128[1]);
435
436         copy_from_user(num128, &save->_xmm[4], sizeof(struct _xmmreg_ia32));
437         __ldf8(24, &num128[0]);
438         __ldf8(25, &num128[1]);
439
440         copy_from_user(num128, &save->_xmm[5], sizeof(struct _xmmreg_ia32));
441         __ldf8(26, &num128[0]);
442         __ldf8(27, &num128[1]);
443
444         copy_from_user(num128, &save->_xmm[6], sizeof(struct _xmmreg_ia32));
445         __ldf8(28, &num128[0]);
446         __ldf8(29, &num128[1]);
447
448         copy_from_user(num128, &save->_xmm[7], sizeof(struct _xmmreg_ia32));
449         __ldf8(30, &num128[0]);
450         __ldf8(31, &num128[1]);
451         return 0;
452 }
453
454 static inline void
455 sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int restorer)
456 {
457         if (handler + 1 <= 2)
458                 /* SIG_DFL, SIG_IGN, or SIG_ERR: must sign-extend to 64-bits */
459                 sa->sa.sa_handler = (__sighandler_t) A((int) handler);
460         else
461                 sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler);
462 }
463
464 asmlinkage long
465 ia32_rt_sigsuspend (sigset32_t *uset, unsigned int sigsetsize, struct sigscratch *scr)
466 {
467         extern long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall);
468         sigset_t oldset, set;
469
470         scr->scratch_unat = 0;  /* avoid leaking kernel bits to user level */
471         memset(&set, 0, sizeof(&set));
472
473         if (sigsetsize > sizeof(sigset_t))
474                 return -EINVAL;
475
476         if (copy_from_user(&set.sig, &uset->sig, sigsetsize))
477                 return -EFAULT;
478
479         sigdelsetmask(&set, ~_BLOCKABLE);
480
481         spin_lock_irq(&current->sigmask_lock);
482         {
483                 oldset = current->blocked;
484                 current->blocked = set;
485                 recalc_sigpending(current);
486         }
487         spin_unlock_irq(&current->sigmask_lock);
488
489         /*
490          * The return below usually returns to the signal handler.  We need to pre-set the
491          * correct error code here to ensure that the right values get saved in sigcontext
492          * by ia64_do_signal.
493          */
494         scr->pt.r8 = -EINTR;
495         while (1) {
496                 current->state = TASK_INTERRUPTIBLE;
497                 schedule();
498                 if (ia64_do_signal(&oldset, scr, 1))
499                         return -EINTR;
500         }
501 }
502
503 asmlinkage long
504 ia32_sigsuspend (unsigned int mask, struct sigscratch *scr)
505 {
506         return ia32_rt_sigsuspend((sigset32_t *)&mask, sizeof(mask), scr);
507 }
508
509 asmlinkage long
510 sys32_signal (int sig, unsigned int handler)
511 {
512         struct k_sigaction new_sa, old_sa;
513         int ret;
514
515         sigact_set_handler(&new_sa, handler, 0);
516         new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK;
517
518         ret = do_sigaction(sig, &new_sa, &old_sa);
519
520         return ret ? ret : IA32_SA_HANDLER(&old_sa);
521 }
522
523 asmlinkage long
524 sys32_rt_sigaction (int sig, struct sigaction32 *act,
525                     struct sigaction32 *oact, unsigned int sigsetsize)
526 {
527         struct k_sigaction new_ka, old_ka;
528         unsigned int handler, restorer;
529         int ret;
530
531         /* XXX: Don't preclude handling different sized sigset_t's.  */
532         if (sigsetsize != sizeof(sigset32_t))
533                 return -EINVAL;
534
535         if (act) {
536                 ret = get_user(handler, &act->sa_handler);
537                 ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags);
538                 ret |= get_user(restorer, &act->sa_restorer);
539                 ret |= copy_from_user(&new_ka.sa.sa_mask, &act->sa_mask, sizeof(sigset32_t));
540                 if (ret)
541                         return -EFAULT;
542
543                 sigact_set_handler(&new_ka, handler, restorer);
544         }
545
546         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
547
548         if (!ret && oact) {
549                 ret = put_user(IA32_SA_HANDLER(&old_ka), &oact->sa_handler);
550                 ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags);
551                 ret |= put_user(IA32_SA_RESTORER(&old_ka), &oact->sa_restorer);
552                 ret |= copy_to_user(&oact->sa_mask, &old_ka.sa.sa_mask, sizeof(sigset32_t));
553         }
554         return ret;
555 }
556
557
558 extern asmlinkage long sys_rt_sigprocmask (int how, sigset_t *set, sigset_t *oset,
559                                            size_t sigsetsize);
560
561 asmlinkage long
562 sys32_rt_sigprocmask (int how, sigset32_t *set, sigset32_t *oset, unsigned int sigsetsize)
563 {
564         mm_segment_t old_fs = get_fs();
565         sigset_t s;
566         long ret;
567
568         if (sigsetsize > sizeof(s))
569                 return -EINVAL;
570
571         if (set) {
572                 memset(&s, 0, sizeof(s));
573                 if (copy_from_user(&s.sig, set, sigsetsize))
574                         return -EFAULT;
575         }
576         set_fs(KERNEL_DS);
577         ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sizeof(s));
578         set_fs(old_fs);
579         if (ret)
580                 return ret;
581         if (oset) {
582                 if (copy_to_user(oset, &s.sig, sigsetsize))
583                         return -EFAULT;
584         }
585         return 0;
586 }
587
588 asmlinkage long
589 sys32_sigprocmask (int how, unsigned int *set, unsigned int *oset)
590 {
591         return sys32_rt_sigprocmask(how, (sigset32_t *) set, (sigset32_t *) oset, sizeof(*set));
592 }
593
594 asmlinkage long
595 sys32_rt_sigtimedwait (sigset32_t *uthese, siginfo_t32 *uinfo, struct timespec32 *uts,
596                        unsigned int sigsetsize)
597 {
598         extern asmlinkage long sys_rt_sigtimedwait (const sigset_t *, siginfo_t *,
599                                                     const struct timespec *, size_t);
600         extern int copy_siginfo_to_user32 (siginfo_t32 *, siginfo_t *);
601         mm_segment_t old_fs = get_fs();
602         struct timespec t;
603         siginfo_t info;
604         sigset_t s;
605         int ret;
606
607         if (copy_from_user(&s.sig, uthese, sizeof(sigset32_t)))
608                 return -EFAULT;
609         if (uts) {
610                 ret = get_user(t.tv_sec, &uts->tv_sec);
611                 ret |= get_user(t.tv_nsec, &uts->tv_nsec);
612                 if (ret)
613                         return -EFAULT;
614         }
615         set_fs(KERNEL_DS);
616         ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize);
617         set_fs(old_fs);
618         if (ret >= 0 && uinfo) {
619                 if (copy_siginfo_to_user32(uinfo, &info))
620                         return -EFAULT;
621         }
622         return ret;
623 }
624
625 asmlinkage long
626 sys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 *uinfo)
627 {
628         extern asmlinkage long sys_rt_sigqueueinfo (int, int, siginfo_t *);
629         extern int copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from);
630         mm_segment_t old_fs = get_fs();
631         siginfo_t info;
632         int ret;
633
634         if (copy_siginfo_from_user32(&info, uinfo))
635                 return -EFAULT;
636         set_fs(KERNEL_DS);
637         ret = sys_rt_sigqueueinfo(pid, sig, &info);
638         set_fs(old_fs);
639         return ret;
640 }
641
642 asmlinkage long
643 sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
644 {
645         struct k_sigaction new_ka, old_ka;
646         unsigned int handler, restorer;
647         int ret;
648
649         if (act) {
650                 old_sigset32_t mask;
651
652                 ret = get_user(handler, &act->sa_handler);
653                 ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags);
654                 ret |= get_user(restorer, &act->sa_restorer);
655                 ret |= get_user(mask, &act->sa_mask);
656                 if (ret)
657                         return ret;
658
659                 sigact_set_handler(&new_ka, handler, restorer);
660                 siginitset(&new_ka.sa.sa_mask, mask);
661         }
662
663         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
664
665         if (!ret && oact) {
666                 ret = put_user(IA32_SA_HANDLER(&old_ka), &oact->sa_handler);
667                 ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags);
668                 ret |= put_user(IA32_SA_RESTORER(&old_ka), &oact->sa_restorer);
669                 ret |= put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
670         }
671
672         return ret;
673 }
674
675 static int
676 setup_sigcontext_ia32 (struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate,
677                        struct pt_regs *regs, unsigned long mask)
678 {
679         int  err = 0;
680         unsigned long flag;
681
682         if (!access_ok(VERIFY_WRITE, sc, sizeof(*sc)))
683                 return -EFAULT;
684
685         err |= __put_user((regs->r16 >> 32) & 0xffff, (unsigned int *)&sc->fs);
686         err |= __put_user((regs->r16 >> 48) & 0xffff, (unsigned int *)&sc->gs);
687         err |= __put_user((regs->r16 >> 16) & 0xffff, (unsigned int *)&sc->es);
688         err |= __put_user(regs->r16 & 0xffff, (unsigned int *)&sc->ds);
689         err |= __put_user(regs->r15, &sc->edi);
690         err |= __put_user(regs->r14, &sc->esi);
691         err |= __put_user(regs->r13, &sc->ebp);
692         err |= __put_user(regs->r12, &sc->esp);
693         err |= __put_user(regs->r11, &sc->ebx);
694         err |= __put_user(regs->r10, &sc->edx);
695         err |= __put_user(regs->r9, &sc->ecx);
696         err |= __put_user(regs->r8, &sc->eax);
697 #if 0
698         err |= __put_user(current->tss.trap_no, &sc->trapno);
699         err |= __put_user(current->tss.error_code, &sc->err);
700 #endif
701         err |= __put_user(regs->cr_iip, &sc->eip);
702         err |= __put_user(regs->r17 & 0xffff, (unsigned int *)&sc->cs);
703         /*
704          *  `eflags' is in an ar register for this context
705          */
706         asm volatile ("mov %0=ar.eflag ;;" : "=r"(flag));
707         err |= __put_user((unsigned int)flag, &sc->eflags);
708         err |= __put_user(regs->r12, &sc->esp_at_signal);
709         err |= __put_user((regs->r17 >> 16) & 0xffff, (unsigned int *)&sc->ss);
710
711         if ( save_ia32_fpstate_live(fpstate) < 0 )
712                 err = -EFAULT;
713         else
714                 err |= __put_user((u32)(u64)fpstate, &sc->fpstate);
715
716 #if 0
717         tmp = save_i387(fpstate);
718         if (tmp < 0)
719                 err = 1;
720         else
721                 err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);
722
723         /* non-iBCS2 extensions.. */
724 #endif
725         err |= __put_user(mask, &sc->oldmask);
726 #if 0
727         err |= __put_user(current->tss.cr2, &sc->cr2);
728 #endif
729         return err;
730 }
731
732 static int
733 restore_sigcontext_ia32 (struct pt_regs *regs, struct sigcontext_ia32 *sc, int *peax)
734 {
735         unsigned int err = 0;
736
737         if (!access_ok(VERIFY_READ, sc, sizeof(*sc)))
738                 return(-EFAULT);
739
740 #define COPY(ia64x, ia32x)      err |= __get_user(regs->ia64x, &sc->ia32x)
741
742 #define copyseg_gs(tmp)         (regs->r16 |= (unsigned long) tmp << 48)
743 #define copyseg_fs(tmp)         (regs->r16 |= (unsigned long) tmp << 32)
744 #define copyseg_cs(tmp)         (regs->r17 |= tmp)
745 #define copyseg_ss(tmp)         (regs->r17 |= (unsigned long) tmp << 16)
746 #define copyseg_es(tmp)         (regs->r16 |= (unsigned long) tmp << 16)
747 #define copyseg_ds(tmp)         (regs->r16 |= tmp)
748
749 #define COPY_SEG(seg)                                   \
750         {                                               \
751                 unsigned short tmp;                     \
752                 err |= __get_user(tmp, &sc->seg);       \
753                 copyseg_##seg(tmp);                     \
754         }
755 #define COPY_SEG_STRICT(seg)                            \
756         {                                               \
757                 unsigned short tmp;                     \
758                 err |= __get_user(tmp, &sc->seg);       \
759                 copyseg_##seg(tmp|3);                   \
760         }
761
762         /* To make COPY_SEGs easier, we zero r16, r17 */
763         regs->r16 = 0;
764         regs->r17 = 0;
765
766         COPY_SEG(gs);
767         COPY_SEG(fs);
768         COPY_SEG(es);
769         COPY_SEG(ds);
770         COPY(r15, edi);
771         COPY(r14, esi);
772         COPY(r13, ebp);
773         COPY(r12, esp);
774         COPY(r11, ebx);
775         COPY(r10, edx);
776         COPY(r9, ecx);
777         COPY(cr_iip, eip);
778         COPY_SEG_STRICT(cs);
779         COPY_SEG_STRICT(ss);
780         ia32_load_segment_descriptors(current);
781         {
782                 unsigned int tmpflags;
783                 unsigned long flag;
784
785                 /*
786                  *  IA32 `eflags' is not part of `pt_regs', it's in an ar register which
787                  *  is part of the thread context.  Fortunately, we are executing in the
788                  *  IA32 process's context.
789                  */
790                 err |= __get_user(tmpflags, &sc->eflags);
791                 asm volatile ("mov %0=ar.eflag ;;" : "=r"(flag));
792                 flag &= ~0x40DD5;
793                 flag |= (tmpflags & 0x40DD5);
794                 asm volatile ("mov ar.eflag=%0 ;;" :: "r"(flag));
795
796                 regs->r1 = -1;  /* disable syscall checks, r1 is orig_eax */
797         }
798
799         {
800                 struct _fpstate_ia32 *buf = NULL;
801                 u32    fpstate_ptr;
802                 err |= get_user(fpstate_ptr, &(sc->fpstate));
803                 buf = (struct _fpstate_ia32 *)(u64)fpstate_ptr;
804                 if (buf) {
805                         err |= restore_ia32_fpstate_live(buf);
806                 }
807         }
808
809 #if 0
810         {
811                 struct _fpstate * buf;
812                 err |= __get_user(buf, &sc->fpstate);
813                 if (buf) {
814                         if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
815                                 goto badframe;
816                         err |= restore_i387(buf);
817                 }
818         }
819 #endif
820
821         err |= __get_user(*peax, &sc->eax);
822         return err;
823
824 #if 0
825   badframe:
826         return 1;
827 #endif
828 }
829
830 /*
831  * Determine which stack to use..
832  */
833 static inline void *
834 get_sigframe (struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
835 {
836         unsigned long esp;
837
838         /* Default to using normal stack (truncate off sign-extension of bit 31: */
839         esp = (unsigned int) regs->r12;
840
841         /* This is the X/Open sanctioned signal stack switching.  */
842         if (ka->sa.sa_flags & SA_ONSTACK) {
843                 if (!on_sig_stack(esp))
844                         esp = current->sas_ss_sp + current->sas_ss_size;
845         }
846         /* Legacy stack switching not supported */
847
848         return (void *)((esp - frame_size) & -8ul);
849 }
850
851 static int
852 setup_frame_ia32 (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs)
853 {
854         struct exec_domain *ed = current->exec_domain;
855         struct sigframe_ia32 *frame;
856         int err = 0;
857
858         frame = get_sigframe(ka, regs, sizeof(*frame));
859
860         if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
861                 goto give_sigsegv;
862
863         err |= __put_user((ed && ed->signal_invmap
864                            && sig < 32 ? (int)(ed->signal_invmap[sig]) : sig), &frame->sig);
865
866         err |= setup_sigcontext_ia32(&frame->sc, &frame->fpstate, regs, set->sig[0]);
867
868         if (_IA32_NSIG_WORDS > 1)
869                 err |= __copy_to_user(frame->extramask, (char *) &set->sig + 4,
870                                       sizeof(frame->extramask));
871
872         /* Set up to return from userspace.  If provided, use a stub
873            already in userspace.  */
874         if (ka->sa.sa_flags & SA_RESTORER) {
875                 unsigned int restorer = IA32_SA_RESTORER(ka);
876                 err |= __put_user(restorer, &frame->pretcode);
877         } else {
878                 err |= __put_user((long)frame->retcode, &frame->pretcode);
879                 /* This is popl %eax ; movl $,%eax ; int $0x80 */
880                 err |= __put_user(0xb858, (short *)(frame->retcode+0));
881                 err |= __put_user(__IA32_NR_sigreturn & 0xffff, (short *)(frame->retcode+2));
882                 err |= __put_user(__IA32_NR_sigreturn >> 16, (short *)(frame->retcode+4));
883                 err |= __put_user(0x80cd, (short *)(frame->retcode+6));
884         }
885
886         if (err)
887                 goto give_sigsegv;
888
889         /* Set up registers for signal handler */
890         regs->r12 = (unsigned long) frame;
891         regs->cr_iip = IA32_SA_HANDLER(ka);
892
893         set_fs(USER_DS);
894         regs->r16 = (__USER_DS << 16) |  (__USER_DS); /* ES == DS, GS, FS are zero */
895         regs->r17 = (__USER_DS << 16) | __USER_CS;
896
897 #if 0
898         regs->eflags &= ~TF_MASK;
899 #endif
900
901 #if 0
902         printk("SIG deliver (%s:%d): sig=%d sp=%p pc=%lx ra=%x\n",
903                current->comm, current->pid, sig, (void *) frame, regs->cr_iip, frame->pretcode);
904 #endif
905
906         return 1;
907
908   give_sigsegv:
909         if (sig == SIGSEGV)
910                 ka->sa.sa_handler = SIG_DFL;
911         force_sig(SIGSEGV, current);
912         return 0;
913 }
914
915 static int
916 setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info,
917                      sigset_t *set, struct pt_regs * regs)
918 {
919         struct exec_domain *ed = current->exec_domain;
920         struct rt_sigframe_ia32 *frame;
921         int err = 0;
922
923         frame = get_sigframe(ka, regs, sizeof(*frame));
924
925         if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
926                 goto give_sigsegv;
927
928         err |= __put_user((ed && ed->signal_invmap
929                            && sig < 32 ? ed->signal_invmap[sig] : sig),
930                           &frame->sig);
931         err |= __put_user((long)&frame->info, &frame->pinfo);
932         err |= __put_user((long)&frame->uc, &frame->puc);
933         err |= copy_siginfo_to_user32(&frame->info, info);
934
935         /* Create the ucontext.  */
936         err |= __put_user(0, &frame->uc.uc_flags);
937         err |= __put_user(0, &frame->uc.uc_link);
938         err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
939         err |= __put_user(sas_ss_flags(regs->r12), &frame->uc.uc_stack.ss_flags);
940         err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
941         err |= setup_sigcontext_ia32(&frame->uc.uc_mcontext, &frame->fpstate, regs, set->sig[0]);
942         err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
943         if (err)
944                 goto give_sigsegv;
945
946         /* Set up to return from userspace.  If provided, use a stub
947            already in userspace.  */
948         if (ka->sa.sa_flags & SA_RESTORER) {
949                 unsigned int restorer = IA32_SA_RESTORER(ka);
950                 err |= __put_user(restorer, &frame->pretcode);
951         } else {
952                 err |= __put_user((long)frame->retcode, &frame->pretcode);
953                 /* This is movl $,%eax ; int $0x80 */
954                 err |= __put_user(0xb8, (char *)(frame->retcode+0));
955                 err |= __put_user(__IA32_NR_rt_sigreturn, (int *)(frame->retcode+1));
956                 err |= __put_user(0x80cd, (short *)(frame->retcode+5));
957         }
958
959         if (err)
960                 goto give_sigsegv;
961
962         /* Set up registers for signal handler */
963         regs->r12 = (unsigned long) frame;
964         regs->cr_iip = IA32_SA_HANDLER(ka);
965
966         set_fs(USER_DS);
967
968         regs->r16 = (__USER_DS << 16) |  (__USER_DS); /* ES == DS, GS, FS are zero */
969         regs->r17 = (__USER_DS << 16) | __USER_CS;
970
971 #if 0
972         regs->eflags &= ~TF_MASK;
973 #endif
974
975 #if 0
976         printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%x\n",
977                current->comm, current->pid, (void *) frame, regs->cr_iip, frame->pretcode);
978 #endif
979
980         return 1;
981
982 give_sigsegv:
983         if (sig == SIGSEGV)
984                 ka->sa.sa_handler = SIG_DFL;
985         force_sig(SIGSEGV, current);
986         return 0;
987 }
988
989 int
990 ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info,
991                    sigset_t *set, struct pt_regs *regs)
992 {
993        /* Set up the stack frame */
994        if (ka->sa.sa_flags & SA_SIGINFO)
995                return setup_rt_frame_ia32(sig, ka, info, set, regs);
996        else
997                return setup_frame_ia32(sig, ka, set, regs);
998 }
999
1000 asmlinkage long
1001 sys32_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7,
1002                  unsigned long stack)
1003 {
1004         struct pt_regs *regs = (struct pt_regs *) &stack;
1005         unsigned long esp = (unsigned int) regs->r12;
1006         struct sigframe_ia32 *frame = (struct sigframe_ia32 *)(esp - 8);
1007         sigset_t set;
1008         int eax;
1009
1010         if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
1011                 goto badframe;
1012
1013         if (__get_user(set.sig[0], &frame->sc.oldmask)
1014             || (_IA32_NSIG_WORDS > 1 && __copy_from_user((char *) &set.sig + 4, &frame->extramask,
1015                                                          sizeof(frame->extramask))))
1016                 goto badframe;
1017
1018         sigdelsetmask(&set, ~_BLOCKABLE);
1019         spin_lock_irq(&current->sigmask_lock);
1020         current->blocked = (sigset_t) set;
1021         recalc_sigpending(current);
1022         spin_unlock_irq(&current->sigmask_lock);
1023
1024         if (restore_sigcontext_ia32(regs, &frame->sc, &eax))
1025                 goto badframe;
1026         return eax;
1027
1028   badframe:
1029         force_sig(SIGSEGV, current);
1030         return 0;
1031 }
1032
1033 asmlinkage long
1034 sys32_rt_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7,
1035                     unsigned long stack)
1036 {
1037         struct pt_regs *regs = (struct pt_regs *) &stack;
1038         unsigned long esp = (unsigned int) regs->r12;
1039         struct rt_sigframe_ia32 *frame = (struct rt_sigframe_ia32 *)(esp - 4);
1040         sigset_t set;
1041         stack_t st;
1042         int eax;
1043
1044         if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
1045                 goto badframe;
1046         if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
1047                 goto badframe;
1048
1049         sigdelsetmask(&set, ~_BLOCKABLE);
1050         spin_lock_irq(&current->sigmask_lock);
1051         current->blocked =  set;
1052         recalc_sigpending(current);
1053         spin_unlock_irq(&current->sigmask_lock);
1054
1055         if (restore_sigcontext_ia32(regs, &frame->uc.uc_mcontext, &eax))
1056                 goto badframe;
1057
1058         if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
1059                 goto badframe;
1060         /* It is more difficult to avoid calling this function than to
1061            call it and ignore errors.  */
1062         do_sigaltstack(&st, NULL, esp);
1063
1064         return eax;
1065
1066   badframe:
1067         force_sig(SIGSEGV, current);
1068         return 0;
1069 }