This source file includes following definitions.
- do_sigsuspend
- do_sigreturn
- setup_frame
- do_signal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #include <linux/sched.h>
16 #include <linux/mm.h>
17 #include <linux/kernel.h>
18 #include <linux/signal.h>
19 #include <linux/errno.h>
20 #include <linux/wait.h>
21 #include <linux/ptrace.h>
22 #include <linux/unistd.h>
23
24 #include <asm/segment.h>
25 #include <asm/pgtable.h>
26 #include <asm/traps.h>
27 #include <asm/bootinfo.h>
28
29 #define offsetof(type, member) ((size_t)(&((type *)0)->member))
30
31 #define _S(nr) (1<<((nr)-1))
32
33 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
34
35 asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
36 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs);
37
38 static const int extra_sizes[16] = {
39 0,
40 -1,
41 sizeof(((struct frame *)0)->un.fmt2),
42 sizeof(((struct frame *)0)->un.fmt3),
43 sizeof(((struct frame *)0)->un.fmt4),
44 -1,
45 -1,
46 sizeof(((struct frame *)0)->un.fmt7),
47 -1,
48 sizeof(((struct frame *)0)->un.fmt9),
49 sizeof(((struct frame *)0)->un.fmta),
50 sizeof(((struct frame *)0)->un.fmtb),
51 -1,
52 -1,
53 -1,
54 -1,
55 };
56
57
58
59
60 asmlinkage int do_sigsuspend(struct pt_regs *regs)
61 {
62 unsigned long oldmask = current->blocked;
63 unsigned long newmask = regs->d3;
64
65 current->blocked = newmask & _BLOCKABLE;
66 regs->d0 = -EINTR;
67 while (1) {
68 current->state = TASK_INTERRUPTIBLE;
69 schedule();
70 if (do_signal(oldmask, regs))
71 return -EINTR;
72 }
73 }
74
75 static unsigned char fpu_version = 0;
76
77
78
79
80 asmlinkage int do_sigreturn(unsigned long __unused)
81 {
82 struct sigcontext_struct context;
83 struct frame * regs;
84 struct switch_stack *sw;
85 int fsize = 0;
86 int formatvec = 0;
87 unsigned long fp;
88 unsigned long usp = rdusp();
89
90 #if 0
91 printk("sys_sigreturn, usp=%08x\n", (unsigned) usp);
92 #endif
93
94
95 sw = (struct switch_stack *) &__unused;
96 regs = (struct frame *) (sw + 1);
97
98
99 if (verify_area(VERIFY_READ, (void *)usp, sizeof(context)))
100 goto badframe;
101
102 memcpy_fromfs(&context,(void *)usp, sizeof(context));
103
104 fp = usp + sizeof (context);
105
106
107 current->blocked = context.sc_mask & _BLOCKABLE;
108
109
110 regs->ptregs.d0 = context.sc_d0;
111 regs->ptregs.d1 = context.sc_d1;
112 regs->ptregs.a0 = context.sc_a0;
113 regs->ptregs.a1 = context.sc_a1;
114 regs->ptregs.sr = (regs->ptregs.sr & 0xff00)|(context.sc_sr & 0xff);
115 regs->ptregs.pc = context.sc_pc;
116
117 wrusp(context.sc_usp);
118 formatvec = context.sc_formatvec;
119 regs->ptregs.format = formatvec >> 12;
120 regs->ptregs.vector = formatvec & 0xfff;
121 if (context.sc_fpstate[0])
122 {
123
124 if (context.sc_fpstate[0] != fpu_version){
125 #if DEBUG
126 printk("fpregs=%08x fpcntl=%08x\n", context.sc_fpregs,
127 context.sc_fpcntl);
128 printk("Wrong fpu: sc_fpstate[0]=%02x fpu_version=%02x\n",
129 (unsigned) context.sc_fpstate[0], (unsigned) fpu_version);
130 {
131 int i;
132 printk("Saved fp_state: ");
133 for (i = 0; i < 216; i++){
134 printk("%02x ", context.sc_fpstate[i]);
135 }
136 printk("\n");
137 }
138 #endif
139 goto badframe;
140 }
141 if (boot_info.cputype & FPU_68881)
142 {
143 if (context.sc_fpstate[1] != 0x18
144 && context.sc_fpstate[1] != 0xb4)
145 goto badframe;
146 }
147 else if (boot_info.cputype & FPU_68882)
148 {
149 if (context.sc_fpstate[1] != 0x38
150 && context.sc_fpstate[1] != 0xd4){
151 #if 0
152 printk("Wrong 68882 fpu-state\n");
153 #endif
154 goto badframe;
155 }
156 }
157 else if (boot_info.cputype & FPU_68040)
158 {
159 if (!((context.sc_fpstate[1] == 0x00)|| \
160 (context.sc_fpstate[1] == 0x28)|| \
161 (context.sc_fpstate[1] == 0x60))){
162 #if 0
163 printk("Wrong 68040 fpu-state\n");
164 #endif
165 goto badframe;
166 }
167 }
168 else if (boot_info.cputype & FPU_68060)
169 {
170 if (!((context.sc_fpstate[1] == 0x00)|| \
171 (context.sc_fpstate[1] == 0x60)|| \
172 (context.sc_fpstate[1] == 0xe0))){
173 #if 0
174 printk("Wrong 68060 fpu-state\n");
175 #endif
176 goto badframe;
177 }
178 }
179 __asm__ volatile ("fmovemx %0,%/fp0-%/fp1\n\t"
180 "fmoveml %1,%/fpcr/%/fpsr/%/fpiar"
181 :
182 : "m" (*context.sc_fpregs),
183 "m" (*context.sc_fpcntl));
184 }
185 __asm__ volatile ("frestore %0" : : "m" (*context.sc_fpstate));
186
187 fsize = extra_sizes[regs->ptregs.format];
188 if (fsize < 0) {
189
190
191
192 #if DEBUG
193 printk("user process returning with weird frame format\n");
194 #endif
195 goto badframe;
196 }
197
198
199
200
201
202 if (fsize) {
203 if (verify_area(VERIFY_READ, (void *)fp, fsize))
204 goto badframe;
205
206 #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
207 __asm__ __volatile__
208 ("movel %0,%/a0\n\t"
209 "subl %1,%/a0\n\t"
210 "movel %/a0,%/sp\n\t"
211
212 "1: movel %0@+,%/a0@+\n\t"
213 " dbra %2,1b\n\t"
214 "lea %/sp@(%c3),%/a0\n\t"
215 "lsrl #2,%1\n\t"
216 "subql #1,%1\n\t"
217 "2: movesl %4@+,%2\n\t"
218 " movel %2,%/a0@+\n\t"
219 " dbra %1,2b\n\t"
220 "bral " SYMBOL_NAME_STR(ret_from_signal)
221 :
222 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
223 "n" (frame_offset), "a" (fp)
224 : "a0");
225 #undef frame_offset
226 goto badframe;
227
228 }
229
230 return regs->ptregs.d0;
231 badframe:
232 do_exit(SIGSEGV);
233 }
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276 #define UFRAME_SIZE(fs) (sizeof(struct sigcontext_struct)/4 + 6 + fs/4)
277
278 static void setup_frame (struct sigaction * sa, unsigned long **fp,
279 unsigned long pc, struct frame *regs, int
280 signr, unsigned long oldmask)
281 {
282 struct sigcontext_struct context;
283 unsigned long *frame, *tframe;
284 int fsize = extra_sizes[regs->ptregs.format];
285
286 if (fsize < 0) {
287 printk ("setup_frame: Unknown frame format %#x\n",
288 regs->ptregs.format);
289 do_exit(SIGSEGV);
290 }
291 frame = *fp - UFRAME_SIZE(fsize);
292 if (verify_area(VERIFY_WRITE,frame,UFRAME_SIZE(fsize)*4))
293 do_exit(SIGSEGV);
294 if (fsize) {
295 memcpy_tofs (frame + UFRAME_SIZE(0), ®s->un, fsize);
296 regs->ptregs.stkadj = fsize;
297 }
298
299
300 tframe = frame;
301
302
303 put_user((ulong)(frame+4), tframe); tframe++;
304 if (current->exec_domain && current->exec_domain->signal_invmap)
305 put_user(current->exec_domain->signal_invmap[signr], tframe);
306 else
307 put_user(signr, tframe);
308 tframe++;
309
310 put_user(regs->ptregs.vector, tframe); tframe++;
311
312 put_user((ulong)(frame+6), tframe); tframe++;
313
314
315 put_user(0xdefc0014,tframe); tframe++;
316 put_user(0x70774e40,tframe); tframe++;
317
318
319 cache_push_v ((unsigned long)frame, (int)tframe - (int)frame);
320
321
322 context.sc_mask = oldmask;
323 context.sc_usp = (unsigned long)*fp;
324 context.sc_d0 = regs->ptregs.d0;
325 context.sc_d1 = regs->ptregs.d1;
326 context.sc_a0 = regs->ptregs.a0;
327 context.sc_a1 = regs->ptregs.a1;
328 context.sc_sr = regs->ptregs.sr;
329 context.sc_pc = pc;
330 context.sc_formatvec = (regs->ptregs.format << 12 |
331 regs->ptregs.vector);
332 #if DEBUG
333 printk("formatvec: %02x\n", (unsigned) context.sc_formatvec);
334 #endif
335 __asm__ volatile ("fsave %0" : : "m" (*context.sc_fpstate) : "memory");
336 if (context.sc_fpstate[0])
337 {
338 fpu_version = context.sc_fpstate[0];
339 #if DEBUG
340 {
341 int i;
342 printk("Saved fp_state: ");
343 for (i = 0; i < 216; i++){
344 printk("%02x ", context.sc_fpstate[i]);
345 }
346 printk("\n");
347 }
348 printk("fpregs=%08x fpcntl=%08x\n", context.sc_fpregs,
349 context.sc_fpcntl);
350 #endif
351 __asm__ volatile ("fmovemx %/fp0-%/fp1,%0\n\t"
352 "fmoveml %/fpcr/%/fpsr/%/fpiar,%1"
353 :
354 : "m" (*context.sc_fpregs),
355 "m" (*context.sc_fpcntl)
356 : "memory");
357 }
358 #if DEBUG
359 {
360 int i;
361 printk("Saved fp_state: ");
362 for (i = 0; i < 216; i++){
363 printk("%02x ", context.sc_fpstate[i]);
364 }
365 printk("\n");
366 }
367 #endif
368 memcpy_tofs (tframe, &context, sizeof(context));
369
370
371
372
373 regs->ptregs.format = 0;
374
375
376 *fp = frame;
377 }
378
379
380
381
382
383
384
385
386
387
388 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs_in)
389 {
390 unsigned long mask = ~current->blocked;
391 unsigned long handler_signal = 0;
392 unsigned long *frame = NULL;
393 unsigned long pc = 0;
394 unsigned long signr;
395 struct frame *regs = (struct frame *)regs_in;
396 struct sigaction * sa;
397
398 current->tss.esp0 = (unsigned long) regs;
399
400 while ((signr = current->signal & mask)) {
401 __asm__("bfffo %2,#0,#0,%1\n\t"
402 "bfclr %0,%1,#1\n\t"
403 "eorw #31,%1"
404 :"=m" (current->signal),"=r" (signr)
405 :"1" (signr));
406 sa = current->sig->action + signr;
407 signr++;
408
409 if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
410 current->exit_code = signr;
411 current->state = TASK_STOPPED;
412 notify_parent(current);
413 schedule();
414 if (!(signr = current->exit_code)) {
415 discard_frame:
416
417
418 switch (regs->ptregs.format) {
419 case 7:
420 case 9:
421 case 10:
422 case 11:
423 regs->ptregs.stkadj = extra_sizes[regs->ptregs.format];
424 regs->ptregs.format = 0;
425 break;
426 }
427 continue;
428 }
429 current->exit_code = 0;
430 if (signr == SIGSTOP)
431 goto discard_frame;
432 if (_S(signr) & current->blocked) {
433 current->signal |= _S(signr);
434 continue;
435 }
436 sa = current->sig->action + signr - 1;
437 }
438 if (sa->sa_handler == SIG_IGN) {
439 if (signr != SIGCHLD)
440 continue;
441
442 while (sys_waitpid(-1,NULL,WNOHANG) > 0)
443 ;
444 continue;
445 }
446 if (sa->sa_handler == SIG_DFL) {
447 if (current->pid == 1)
448 continue;
449 switch (signr) {
450 case SIGCONT: case SIGCHLD: case SIGWINCH:
451 continue;
452
453 case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
454 if (current->flags & PF_PTRACED)
455 continue;
456 current->state = TASK_STOPPED;
457 current->exit_code = signr;
458 if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
459 SA_NOCLDSTOP))
460 notify_parent(current);
461 schedule();
462 continue;
463
464 case SIGQUIT: case SIGILL: case SIGTRAP:
465 case SIGIOT: case SIGFPE: case SIGSEGV:
466 if (current->binfmt && current->binfmt->core_dump) {
467 if (current->binfmt->core_dump(signr, (struct pt_regs *)regs))
468 signr |= 0x80;
469 }
470
471 default:
472 current->signal |= _S(signr & 0x7f);
473 do_exit(signr);
474 }
475 }
476
477
478
479 if (regs->ptregs.orig_d0 >= 0) {
480 if (regs->ptregs.d0 == -ERESTARTNOHAND ||
481 (regs->ptregs.d0 == -ERESTARTSYS &&
482 !(sa->sa_flags & SA_RESTART)))
483 regs->ptregs.d0 = -EINTR;
484 }
485 handler_signal |= 1 << (signr-1);
486 mask &= ~sa->sa_mask;
487 }
488 if (regs->ptregs.orig_d0 >= 0 &&
489 (regs->ptregs.d0 == -ERESTARTNOHAND ||
490 regs->ptregs.d0 == -ERESTARTSYS ||
491 regs->ptregs.d0 == -ERESTARTNOINTR)) {
492 regs->ptregs.d0 = regs->ptregs.orig_d0;
493 regs->ptregs.pc -= 2;
494 }
495 if (!handler_signal)
496 {
497
498
499 if (regs->ptregs.stkadj)
500 {
501 struct frame *tregs =
502 (struct frame *) ((ulong) regs + regs->ptregs.stkadj);
503
504
505
506 tregs->ptregs.vector = regs->ptregs.vector;
507 tregs->ptregs.format = regs->ptregs.format;
508 tregs->ptregs.pc = regs->ptregs.pc;
509 tregs->ptregs.sr = regs->ptregs.sr;
510 }
511 return 0;
512 }
513 pc = regs->ptregs.pc;
514 frame = (unsigned long *)rdusp();
515 signr = 1;
516 sa = current->sig->action;
517 for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
518 if (mask > handler_signal)
519 break;
520 if (!(mask & handler_signal))
521 continue;
522 setup_frame(sa,&frame,pc,regs,signr,oldmask);
523 pc = (unsigned long) sa->sa_handler;
524 if (sa->sa_flags & SA_ONESHOT)
525 sa->sa_handler = NULL;
526
527 __asm__ __volatile__("movesb %0,%/d0": :"m" (*(char *)pc):"d0");
528 current->blocked |= sa->sa_mask;
529 oldmask |= sa->sa_mask;
530 }
531 wrusp((unsigned long)frame);
532 regs->ptregs.pc = pc;
533
534
535
536
537
538
539
540
541 if (regs->ptregs.stkadj) {
542 struct frame *tregs =
543 (struct frame *)((ulong)regs + regs->ptregs.stkadj);
544 #if DEBUG
545 printk("Performing stackadjust=%04x\n", (unsigned)
546 regs->ptregs.stkadj);
547 #endif
548
549
550 tregs->ptregs.vector = regs->ptregs.vector;
551 tregs->ptregs.format = regs->ptregs.format;
552 tregs->ptregs.pc = regs->ptregs.pc;
553 tregs->ptregs.sr = regs->ptregs.sr;
554 }
555
556 return 1;
557 }