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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [arch/] [i960/] [kernel/] [signal.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *  linux/arch/i960/kernel/signal.c
3
 *
4
 *  Copyright (C) 1999  Keith Adams     <kma@cse.ogi.edu>
5
 *                      Oregon Graduate Institute
6
 *
7
 *  Based on:
8
 *
9
 *  linux/arch/m68k/kernel/signal.c
10
 *
11
 *  Copyright (C) 1991, 1992  Linus Torvalds
12
 *
13
 * This file is subject to the terms and conditions of the GNU General Public
14
 * License.  See the file COPYING in the main directory of this archive
15
 * for more details.
16
 */
17
 
18
#include <linux/config.h>
19
 
20
#include <linux/sched.h>
21
#include <linux/mm.h>
22
#include <linux/kernel.h>
23
#include <linux/signal.h>
24
#include <linux/errno.h>
25
#include <linux/wait.h>
26
#include <linux/ptrace.h>
27
#include <linux/unistd.h>
28
 
29
#include <asm/setup.h>
30
#include <asm/segment.h>
31
#include <asm/pgtable.h>
32
#include <asm/traps.h>
33
 
34
 
35
#define _S(nr) (1<<((nr)-1))
36
 
37
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
38
 
39
int do_signal(struct pt_regs *regs);
40
 
41
/*
42
 * atomically swap in the new signal mask, and wait for a signal.
43
 */
44
asmlinkage int do_sigsuspend(struct pt_regs* regs)
45
{
46
        int err;
47
        sigset_t* set = (sigset_t*) regs->gregs[0];
48
        unsigned long mask;
49
 
50
        if ((err=verify_area(VERIFY_READ, set, 4)))
51
                return -EINTR;
52
 
53
        mask = current->blocked;
54
        current->blocked = *set & _BLOCKABLE;
55
        regs->gregs[0] = -EINTR;
56
        for (;;) {
57
                current->state = TASK_INTERRUPTIBLE;
58
                schedule();
59
                if (do_signal(regs))
60
                        return -EINTR;
61
        }
62
}
63
 
64
/*
65
 * We don't ever need this on i960; the function return path lets setup_frame
66
 * return straight to the faulting instruction.
67
 */
68
asmlinkage int do_sigreturn(unsigned long __unused)
69
{
70
        printk("killing %d for trying to sigreturn\n");
71
        do_exit(SIGSEGV);
72
        return -1;
73
}
74
 
75
#define STACK_ALIGN 16
76
static inline unsigned long stack_align(unsigned long sp)
77
{
78
        int lobits  = sp & (STACK_ALIGN -1);
79
 
80
        if (sp & lobits)
81
                sp += STACK_ALIGN - lobits;
82
        return sp;
83
}
84
 
85
/*
86
 * Note that 'init' is a special process: it doesn't get signals it doesn't
87
 * want to handle. Thus you cannot kill init even with a SIGKILL even by
88
 * mistake.
89
 *
90
 * Note that we go through the signals twice: once to check the signals
91
 * that the kernel can handle, and then we build all the user-level signal
92
 * handling stack-frames in one go after that.
93
 *
94
 * XXX: todo: sigcontext stuff.
95
 */
96
 
97
asmlinkage int do_signal(struct pt_regs *regs)
98
{
99
        unsigned long mask = ~current->blocked;
100
        unsigned long handler_signal = 0;
101
        unsigned long signr;
102
        struct sigaction * sa;
103
 
104
        while ((signr = current->signal & mask)) {
105
                signr = ffz(~signr);
106
                clear_bit(signr, &current->signal);
107
                sa = current->sig->action + signr;
108
                signr++;
109
 
110
                if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
111
                        current->exit_code = signr;
112
                        current->state = TASK_STOPPED;
113
                        notify_parent(current, signr);
114
                        schedule();
115
 
116
                        if (!(signr = current->exit_code))
117
                                continue;
118
                        current->exit_code = 0;
119
                        if (signr == SIGSTOP)
120
                                continue;
121
                        if (_S(signr) & current->blocked) {
122
                                current->signal |= _S(signr);
123
                                continue;
124
                        }
125
                        sa = current->sig->action + signr - 1;
126
                }
127
 
128
                if (sa->sa_handler == SIG_IGN) {
129
                        if (signr != SIGCHLD)
130
                                continue;
131
                        /* SIGCHLD is special */
132
                        while (sys_waitpid(-1,0,WNOHANG) > 0)
133
                                ;
134
                        continue;
135
                }
136
                if (sa->sa_handler == SIG_DFL) {
137
                        if (current->pid == 1)
138
                                continue;
139
                        switch(signr) {
140
                        case SIGCONT: case SIGCHLD: case SIGWINCH:
141
                                      continue;
142
                        case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
143
                                if (current->flags & PF_PTRACED)
144
                                        continue;
145
                                current->state = TASK_STOPPED;
146
                                current->exit_code = signr;
147
                                if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
148
                                                SA_NOCLDSTOP))
149
                                        notify_parent(current, signr);
150
                                schedule();
151
                                continue;
152
 
153
                        case SIGQUIT: case SIGILL: case SIGTRAP:
154
                        case SIGIOT: case SIGFPE: case SIGSEGV: case SIGBUS:
155
                                if (current->binfmt && current->binfmt->core_dump) {
156
                                        if (current->binfmt->core_dump(signr, regs))
157
                                                signr |= 0x80;
158
                                }
159
                                /* fall through */
160
                        default:
161
                                current->signal |= _S(signr & 0x7f);
162
                                current->flags |= PF_SIGNALED;
163
                                do_exit(signr);
164
                        }
165
                }
