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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  arch/s390/kernel/signal.c
3
 *
4
 *  S390 version
5
 *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
6
 *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
7
 *
8
 *    Based on Intel version
9
 *
10
 *  Copyright (C) 1991, 1992  Linus Torvalds
11
 *
12
 *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
13
 */
14
 
15
#include <linux/config.h>
16
#include <linux/sched.h>
17
#include <linux/mm.h>
18
#include <linux/smp.h>
19
#include <linux/smp_lock.h>
20
#include <linux/kernel.h>
21
#include <linux/signal.h>
22
#include <linux/errno.h>
23
#include <linux/wait.h>
24
#include <linux/ptrace.h>
25
#include <linux/unistd.h>
26
#include <linux/stddef.h>
27
#include <linux/personality.h>
28
#include <asm/ucontext.h>
29
#include <asm/uaccess.h>
30
 
31
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
32
 
33
 
34
typedef struct
35
{
36
        __u8 callee_used_stack[__SIGNAL_FRAMESIZE];
37
        struct sigcontext sc;
38
        _sigregs sregs;
39
        __u8 retcode[S390_SYSCALL_SIZE];
40
} sigframe;
41
 
42
typedef struct
43
{
44
        __u8 callee_used_stack[__SIGNAL_FRAMESIZE];
45
        __u8 retcode[S390_SYSCALL_SIZE];
46
        struct siginfo info;
47
        struct ucontext uc;
48
} rt_sigframe;
49
 
50
asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
51
 
52
int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
53
{
54
        if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
55
                return -EFAULT;
56
        if (from->si_code < 0)
57
                return __copy_to_user(to, from, sizeof(siginfo_t));
58
        else {
59
                int err;
60
 
61
                /* If you change siginfo_t structure, please be sure
62
                   this code is fixed accordingly.
63
                   It should never copy any pad contained in the structure
64
                   to avoid security leaks, but must copy the generic
65
                   3 ints plus the relevant union member.  */
66
                err = __put_user(from->si_signo, &to->si_signo);
67
                err |= __put_user(from->si_errno, &to->si_errno);
68
                err |= __put_user((short)from->si_code, &to->si_code);
69
                /* First 64bits of unions are always present.  */
70
                err |= __put_user(from->si_pid, &to->si_pid);
71
                err |= __put_user(from->si_uid, &to->si_uid);
72
                switch (from->si_code >> 16) {
73
                case __SI_CHLD >> 16:
74
                        err |= __put_user(from->si_utime, &to->si_utime);
75
                        err |= __put_user(from->si_stime, &to->si_stime);
76
                        err |= __put_user(from->si_status, &to->si_status);
77
                default:
78
                        break;
79
                /* case __SI_RT: This is not generated by the kernel as of now.  */
80
                }
81
                return err;
82
        }
83
}
84
 
85
/*
86
 * Atomically swap in the new signal mask, and wait for a signal.
87
 */
88
asmlinkage int
89
sys_sigsuspend(struct pt_regs * regs,int history0, int history1, old_sigset_t mask)
90
{
91
        sigset_t saveset;
92
 
93
        mask &= _BLOCKABLE;
94
        spin_lock_irq(&current->sigmask_lock);
95
        saveset = current->blocked;
96
        siginitset(&current->blocked, mask);
97
        recalc_sigpending(current);
98
        spin_unlock_irq(&current->sigmask_lock);
99
        regs->gprs[2] = -EINTR;
100
 
101
        while (1) {
102
                set_current_state(TASK_INTERRUPTIBLE);
103
                schedule();
104
                if (do_signal(regs, &saveset))
105
                        return -EINTR;
106
        }
107
}
108
 
