This source file includes following definitions.
- sys_sigsuspend
- sys_sigreturn
- setup_frame
- do_signal
1
2
3
4
5
6 #include <linux/sched.h>
7 #include <linux/mm.h>
8 #include <linux/kernel.h>
9 #include <linux/signal.h>
10 #include <linux/errno.h>
11 #include <linux/wait.h>
12 #include <linux/ptrace.h>
13 #include <linux/unistd.h>
14
15 #include <asm/bitops.h>
16 #include <asm/segment.h>
17 #include <asm/cachectl.h>
18
19 #define _S(nr) (1<<((nr)-1))
20
21 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
22
23 asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
24 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs);
25
26
27
28
29 asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set)
30 {
31 unsigned long mask;
32 struct pt_regs * regs = (struct pt_regs *) &restart;
33
34 mask = current->blocked;
35 current->blocked = set & _BLOCKABLE;
36 regs->reg2 = -EINTR;
37 while (1) {
38 current->state = TASK_INTERRUPTIBLE;
39 schedule();
40 if (do_signal(mask,regs))
41 return -EINTR;
42 }
43 }
44
45
46
47
48 asmlinkage int sys_sigreturn(struct pt_regs *regs)
49 {
50 struct sigcontext_struct *context;
51
52
53
54
55
56
57 context = (struct sigcontext_struct *) regs->reg29;
58 if (verify_area(VERIFY_READ, context, sizeof(struct sigcontext_struct)) ||
59 (regs->reg29 & 3))
60 goto badframe;
61
62 current->blocked = context->sc_oldmask & _BLOCKABLE;
63 regs->reg1 = context->sc_at;
64 regs->reg2 = context->sc_v0;
65 regs->reg3 = context->sc_v1;
66 regs->reg4 = context->sc_a0;
67 regs->reg5 = context->sc_a1;
68 regs->reg6 = context->sc_a2;
69 regs->reg7 = context->sc_a3;
70 regs->reg8 = context->sc_t0;
71 regs->reg9 = context->sc_t1;
72 regs->reg10 = context->sc_t2;
73 regs->reg11 = context->sc_t3;
74 regs->reg12 = context->sc_t4;
75 regs->reg13 = context->sc_t5;
76 regs->reg14 = context->sc_t6;
77 regs->reg15 = context->sc_t7;
78 regs->reg16 = context->sc_s0;
79 regs->reg17 = context->sc_s1;
80 regs->reg18 = context->sc_s2;
81 regs->reg19 = context->sc_s3;
82 regs->reg20 = context->sc_s4;
83 regs->reg21 = context->sc_s5;
84 regs->reg22 = context->sc_s6;
85 regs->reg23 = context->sc_s7;
86 regs->reg24 = context->sc_t8;
87 regs->reg25 = context->sc_t9;
88
89
90
91 regs->reg28 = context->sc_gp;
92 regs->reg29 = context->sc_sp;
93 regs->reg30 = context->sc_fp;
94 regs->reg31 = context->sc_ra;
95 regs->cp0_epc = context->sc_epc;
96 regs->cp0_cause = context->sc_cause;
97
98
99
100
101 regs->orig_reg2 = -1;
102 return context->sc_v0;
103
104 badframe:
105 do_exit(SIGSEGV);
106 }
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 struct sc {
140 unsigned long ass[4];
141 unsigned int code[4];
142 struct sigcontext_struct scc;
143 };
144 #define scc_offset ((size_t)&((struct sc *)0)->scc)
145
146 static void setup_frame(struct sigaction * sa, struct sc **fp,
147 unsigned long pc, struct pt_regs *regs,
148 int signr, unsigned long oldmask)
149 {
150 struct sc *frame;
151
152 frame = *fp;
153 frame--;
154
155
156
157
158
159
160 if (verify_area(VERIFY_WRITE, frame, sizeof (struct sc)) ||
161 ((unsigned long)frame & 3))
162 do_exit(SIGSEGV);
163
164
165
166
167
168
169
170
171
172
173 frame->code[0] = 0x27bd0000 + scc_offset;
174 frame->code[1] = 0x24020000 + __NR_sigreturn;
175 frame->code[2] = 0x0000000c;
176
177
178
179
180 sys_cacheflush (frame->code, sizeof (frame->code), ICACHE);
181
182
183
184
185 frame->scc.sc_at = regs->reg1;
186 frame->scc.sc_v0 = regs->reg2;
187 frame->scc.sc_v1 = regs->reg3;
188 frame->scc.sc_a0 = regs->reg4;
189 frame->scc.sc_a1 = regs->reg5;
190 frame->scc.sc_a2 = regs->reg6;
191 frame->scc.sc_a3 = regs->reg7;
192
193 frame->scc.sc_t0 = regs->reg8;
194 frame->scc.sc_t1 = regs->reg9;
195 frame->scc.sc_t2 = regs->reg10;
196 frame->scc.sc_t3 = regs->reg11;
197 frame->scc.sc_t4 = regs->reg12;
198 frame->scc.sc_t5 = regs->reg13;
199 frame->scc.sc_t6 = regs->reg14;
200 frame->scc.sc_t7 = regs->reg15;
201
202 frame->scc.sc_s0 = regs->reg16;
203 frame->scc.sc_s1 = regs->reg17;
204 frame->scc.sc_s2 = regs->reg18;
205 frame->scc.sc_s3 = regs->reg19;
206 frame->scc.sc_s4 = regs->reg20;
207 frame->scc.sc_s5 = regs->reg21;
208 frame->scc.sc_s6 = regs->reg22;
209 frame->scc.sc_s7 = regs->reg23;
210
211 frame->scc.sc_t8 = regs->reg24;
212 frame->scc.sc_t9 = regs->reg25;
213
214
215
216
217 frame->scc.sc_gp = regs->reg28;
218 frame->scc.sc_sp = regs->reg29;
219 frame->scc.sc_fp = regs->reg30;
220 frame->scc.sc_ra = regs->reg31;
221
222 frame->scc.sc_epc = regs->cp0_epc;
223 frame->scc.sc_cause = regs->cp0_cause;
224
225 frame->scc.sc_oldmask = oldmask;
226 *fp = frame;
227
228 regs->reg4 = signr;
229 }
230
231
232
233
234
235
236
237
238
239
240 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
241 {
242 unsigned long mask = ~current->blocked;
243 unsigned long handler_signal = 0;
244 struct sc *frame = NULL;
245 unsigned long pc = 0;
246 unsigned long signr;
247 struct sigaction * sa;
248
249 while ((signr = current->signal & mask)) {
250 signr = ffz(~signr);
251 clear_bit(signr, ¤t->signal);
252 sa = current->sig->action + signr;
253 signr++;
254 if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
255 current->exit_code = signr;
256 current->state = TASK_STOPPED;
257 notify_parent(current);
258 schedule();
259 if (!(signr = current->exit_code))
260 continue;
261 current->exit_code = 0;
262 if (signr == SIGSTOP)
263 continue;
264 if (_S(signr) & current->blocked) {
265 current->signal |= _S(signr);
266 continue;
267 }
268 sa = current->sig->action + signr - 1;
269 }
270 if (sa->sa_handler == SIG_IGN) {
271 if (signr != SIGCHLD)
272 continue;
273
274 while (sys_waitpid(-1,NULL,WNOHANG) > 0)
275 ;
276 continue;
277 }
278 if (sa->sa_handler == SIG_DFL) {
279 if (current->pid == 1)
280 continue;
281 switch (signr) {
282 case SIGCONT: case SIGCHLD: case SIGWINCH:
283 continue;
284
285 case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
286 if (current->flags & PF_PTRACED)
287 continue;
288 current->state = TASK_STOPPED;
289 current->exit_code = signr;
290 if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
291 SA_NOCLDSTOP))
292 notify_parent(current);
293 schedule();
294 continue;
295
296 case SIGQUIT: case SIGILL: case SIGTRAP:
297 case SIGIOT: case SIGFPE: case SIGSEGV: case SIGBUS:
298 if (current->binfmt && current->binfmt->core_dump) {
299 if (current->binfmt->core_dump(signr, regs))
300 signr |= 0x80;
301 }
302
303 default:
304 current->signal |= _S(signr & 0x7f);
305 current->flags |= PF_SIGNALED;
306 do_exit(signr);
307 }
308 }
309
310
311
312 if (regs->orig_reg2 >= 0) {
313 if (regs->reg2 == -ERESTARTNOHAND ||
314 (regs->reg2 == -ERESTARTSYS &&
315 !(sa->sa_flags & SA_RESTART)))
316 regs->reg2 = -EINTR;
317 }
318 handler_signal |= 1 << (signr-1);
319 mask &= ~sa->sa_mask;
320 }
321
322
323
324
325
326 if (regs->orig_reg2 >= 0 &&
327 (regs->reg2 == -ERESTARTNOHAND ||
328 regs->reg2 == -ERESTARTSYS ||
329 regs->reg2 == -ERESTARTNOINTR))
330 {
331 regs->reg2 = regs->orig_reg2;
332 regs->cp0_epc -= 8;
333 }
334 if (!handler_signal)
335 return 0;
336 pc = regs->cp0_epc;
337 frame = (struct sc *) regs->reg29;
338 signr = 1;
339 sa = current->sig->action;
340 for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
341 if (mask > handler_signal)
342 break;
343 if (!(mask & handler_signal))
344 continue;
345 setup_frame(sa, &frame, pc, regs, signr, oldmask);
346 pc = (unsigned long) sa->sa_handler;
347 if (sa->sa_flags & SA_ONESHOT)
348 sa->sa_handler = NULL;
349 current->blocked |= sa->sa_mask;
350 oldmask |= sa->sa_mask;
351 }
352 regs->reg29 = (unsigned long) frame;
353 regs->reg31 = (unsigned long) frame->code;
354 regs->cp0_epc = pc;
355
356 return 1;
357 }