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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [sparc64/] [kernel/] [signal.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*  $Id: signal.c,v 1.1.1.1 2004-04-15 01:34:14 phoenix Exp $
2
 *  arch/sparc64/kernel/signal.c
3
 *
4
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6
 *  Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
7
 *  Copyright (C) 1997 Eddie C. Dost   (ecd@skynet.be)
8
 *  Copyright (C) 1997,1998 Jakub Jelinek   (jj@sunsite.mff.cuni.cz)
9
 */
10
 
11
#include <linux/config.h>
12
#include <linux/sched.h>
13
#include <linux/kernel.h>
14
#include <linux/signal.h>
15
#include <linux/errno.h>
16
#include <linux/wait.h>
17
#include <linux/ptrace.h>
18
#include <linux/unistd.h>
19
#include <linux/mm.h>
20
#include <linux/smp_lock.h>
21
 
22
#include <asm/uaccess.h>
23
#include <asm/bitops.h>
24
#include <asm/ptrace.h>
25
#include <asm/svr4.h>
26
#include <asm/pgtable.h>
27
#include <asm/fpumacro.h>
28
#include <asm/uctx.h>
29
#include <asm/siginfo.h>
30
#include <asm/visasm.h>
31
 
32
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
33
 
34
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
35
                         unsigned long orig_o0, int ret_from_syscall);
36
 
37
/* This turned off for production... */
38
/* #define DEBUG_SIGNALS 1 */
39
/* #define DEBUG_SIGNALS_TRACE 1 */
40
/* #define DEBUG_SIGNALS_MAPS 1 */
41
 
42
int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
43
{
44
        if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
45
                return -EFAULT;
46
        if (from->si_code < 0)
47
                return __copy_to_user(to, from, sizeof(siginfo_t));
48
        else {
49
                int err;
50
 
51
                /* If you change siginfo_t structure, please be sure
52
                   this code is fixed accordingly.
53
                   It should never copy any pad contained in the structure
54
                   to avoid security leaks, but must copy the generic
55
                   3 ints plus the relevant union member.  */
56
                err = __put_user(*(long *)&from->si_signo, (long *)&to->si_signo);
57
                err |= __put_user((short)from->si_code, &to->si_code);
58
                switch (from->si_code >> 16) {
59
                case __SI_CHLD >> 16:
60
                        err |= __put_user(from->si_utime, &to->si_utime);
61
                        err |= __put_user(from->si_stime, &to->si_stime);
62
                case __SI_FAULT >> 16:
63
                case __SI_POLL >> 16:
64
                        err |= __put_user(from->si_trapno, &to->si_trapno);
65
                default:
66
                        err |= __put_user(from->si_addr, &to->si_addr);
67
                        break;
68
                /* case __SI_RT: This is not generated by the kernel as of now.  */
69
                }
70
                return err;
71
        }
72
}
73
 
74
/* {set, get}context() needed for 64-bit SparcLinux userland. */
75
asmlinkage void sparc64_set_context(struct pt_regs *regs)
76
{
77
        struct ucontext *ucp = (struct ucontext *) regs->u_regs[UREG_I0];
78
        struct thread_struct *tp = &current->thread;
79
        mc_gregset_t *grp;
80
        unsigned long pc, npc, tstate;
81
        unsigned long fp, i7;
82
        unsigned char fenab;
83
        int err;
84
 
85
        flush_user_windows();
86
        if(tp->w_saved                                          ||
87
           (((unsigned long)ucp) & (sizeof(unsigned long)-1))   ||
88
           (!__access_ok((unsigned long)ucp, sizeof(*ucp))))
89
                goto do_sigsegv;
90
        grp  = &ucp->uc_mcontext.mc_gregs;
91
        err  = __get_user(pc, &((*grp)[MC_PC]));
92
        err |= __get_user(npc, &((*grp)[MC_NPC]));
93
        if(err || ((pc | npc) & 3))
94
                goto do_sigsegv;
95
        if(regs->u_regs[UREG_I1]) {
96
                sigset_t set;
97
 
98
                if (_NSIG_WORDS == 1) {
99
                        if (__get_user(set.sig[0], &ucp->uc_sigmask.sig[0]))
100
                                goto do_sigsegv;
101
                } else {
102
                        if (__copy_from_user(&set, &ucp->uc_sigmask, sizeof(sigset_t)))
103
                                goto do_sigsegv;
104
                }
105
                sigdelsetmask(&set, ~_BLOCKABLE);
106
                spin_lock_irq(&current->sigmask_lock);
107
                current->blocked = set;
108
                recalc_sigpending(current);
109
                spin_unlock_irq(&current->sigmask_lock);
110
        }
111
        if ((tp->flags & SPARC_FLAG_32BIT) != 0) {
112
                pc &= 0xffffffff;
113
                npc &= 0xffffffff;
114
        }
115
        regs->tpc = pc;
116
        regs->tnpc = npc;
117
        err |= __get_user(regs->y, &((*grp)[MC_Y]));
118
        err |= __get_user(tstate, &((*grp)[MC_TSTATE]));
119
        regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
120
        regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC));