109
asmlinkage int
110
sys_rt_sigsuspend(struct pt_regs * regs,sigset_t *unewset, size_t sigsetsize)
111
{
112
        sigset_t saveset, newset;
113
 
114
        /* XXX: Don't preclude handling different sized sigset_t's.  */
115
        if (sigsetsize != sizeof(sigset_t))
116
                return -EINVAL;
117
 
118
        if (copy_from_user(&newset, unewset, sizeof(newset)))
119
                return -EFAULT;
120
        sigdelsetmask(&newset, ~_BLOCKABLE);
121
 
122
        spin_lock_irq(&current->sigmask_lock);
123
        saveset = current->blocked;
124
        current->blocked = newset;
125
        recalc_sigpending(current);
126
        spin_unlock_irq(&current->sigmask_lock);
127
        regs->gprs[2] = -EINTR;
128
 
129
        while (1) {
130
                set_current_state(TASK_INTERRUPTIBLE);
131
                schedule();
132
                if (do_signal(regs, &saveset))
133
                        return -EINTR;
134
        }
135
}
136
 
137
asmlinkage int
138
sys_sigaction(int sig, const struct old_sigaction *act,
139
              struct old_sigaction *oact)
140
{
141
        struct k_sigaction new_ka, old_ka;
142
        int ret;
143
 
144
        if (act) {
145
                old_sigset_t mask;
146
                if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
147
                    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
148
                    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
149
                        return -EFAULT;
150
                __get_user(new_ka.sa.sa_flags, &act->sa_flags);
151
                __get_user(mask, &act->sa_mask);
152
                siginitset(&new_ka.sa.sa_mask, mask);
153
        }
154
 
155
        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
156
 
157
        if (!ret && oact) {
158
                if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
159
                    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
160
                    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
161
                        return -EFAULT;
162
                __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
163
                __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
164
        }
165
 
166
        return ret;
167
}
168
 
169
asmlinkage int
170
sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs)
171
{
172
        return do_sigaltstack(uss, uoss, regs->gprs[15]);
173
}
174
 
175
 
176
 
177
 
178
static int save_sigregs(struct pt_regs *regs,_sigregs *sregs)
179
{
180
        int err;
181
        s390_fp_regs fpregs;
182
 
183
        err = __copy_to_user(&sregs->regs,regs,sizeof(_s390_regs_common));
184
        if(!err)
185
        {
186
                save_fp_regs(&fpregs);
187
                err=__copy_to_user(&sregs->fpregs,&fpregs,sizeof(fpregs));
188
        }
189
        return(err);
190
 
191
}
192
 
193
static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs)
194
{
195
        int err;
196
        s390_fp_regs fpregs;
197
        psw_t saved_psw=regs->psw;
198
        err=__copy_from_user(regs,&sregs->regs,sizeof(_s390_regs_common));
199
        if(!err)
200
        {
201
                regs->trap = -1;                /* disable syscall checks */
202
                regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)|
203
                (regs->psw.mask&PSW_MASK_DEBUGCHANGE);
204
                regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)|
205
                (regs->psw.addr&PSW_ADDR_DEBUGCHANGE);
206
                err=__copy_from_user(&fpregs,&sregs->fpregs,sizeof(fpregs));
207
                if(!err)
208
                        restore_fp_regs(&fpregs);
209
        }
210
        return(err);
211
}
212
 
213
asmlinkage long sys_sigreturn(struct pt_regs *regs)
214
{
215
        sigframe *frame = (sigframe *)regs->gprs[15];
216
        sigset_t set;
217
 
218
        if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
219
                goto badframe;
220
        if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE))
221
                goto badframe;
222
 
223
        sigdelsetmask(&set, ~_BLOCKABLE);
224
        spin_lock_irq(&current->sigmask_lock);
225
        current->blocked = set;
226
        recalc_sigpending(current);
227
        spin_unlock_irq(&current->sigmask_lock);
228
 
229
        if (restore_sigregs(regs, &frame->sregs))
230
                goto badframe;
231
 
232
        return regs->gprs[2];
233
 
234
badframe:
235
        force_sig(SIGSEGV, current);
236
        return 0;
237
}
238
 
239
asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
240
{
241
        rt_sigframe *frame = (rt_sigframe *)regs->gprs[15];
242
        sigset_t set;
243
 
244
        if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
245
                goto badframe;
246
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
247
                goto badframe;
248
 
249
        sigdelsetmask(&set, ~_BLOCKABLE);
250
        spin_lock_irq(&current->sigmask_lock);
251
        current->blocked = set;
252
        recalc_sigpending(current);
253
        spin_unlock_irq(&current->sigmask_lock);
254
 
255
        if (restore_sigregs(regs, &frame->uc.uc_mcontext))
256
                goto badframe;
257
 
258
        /* It is more difficult to avoid calling this function than to
259
           call it and ignore errors.  */
260
        do_sigaltstack(&frame->uc.uc_stack, NULL, regs->gprs[15]);
261
        return regs->gprs[2];
262
 
263
badframe:
264
        force_sig(SIGSEGV, current);
265
        return 0;
266
}
267
 