166
 
167
                /*
168
                 * OK, we're invoking a handler
169
                 */
170
#ifdef DEBUG
171
                printk("user-specified handler for signal: %d\n", signr);
172
#endif
173
                handler_signal |= 1 << (signr-1);
174
                mask &= ~sa->sa_mask;
175
        }
176
 
177
        if (! handler_signal)
178
                return 0;
179
 
180
        /*
181
         * We chain user frames for the various handlers together. Since we use
182
         * local regs to pass parameters, all RIPs go to the asm routine
183
         * signal_head found in entry.S; if we were an MMU-full system, we would
184
         * have to copy signal_head out to the user process's stack.
185
         */
186
        {
187
                extern void signal_head(void);
188
                struct frame {
189
                        unsigned long pfp;
190
                        unsigned long sp;
191
                        unsigned long rip;
192
                        unsigned long* args[13];
193
                } *userframe, *newframe;
194
                unsigned long type;
195
 
196
#ifdef DEBUG
197
                stack_trace();
198
#endif
199
                asm("flushreg");
200
                type = regs->lregs[PT_PFP] & 0x7;
201
#ifdef DEBUG
202
                printk("pfp, type: 0x%8x, 0x%8x\n", regs->lregs[PT_PFP], type);
203
#endif
204
                userframe = (struct frame*)
205
                        (((unsigned long) regs->lregs[PT_PFP]) & ~0x7);
206
#ifdef DEBUG
207
                printk("userframe: 0x%8x\n", userframe);
208
                stack_trace_from((unsigned long) userframe);
209
#endif
210
 
211
                for (sa=current->sig->action, signr=1, mask=1;
212
                     mask;
213
                     sa++, signr++, mask<<=1) {
214
                        if (mask > handler_signal)
215
                                break;
216
                        if ((!(mask & handler_signal)) || (!sa->sa_handler))
217
                                continue;
218
#ifdef DEBUG
219
                        printk("userframe->rip: 0x%8x\n", userframe->rip);
220
#endif
221
                        newframe = stack_align(userframe->sp);
222
                        newframe->rip = (unsigned long) signal_head;
223
                        newframe->args[0] = (unsigned long) sa->sa_handler;
224
                        newframe->args[1] = signr;
225
#ifdef DEBUG
226
                        printk("r3,r4: 0x%8x, %d\n", sa->sa_handler, signr);
227
#endif
228
                        newframe->pfp = (unsigned long) userframe;
229
                        newframe->sp = (unsigned long)(newframe) + 64;
230
                        userframe = newframe;
231
                }
232
 
233
#ifdef DEBUG
234
                printk("done; look:\n");
235
                stack_trace();
236
#endif
237
                regs->lregs[PT_PFP] = (unsigned long)userframe | type;
238
                asm("flushreg");
239
 
240
                /*
241
                 * appropriate syscalls should return EINTR
242
                 */
243
                if ((type & 6) == 2 &&
244
                    (regs->gregs[0] == -ERESTARTNOHAND ||
245
                     regs->gregs[0] == -ERESTARTSYS ||
246
                     regs->gregs[0] == -ERESTARTNOINTR))
247
                        regs->gregs[0] = -EINTR;
248
        }
249
 
250
        return 1;
251
}

powered by: WebSVN 2.1.0

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