121
        err |= __get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1]));
122
        err |= __get_user(regs->u_regs[UREG_G2], (&(*grp)[MC_G2]));
123
        err |= __get_user(regs->u_regs[UREG_G3], (&(*grp)[MC_G3]));
124
        err |= __get_user(regs->u_regs[UREG_G4], (&(*grp)[MC_G4]));
125
        err |= __get_user(regs->u_regs[UREG_G5], (&(*grp)[MC_G5]));
126
        err |= __get_user(regs->u_regs[UREG_G6], (&(*grp)[MC_G6]));
127
        err |= __get_user(regs->u_regs[UREG_G7], (&(*grp)[MC_G7]));
128
        err |= __get_user(regs->u_regs[UREG_I0], (&(*grp)[MC_O0]));
129
        err |= __get_user(regs->u_regs[UREG_I1], (&(*grp)[MC_O1]));
130
        err |= __get_user(regs->u_regs[UREG_I2], (&(*grp)[MC_O2]));
131
        err |= __get_user(regs->u_regs[UREG_I3], (&(*grp)[MC_O3]));
132
        err |= __get_user(regs->u_regs[UREG_I4], (&(*grp)[MC_O4]));
133
        err |= __get_user(regs->u_regs[UREG_I5], (&(*grp)[MC_O5]));
134
        err |= __get_user(regs->u_regs[UREG_I6], (&(*grp)[MC_O6]));
135
        err |= __get_user(regs->u_regs[UREG_I7], (&(*grp)[MC_O7]));
136
 
137
        err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp));
138
        err |= __get_user(i7, &(ucp->uc_mcontext.mc_i7));
139
        err |= __put_user(fp,
140
              (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6])));
141
        err |= __put_user(i7,
142
              (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7])));
143
 
144
        err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
145
        if(fenab) {
146
                unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
147
                unsigned long fprs;
148
 
149
                fprs_write(0);
150
                err |= __get_user(fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs));
151
                if (fprs & FPRS_DL)
152
                        err |= copy_from_user(fpregs,
153
                                              &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs),
154
                                              (sizeof(unsigned int) * 32));
155
                if (fprs & FPRS_DU)
156
                        err |= copy_from_user(fpregs+16,
157
                         ((unsigned long *)&(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs))+16,
158
                         (sizeof(unsigned int) * 32));
159
                err |= __get_user(current->thread.xfsr[0],
160
                                  &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
161
                err |= __get_user(current->thread.gsr[0],
162
                                  &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
163
                regs->tstate &= ~TSTATE_PEF;
164
        }
165
        if (err)
166
                goto do_sigsegv;
167
 
168
        return;
169
do_sigsegv:
170
        do_exit(SIGSEGV);
171
}
172
 