268
/*
269
 * Set up a signal frame.
270
 */
271
 
272
 
273
/*
274
 * Determine which stack to use..
275
 */
276
static inline void *
277
get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
278
{
279
        unsigned long sp;
280
 
281
        /* Default to using normal stack */
282
        sp = regs->gprs[15];
283
 
284
        /* This is the X/Open sanctioned signal stack switching.  */
285
        if (ka->sa.sa_flags & SA_ONSTACK) {
286
                if (! on_sig_stack(sp))
287
                        sp = current->sas_ss_sp + current->sas_ss_size;
288
        }
289
 
290
        /* This is the legacy signal stack switching. */
291
        else if (!user_mode(regs) &&
292
                 !(ka->sa.sa_flags & SA_RESTORER) &&
293
                 ka->sa.sa_restorer) {
294
                sp = (unsigned long) ka->sa.sa_restorer;
295
        }
296
 
297
        return (void *)((sp - frame_size) & -8ul);
298
}
299
 
300
static inline int map_signal(int sig)
301
{
302
        if (current->exec_domain
303
            && current->exec_domain->signal_invmap
304
            && sig < 32)
305
                return current->exec_domain->signal_invmap[sig];
306
        else
307
                return sig;
308
}
309
 
310
static void setup_frame(int sig, struct k_sigaction *ka,
311
                        sigset_t *set, struct pt_regs * regs)
312
{
313
        sigframe *frame = get_sigframe(ka, regs, sizeof(sigframe));
314
        if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe)))
315
                goto give_sigsegv;
316
 
317
        if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE))
318
                goto give_sigsegv;
319
 
320
        if (save_sigregs(regs, &frame->sregs))
321
                goto give_sigsegv;
322
        if (__put_user(&frame->sregs, &frame->sc.sregs))
323
                goto give_sigsegv;
324
 
325
        /* Set up to return from userspace.  If provided, use a stub
326
           already in userspace.  */
327
        if (ka->sa.sa_flags & SA_RESTORER) {
328
                regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
329
        } else {
330
                regs->gprs[14] = FIX_PSW(frame->retcode);
331
                if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
332
                               (u16 *)(frame->retcode)))
333
                        goto give_sigsegv;
334
        }
335
 
336
        /* Set up backchain. */
337
        if (__put_user(regs->gprs[15], (addr_t *) frame))
338
                goto give_sigsegv;
339
 
340
        /* Set up registers for signal handler */
341
        regs->gprs[15] = (addr_t)frame;
342
        regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
343
        regs->psw.mask = _USER_PSW_MASK;
344
 
345
        regs->gprs[2] = map_signal(sig);
346
        regs->gprs[3] = (addr_t)&frame->sc;
347
 
348
        /* We forgot to include these in the sigcontext.
349
           To avoid breaking binary compatibility, they are passed as args. */
350
        regs->gprs[4] = current->thread.trap_no;
351
        regs->gprs[5] = current->thread.prot_addr;
352
        return;
353
 
354
give_sigsegv:
355
        if (sig == SIGSEGV)
356
                ka->sa.sa_handler = SIG_DFL;
357
        force_sig(SIGSEGV, current);
358
}
359
 
360
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
361
                           sigset_t *set, struct pt_regs * regs)
362
{
363
        int err = 0;
364
        rt_sigframe *frame = get_sigframe(ka, regs, sizeof(rt_sigframe));
365
        if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe)))
366
                goto give_sigsegv;
367
 
368
        if (copy_siginfo_to_user(&frame->info, info))
369
                goto give_sigsegv;
370
 
371
        /* Create the ucontext.  */
372
        err |= __put_user(0, &frame->uc.uc_flags);
