OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [ia64/] [ia32/] [ia32_signal.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.