173
asmlinkage void sparc64_get_context(struct pt_regs *regs)
174
{
175
        struct ucontext *ucp = (struct ucontext *) regs->u_regs[UREG_I0];
176
        struct thread_struct *tp = &current->thread;
177
        mc_gregset_t *grp;
178
        mcontext_t *mcp;
179
        unsigned long fp, i7;
180
        unsigned char fenab;
181
        int err;
182
 
183
        synchronize_user_stack();
184
        if(tp->w_saved || clear_user(ucp, sizeof(*ucp)))
185
                goto do_sigsegv;
186
 
187
#if 1
188
        fenab = 0; /* IMO get_context is like any other system call, thus modifies FPU state -jj */
189
#else
190
        fenab = (current->thread.fpsaved[0] & FPRS_FEF);
191
#endif
192
 
193
        mcp = &ucp->uc_mcontext;
194
        grp = &mcp->mc_gregs;
195
 
196
        /* Skip over the trap instruction, first. */
197
        if ((tp->flags & SPARC_FLAG_32BIT) != 0) {
198
                regs->tpc   = (regs->tnpc & 0xffffffff);
199
                regs->tnpc  = (regs->tnpc + 4) & 0xffffffff;
200
        } else {
201
                regs->tpc   = regs->tnpc;
202
                regs->tnpc += 4;
203
        }
204
        err = 0;
205
        if (_NSIG_WORDS == 1)
206
                err |= __put_user(current->blocked.sig[0],
207
                                  (unsigned long *)&ucp->uc_sigmask);
208
        else
209
                err |= __copy_to_user(&ucp->uc_sigmask, &current->blocked,
210
                                      sizeof(sigset_t));
211
 
212
        err |= __put_user(regs->tstate, &((*grp)[MC_TSTATE]));
213
        err |= __put_user(regs->tpc, &((*grp)[MC_PC]));
214
        err |= __put_user(regs->tnpc, &((*grp)[MC_NPC]));
215
        err |= __put_user(regs->y, &((*grp)[MC_Y]));
216
        err |= __put_user(regs->u_regs[UREG_G1], &((*grp)[MC_G1]));
217
        err |= __put_user(regs->u_regs[UREG_G2], &((*grp)[MC_G2]));
218
        err |= __put_user(regs->u_regs[UREG_G3], &((*grp)[MC_G3]));
219
        err |= __put_user(regs->u_regs[UREG_G4], &((*grp)[MC_G4]));
220
        err |= __put_user(regs->u_regs[UREG_G5], &((*grp)[MC_G5]));
221
        err |= __put_user(regs->u_regs[UREG_G6], &((*grp)[MC_G6]));
222
        err |= __put_user(regs->u_regs[UREG_G7], &((*grp)[MC_G7]));
223
        err |= __put_user(regs->u_regs[UREG_I0], &((*grp)[MC_O0]));
224
        err |= __put_user(regs->u_regs[UREG_I1], &((*grp)[MC_O1]));
225
        err |= __put_user(regs->u_regs[UREG_I2], &((*grp)[MC_O2]));
226
        err |= __put_user(regs->u_regs[UREG_I3], &((*grp)[MC_O3]));
227
        err |= __put_user(regs->u_regs[UREG_I4], &((*grp)[MC_O4]));
228
        err |= __put_user(regs->u_regs[UREG_I5], &((*grp)[MC_O5]));
229
        err |= __put_user(regs->u_regs[UREG_I6], &((*grp)[MC_O6]));
230
        err |= __put_user(regs->u_regs[UREG_I7], &((*grp)[MC_O7]));
231
 
232
        err |= __get_user(fp,
233
                 (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6])));
234
        err |= __get_user(i7,
235
                 (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7])));
236
        err |= __put_user(fp, &(mcp->mc_fp));
237
        err |= __put_user(i7, &(mcp->mc_i7));
238
 
239
        err |= __put_user(fenab, &(mcp->mc_fpregs.mcfpu_enab));
240
        if(fenab) {
241
                unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
242
                unsigned long fprs;
243
 
244
                fprs = current->thread.fpsaved[0];
245
                if (fprs & FPRS_DL)
246
                        err |= copy_to_user(&(mcp->mc_fpregs.mcfpu_fregs), fpregs,
247
                                            (sizeof(unsigned int) * 32));
248
                if (fprs & FPRS_DU)
249
                        err |= copy_to_user(
250
                          ((unsigned long *)&(mcp->mc_fpregs.mcfpu_fregs))+16, fpregs+16,
251
                          (sizeof(unsigned int) * 32));
252
                err |= __put_user(current->thread.xfsr[0], &(mcp->mc_fpregs.mcfpu_fsr));
253
                err |= __put_user(current->thread.gsr[0], &(mcp->mc_fpregs.mcfpu_gsr));
254
                err |= __put_user(fprs, &(mcp->mc_fpregs.mcfpu_fprs));
255
        }
256
        if (err)
257
                goto do_sigsegv;
258
 
259
        return;
260
do_sigsegv:
261
        do_exit(SIGSEGV);
262
}
263
 
