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 do_exit(signr);
306 }
307 }
308
309
310
311 if (regs->orig_reg2 >= 0) {
312 if (regs->reg2 == -ERESTARTNOHAND ||
313 (regs->reg2 == -ERESTARTSYS &&
314 !(sa->sa_flags & SA_RESTART)))
315 regs->reg2 = -EINTR;
316 }
317 handler_signal |= 1 << (signr-1);
318 mask &= ~sa->sa_mask;
319 }
320
321
322
323
324
325 if (regs->orig_reg2 >= 0 &&
326 (regs->reg2 == -ERESTARTNOHAND ||
327 regs->reg2 == -ERESTARTSYS ||
328 regs->reg2 == -ERESTARTNOINTR))
329 {
330 regs->reg2 = regs->orig_reg2;
331 regs->cp0_epc -= 8;
332 }
333 if (!handler_signal)
334 return 0;
335 pc = regs->cp0_epc;
336 frame = (struct sc *) regs->reg29;
337 signr = 1;
338 sa = current->sig->action;
339 for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
340 if (mask > handler_signal)
341 break;
342 if (!(mask & handler_signal))
343 continue;
344 setup_frame(sa, &frame, pc, regs, signr, oldmask);
345 pc = (unsigned long) sa->sa_handler;
346 if (sa->sa_flags & SA_ONESHOT)
347 sa->sa_handler = NULL;
348 current->blocked |= sa->sa_mask;
349 oldmask |= sa->sa_mask;
350 }
351 regs->reg29 = (unsigned long) frame;
352 regs->reg31 = (unsigned long) frame->code;
353 regs->cp0_epc = pc;
354
355 return 1;
356 }