373
        err |= __put_user(0, &frame->uc.uc_link);
374
        err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
375
        err |= __put_user(sas_ss_flags(regs->gprs[15]),
376
                          &frame->uc.uc_stack.ss_flags);
377
        err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
378
        err |= save_sigregs(regs, &frame->uc.uc_mcontext);
379
        err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
380
        if (err)
381
                goto give_sigsegv;
382
 
383
        /* Set up to return from userspace.  If provided, use a stub
384
           already in userspace.  */
385
        if (ka->sa.sa_flags & SA_RESTORER) {
386
                regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
387
        } else {
388
                regs->gprs[14] = FIX_PSW(frame->retcode);
389
                err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
390
                                  (u16 *)(frame->retcode));
391
        }
392
 
393
        /* Set up backchain. */
394
        if (__put_user(regs->gprs[15], (addr_t *) frame))
395
                goto give_sigsegv;
396
 
397
        /* Set up registers for signal handler */
398
        regs->gprs[15] = (addr_t)frame;
399
        regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
400
        regs->psw.mask = _USER_PSW_MASK;
401
 
402
        regs->gprs[2] = map_signal(sig);
403
        regs->gprs[3] = (addr_t)&frame->info;
404
        regs->gprs[4] = (addr_t)&frame->uc;
405
        return;
406
 
407
give_sigsegv:
408
        if (sig == SIGSEGV)
409
                ka->sa.sa_handler = SIG_DFL;
410
        force_sig(SIGSEGV, current);
411
}
412
 
413
/*
414
 * OK, we're invoking a handler
415
 */
416
 