264
struct rt_signal_frame {
265
        struct sparc_stackf     ss;
266
        siginfo_t               info;
267
        struct pt_regs          regs;
268
        __siginfo_fpu_t *       fpu_save;
269
        stack_t                 stack;
270
        sigset_t                mask;
271
        __siginfo_fpu_t         fpu_state;
272
};
273
 
274
/* Align macros */
275
#define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame) + 7) & (~7)))
276
 
277
/*
278
 * atomically swap in the new signal mask, and wait for a signal.
279
 * This is really tricky on the Sparc, watch out...
280
 */
281
asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs)
282
{
283
        sigset_t saveset;
284
 
285
#ifdef CONFIG_SPARC32_COMPAT
286
        if (current->thread.flags & SPARC_FLAG_32BIT) {
287
                extern asmlinkage void _sigpause32_common(old_sigset_t32,
288
                                                          struct pt_regs *);
289
                _sigpause32_common(set, regs);
290
                return;
291
        }
292
#endif
293
        set &= _BLOCKABLE;
294
        spin_lock_irq(&current->sigmask_lock);
295
        saveset = current->blocked;
296
        siginitset(&current->blocked, set);
297
        recalc_sigpending(current);
298
        spin_unlock_irq(&current->sigmask_lock);
299
 
300
        if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
301
                regs->tpc = (regs->tnpc & 0xffffffff);
302
                regs->tnpc = (regs->tnpc + 4) & 0xffffffff;
303
        } else {
304
                regs->tpc = regs->tnpc;
305
                regs->tnpc += 4;
306
        }
307
 
308
        /* Condition codes and return value where set here for sigpause,
309
         * and so got used by setup_frame, which again causes sigreturn()
310
         * to return -EINTR.
311
         */
312
        while (1) {
313
                current->state = TASK_INTERRUPTIBLE;
314
                schedule();
315
                /*
316
                 * Return -EINTR and set condition code here,
317
                 * so the interrupted system call actually returns
318
                 * these.
319
                 */
320
                regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
321
                regs->u_regs[UREG_I0] = EINTR;
322
                if (do_signal(&saveset, regs, 0, 0))
323
                        return;
324
        }
325
}
326
 
327
asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs)
328
{
329
        _sigpause_common(set, regs);
330
}
331
 
332
asmlinkage void do_sigsuspend(struct pt_regs *regs)
333
{
334
        _sigpause_common(regs->u_regs[UREG_I0], regs);
335
}
336
 
337
asmlinkage void do_rt_sigsuspend(sigset_t *uset, size_t sigsetsize, struct pt_regs *regs)
338
{
339
        sigset_t oldset, set;
340
 
341
        /* XXX: Don't preclude handling different sized sigset_t's.  */
342
        if (sigsetsize != sizeof(sigset_t)) {
343
                regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
344
                regs->u_regs[UREG_I0] = EINVAL;
345
                return;
346
        }
347
        if (copy_from_user(&set, uset, sizeof(set))) {
348
                regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
349
                regs->u_regs[UREG_I0] = EFAULT;
350
                return;
351
        }
352
 
353
        sigdelsetmask(&set, ~_BLOCKABLE);
354
        spin_lock_irq(&current->sigmask_lock);
355
        oldset = current->blocked;
356
        current->blocked = set;
357
        recalc_sigpending(current);
358
        spin_unlock_irq(&current->sigmask_lock);
359
 
360
        if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
361
                regs->tpc = (regs->tnpc & 0xffffffff);
362
                regs->tnpc = (regs->tnpc + 4) & 0xffffffff;
363
        } else {
364
                regs->tpc = regs->tnpc;
365
                regs->tnpc += 4;
366
        }
367
 
368
        /* Condition codes and return value where set here for sigpause,
369
         * and so got used by setup_frame, which again causes sigreturn()
370
         * to return -EINTR.
371
         */
372
        while (1) {
373
                current->state = TASK_INTERRUPTIBLE;
374
                schedule();
375
                /*
376
                 * Return -EINTR and set condition code here,
377
                 * so the interrupted system call actually returns
378
                 * these.
379
                 */
380
                regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
381
                regs->u_regs[UREG_I0] = EINTR;
382
                if (do_signal(&oldset, regs, 0, 0))
383
                        return;
384
        }
385
}
386
 
