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