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