387
static inline int
388
restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
389
{
390
        unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
391
        unsigned long fprs;
392
        int err;
393
 
394
        err = __get_user(fprs, &fpu->si_fprs);
395
        fprs_write(0);
396
        regs->tstate &= ~TSTATE_PEF;
397
        if (fprs & FPRS_DL)
398
                err |= copy_from_user(fpregs, &fpu->si_float_regs[0],
399
                               (sizeof(unsigned int) * 32));
400
        if (fprs & FPRS_DU)
401
                err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32],
402
                               (sizeof(unsigned int) * 32));
403
        err |= __get_user(current->thread.xfsr[0], &fpu->si_fsr);
404
        err |= __get_user(current->thread.gsr[0], &fpu->si_gsr);
405
        current->thread.fpsaved[0] |= fprs;
406
        return err;
407
}
408
 
409
void do_rt_sigreturn(struct pt_regs *regs)
410
{
411
        struct rt_signal_frame *sf;
412
        unsigned long tpc, tnpc, tstate;
413
        __siginfo_fpu_t *fpu_save;
414
        mm_segment_t old_fs;
415
        sigset_t set;
416
        stack_t st;
417
        int err;
418
 
419
        synchronize_user_stack ();
420
        sf = (struct rt_signal_frame *)
421
                (regs->u_regs [UREG_FP] + STACK_BIAS);
422
 
423
        /* 1. Make sure we are not getting garbage from the user */
424
        if (((unsigned long) sf) & 3)
425
                goto segv;
426
 
427
        err = get_user(tpc, &sf->regs.tpc);
428
        err |= __get_user(tnpc, &sf->regs.tnpc);
429
        if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
430
                tpc &= 0xffffffff;
431
                tnpc &= 0xffffffff;
432
        }
433
        err |= ((tpc | tnpc) & 3);
434
 
435
        /* 2. Restore the state */
436
        err |= __get_user(regs->y, &sf->regs.y);
437
        err |= __get_user(tstate, &sf->regs.tstate);
438
        err |= copy_from_user(regs->u_regs, sf->regs.u_regs, sizeof(regs->u_regs));
439
 
440
        /* User can only change condition codes in %tstate. */
441
        regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
442
        regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC));
443
 
444
        err |= __get_user(fpu_save, &sf->fpu_save);
445
        if (fpu_save)
446
                err |= restore_fpu_state(regs, &sf->fpu_state);
447
 
448
        err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
449
        err |= __copy_from_user(&st, &sf->stack, sizeof(stack_t));
450
 
451
        if (err)
452
                goto segv;
453
 
454
        regs->tpc = tpc;
455
        regs->tnpc = tnpc;
456
 
457
        /* It is more difficult to avoid calling this function than to
458
           call it and ignore errors.  */
459
        old_fs = get_fs();
460
        set_fs(KERNEL_DS);
461
        do_sigaltstack(&st, NULL, (unsigned long)sf);
462
        set_fs(old_fs);
463
 
464
        sigdelsetmask(&set, ~_BLOCKABLE);
465
        spin_lock_irq(&current->sigmask_lock);
466
        current->blocked = set;
467
        recalc_sigpending(current);
468
        spin_unlock_irq(&current->sigmask_lock);
469
        return;
470
segv:
471
        send_sig(SIGSEGV, current, 1);
472
}
473
 
474
/* Checks if the fp is valid */
475
static int invalid_frame_pointer(void *fp, int fplen)
476
{
477
        if (((unsigned long) fp) & 7)
478
                return 1;
479
        return 0;
480
}
481
 
482
static inline int
483
save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
484
{
485
        unsigned long *fpregs = (unsigned long *)(regs+1);
486
        unsigned long fprs;
487
        int err = 0;
488
 
489
        fprs = current->thread.fpsaved[0];
490
        if (fprs & FPRS_DL)
491
                err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
492
                                    (sizeof(unsigned int) * 32));
493
        if (fprs & FPRS_DU)
494
                err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
495
                                    (sizeof(unsigned int) * 32));
496
        err |= __put_user(current->thread.xfsr[0], &fpu->si_fsr);
497
        err |= __put_user(current->thread.gsr[0], &fpu->si_gsr);
498
        err |= __put_user(fprs, &fpu->si_fprs);
499
 
500
        return err;
501
}
502
 
