aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k')
-rw-r--r--arch/m68k/include/asm/sun3_pgtable.h5
-rw-r--r--arch/m68k/include/asm/thread_info.h1
-rw-r--r--arch/m68k/include/asm/unistd.h1
-rw-r--r--arch/m68k/kernel/entry.S30
-rw-r--r--arch/m68k/kernel/signal.c314
5 files changed, 141 insertions, 210 deletions
diff --git a/arch/m68k/include/asm/sun3_pgtable.h b/arch/m68k/include/asm/sun3_pgtable.h
index cf5fad9b525..f55aa04161e 100644
--- a/arch/m68k/include/asm/sun3_pgtable.h
+++ b/arch/m68k/include/asm/sun3_pgtable.h
@@ -217,9 +217,8 @@ static inline pte_t pgoff_to_pte(unsigned off)
217/* Find an entry in the third-level pagetable. */ 217/* Find an entry in the third-level pagetable. */
218#define pte_index(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE-1)) 218#define pte_index(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
219#define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + pte_index(address)) 219#define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + pte_index(address))
220/* FIXME: should we bother with kmap() here? */ 220#define pte_offset_map(pmd, address) ((pte_t *)page_address(pmd_page(*pmd)) + pte_index(address))
221#define pte_offset_map(pmd, address) ((pte_t *)kmap(pmd_page(*pmd)) + pte_index(address)) 221#define pte_unmap(pte) do { } while (0)
222#define pte_unmap(pte) kunmap(pte)
223 222
224/* Macros to (de)construct the fake PTEs representing swap pages. */ 223/* Macros to (de)construct the fake PTEs representing swap pages. */
225#define __swp_type(x) ((x).val & 0x7F) 224#define __swp_type(x) ((x).val & 0x7F)
diff --git a/arch/m68k/include/asm/thread_info.h b/arch/m68k/include/asm/thread_info.h
index 1da5d53a00e..790988967ba 100644
--- a/arch/m68k/include/asm/thread_info.h
+++ b/arch/m68k/include/asm/thread_info.h
@@ -104,5 +104,6 @@ static inline struct thread_info *current_thread_info(void)
104#define TIF_SYSCALL_TRACE 15 /* syscall trace active */ 104#define TIF_SYSCALL_TRACE 15 /* syscall trace active */
105#define TIF_MEMDIE 16 /* is terminating due to OOM killer */ 105#define TIF_MEMDIE 16 /* is terminating due to OOM killer */
106#define TIF_FREEZE 17 /* thread is freezing for suspend */ 106#define TIF_FREEZE 17 /* thread is freezing for suspend */
107#define TIF_RESTORE_SIGMASK 18 /* restore signal mask in do_signal */
107 108
108#endif /* _ASM_M68K_THREAD_INFO_H */ 109#endif /* _ASM_M68K_THREAD_INFO_H */
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h
index b43b36beafe..26d851d385b 100644
--- a/arch/m68k/include/asm/unistd.h
+++ b/arch/m68k/include/asm/unistd.h
@@ -373,6 +373,7 @@
373#define __ARCH_WANT_SYS_SIGPENDING 373#define __ARCH_WANT_SYS_SIGPENDING
374#define __ARCH_WANT_SYS_SIGPROCMASK 374#define __ARCH_WANT_SYS_SIGPROCMASK
375#define __ARCH_WANT_SYS_RT_SIGACTION 375#define __ARCH_WANT_SYS_RT_SIGACTION
376#define __ARCH_WANT_SYS_RT_SIGSUSPEND
376 377
377/* 378/*
378 * "Conditional" syscalls 379 * "Conditional" syscalls
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 6360c437dcf..1559dea36e5 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -99,7 +99,10 @@ do_trace_exit:
99 jra .Lret_from_exception 99 jra .Lret_from_exception
100 100
101ENTRY(ret_from_signal) 101ENTRY(ret_from_signal)
102 RESTORE_SWITCH_STACK 102 tstb %curptr@(TASK_INFO+TINFO_FLAGS+2)
103 jge 1f
104 jbsr syscall_trace
1051: RESTORE_SWITCH_STACK
103 addql #4,%sp 106 addql #4,%sp
104/* on 68040 complete pending writebacks if any */ 107/* on 68040 complete pending writebacks if any */
105#ifdef CONFIG_M68040 108#ifdef CONFIG_M68040
@@ -174,16 +177,11 @@ do_signal_return:
174 subql #4,%sp | dummy return address 177 subql #4,%sp | dummy return address
175 SAVE_SWITCH_STACK 178 SAVE_SWITCH_STACK
176 pea %sp@(SWITCH_STACK_SIZE) 179 pea %sp@(SWITCH_STACK_SIZE)
177 clrl %sp@-
178 bsrl do_signal 180 bsrl do_signal
179 addql #8,%sp 181 addql #4,%sp
180 RESTORE_SWITCH_STACK 182 RESTORE_SWITCH_STACK
181 addql #4,%sp 183 addql #4,%sp
182 tstl %d0 184 jbra resume_userspace
183 jeq resume_userspace
184 | when single stepping into handler stop at the first insn
185 btst #6,%curptr@(TASK_INFO+TINFO_FLAGS+2)
186 jeq resume_userspace
187 185
188do_delayed_trace: 186do_delayed_trace:
189 bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR 187 bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR
@@ -290,22 +288,6 @@ ENTRY(sys_vfork)
290 RESTORE_SWITCH_STACK 288 RESTORE_SWITCH_STACK
291 rts 289 rts
292 290
293ENTRY(sys_sigsuspend)
294 SAVE_SWITCH_STACK
295 pea %sp@(SWITCH_STACK_SIZE)
296 jbsr do_sigsuspend
297 addql #4,%sp
298 RESTORE_SWITCH_STACK
299 rts
300
301ENTRY(sys_rt_sigsuspend)
302 SAVE_SWITCH_STACK
303 pea %sp@(SWITCH_STACK_SIZE)
304 jbsr do_rt_sigsuspend
305 addql #4,%sp
306 RESTORE_SWITCH_STACK
307 rts
308
309ENTRY(sys_sigreturn) 291ENTRY(sys_sigreturn)
310 SAVE_SWITCH_STACK 292 SAVE_SWITCH_STACK
311 jbsr do_sigreturn 293 jbsr do_sigreturn
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 4b387538706..d12c3b0d9e4 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -51,8 +51,6 @@
51 51
52#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 52#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
53 53
54asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
55
56const int frame_extra_sizes[16] = { 54const int frame_extra_sizes[16] = {
57 [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */ 55 [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */
58 [2] = sizeof(((struct frame *)0)->un.fmt2), 56 [2] = sizeof(((struct frame *)0)->un.fmt2),
@@ -74,51 +72,21 @@ const int frame_extra_sizes[16] = {
74/* 72/*
75 * Atomically swap in the new signal mask, and wait for a signal. 73 * Atomically swap in the new signal mask, and wait for a signal.
76 */ 74 */
77asmlinkage int do_sigsuspend(struct pt_regs *regs) 75asmlinkage int
76sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
78{ 77{
79 old_sigset_t mask = regs->d3;
80 sigset_t saveset;
81
82 mask &= _BLOCKABLE; 78 mask &= _BLOCKABLE;
83 saveset = current->blocked; 79 spin_lock_irq(&current->sighand->siglock);
80 current->saved_sigmask = current->blocked;
84 siginitset(&current->blocked, mask); 81 siginitset(&current->blocked, mask);
85 recalc_sigpending(); 82 recalc_sigpending();
83 spin_unlock_irq(&current->sighand->siglock);
86 84
87 regs->d0 = -EINTR; 85 current->state = TASK_INTERRUPTIBLE;
88 while (1) { 86 schedule();
89 current->state = TASK_INTERRUPTIBLE; 87 set_restore_sigmask();
90 schedule();
91 if (do_signal(&saveset, regs))
92 return -EINTR;
93 }
94}
95
96asmlinkage int
97do_rt_sigsuspend(struct pt_regs *regs)
98{
99 sigset_t __user *unewset = (sigset_t __user *)regs->d1;
100 size_t sigsetsize = (size_t)regs->d2;
101 sigset_t saveset, newset;
102
103 /* XXX: Don't preclude handling different sized sigset_t's. */
104 if (sigsetsize != sizeof(sigset_t))
105 return -EINVAL;
106 88
107 if (copy_from_user(&newset, unewset, sizeof(newset))) 89 return -ERESTARTNOHAND;
108 return -EFAULT;
109 sigdelsetmask(&newset, ~_BLOCKABLE);
110
111 saveset = current->blocked;
112 current->blocked = newset;
113 recalc_sigpending();
114
115 regs->d0 = -EINTR;
116 while (1) {
117 current->state = TASK_INTERRUPTIBLE;
118 schedule();
119 if (do_signal(&saveset, regs))
120 return -EINTR;
121 }
122} 90}
123 91
124asmlinkage int 92asmlinkage int
@@ -132,10 +100,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
132 old_sigset_t mask; 100 old_sigset_t mask;
133 if (!access_ok(VERIFY_READ, act, sizeof(*act)) || 101 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
134 __get_user(new_ka.sa.sa_handler, &act->sa_handler) || 102 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
135 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) 103 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
104 __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
105 __get_user(mask, &act->sa_mask))
136 return -EFAULT; 106 return -EFAULT;
137 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
138 __get_user(mask, &act->sa_mask);
139 siginitset(&new_ka.sa.sa_mask, mask); 107 siginitset(&new_ka.sa.sa_mask, mask);
140 } 108 }
141 109
@@ -144,10 +112,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
144 if (!ret && oact) { 112 if (!ret && oact) {
145 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || 113 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
146 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || 114 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
147 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) 115 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
116 __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
117 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
148 return -EFAULT; 118 return -EFAULT;
149 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
150 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
151 } 119 }
152 120
153 return ret; 121 return ret;
@@ -318,36 +286,10 @@ out:
318 return err; 286 return err;
319} 287}
320 288
321static inline int 289static int mangle_kernel_stack(struct pt_regs *regs, int formatvec,
322restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp, 290 void __user *fp)
323 int *pd0)
324{ 291{
325 int fsize, formatvec; 292 int fsize = frame_extra_sizes[formatvec >> 12];
326 struct sigcontext context;
327 int err;
328
329 /* Always make any pending restarted system calls return -EINTR */
330 current_thread_info()->restart_block.fn = do_no_restart_syscall;
331
332 /* get previous context */
333 if (copy_from_user(&context, usc, sizeof(context)))
334 goto badframe;
335
336 /* restore passed registers */
337 regs->d1 = context.sc_d1;
338 regs->a0 = context.sc_a0;
339 regs->a1 = context.sc_a1;
340 regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
341 regs->pc = context.sc_pc;
342 regs->orig_d0 = -1; /* disable syscall checks */
343 wrusp(context.sc_usp);
344 formatvec = context.sc_formatvec;
345 regs->format = formatvec >> 12;
346 regs->vector = formatvec & 0xfff;
347
348 err = restore_fpu_state(&context);
349
350 fsize = frame_extra_sizes[regs->format];
351 if (fsize < 0) { 293 if (fsize < 0) {
352 /* 294 /*
353 * user process trying to return with weird frame format 295 * user process trying to return with weird frame format
@@ -355,16 +297,22 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u
355#ifdef DEBUG 297#ifdef DEBUG
356 printk("user process returning with weird frame format\n"); 298 printk("user process returning with weird frame format\n");
357#endif 299#endif
358 goto badframe; 300 return 1;
359 } 301 }
302 if (!fsize) {
303 regs->format = formatvec >> 12;
304 regs->vector = formatvec & 0xfff;
305 } else {
306 struct switch_stack *sw = (struct switch_stack *)regs - 1;
307 unsigned long buf[fsize / 2]; /* yes, twice as much */
360 308
361 /* OK. Make room on the supervisor stack for the extra junk, 309 /* that'll make sure that expansion won't crap over data */
362 * if necessary. 310 if (copy_from_user(buf + fsize / 4, fp, fsize))
363 */ 311 return 1;
364 312
365 if (fsize) { 313 /* point of no return */
366 struct switch_stack *sw = (struct switch_stack *)regs - 1; 314 regs->format = formatvec >> 12;
367 regs->d0 = context.sc_d0; 315 regs->vector = formatvec & 0xfff;
368#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) 316#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
369 __asm__ __volatile__ 317 __asm__ __volatile__
370 (" movel %0,%/a0\n\t" 318 (" movel %0,%/a0\n\t"
@@ -376,30 +324,50 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u
376 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */ 324 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
377 " lsrl #2,%1\n\t" 325 " lsrl #2,%1\n\t"
378 " subql #1,%1\n\t" 326 " subql #1,%1\n\t"
379 "2: movesl %4@+,%2\n\t" 327 /* copy to the gap we'd made */
380 "3: movel %2,%/a0@+\n\t" 328 "2: movel %4@+,%/a0@+\n\t"
381 " dbra %1,2b\n\t" 329 " dbra %1,2b\n\t"
382 " bral ret_from_signal\n" 330 " bral ret_from_signal\n"
383 "4:\n"
384 ".section __ex_table,\"a\"\n"
385 " .align 4\n"
386 " .long 2b,4b\n"
387 " .long 3b,4b\n"
388 ".previous"
389 : /* no outputs, it doesn't ever return */ 331 : /* no outputs, it doesn't ever return */
390 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), 332 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
391 "n" (frame_offset), "a" (fp) 333 "n" (frame_offset), "a" (buf + fsize/4)
392 : "a0"); 334 : "a0");
393#undef frame_offset 335#undef frame_offset
394 /*
395 * If we ever get here an exception occurred while
396 * building the above stack-frame.
397 */
398 goto badframe;
399 } 336 }
337 return 0;
338}
400 339
401 *pd0 = context.sc_d0; 340static inline int
402 return err; 341restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp)
342{
343 int formatvec;
344 struct sigcontext context;
345 int err;
346
347 /* Always make any pending restarted system calls return -EINTR */
348 current_thread_info()->restart_block.fn = do_no_restart_syscall;
349
350 /* get previous context */
351 if (copy_from_user(&context, usc, sizeof(context)))
352 goto badframe;
353
354 /* restore passed registers */
355 regs->d0 = context.sc_d0;
356 regs->d1 = context.sc_d1;
357 regs->a0 = context.sc_a0;
358 regs->a1 = context.sc_a1;
359 regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
360 regs->pc = context.sc_pc;
361 regs->orig_d0 = -1; /* disable syscall checks */
362 wrusp(context.sc_usp);
363 formatvec = context.sc_formatvec;
364
365 err = restore_fpu_state(&context);
366
367 if (err || mangle_kernel_stack(regs, formatvec, fp))
368 goto badframe;
369
370 return 0;
403 371
404badframe: 372badframe:
405 return 1; 373 return 1;
@@ -407,9 +375,9 @@ badframe:
407 375
408static inline int 376static inline int
409rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, 377rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
410 struct ucontext __user *uc, int *pd0) 378 struct ucontext __user *uc)
411{ 379{
412 int fsize, temp; 380 int temp;
413 greg_t __user *gregs = uc->uc_mcontext.gregs; 381 greg_t __user *gregs = uc->uc_mcontext.gregs;
414 unsigned long usp; 382 unsigned long usp;
415 int err; 383 int err;
@@ -443,65 +411,16 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
443 regs->sr = (regs->sr & 0xff00) | (temp & 0xff); 411 regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
444 regs->orig_d0 = -1; /* disable syscall checks */ 412 regs->orig_d0 = -1; /* disable syscall checks */
445 err |= __get_user(temp, &uc->uc_formatvec); 413 err |= __get_user(temp, &uc->uc_formatvec);
446 regs->format = temp >> 12;
447 regs->vector = temp & 0xfff;
448 414
449 err |= rt_restore_fpu_state(uc); 415 err |= rt_restore_fpu_state(uc);
450 416
451 if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT) 417 if (err || do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
452 goto badframe; 418 goto badframe;
453 419
454 fsize = frame_extra_sizes[regs->format]; 420 if (mangle_kernel_stack(regs, temp, &uc->uc_extra))
455 if (fsize < 0) {
456 /*
457 * user process trying to return with weird frame format
458 */
459#ifdef DEBUG
460 printk("user process returning with weird frame format\n");
461#endif
462 goto badframe; 421 goto badframe;
463 }
464
465 /* OK. Make room on the supervisor stack for the extra junk,
466 * if necessary.
467 */
468 422
469 if (fsize) { 423 return 0;
470#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
471 __asm__ __volatile__
472 (" movel %0,%/a0\n\t"
473 " subl %1,%/a0\n\t" /* make room on stack */
474 " movel %/a0,%/sp\n\t" /* set stack pointer */
475 /* move switch_stack and pt_regs */
476 "1: movel %0@+,%/a0@+\n\t"
477 " dbra %2,1b\n\t"
478 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
479 " lsrl #2,%1\n\t"
480 " subql #1,%1\n\t"
481 "2: movesl %4@+,%2\n\t"
482 "3: movel %2,%/a0@+\n\t"
483 " dbra %1,2b\n\t"
484 " bral ret_from_signal\n"
485 "4:\n"
486 ".section __ex_table,\"a\"\n"
487 " .align 4\n"
488 " .long 2b,4b\n"
489 " .long 3b,4b\n"
490 ".previous"
491 : /* no outputs, it doesn't ever return */
492 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
493 "n" (frame_offset), "a" (&uc->uc_extra)
494 : "a0");
495#undef frame_offset
496 /*
497 * If we ever get here an exception occurred while
498 * building the above stack-frame.
499 */
500 goto badframe;
501 }
502
503 *pd0 = regs->d0;
504 return err;
505 424
506badframe: 425badframe:
507 return 1; 426 return 1;
@@ -514,7 +433,6 @@ asmlinkage int do_sigreturn(unsigned long __unused)
514 unsigned long usp = rdusp(); 433 unsigned long usp = rdusp();
515 struct sigframe __user *frame = (struct sigframe __user *)(usp - 4); 434 struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
516 sigset_t set; 435 sigset_t set;
517 int d0;
518 436
519 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 437 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
520 goto badframe; 438 goto badframe;
@@ -528,9 +446,9 @@ asmlinkage int do_sigreturn(unsigned long __unused)
528 current->blocked = set; 446 current->blocked = set;
529 recalc_sigpending(); 447 recalc_sigpending();
530 448
531 if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0)) 449 if (restore_sigcontext(regs, &frame->sc, frame + 1))
532 goto badframe; 450 goto badframe;
533 return d0; 451 return regs->d0;
534 452
535badframe: 453badframe:
536 force_sig(SIGSEGV, current); 454 force_sig(SIGSEGV, current);
@@ -544,7 +462,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
544 unsigned long usp = rdusp(); 462 unsigned long usp = rdusp();
545 struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4); 463 struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
546 sigset_t set; 464 sigset_t set;
547 int d0;
548 465
549 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 466 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
550 goto badframe; 467 goto badframe;
@@ -555,9 +472,9 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
555 current->blocked = set; 472 current->blocked = set;
556 recalc_sigpending(); 473 recalc_sigpending();
557 474
558 if (rt_restore_ucontext(regs, sw, &frame->uc, &d0)) 475 if (rt_restore_ucontext(regs, sw, &frame->uc))
559 goto badframe; 476 goto badframe;
560 return d0; 477 return regs->d0;
561 478
562badframe: 479badframe:
563 force_sig(SIGSEGV, current); 480 force_sig(SIGSEGV, current);
@@ -775,7 +692,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
775 return (void __user *)((usp - frame_size) & -8UL); 692 return (void __user *)((usp - frame_size) & -8UL);
776} 693}
777 694
778static void setup_frame (int sig, struct k_sigaction *ka, 695static int setup_frame (int sig, struct k_sigaction *ka,
779 sigset_t *set, struct pt_regs *regs) 696 sigset_t *set, struct pt_regs *regs)
780{ 697{
781 struct sigframe __user *frame; 698 struct sigframe __user *frame;
@@ -793,10 +710,8 @@ static void setup_frame (int sig, struct k_sigaction *ka,
793 710
794 frame = get_sigframe(ka, regs, sizeof(*frame) + fsize); 711 frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
795 712
796 if (fsize) { 713 if (fsize)
797 err |= copy_to_user (frame + 1, regs + 1, fsize); 714 err |= copy_to_user (frame + 1, regs + 1, fsize);
798 regs->stkadj = fsize;
799 }
800 715
801 err |= __put_user((current_thread_info()->exec_domain 716 err |= __put_user((current_thread_info()->exec_domain
802 && current_thread_info()->exec_domain->signal_invmap 717 && current_thread_info()->exec_domain->signal_invmap
@@ -826,11 +741,21 @@ static void setup_frame (int sig, struct k_sigaction *ka,
826 741
827 push_cache ((unsigned long) &frame->retcode); 742 push_cache ((unsigned long) &frame->retcode);
828 743
829 /* Set up registers for signal handler */ 744 /*
745 * Set up registers for signal handler. All the state we are about
746 * to destroy is successfully copied to sigframe.
747 */
830 wrusp ((unsigned long) frame); 748 wrusp ((unsigned long) frame);
831 regs->pc = (unsigned long) ka->sa.sa_handler; 749 regs->pc = (unsigned long) ka->sa.sa_handler;
832 750
833adjust_stack: 751 /*
752 * This is subtle; if we build more than one sigframe, all but the
753 * first one will see frame format 0 and have fsize == 0, so we won't
754 * screw stkadj.
755 */
756 if (fsize)
757 regs->stkadj = fsize;
758
834 /* Prepare to skip over the extra stuff in the exception frame. */ 759 /* Prepare to skip over the extra stuff in the exception frame. */
835 if (regs->stkadj) { 760 if (regs->stkadj) {
836 struct pt_regs *tregs = 761 struct pt_regs *tregs =
@@ -845,14 +770,14 @@ adjust_stack:
845 tregs->pc = regs->pc; 770 tregs->pc = regs->pc;
846 tregs->sr = regs->sr; 771 tregs->sr = regs->sr;
847 } 772 }
848 return; 773 return 0;
849 774
850give_sigsegv: 775give_sigsegv:
851 force_sigsegv(sig, current); 776 force_sigsegv(sig, current);
852 goto adjust_stack; 777 return err;
853} 778}
854 779
855static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, 780static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
856 sigset_t *set, struct pt_regs *regs) 781 sigset_t *set, struct pt_regs *regs)
857{ 782{
858 struct rt_sigframe __user *frame; 783 struct rt_sigframe __user *frame;
@@ -869,10 +794,8 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
869 794
870 frame = get_sigframe(ka, regs, sizeof(*frame)); 795 frame = get_sigframe(ka, regs, sizeof(*frame));
871 796
872 if (fsize) { 797 if (fsize)
873 err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize); 798 err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
874 regs->stkadj = fsize;
875 }
876 799
877 err |= __put_user((current_thread_info()->exec_domain 800 err |= __put_user((current_thread_info()->exec_domain
878 && current_thread_info()->exec_domain->signal_invmap 801 && current_thread_info()->exec_domain->signal_invmap
@@ -914,11 +837,21 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
914 837
915 push_cache ((unsigned long) &frame->retcode); 838 push_cache ((unsigned long) &frame->retcode);
916 839
917 /* Set up registers for signal handler */ 840 /*
841 * Set up registers for signal handler. All the state we are about
842 * to destroy is successfully copied to sigframe.
843 */
918 wrusp ((unsigned long) frame); 844 wrusp ((unsigned long) frame);
919 regs->pc = (unsigned long) ka->sa.sa_handler; 845 regs->pc = (unsigned long) ka->sa.sa_handler;
920 846
921adjust_stack: 847 /*
848 * This is subtle; if we build more than one sigframe, all but the
849 * first one will see frame format 0 and have fsize == 0, so we won't
850 * screw stkadj.
851 */
852 if (fsize)
853 regs->stkadj = fsize;
854
922 /* Prepare to skip over the extra stuff in the exception frame. */ 855 /* Prepare to skip over the extra stuff in the exception frame. */
923 if (regs->stkadj) { 856 if (regs->stkadj) {
924 struct pt_regs *tregs = 857 struct pt_regs *tregs =
@@ -933,11 +866,11 @@ adjust_stack:
933 tregs->pc = regs->pc; 866 tregs->pc = regs->pc;
934 tregs->sr = regs->sr; 867 tregs->sr = regs->sr;
935 } 868 }
936 return; 869 return 0;
937 870
938give_sigsegv: 871give_sigsegv:
939 force_sigsegv(sig, current); 872 force_sigsegv(sig, current);
940 goto adjust_stack; 873 return err;
941} 874}
942 875
943static inline void 876static inline void
@@ -995,6 +928,7 @@ static void
995handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, 928handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
996 sigset_t *oldset, struct pt_regs *regs) 929 sigset_t *oldset, struct pt_regs *regs)
997{ 930{
931 int err;
998 /* are we from a system call? */ 932 /* are we from a system call? */
999 if (regs->orig_d0 >= 0) 933 if (regs->orig_d0 >= 0)
1000 /* If so, check system call restarting.. */ 934 /* If so, check system call restarting.. */
@@ -1002,17 +936,24 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
1002 936
1003 /* set up the stack frame */ 937 /* set up the stack frame */
1004 if (ka->sa.sa_flags & SA_SIGINFO) 938 if (ka->sa.sa_flags & SA_SIGINFO)
1005 setup_rt_frame(sig, ka, info, oldset, regs); 939 err = setup_rt_frame(sig, ka, info, oldset, regs);
1006 else 940 else
1007 setup_frame(sig, ka, oldset, regs); 941 err = setup_frame(sig, ka, oldset, regs);
1008 942
1009 if (ka->sa.sa_flags & SA_ONESHOT) 943 if (err)
1010 ka->sa.sa_handler = SIG_DFL; 944 return;
1011 945
1012 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); 946 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
1013 if (!(ka->sa.sa_flags & SA_NODEFER)) 947 if (!(ka->sa.sa_flags & SA_NODEFER))
1014 sigaddset(&current->blocked,sig); 948 sigaddset(&current->blocked,sig);
1015 recalc_sigpending(); 949 recalc_sigpending();
950
951 if (test_thread_flag(TIF_DELAYED_TRACE)) {
952 regs->sr &= ~0x8000;
953 send_sig(SIGTRAP, current, 1);
954 }
955
956 clear_thread_flag(TIF_RESTORE_SIGMASK);
1016} 957}
1017 958
1018/* 959/*
@@ -1020,22 +961,25 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
1020 * want to handle. Thus you cannot kill init even with a SIGKILL even by 961 * want to handle. Thus you cannot kill init even with a SIGKILL even by
1021 * mistake. 962 * mistake.
1022 */ 963 */
1023asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) 964asmlinkage void do_signal(struct pt_regs *regs)
1024{ 965{
1025 siginfo_t info; 966 siginfo_t info;
1026 struct k_sigaction ka; 967 struct k_sigaction ka;
1027 int signr; 968 int signr;
969 sigset_t *oldset;
1028 970
1029 current->thread.esp0 = (unsigned long) regs; 971 current->thread.esp0 = (unsigned long) regs;
1030 972
1031 if (!oldset) 973 if (test_thread_flag(TIF_RESTORE_SIGMASK))
974 oldset = &current->saved_sigmask;
975 else
1032 oldset = &current->blocked; 976 oldset = &current->blocked;
1033 977
1034 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 978 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
1035 if (signr > 0) { 979 if (signr > 0) {
1036 /* Whee! Actually deliver the signal. */ 980 /* Whee! Actually deliver the signal. */
1037 handle_signal(signr, &ka, &info, oldset, regs); 981 handle_signal(signr, &ka, &info, oldset, regs);
1038 return 1; 982 return;
1039 } 983 }
1040 984
1041 /* Did we come from a system call? */ 985 /* Did we come from a system call? */
@@ -1043,5 +987,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
1043 /* Restart the system call - no handlers present */ 987 /* Restart the system call - no handlers present */
1044 handle_restart(regs, NULL, 0); 988 handle_restart(regs, NULL, 0);
1045 989
1046 return 0; 990 /* If there's no signal to deliver, we just restore the saved mask. */
991 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
992 clear_thread_flag(TIF_RESTORE_SIGMASK);
993 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
994 }
1047} 995}