417
static void
418
handle_signal(unsigned long sig, struct k_sigaction *ka,
419
              siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
420
{
421
        /* Are we from a system call? */
422
        if (regs->trap == __LC_SVC_OLD_PSW) {
423
                /* If so, check system call restarting.. */
424
                switch (regs->gprs[2]) {
425
                        case -ERESTARTNOHAND:
426
                                regs->gprs[2] = -EINTR;
427
                                break;
428
 
429
                        case -ERESTARTSYS:
430
                                if (!(ka->sa.sa_flags & SA_RESTART)) {
431
                                        regs->gprs[2] = -EINTR;
432
                                        break;
433
                                }
434
                        /* fallthrough */
435
                        case -ERESTARTNOINTR:
436
                                regs->gprs[2] = regs->orig_gpr2;
437
                                regs->psw.addr -= 2;
438
                }
439
        }
440
 
441
        /* Set up the stack frame */
442
        if (ka->sa.sa_flags & SA_SIGINFO)
443
                setup_rt_frame(sig, ka, info, oldset, regs);
444
        else
445
                setup_frame(sig, ka, oldset, regs);
446
 
447
        if (ka->sa.sa_flags & SA_ONESHOT)
448
                ka->sa.sa_handler = SIG_DFL;
449
 
450
        if (!(ka->sa.sa_flags & SA_NODEFER)) {
451
                spin_lock_irq(&current->sigmask_lock);
452
                sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
453
                sigaddset(&current->blocked,sig);
454
                recalc_sigpending(current);
455
                spin_unlock_irq(&current->sigmask_lock);
456
        }
457
}
458
 
459
/*
460
 * Note that 'init' is a special process: it doesn't get signals it doesn't
461
 * want to handle. Thus you cannot kill init even with a SIGKILL even by
462
 * mistake.
463
 *
464
 * Note that we go through the signals twice: once to check the signals that
465
 * the kernel can handle, and then we build all the user-level signal handling
466
 * stack-frames in one go after that.
467
 */
468
int do_signal(struct pt_regs *regs, sigset_t *oldset)
469
{
470
        siginfo_t info;
471
        struct k_sigaction *ka;
472
 
473
        /*
474
         * We want the common case to go fast, which
475
         * is why we may in certain cases get here from
476
         * kernel mode. Just return without doing anything
477
         * if so.
478
         */
479
        if (!user_mode(regs))
480
                return 1;
481
 
482
        if (!oldset)
483
                oldset = &current->blocked;
484
#ifdef CONFIG_S390_SUPPORT 
485
        if (current->thread.flags & S390_FLAG_31BIT) {
486
                extern asmlinkage int do_signal32(struct pt_regs *regs, sigset_t *oldset);
487
                return do_signal32(regs, oldset);
488
        }
489
#endif 
490
 
491
        for (;;) {
492
                unsigned long signr;
493
 
494
                spin_lock_irq(&current->sigmask_lock);
495
                signr = dequeue_signal(&current->blocked, &info);
496
                spin_unlock_irq(&current->sigmask_lock);
497
 
498
                if (!signr)
499
                        break;
500
 
501
                if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
502
                        /* Let the debugger run.  */
503
                        current->exit_code = signr;
504
                        set_current_state(TASK_STOPPED);
505
                        notify_parent(current, SIGCHLD);
506
                        schedule();
507
 
508
                        /* We're back.  Did the debugger cancel the sig?  */
509
                        if (!(signr = current->exit_code))
510
                                continue;
511
                        current->exit_code = 0;
512
 
513
                        /* The debugger continued.  Ignore SIGSTOP.  */
514
                        if (signr == SIGSTOP)
515
                                continue;
516
 
517
                        /* Update the siginfo structure.  Is this good?  */
518
                        if (signr != info.si_signo) {
519
                                info.si_signo = signr;
520
                                info.si_errno = 0;
521
                                info.si_code = SI_USER;
522
                                info.si_pid = current->p_pptr->pid;
523
                                info.si_uid = current->p_pptr->uid;
524
                        }
525
 
526
                        /* If the (new) signal is now blocked, requeue it.  */
527
                        if (sigismember(&current->blocked, signr)) {
528
                                send_sig_info(signr, &info, current);
529
                                continue;
530
                        }
531
                }
532
 
533
                ka = &current->sig->action[signr-1];
534
                if (ka->sa.sa_handler == SIG_IGN) {
535
                        if (signr != SIGCHLD)
536
                                continue;
537
                        /* Check for SIGCHLD: it's special.  */
538
                        while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
539
                                /* nothing */;
540
                        continue;
541
                }
542
 
543
                if (ka->sa.sa_handler == SIG_DFL) {
544
                        int exit_code = signr;
545
 
546
                        /* Init gets no signals it doesn't want.  */
547
                        if (current->pid == 1)
548
                                continue;
549
 
550
                        switch (signr) {
551
                        case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
552
                                continue;
553
 
554
                        case SIGTSTP: case SIGTTIN: case SIGTTOU:
555
                                if (is_orphaned_pgrp(current->pgrp))
556
                                        continue;
557
                                /* FALLTHRU */
558
 
559
                        case SIGSTOP: {
560
                                struct signal_struct *sig;
561
                                set_current_state(TASK_STOPPED);
562
                                current->exit_code = signr;
563
                                sig = current->p_pptr->sig;
564
                                if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
565
                                        notify_parent(current, SIGCHLD);
566
                                schedule();
567
                                continue;
568
                        }
569
 
570
                        case SIGQUIT: case SIGILL: case SIGTRAP:
571
                        case SIGABRT: case SIGFPE: case SIGSEGV:
572
                        case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
573
                                if (do_coredump(signr, regs))
574
                                        exit_code |= 0x80;
575
                                /* FALLTHRU */
576
 
577
                        default:
578
                                sig_exit(signr, exit_code, &info);
579
                                /* NOTREACHED */
580
                        }
581
                }
582
 
583
                /* Whee!  Actually deliver the signal.  */
584
                handle_signal(signr, ka, &info, oldset, regs);
585
                return 1;
586
        }
587
 
588
        /* Did we come from a system call? */
589
        if ( regs->trap == __LC_SVC_OLD_PSW /* System Call! */ ) {
590
                /* Restart the system call - no handlers present */
591
                if (regs->gprs[2] == -ERESTARTNOHAND ||
592
                    regs->gprs[2] == -ERESTARTSYS ||
593
                    regs->gprs[2] == -ERESTARTNOINTR) {
594
                        regs->gprs[2] = regs->orig_gpr2;
595
                        regs->psw.addr -= 2;
596
                }
597
        }
598
        return 0;
599
}

powered by: WebSVN 2.1.0

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