503
static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize)
504
{
505
        unsigned long sp;
506
 
507
        sp = regs->u_regs[UREG_FP] + STACK_BIAS;
508
 
509
        /* This is the X/Open sanctioned signal stack switching.  */
510
        if (ka->sa.sa_flags & SA_ONSTACK) {
511
                if (!on_sig_stack(sp) &&
512
                    !((current->sas_ss_sp + current->sas_ss_size) & 7))
513
                        sp = current->sas_ss_sp + current->sas_ss_size;
514
        }
515
        return (void *)(sp - framesize);
516
}
517
 
518
static inline void
519
setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
520
               int signo, sigset_t *oldset, siginfo_t *info)
521
{
522
        struct rt_signal_frame *sf;
523
        int sigframe_size, err;
524
 
525
        /* 1. Make sure everything is clean */
526
        synchronize_user_stack();
527
        save_and_clear_fpu();
528
 
529
        sigframe_size = RT_ALIGNEDSZ;
530
        if (!(current->thread.fpsaved[0] & FPRS_FEF))
531
                sigframe_size -= sizeof(__siginfo_fpu_t);
532
 
533
        sf = (struct rt_signal_frame *)get_sigframe(ka, regs, sigframe_size);
534
 
535
        if (invalid_frame_pointer (sf, sigframe_size))
536
                goto sigill;
537
 
538
        if (current->thread.w_saved != 0) {
539
#ifdef DEBUG_SIGNALS
540
                printk ("%s[%d]: Invalid user stack frame for "
541
                        "signal delivery.\n", current->comm, current->pid);
542
#endif
543
                goto sigill;
544
        }
545
 
546
        /* 2. Save the current process state */
547
        err = copy_to_user(&sf->regs, regs, sizeof (*regs));
548
 
549
        if (current->thread.fpsaved[0] & FPRS_FEF) {
550
                err |= save_fpu_state(regs, &sf->fpu_state);
551
                err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save);
552
        } else {
553
                err |= __put_user(0, &sf->fpu_save);
554
        }
555
 
556
        /* Setup sigaltstack */
557
        err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
558
        err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
559
        err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);
560
 
561
        err |= copy_to_user(&sf->mask, oldset, sizeof(sigset_t));
562
 
563
        err |= copy_in_user((u64 *)sf,
564
                            (u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS),
565
                            sizeof(struct reg_window));
566
 
567
        if (info)
568
                err |= copy_siginfo_to_user(&sf->info, info);
569
        else {
570
                err |= __put_user(signo, &sf->info.si_signo);
571
                err |= __put_user(SI_NOINFO, &sf->info.si_code);
572
        }
573
        if (err)
574
                goto sigsegv;
575
 
576
        /* 3. signal handler back-trampoline and parameters */
577
        regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS;
578
        regs->u_regs[UREG_I0] = signo;
579
        regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
580
 
581
        /* The sigcontext is passed in this way because of how it
582
         * is defined in GLIBC's /usr/include/bits/sigcontext.h
583
         * for sparc64.  It includes the 128 bytes of siginfo_t.
584
         */
585
        regs->u_regs[UREG_I2] = (unsigned long) &sf->info;
586
 
587
        /* 5. signal handler */
588
        regs->tpc = (unsigned long) ka->sa.sa_handler;
589
        regs->tnpc = (regs->tpc + 4);
590
        if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
591
                regs->tpc &= 0xffffffff;
592
                regs->tnpc &= 0xffffffff;
593
        }
594
        /* 4. return to kernel instructions */
595
        regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
596
        return;
597
 
598
sigill:
599
        do_exit(SIGILL);
600
sigsegv:
601
        do_exit(SIGSEGV);
602
}
603
 
604
static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
605
                                 siginfo_t *info,
606
                                 sigset_t *oldset, struct pt_regs *regs)
607
{
608
        setup_rt_frame(ka, regs, signr, oldset, (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
609
        if(ka->sa.sa_flags & SA_ONESHOT)
610
                ka->sa.sa_handler = SIG_DFL;
611
        if(!(ka->sa.sa_flags & SA_NOMASK)) {
612
                spin_lock_irq(&current->sigmask_lock);
613
                sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
614
                sigaddset(&current->blocked,signr);
615
                recalc_sigpending(current);
616
                spin_unlock_irq(&current->sigmask_lock);
617
        }
618
}
619
 
620
static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
621
                                     struct sigaction *sa)
622
{
623
        switch(regs->u_regs[UREG_I0]) {
624
                case ERESTARTNOHAND:
625
                no_system_call_restart:
626
                        regs->u_regs[UREG_I0] = EINTR;
627
                        regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
628
                        break;
629
                case ERESTARTSYS:
630
                        if(!(sa->sa_flags & SA_RESTART))
631
                                goto no_system_call_restart;
632
                /* fallthrough */
633
                case ERESTARTNOINTR:
634
                        regs->u_regs[UREG_I0] = orig_i0;
635
                        regs->tpc -= 4;
636
                        regs->tnpc -= 4;
637
        }
638
}
639
 
640
#ifdef DEBUG_SIGNALS_MAPS
641
 
642
#define MAPS_LINE_FORMAT          "%016lx-%016lx %s %016lx %s %lu "
643
 
644
static inline void read_maps (void)
645
{
646
        struct vm_area_struct * map, * next;
647
        char * buffer;
648
        ssize_t i;
649
 
650
        buffer = (char*)__get_free_page(GFP_KERNEL);
651
        if (!buffer)
652
                return;
653
 
654
        for (map = current->mm->mmap ; map ; map = next ) {
655
                /* produce the next line */
656
                char *line;
657
                char str[5], *cp = str;
658
                int flags;
659
                kdev_t dev;
660
                unsigned long ino;
661
 
662
                /*
663
                 * Get the next vma now (but it won't be used if we sleep).
664
                 */
665
                next = map->vm_next;
666
                flags = map->vm_flags;
667
 
668
                *cp++ = flags & VM_READ ? 'r' : '-';
669
                *cp++ = flags & VM_WRITE ? 'w' : '-';
670
                *cp++ = flags & VM_EXEC ? 'x' : '-';
671
                *cp++ = flags & VM_MAYSHARE ? 's' : 'p';
672
                *cp++ = 0;
673
 
674
                dev = 0;
675
                ino = 0;
676
                if (map->vm_file != NULL) {
677
                        dev = map->vm_file->f_dentry->d_inode->i_dev;
678
                        ino = map->vm_file->f_dentry->d_inode->i_ino;
679
                        line = d_path(map->vm_file->f_dentry,
680
                                      map->vm_file->f_vfsmnt,
681
                                      buffer, PAGE_SIZE);
682
                        if (IS_ERR(line))
683
                                break;
684
                }
685
                printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT,
686
                              kdevname(dev), ino);
687
                if (map->vm_file != NULL)
688
                        printk("%s\n", line);
689
                else
690
                        printk("\n");
691
        }
692
        free_page((unsigned long)buffer);
693
        return;
694
}
695
 
696
#endif
697
 
698
/* Note that 'init' is a special process: it doesn't get signals it doesn't
699
 * want to handle. Thus you cannot kill init even with a SIGKILL even by
700
 * mistake.
701
 */
702
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
703
                         unsigned long orig_i0, int restart_syscall)
704
{
705
        unsigned long signr;
706
        siginfo_t info;
707
        struct k_sigaction *ka;
708
 
709
        if (!oldset)
710
                oldset = &current->blocked;
711
 
712
#ifdef CONFIG_SPARC32_COMPAT
713
        if (current->thread.flags & SPARC_FLAG_32BIT) {
714
                extern asmlinkage int do_signal32(sigset_t *, struct pt_regs *,
715
                                                  unsigned long, int);
716
                return do_signal32(oldset, regs, orig_i0, restart_syscall);
717
        }
718
#endif  
719
        for (;;) {
720
                spin_lock_irq(&current->sigmask_lock);
721
                signr = dequeue_signal(&current->blocked, &info);
722
                spin_unlock_irq(&current->sigmask_lock);
723
 
724
                if (!signr)
725
                        break;
726
 
727
                if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
728
                        /* Do the syscall restart before we let the debugger
729
                         * look at the child registers.
730
                         */
731
                        if (restart_syscall &&
732
                            (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
733
                             regs->u_regs[UREG_I0] == ERESTARTSYS ||
734
                             regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
735
                                regs->u_regs[UREG_I0] = orig_i0;
736
                                regs->tpc -= 4;
737
                                regs->tnpc -= 4;
738
                                restart_syscall = 0;
739
                        }
740
 
741
                        current->exit_code = signr;
742
                        current->state = TASK_STOPPED;
743
                        notify_parent(current, SIGCHLD);
744
                        schedule();
745
                        if (!(signr = current->exit_code))
746
                                continue;
747
                        current->exit_code = 0;
748
                        if (signr == SIGSTOP)
749
                                continue;
750
 
751
                        /* Update the siginfo structure.  Is this good?  */
752
                        if (signr != info.si_signo) {
753
                                info.si_signo = signr;
754
                                info.si_errno = 0;
755
                                info.si_code = SI_USER;
756
                                info.si_pid = current->p_pptr->pid;
757
                                info.si_uid = current->p_pptr->uid;
758
                        }
759
 
760
                        /* If the (new) signal is now blocked, requeue it.  */
761
                        if (sigismember(&current->blocked, signr)) {
762
                                send_sig_info(signr, &info, current);
763
                                continue;
764
                        }
765
                }
766
 
767
                ka = &current->sig->action[signr-1];
768
 
769
                if (ka->sa.sa_handler == SIG_IGN) {
770
                        if (signr != SIGCHLD)
771
                                continue;
772
 
773
                        /* sys_wait4() grabs the master kernel lock, so
774
                         * we need not do so, that sucker should be
775
                         * threaded and would not be that difficult to
776
                         * do anyways.
777
                         */
778
                        while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
779
                                ;
780
                        continue;
781
                }
782
                if (ka->sa.sa_handler == SIG_DFL) {
783
                        unsigned long exit_code = signr;
784
 
785
                        if (current->pid == 1)
786
                                continue;
787
                        switch (signr) {
788
                        case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
789
                                continue;
790
 
791
                        case SIGTSTP: case SIGTTIN: case SIGTTOU:
792
                                if (is_orphaned_pgrp(current->pgrp))
793
                                        continue;
794
 
795
                        case SIGSTOP:
796
                                if (current->ptrace & PT_PTRACED)
797
                                        continue;
798
                                current->state = TASK_STOPPED;
799
                                current->exit_code = signr;
800
                                if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags &
801
                                      SA_NOCLDSTOP))
802
                                        notify_parent(current, SIGCHLD);
803
                                schedule();
804
                                continue;
805
 
806
                        case SIGQUIT: case SIGILL: case SIGTRAP:
807
                        case SIGABRT: case SIGFPE: case SIGSEGV:
808
                        case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
809
                                if (do_coredump(signr, regs))
810
                                        exit_code |= 0x80;
811
#ifdef DEBUG_SIGNALS
812
                                /* Very useful to debug the dynamic linker */
813
                                printk ("Sig %d going...\n", (int)signr);
814
                                show_regs (regs);
815
#ifdef DEBUG_SIGNALS_TRACE
816
                                {
817
                                        struct reg_window *rw = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
818
                                        unsigned long ins[8];
819
 
820
                                        while (rw &&
821
                                               !(((unsigned long) rw) & 0x3)) {
822
                                                copy_from_user(ins, &rw->ins[0], sizeof(ins));
823
                                                printk("Caller[%016lx](%016lx,%016lx,%016lx,%016lx,%016lx,%016lx)\n", ins[7], ins[0], ins[1], ins[2], ins[3], ins[4], ins[5]);
824
                                                rw = (struct reg_window *)(unsigned long)(ins[6] + STACK_BIAS);
825
                                        }
826
                                }
827
#endif                  
828
#ifdef DEBUG_SIGNALS_MAPS       
829
                                printk("Maps:\n");
830
                                read_maps();
831
#endif
832
#endif
833
                                /* fall through */
834
                        default:
835
                                sig_exit(signr, exit_code, &info);
836
                                /* NOT REACHED */
837
                        }
838
                }
839
                if (restart_syscall)
840
                        syscall_restart(orig_i0, regs, &ka->sa);
841
                handle_signal(signr, ka, &info, oldset, regs);
842
                return 1;
843
        }
844
        if (restart_syscall &&
845
            (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
846
             regs->u_regs[UREG_I0] == ERESTARTSYS ||
847
             regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
848
                /* replay the system call when we are done */
849
                regs->u_regs[UREG_I0] = orig_i0;
850
                regs->tpc -= 4;
851
                regs->tnpc -= 4;
852
        }
853
        return 0;
854
}

powered by: WebSVN 2.1.0

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